Skip to content

CSharpFileParser serializes only the code — IsExecutable / ActivityParentPath are silently lost on every FS, blob and GitSync round-trip #912

Closed

Description

@rbuergi

Found while fixing #841 (ExecuteScript silent dispatch death), and deliberately not fixed there because the blast radius crosses into users' git repositories.

The defect

CSharpFileParser.SerializeCodeConfiguration (src/MeshWeaver.Hosting/Persistence/Parsers/CSharpFileParser.cs:100) writes only config.Code — it emits no // <meshweaver> header. The read side then rebuilds a CodeConfiguration { Code, Language }, so on any file-system or blob-storage round-trip these are silently lost:

  • IsExecutable
  • ActivityParentPath
  • every Last* stamp

Consequence

On an FS/blob-backed mesh, every executable Code node comes back non-executable, and ExecuteScript then refuses it. Pre-#841 that refusal was reported to nobody at all, which is why this stayed invisible.

Proven by a controlled A/B: the identical node executes on an in-memory mesh; the same node persisted to the file system reads back IsExecutable=false, and the on-disk Scripts/exec-….cs contains just the code with no header.

Why it wasn't fixed in #841

The same serializer is what GitSync writes into users' git repositories (GitHubSyncService.cs:263, NodeFileMapper.cs:38) and what AzureBlobStorageAdapter.cs:151 persists. Emitting a header is therefore a cross-repo file-format change, and it brushes the .cs/.json authoring contract in AGENTS.md — which already documents the read-side half of this trap:

the .cs header carries ONLY Id/DisplayName/NodeType, so a cell with isExecutable/activityParentPath (or node-level description/order) authored as .cs silently loses its Run button on import (e.g. Data/Architecture/PythonCodeNodes/SampleStatistics.json stays JSON deliberately)

So the documented workaround is "author those as .json". This issue is the write side of the same gap: a node that was correctly created in the mesh loses those fields when serialized out, with no authoring mistake involved.

Options (needs a decision)

  1. Extend the .cs header to carry IsExecutable / ActivityParentPath (and decide about the Last* stamps, which are arguably runtime state that should not be in a source file at all). Changes the file format in every synced git repo.
  2. Route executable Code nodes to .json on serialize, matching the documented authoring guidance, so the .cs form stays a pure source file.
  3. Accept the loss and make it loud at serialize time rather than silent.

Current state

McpReadYourWritesTest.ExecuteScript_ForIsExecutableCodeNode_SurfacesTheFileSystemRoundTripLoss is an explicitly-labelled characterization test added in #841: it pins the truthful current behaviour, and its doc comment says to flip the expectation back to Dispatched once the serializer is fixed.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions