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
validate and archive read a change's deltas only from specs/<capability-path>/spec.md (discoverSpecFiles). The spec-driven schema
declares the specs artifact as generates: "specs/**/*.md", so status and instructions apply count any markdown file under specs/ as the specs being
written.
A delta written as specs/user-auth.md, one level too shallow, therefore:
is rejected by openspec validate only as "Change must have at least one
delta",
and is archived by openspec archive with exit 0. Nothing is merged into openspec/specs/, and the output does not mention specs at all.
The authored requirement never reaches the main spec, and the change is filed
as done. The same happens to delta sections in a second file beside a
capability's spec.md (for example specs/user-auth/more.md).
Reproduction
In a project created by openspec init --tools claude:
openspec new change add-login
cd openspec/changes/add-login
# proposal.md, design.md and tasks.md written, every task checked
mkdir -p specs
cat > specs/user-auth.md <<'MD'## ADDED Requirements### Requirement: Password LoginThe system SHALL let a user sign in with a password.#### Scenario: Valid password- **WHEN** a user submits a valid password- **THEN** a session is createdMDcd ../../..
openspec status --change add-login --json # specs: done, isPlanningComplete: true
openspec instructions apply --change add-login --json # state: all_done, no warnings
openspec validate add-login # exit 1: "No deltas found"
openspec archive add-login --yes # exit 0
Expected
No surface green-lights a change whose delta validate and archive cannot
read. At minimum, archive must not archive it as complete. docs/cli.md
says archive "Validates the change (unless --no-validate)", and here
validation fails while archive succeeds.
Actual
status: specs=done isPlanningComplete=True
apply: state=all_done warnings=None
validate rc=1 :: ✗ [ERROR] file: Change must have at least one delta. No deltas found. ...
archive (full output):
| Task status: ✓ Complete
| Change 'add-login' archived as '2026-09-11-add-login'.
exit=0 main specs after: (none) archived delta still on disk: specs/user-auth.md
With the delta at specs/user-auth/spec.md instead, validate passes and archive merges it (Totals: + 1).
Root cause
schemas/spec-driven/schema.yaml:51 declares the specs artifact as generates: "specs/**/*.md"; artifact completion and the apply warning in src/commands/workflow/instructions.ts (collectApplyWarnings) resolve that
glob.
src/utils/spec-discovery.ts (discoverSpecFiles) reads only spec.md
inside a capability folder. validate and archive use it.
src/core/archive.ts runs delta validation only when it finds delta content
it can read, or a specs/spec.md at the root (validate accepts a delta spec.md directly under specs/ that archive silently drops #1385). Otherwise it takes the
zero-delta path its own comment acknowledges: "An UNMARKED zero-delta change
still archives with only non-blocking proposal warnings".
Impact
Delta specs are what OpenSpec asks an AI agent to write, and writing one file
per capability as specs/<capability>.md is a natural slip. Every surface an
agent checks says the specs are done, and archive then files the change with
its requirements silently discarded.
Environment
OpenSpec 1.13.0 (reproduced on the published npm package and on a build of main @ 9d4e597)
Node v22, Linux
Reproduced in a project created entirely by openspec init + openspec new change
Related: #1385 (a spec.md at the specs/ root, fixed). This is the same drop
for a capability-named file, which that fix does not cover.
Description
validateandarchiveread a change's deltas only fromspecs/<capability-path>/spec.md(discoverSpecFiles). The spec-driven schemadeclares the specs artifact as
generates: "specs/**/*.md", sostatusandinstructions applycount any markdown file underspecs/as the specs beingwritten.
A delta written as
specs/user-auth.md, one level too shallow, therefore:openspec status,all_donefromopenspec instructions applywith no warning (thefix(apply): warn when a change is ready to implement with no specs #1783 no-specs warning uses the same glob, so it does not fire),
openspec validateonly as "Change must have at least onedelta",
openspec archivewith exit 0. Nothing is merged intoopenspec/specs/, and the output does not mention specs at all.The authored requirement never reaches the main spec, and the change is filed
as done. The same happens to delta sections in a second file beside a
capability's
spec.md(for examplespecs/user-auth/more.md).Reproduction
In a project created by
openspec init --tools claude:Expected
No surface green-lights a change whose delta
validateandarchivecannotread. At minimum,
archivemust not archive it as complete.docs/cli.mdsays archive "Validates the change (unless
--no-validate)", and herevalidation fails while archive succeeds.
Actual
With the delta at
specs/user-auth/spec.mdinstead,validatepasses andarchivemerges it (Totals: + 1).Root cause
schemas/spec-driven/schema.yaml:51declares the specs artifact asgenerates: "specs/**/*.md"; artifact completion and the apply warning insrc/commands/workflow/instructions.ts(collectApplyWarnings) resolve thatglob.
src/utils/spec-discovery.ts(discoverSpecFiles) reads onlyspec.mdinside a capability folder.
validateandarchiveuse it.src/core/archive.tsruns delta validation only when it finds delta contentit can read, or a
specs/spec.mdat the root (validate accepts a delta spec.md directly under specs/ that archive silently drops #1385). Otherwise it takes thezero-delta path its own comment acknowledges: "An UNMARKED zero-delta change
still archives with only non-blocking proposal warnings".
Impact
Delta specs are what OpenSpec asks an AI agent to write, and writing one file
per capability as
specs/<capability>.mdis a natural slip. Every surface anagent checks says the specs are done, and
archivethen files the change withits requirements silently discarded.
Environment
main@9d4e597)openspec init+openspec new changeRelated: #1385 (a
spec.mdat thespecs/root, fixed). This is the same dropfor a capability-named file, which that fix does not cover.