Summary
The generated openspec-archive-change skill (v1.6.0, dist/core/templates/workflows/archive-change.js; observed in .claude/skills/openspec-archive-change/SKILL.md after openspec init) can archive a change before its spec sync completes, leaving the change archived while openspec/specs/ was never updated.
The instructions in question
Step 4 (delta sync assessment) ends with:
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change ''. …"). Proceed to archive regardless of choice.
Step 5 then immediately moves the change folder:
mv "<changeRoot>" "<planningHome.changesDir>/archive/YYYY-MM-DD-<name>"
Nothing between the two requires waiting for the dispatched sync or verifying its result.
Why this races
- In harnesses where subagents/Tasks run asynchronously (e.g. Claude Code's current default), the parent agent proceeds to step 5 while the sync subagent is still working. The
mv relocates the delta specs out from under it.
- The sync subagent is told to operate on change
<name>; once the folder is moved to archive/, the change no longer resolves as an active change, so even a late-starting sync fails.
- In harnesses where Tasks block, it happens to work — but correctness then depends on unstated harness scheduling semantics rather than the skill's instructions.
Impact
The archive completes and reports "Specs: ✓ Synced" per the success template, while openspec/specs/ never received the delta requirements — silently breaking the specs-reflect-archived-changes invariant.
Suggested fix
Make step 5 conditional on sync completion: run the sync inline (or explicitly wait for the subagent and check its result), verify the merged requirements are present in openspec/specs/, and only then move changeRoot. Alternatively, reorder the skill to sync-then-archive as strictly sequential steps with a verification gate between them.
Related but distinct: #1381 covers a different defect in the same step ("Proceed to archive regardless of choice" also overriding Cancel).
Summary
The generated
openspec-archive-changeskill (v1.6.0,dist/core/templates/workflows/archive-change.js; observed in.claude/skills/openspec-archive-change/SKILL.mdafteropenspec init) can archive a change before its spec sync completes, leaving the change archived whileopenspec/specs/was never updated.The instructions in question
Step 4 (delta sync assessment) ends with:
Step 5 then immediately moves the change folder:
Nothing between the two requires waiting for the dispatched sync or verifying its result.
Why this races
mvrelocates the delta specs out from under it.<name>; once the folder is moved toarchive/, the change no longer resolves as an active change, so even a late-starting sync fails.Impact
The archive completes and reports "Specs: ✓ Synced" per the success template, while
openspec/specs/never received the delta requirements — silently breaking the specs-reflect-archived-changes invariant.Suggested fix
Make step 5 conditional on sync completion: run the sync inline (or explicitly wait for the subagent and check its result), verify the merged requirements are present in
openspec/specs/, and only then movechangeRoot. Alternatively, reorder the skill to sync-then-archive as strictly sequential steps with a verification gate between them.Related but distinct: #1381 covers a different defect in the same step ("Proceed to archive regardless of choice" also overriding Cancel).