Problem
When a workflow (/opsx:propose, /opsx:ff, etc.) is interrupted mid-execution, partially-written artifact files remain on disk. On re-execution, the system detects these files and marks the artifacts as status: "done", causing the workflow to skip them — leaving the change in an inconsistent state with incomplete artifacts that cascade into poor downstream output.
Root Cause
detectCompleted() in src/core/artifact-graph/state.ts uses artifactOutputExists() which only checks file existence (fs.statSync / glob match). No content validation is performed — an empty or half-written file is treated identically to a complete one.
Reproduction
- Run
/opsx:propose "add-dark-mode"
- Interrupt after
proposal.md is created but before content is fully written
- Re-run
/opsx:continue on the same change
openspec status --json reports proposal as status: "done" → workflow skips it
Impact
- Stuck workflows — no clean way to resume after interruption
- Cascading quality degradation — downstream artifacts built on incomplete context
- Silent failure — no warning or error is produced
- Only workaround is manually finding and deleting the incomplete files
Affected Code
src/core/artifact-graph/state.ts — detectCompleted(), isArtifactComplete()
src/core/artifact-graph/outputs.ts — artifactOutputExists(), resolveArtifactOutputs()
Problem
When a workflow (
/opsx:propose,/opsx:ff, etc.) is interrupted mid-execution, partially-written artifact files remain on disk. On re-execution, the system detects these files and marks the artifacts asstatus: "done", causing the workflow to skip them — leaving the change in an inconsistent state with incomplete artifacts that cascade into poor downstream output.Root Cause
detectCompleted()insrc/core/artifact-graph/state.tsusesartifactOutputExists()which only checks file existence (fs.statSync/ glob match). No content validation is performed — an empty or half-written file is treated identically to a complete one.Reproduction
/opsx:propose "add-dark-mode"proposal.mdis created but before content is fully written/opsx:continueon the same changeopenspec status --jsonreportsproposalasstatus: "done"→ workflow skips itImpact
Affected Code
src/core/artifact-graph/state.ts—detectCompleted(),isArtifactComplete()src/core/artifact-graph/outputs.ts—artifactOutputExists(),resolveArtifactOutputs()