Repository navigation
An unrecognized key in a change's .openspec.yaml is silently ignored (e.g. skip_design) #1920
Description
Summary
An unrecognized key in a change's .openspec.yaml is accepted without any warning and has no effect. The plausible one
is skip_design: true, a natural reach next to skip_specs. It reads as suppressing the design artifact; the CLI
still asks for it, and nothing says the key was dropped.
Expected
Either the schema rejects an unknown key, or the CLI warns that it was ignored — the treatment an unknown artifact ID
already gets in openspec/config.yaml:
$ openspec instructions design --change probe # with rules.bogus_artifact in config.yaml
Unknown artifact ID in rules: "bogus_artifact". It matches no artifact in any available schema. Known artifact IDs: design, proposal, specs, tasks
Actual
The key is stripped silently. openspec validate --changes --strict exits 0, and openspec status --change prints
exactly what it prints without the key.
Reproduction
Version 1.13.1 (Homebrew). Starting state: an empty directory.
$ openspec init --tools none # exit 0
$ openspec new change probe # exit 0
$ cat openspec/changes/probe/.openspec.yaml
schema: spec-driven
created: 2026-09-19
A proposal.md is written first, so that the status excerpt below shows the design artifact being demanded rather
than the proposal, and skip_specs: true is added because a change with no deltas fails validation otherwise (see the
last step below). Then the unrecognized keys are appended:
$ cat openspec/changes/probe/.openspec.yaml
schema: spec-driven
created: 2026-09-19
skip_specs: true
skip_design: true
bogus_key: 1
$ openspec validate --changes --strict
✓ change/probe
ℹ [INFO] file: skip_specs is set in .openspec.yaml: change declares no spec-level behavior changes, zero deltas accepted
Totals: 1 passed, 0 failed (1 items)
$ echo $?
0
openspec status --change probe reports (excerpt, with the scratch path elided):
Progress: 1/3 artifacts complete (1 skipped)
[x] proposal
[~] specs (skipped: change declares skip_specs)
[ ] design
[-] tasks (blocked by: design)
Next: openspec instructions design --change "probe" --json
So the design artifact is still demanded — which is precisely what skip_design: true was written to avoid.
Control: the artifact block above is byte-identical with and without skip_design: true. The key has no effect at
all.
Without skip_specs, for completeness — the state a bare new change produces, and why skip_specs was needed:
$ openspec validate --changes
✗ [ERROR] file: Change must have at least one delta. …
$ echo $?
1
Cause, as far as I can tell
src/core/change-metadata/schema.ts defines ChangeMetadataSchema (line 25 on main when this was filed) as a plain
z.object({...}) whose fields are schema, created, goal, affected_areas, initiative, skip_specs and
retire_capabilities — with no .strict(), so unknown keys are stripped. The InitiativeLinkSchema (lines 16–19) is
strict, so the mechanism is already used where it is wanted. (The installed layout carries the same code at
dist/core/change-metadata/schema.js.)
Suggested fix
Warning and continuing on the read path status, validate and archive share would be the gentler fix, and the one
whose cost is lowest: making the object strict would reject the .openspec.yaml files that already carry extra keys —
see below — so it is the harsher option, not the obvious one. Either is better than silence.
The same class elsewhere
This is not the first report of a silent drop in this codebase, so it should not read as a duplicate of them — each is a
different schema or file. All three are closed, and none covers this one:
- Feedback: new change should emit skip_specs when the schema declares no specs artifact #1638 (closed) — primary ask: emit
skip_specs: truewhen a schema declares no specs artifact. Its own secondary
issue is the identical class onSchemaYamlSchema: "not.strict(), so addingskip_specs: truetoschema.yamlis
silently accepted and silently ignored. It reads as configured while having no effect." - A schema's
applyblock is never validated: a typo silently disables the apply gate or blocks it forever #1867 (closed) — a schema'sapplyblock is never validated, so a typo silently disables the apply gate. openspec schema init --defaultsets a config key nothing reads #1708 (closed) —openspec schema init --defaultwrites a config key nothing reads.
No open issue reports this one: ChangeMetadataSchema is not strict, and no key skips a non-spec artifact today
(skip_specs covers only artifacts whose generates path is under specs/).
Why it matters
I hit this in a repository whose change corpus has a dozen .openspec.yaml files carrying skip_design: true — none
generated by the CLI. Each was written by an author who believed a planning artifact was suppressed while
openspec status went on reporting it incomplete and pointing at openspec instructions design. The honest way to skip
design.md today is simply not to write it, which is what those authors thought the key was doing.
Activity
fix(change-metadata): warn on unrecognized .openspec.yaml keys (Fissi…