Repository navigation
A schema's apply block is never validated: a typo silently disables the apply gate or blocks it forever #1867
Description
Description
parseSchema checks every artifact's requires, but never the apply block.
openspec schema validate therefore reports a schema as valid when
apply.requires names an artifact id that does not exist, or when
apply.tracks names a file no artifact generates. Nothing reports the typo
later either:
- Unknown
apply.requiresid: the apply gate turns off. The id is skipped,
so apply reportsreadyand tells the agent "All required artifacts
complete. Proceed with implementation." with only a proposal written. - Unknown
apply.trackspath: apply blocks forever. Apply waits for a file
nothing generates, and its remedy prints a literal<artifact>placeholder.
Meanwhileopenspec listcounts a different file (tasks.md).
The code claims the opposite: src/commands/schema.ts:230-231 says "Dependency
graph validation is already done by parseSchema (it throws on cycles and
invalid references)".
Reproduction
A project schema copied from spec-driven (openspec/schemas/myflow), with
openspec/config.yaml set to schema: myflow.
A: typo in apply.requires. With apply: replaced by
requires: [desgin] and only proposal.md written:
openspec schema validate myflow
✓ Schema 'myflow' is valid
openspec instructions apply --change c --json
state=ready missingArtifacts=None
instruction=All required artifacts complete. Proceed with implementation.
The control, requires: [design], gives state=blocked missingArtifacts=['design'].
B: typo in apply.tracks. With requires: [tasks], tracks: task.md and
every artifact written:
openspec schema validate myflow
✓ Schema 'myflow' is valid
openspec status --change c --json isPlanningComplete=True
openspec instructions apply --change c state=blocked
The task.md file is missing and must be created.
Create it with `openspec instructions <artifact> --change c` ...
openspec list --json 1/2 in-progress
Expected
schema validate rejects an apply.requires id or an apply.tracks path that
no artifact declares, the same way it rejects an invalid artifact requires.
docs/agent-contract.md says missingArtifacts "is what apply blocks on (the
schema's apply.requires)", so apply must never treat an unknown requirement
as satisfied.
Root cause
src/core/artifact-graph/schema.ts:parseSchemaruns
validateRequiresReferences(schema.artifacts)and never looks at
schema.apply.src/commands/workflow/instructions.ts: the missing-artifact check runs
if (artifact && ...), so an unknown id counts as present, and
collectMissingPrerequisitesskips it withif (!artifact) continue.- For
tracks,findArtifactIdForreturnsundefined, and the remedy falls
back to the<artifact>placeholder.
Impact
Only projects with a custom schema are affected, but for them a one-character
typo either turns off the gate that stops an agent implementing before planning
is done, or leaves every change blocked behind a remedy that cannot be followed.
The command meant to catch it says the schema is valid.
Environment
- OpenSpec 1.13.0 (reproduced on the published npm package and on a build of
main@9d4e597) - Node v22, Linux
Activity