You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm a bit confused about open:sync and hoping someone can shed some light.
I ran open:sync the other day, and now my spec.md files look different from what I expected. It's like they're not fully synced, or something got changed unexpectedly.
My main questions are:
Why did this happen? What usually causes spec.md to be different after open:sync? Is it something I'm doing wrong, or is there a common scenario for this?
How do I fix it? If my spec.md is now weird, what's the best way to get it back to normal without losing my work? Are there any commands to help me see the differences or merge them?
How can I avoid this in the future? Any tips or best practices for using open:sync with Git (like when to commit, when to run sync) so this doesn't happen again?
Thanks for reporting this. Here's a breakdown of what's happening and how to address each of your questions.
Why did this happen?
/opsx:sync merges delta specs (from openspec/changes/<change-name>/specs/*/spec.md) into your main specs (at openspec/specs/*/spec.md). The key behavior that likely surprised you:
MODIFIED operations replace entire requirement blocks — they don't do a fine-grained merge. If your delta spec has a ## MODIFIED Requirements section, the entire requirement body in the main spec gets replaced with the delta version (src/core/specs-apply.ts:272-286).
Ordering may change — after sync, requirements are recomposed in a specific order (RENAMED first, then REMOVED, MODIFIED, ADDED), which can rearrange the output compared to what you had before.
No conflict detection for parallel changes — if you had multiple changes touching the same spec, the second sync silently overwrites what the first one wrote. This is a known limitation with planned improvements.
Common scenarios that cause unexpected results:
Scenario
What happens
Delta has MODIFIED section
Entire requirement block is replaced, not merged
Multiple changes target the same spec
Later sync overwrites earlier one
Delta was written against an older version of the spec
New content from other changes can be lost
How to fix it
Check what changed — use git diff on your openspec/specs/ directory to see exactly what sync modified:
git diff openspec/specs/
Revert if needed — if you committed before syncing, you can restore the previous version:
git checkout HEAD -- openspec/specs/
Re-sync selectively — after reverting, you can run /opsx:sync <change-name> targeting a specific change, then review the diff before committing.
Validate specs — run /opsx:status to check if your specs are still structurally valid.
Commit before syncing — always commit (or stash) your current state so you can revert if the merge isn't what you expect.
You often don't need to call sync directly — the archive command prompts for sync if needed. Most users never need to run /opsx:sync manually (docs/commands.md:388).
Review the diff after sync — run git diff immediately after sync to verify the changes look correct before committing.
One change at a time for the same spec — if two changes target the same spec, archive the first before syncing the second. Parallel changes to the same spec are a known source of silent overwrites.
Use sync for preview — sync is useful when you want to preview what the merge looks like before archiving (docs/commands.md:432).
How do I fix it? If my spec.md is now weird, what's the best way to get it back to normal without losing my work? Are there any commands to help me see the differences or merge them?
You don't need special commands! The beauty of LLM's is you can just ask the model to go and fix it, you can literally prompt it to say "hey can you check if this is now wrong, if so what would the fix be?"
Why did this happen? What usually causes spec.md to be different after open:sync? Is it something I'm doing wrong, or is there a common scenario for this?
I would need more details here. Can you maybe retrieve the agent session to give more info?
sync looks at your current change proposal and tries to sync it to the source of truth specs manually.
I think I have your root cause. Hit this in our project after using /opsx:archive (which calls the same openspec-sync-specs skill under the hood) since Feb 2026.
Ran openspec validate --specs against our repo's state immediately after every archive commit:
Archive commit
Passing / Failing
First archive (Feb 2026)
0 / 5
Subsequent archives
~23 / ~22 (consistent)
After manual cleanup of all specs
47 / 0
Every main spec touched by sync-specs has failed validation since day one. The files weren't being "messed up" by some intermittent bug — the skill produces invalid output on every run, and there's no validation step in the archive workflow to catch it.
Two specific defects in openspec-sync-specs (dist/core/templates/workflows/sync-specs.js) account for nearly all failures:
Delta header leaks through. Delta specs use ## ADDED Requirements; main specs require ## Requirements. The skill instructions tell the agent to "apply changes intelligently" but never say to rewrite the header when writing into a main spec. The format reference and example output (lines 73–124, 248–262) show the delta header verbatim with no normalization. Result: ## ADDED Requirements ends up in your main spec.md and the validator rejects it.
## Purpose is only added on the "new spec" branch. Step 3d says to add Purpose when creating a brand-new main spec, but the much more common "main spec already exists, append new requirements" path never mentions Purpose. So existing specs that get touched lose/never gain a Purpose section.
And openspec-archive-change has no validation step, so the broken output ships silently. Adding openspec validate --specs to the end of the archive workflow would have caught this on the very first run.
How to recover your specs:
openspec validate --specs
That will list every main spec that's currently invalid, with the specific defect. In our repo it took one commit to hand-fix: change ## ADDED Requirements → ## Requirements, add a ## Purpose section if missing, and replace any non-RFC2119 wording (lowercase must, requires, by default is) with SHALL/MUST/SHOULD.
To avoid this in the future: run openspec validate --specs after every /opsx:sync or /opsx:archive, and revert + hand-merge if it fails. Until the upstream skill templates are fixed, there's no way to make the agent-driven sync produce valid output reliably.
Related canonical issue: #863 (covers the underlying "archive skill doesn't invoke openspec archive CLI, re-implements it manually without validation" architecture problem). #656 is the original ask.
The concrete cause here — the sync skill leaving delta operation headers (## ADDED Requirements) in your main specs and dropping the ## Purpose section, producing invalid spec.md files — is fixed on main. The openspec-sync-specs workflow now normalizes deltas into a single ## Requirements section, carries the delta's ## Purpose over verbatim, and runs openspec validate --specs at the end so bad output is caught immediately (src/core/templates/workflows/sync-specs.ts; #1402, #1431, #1500).
To recover an already-affected spec: run openspec validate --specs to see each defect, then either git checkout HEAD -- openspec/specs/ and re-sync, or hand-fix the flagged headers/Purpose. Closing as resolved on current versions — please reopen if a fresh sync still corrupts a spec.
Activity
21st-connector commentedon Apr 3, 2026
Task completed.
I'll analyze this issue by exploring the codebase to understand how
open:syncworks and what could cause spec.md files to be modified unexpectedly.View full conversation
Powered by 1Code
21st-connector commentedon Apr 3, 2026
Issue Triage:
open:syncand spec.md behaviorThanks for reporting this. Here's a breakdown of what's happening and how to address each of your questions.
Why did this happen?
/opsx:syncmerges delta specs (fromopenspec/changes/<change-name>/specs/*/spec.md) into your main specs (atopenspec/specs/*/spec.md). The key behavior that likely surprised you:## MODIFIED Requirementssection, the entire requirement body in the main spec gets replaced with the delta version (src/core/specs-apply.ts:272-286).Common scenarios that cause unexpected results:
How to fix it
Check what changed — use
git diffon youropenspec/specs/directory to see exactly what sync modified:Revert if needed — if you committed before syncing, you can restore the previous version:
Re-sync selectively — after reverting, you can run
/opsx:sync <change-name>targeting a specific change, then review the diff before committing.Validate specs — run
/opsx:statusto check if your specs are still structurally valid.How to avoid this in the future
Per the command documentation:
/opsx:syncmanually (docs/commands.md:388).git diffimmediately after sync to verify the changes look correct before committing.Related issues
Relevant code and docs
src/core/specs-apply.tssrc/core/parsers/requirement-blocks.ts/opsx:synccommand docsdocs/commands.md#L386-L440docs/concepts.md#L346-L405openspec-parallel-merge-plan.mdsrc/core/templates/workflows/sync-specs.tsTabishB commentedon Apr 7, 2026
You don't need special commands! The beauty of LLM's is you can just ask the model to go and fix it, you can literally prompt it to say "hey can you check if this is now wrong, if so what would the fix be?"
I would need more details here. Can you maybe retrieve the agent session to give more info?
sync looks at your current change proposal and tries to sync it to the source of truth specs manually.
But hard to say without a proper agent trace.
nagoodman commentedon May 12, 2026
I think I have your root cause. Hit this in our project after using
/opsx:archive(which calls the sameopenspec-sync-specsskill under the hood) since Feb 2026.Ran
openspec validate --specsagainst our repo's state immediately after every archive commit:Every main spec touched by sync-specs has failed validation since day one. The files weren't being "messed up" by some intermittent bug — the skill produces invalid output on every run, and there's no validation step in the archive workflow to catch it.
Two specific defects in
openspec-sync-specs(dist/core/templates/workflows/sync-specs.js) account for nearly all failures:Delta header leaks through. Delta specs use
## ADDED Requirements; main specs require## Requirements. The skill instructions tell the agent to "apply changes intelligently" but never say to rewrite the header when writing into a main spec. The format reference and example output (lines 73–124, 248–262) show the delta header verbatim with no normalization. Result:## ADDED Requirementsends up in your mainspec.mdand the validator rejects it.## Purposeis only added on the "new spec" branch. Step 3d says to add Purpose when creating a brand-new main spec, but the much more common "main spec already exists, append new requirements" path never mentions Purpose. So existing specs that get touched lose/never gain a Purpose section.And
openspec-archive-changehas no validation step, so the broken output ships silently. Addingopenspec validate --specsto the end of the archive workflow would have caught this on the very first run.How to recover your specs:
That will list every main spec that's currently invalid, with the specific defect. In our repo it took one commit to hand-fix: change
## ADDED Requirements→## Requirements, add a## Purposesection if missing, and replace any non-RFC2119 wording (lowercasemust,requires,by default is) withSHALL/MUST/SHOULD.To avoid this in the future: run
openspec validate --specsafter every/opsx:syncor/opsx:archive, and revert + hand-merge if it fails. Until the upstream skill templates are fixed, there's no way to make the agent-driven sync produce valid output reliably.Related canonical issue: #863 (covers the underlying "archive skill doesn't invoke
openspec archiveCLI, re-implements it manually without validation" architecture problem). #656 is the original ask.docs(proposal): add prevent-silent-spec-drop change
docs(proposal): add prevent-silent-spec-drop change
docs(proposal): add prevent-silent-spec-drop change
docs(proposal): add prevent-silent-spec-drop change
docs(proposal): add prevent-silent-spec-drop change
docs(proposal): add prevent-silent-spec-drop change
clay-good commentedon Aug 5, 2026
The concrete cause here — the sync skill leaving delta operation headers (
## ADDED Requirements) in your main specs and dropping the## Purposesection, producing invalidspec.mdfiles — is fixed on main. Theopenspec-sync-specsworkflow now normalizes deltas into a single## Requirementssection, carries the delta's## Purposeover verbatim, and runsopenspec validate --specsat the end so bad output is caught immediately (src/core/templates/workflows/sync-specs.ts; #1402, #1431, #1500).To recover an already-affected spec: run
openspec validate --specsto see each defect, then eithergit checkout HEAD -- openspec/specs/and re-sync, or hand-fix the flagged headers/Purpose. Closing as resolved on current versions — please reopen if a fresh sync still corrupts a spec.