Workflow templates: only update-change keeps a chosen artifact path inside changeRoot; continue, propose and ff do not
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 75/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- tooling
Research direction
Start with the update-change template, which already has the containment sentence about symlinked parent directories, and use it as the model. Then find the glob-write steps in src/core/templates/workflows/continue-change.ts (the partial-artifact step and the ready branch), plus the propose and ff-change templates, and add the same rule before any compare or write. Done means every template that turns a glob into a write path carries that rule, and regenerating the skills with openspec update shows the phrase in each affected SKILL.md.
Written by the indexing model from the issue text.
Description
What happened
When an artifact's output is a glob (spec-driven's specs/**/*.md), the agent picks the concrete file path itself, from the proposal's capability list. Only the update-change template bounds that choice:
Choose a concrete path inside
changeRootthat matchesartifactPaths.<id>.outputPathand does not already exist. Verify it remains insidechangeRootafter resolving any symlinked parent directories.
The other templates that write glob artifacts don't have that sentence:
- continue-change, the new "finish a partly written artifact" step (added in 1.14.1): "resolve each expected path against
changeRootbefore comparing path identity", then "write only the missing files". The path is resolved, but nothing says it has to stay insidechangeRoot. - continue-change, the "ready" branch: "If it is a glob pattern, choose the concrete file path using the schema instruction and the change's context"
- propose and ff-change: "If
resolvedOutputPathis a glob, followinstructionto choose the concrete file path"
A capability path such as ../../x, or a symlinked directory under specs/, resolves outside the change, and these templates would write there. The spec-driven schema already asks for kebab-case segments, so a well-behaved agent won't produce ... The concern is consistency: a protection that one workflow states is missing from the others that write the same kind of artifact.
I checked main just now: src/core/templates/workflows/continue-change.ts still has neither bullet bounded.
What you expected instead
Every template that turns a glob into a concrete write path should carry the same containment rule as update-change. That means: resolve the path against changeRoot, reject it if it lands outside changeRoot after resolving symlinked parent directories, and only then compare or write.
Minimal steps to reproduce
This is a template-text gap, so it shows up in the generated files without running anything:
- Run
openspec init, thenopenspec update, with 1.14.1 and the workflowspropose,continueandupdateenabled. - Search the generated Claude Code skills for
symlinked parent. It appears only inopenspec-update-change/SKILL.md. The equivalent glob-write steps inopenspec-continue-change/SKILL.md(both the partial-artifact step and the ready branch) andopenspec-propose/SKILL.mddon't have it.
OpenSpec version
1.14.1
Coding agent and model
Claude Code, Claude Opus 5.5. An AI code reviewer (CodeRabbit) flagged this on a PR that regenerated our skills. I confirmed it and drafted this issue with Claude Code.
OS and Node version
macOS 26.7.1, Node 24.15.0
- Dominant language
- TypeScript
- Stars
- 71.6k
- Forks
- 4.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 82
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Fission-AI/OpenSpec
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Fission-AI/OpenSpec#2098 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Fission-AI/OpenSpec#1966 · 1 comment ·
Maintainers usually reply within 2 days
-
feat(schemas): open each proposal with a short review focusPossibly taken @GaoSSR claimed this 26 days ago. Opendesign-review
Difficulty 1/5 1-3 hours Newbie friendliness 90/100
Fission-AI/OpenSpec#1908 ·
Maintainers usually reply within 2 days
-
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Fission-AI/OpenSpec#2088 ·
Maintainers usually reply within 2 days
-
validate: a scenario with no WHEN/GIVEN or THEN step counts as a scenario and passesPossibly taken @artemasmith claimed this 2 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 68/100
Fission-AI/OpenSpec#2078 · 1 comment ·
Maintainers usually reply within 2 days
All issues in Fission-AI/OpenSpec
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
juice-shop/juice-shop#3686 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dsh-market/dsh-market#877 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
ScottKirvan/GOMAC#61 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
stellar/stellar-dev-skill#151 ·
Maintainers usually reply within 1 day