Skip to content

workflows: terminal artifact set (result.json + workflow.json) is not committed atomically #110

Description

@tt-a1i

Description

Verified by read-only audit (seal/gpt-5.6-sol subagent, verdict: CONFIRMED).

persistWorkflowJson writes artifacts as a multi-step sequence of individually-atomic writes:

  • extensions/workflows/artifacts.ts:154-165transcripts.json and optionally journal.json
  • artifacts.ts:167-172 — atomic replace of result.json
  • artifacts.ts:174-185 — compact manifest with resultArtifact: "result.json" written separately to workflow.json

writeFileAtomic (serialization.ts:147-161) is a temp-write + renameSync per file — no directory-level transaction.

Impact

Crash window: after the result.json rename succeeds and before the workflow.json rename succeeds, readers retain the prior manifest (typically running, without resultArtifact). Consequences:

  • hydrateRunArtifacts (dashboard.ts:102-114) reads result.json only when the manifest references it.
  • Restart recovery (index.ts:972-990) and status recovery (index.ts:2212-2226) are manifest-driven and never probe an unreferenced result.json.
  • Stale-run recovery (dashboard.ts:483-514) flips persisted running to uncertain without inspecting result.json.
  • No GC, cleanup, or orphan-detection path exists — the terminal result stays orphaned indefinitely and the run is reported as running/uncertain instead of terminal.

Test coverage gap

execute.e2e.test.ts:297-302 covers successful persistence and individual atomic replacement, but not failure/crash between the result.json and workflow.json writes.

Suggested fix

Commit a single manifest only after all dependent artifacts are durably prepared (e.g. transaction-like temp run directory + rename, or a manifest generation/commit marker). Additionally, recovery should detect and reconcile orphan result.json artifacts instead of trusting only the old manifest.

Related: #107, #108, #109 (same delivery/persistence subsystem).

Found by automated workflow audit (run wf_56028a5b018b).

Activity

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

Metadata

Metadata

Assignees

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