Summary
A change can pass both normal and strict validation while being impossible to archive because a MODIFIED requirement omits (or renames) an existing scenario.
openspec archive correctly rejects the delta to prevent silent scenario loss, but openspec validate does not run the same applicability check. This lets an unarchivable change pass validation before implementation begins.
Reproduced with OpenSpec 1.7.0 and 1.6.0.
Minimal reproduction
Create one canonical spec:
<!-- openspec/specs/widgets/spec.md -->
# widgets Specification
## Purpose
Define widget behavior.
## Requirements
### Requirement: Widget state
The system SHALL report the widget state.
#### Scenario: Existing scenario
- **WHEN** the widget is queried
- **THEN** the system reports its state
Create one change that keeps the requirement header but renames the scenario:
<!-- openspec/changes/rename-scenario/specs/widgets/spec.md -->
## MODIFIED Requirements
### Requirement: Widget state
The system SHALL report the widget state.
#### Scenario: Renamed scenario
- **WHEN** the widget is queried
- **THEN** the system reports its state
Run:
$ npx --yes @fission-ai/openspec@1.7.0 validate --type change rename-scenario
Change 'rename-scenario' is valid
$ echo $?
0
$ npx --yes @fission-ai/openspec@1.7.0 validate --strict --type change rename-scenario
Change 'rename-scenario' is valid
$ echo $?
0
$ npx --yes @fission-ai/openspec@1.7.0 archive rename-scenario --yes --json
{
"archive": null,
"status": [
{
"severity": "error",
"code": "archive_spec_update_failed",
"message": "widgets MODIFIED failed for header \"### Requirement: Widget state\" - current spec contains scenario(s) not present in the modified block: \"Existing scenario\". Refresh the change spec before archiving to avoid dropping scenarios.",
"fix": "Fix the change delta specs and rerun. No files were changed."
}
]
}
$ echo $?
1
The failed archive is atomic: the active change remains in place and no archive directory is created.
Expected behavior
openspec validate --type change rename-scenario—or at minimum --strict—should exit nonzero and report that the MODIFIED block omits an existing scenario.
Ideally validation would reuse the same non-mutating applicability/loss-prevention checks that archive performs, so a change reported as valid is known to be applicable to the current canonical specs.
Why this matters
This is easy to produce while editing a scenario name. The change can then pass definition validation, be implemented and reviewed, and fail only at the final archive step days later.
Related issues
This reproduction is distinct: the requirement header exists, there is no parallel change or drift, and the delta is already unarchivable at authoring time because its MODIFIED block omits one canonical scenario.
Summary
A change can pass both normal and strict validation while being impossible to archive because a
MODIFIEDrequirement omits (or renames) an existing scenario.openspec archivecorrectly rejects the delta to prevent silent scenario loss, butopenspec validatedoes not run the same applicability check. This lets an unarchivable change pass validation before implementation begins.Reproduced with OpenSpec 1.7.0 and 1.6.0.
Minimal reproduction
Create one canonical spec:
Create one change that keeps the requirement header but renames the scenario:
Run:
The failed archive is atomic: the active change remains in place and no archive directory is created.
Expected behavior
openspec validate --type change rename-scenario—or at minimum--strict—should exit nonzero and report that theMODIFIEDblock omits an existing scenario.Ideally validation would reuse the same non-mutating applicability/loss-prevention checks that archive performs, so a change reported as valid is known to be applicable to the current canonical specs.
Why this matters
This is easy to produce while editing a scenario name. The change can then pass definition validation, be implemented and reviewed, and fail only at the final archive step days later.
Related issues
MODIFIED/REMOVED/RENAMED-fromrequirement header that does not exist in the canonical spec.This reproduction is distinct: the requirement header exists, there is no parallel change or drift, and the delta is already unarchivable at authoring time because its
MODIFIEDblock omits one canonical scenario.