Summary
The specs artifact instruction tells an agent to read and edit a capability's main spec at openspec/specs/<capability-path>/spec.md — a path relative to the current directory. When the change lives in a registered store, the main spec lives under the store root, so that path is wrong.
The workflow templates already solved this. sync-specs.ts:44 and archive-change.ts:98 both say main specs live under `<planningHome.root>/openspec/specs/` — "use that (store-aware) root for every main-spec path below, not a hardcoded repo path." The schema instruction is the site that was missed.
The two affected operations
schemas/spec-driven/schema.yaml:
| Line |
Text |
Operation |
| 103 |
edit `openspec/specs/<capability-path>/spec.md` directly |
write (fixing a TBD Purpose) |
| 106 |
Locate the existing requirement in openspec/specs/<capability-path>/spec.md |
read (step 1 of the MODIFIED workflow) |
Two other mentions (lines 17 and 75) only describe the shape of a capability path rather than instructing a file operation, so they are not affected.
Reproduction
export XDG_DATA_HOME=/tmp/os-demo/data XDG_CONFIG_HOME=/tmp/os-demo/cfg
openspec store setup mystore --path /tmp/os-demo/mystore
mkdir -p /tmp/os-demo/mystore/openspec/specs/store-only-capability
# ...write a main spec there...
mkdir -p /tmp/os-demo/work && cd /tmp/os-demo/work # a *different* repo
openspec new change modify-store-cap --store mystore
openspec instructions specs --change modify-store-cap --store mystore --json
The returned instruction contains both raw paths, while the very same JSON response reports the correct root:
"planningHome": { "root": "/tmp/os-demo/mystore", ... },
"root": { "path": "/tmp/os-demo/mystore", "source": "store", "store_id": "mystore" }
ls openspec/specs/ in the working repo does not contain store-only-capability — it is in the store.
Why it matters
The MODIFIED workflow's first step is "locate the existing requirement," and step 2 is "copy the ENTIRE requirement block." Sending that read to the wrong root produces one of two outcomes:
- The path does not exist. The agent cannot copy the block and may write a MODIFIED delta from memory — which
validate rejects for dropping scenarios, or which loses content at archive time.
- Worse: a local capability happens to share the name. The read succeeds against a different capability, and the agent copies the wrong requirement block into the delta. This fails silently.
The Purpose edit at line 103 has the same split: it would write to a local file that is not the spec being described.
Suggested fix
Use the store-aware root already returned in the instructions JSON, matching the wording the workflow templates use:
edit `<planningHome.root>/openspec/specs/<capability-path>/spec.md` directly
1. Locate the existing requirement in `<planningHome.root>/openspec/specs/<capability-path>/spec.md`
Guidance text only — no CLI, parser, or archive behavior changes.
Notes
Found while hardening #1700 (which fixes #1689). Kept separate deliberately: #1700 is scoped to teaching the spec-inventory verb, and these two lines predate it.
Summary
The
specsartifact instruction tells an agent to read and edit a capability's main spec atopenspec/specs/<capability-path>/spec.md— a path relative to the current directory. When the change lives in a registered store, the main spec lives under the store root, so that path is wrong.The workflow templates already solved this.
sync-specs.ts:44andarchive-change.ts:98both say main specs live under`<planningHome.root>/openspec/specs/`— "use that (store-aware) root for every main-spec path below, not a hardcoded repo path." The schema instruction is the site that was missed.The two affected operations
schemas/spec-driven/schema.yaml:edit `openspec/specs/<capability-path>/spec.md` directlyTBDPurpose)Locate the existing requirement in openspec/specs/<capability-path>/spec.mdTwo other mentions (lines 17 and 75) only describe the shape of a capability path rather than instructing a file operation, so they are not affected.
Reproduction
The returned
instructioncontains both raw paths, while the very same JSON response reports the correct root:ls openspec/specs/in the working repo does not containstore-only-capability— it is in the store.Why it matters
The MODIFIED workflow's first step is "locate the existing requirement," and step 2 is "copy the ENTIRE requirement block." Sending that read to the wrong root produces one of two outcomes:
validaterejects for dropping scenarios, or which loses content at archive time.The Purpose edit at line 103 has the same split: it would write to a local file that is not the spec being described.
Suggested fix
Use the store-aware root already returned in the instructions JSON, matching the wording the workflow templates use:
Guidance text only — no CLI, parser, or archive behavior changes.
Notes
Found while hardening #1700 (which fixes #1689). Kept separate deliberately: #1700 is scoped to teaching the spec-inventory verb, and these two lines predate it.