docs(openspec): make every spec pass validate --all --strict - #106
Conversation
Two specs failed. Fixing them surfaced a third problem that was not failing, which is the worse one. `cli-update-engine` is deleted. It was a tombstone: the capability was decommissioned, every requirement removed, and the file kept "for historical reference". specs/ describes what is true now, and the history is already in the 2026-03-30-remove-scaffold-dependency archive, including that change's own cli-update-engine delta. Nothing outside the archives referenced it. `cli-rules` gets scenarios and SHALL keywords on 15 requirements, and loses the five that specify `taskless rule verify` — a command this stack removed and replaced with the path-addressed `verify` and `test`, now owned by cli-rule-validation. A requirement stating the subcommand is gone replaces them. Two requirements also named pre-layout paths (`.taskless/rule-tests/<id>.yml`, and deleting "rule and test files" rather than the rule directory); both repathed while being touched. The third problem: a second `##` inside a requirements section ends it, so every requirement below stops being read. `cli-rules` hid 10 behind `## API Contract`, `infrastructure` hid 19, and `skills` hid 6. Those last two PASSED --strict throughout, because the single requirement each still exposed was well-formed. 35 requirements were unread while the validator reported success. The groupings are preserved as bold lead-in lines instead, and un-nesting infrastructure immediately exposed a real requirement with no SHALL, now fixed. `skills` also still told agents to fetch recipes via `npx @taskless/cli help <topic>`. 23 specs, 0 failures. Refs #105 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
There was a problem hiding this comment.
Pull request overview
This PR cleans up OpenSpec capability specs so pnpm openspec validate --all --strict passes across the entire openspec/specs/ tree, removing hidden/invalid requirements and updating spec text to match the current CLI surface.
Changes:
- Remove the decommissioned
cli-update-enginecapability spec that no longer contains requirements. - Fix
cli-rulesstrict-validation failures by adding scenarios/SHALL language, removing obsoletetaskless rule verifyrequirements, and repathing rule/test layout references. - Prevent requirements from being accidentally hidden by nested
##headings ininfrastructureandskills, and updateskillsto referencenpx @taskless/cli agent <topic>.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| openspec/specs/skills/spec.md | Reworks section structure to avoid heading-related parser issues; updates recipe-fetch command to agent. |
| openspec/specs/infrastructure/spec.md | Introduces an explicit ## Requirements section and converts former nested headings into bold lead-ins to keep requirements parseable. |
| openspec/specs/cli-update-engine/spec.md | Deletes the spec content for a removed capability that had zero remaining requirements. |
| openspec/specs/cli-rules/spec.md | Adds scenarios/SHALL wording, removes obsolete rule verify requirements, updates paths, and restructures a section to avoid hidden requirements. |
Suppressed comments (2)
openspec/specs/skills/spec.md:23
- The scenario title still refers to “CLI help”, but the scenario text and the requirement now reference the
agentcommand. Renaming the scenario keeps the spec consistent and easier to search.
#### Scenario: Skill body delegates to CLI help
openspec/specs/cli-rules/spec.md:246
- This PR adds a requirement that
taskless rule verifySHALL NOT exist, but a few lines below the schema requirement’s scenario still references “therule verifycommand”. That makes the spec internally inconsistent; the scenario should describe schema usage without naming a removed command.
### Requirement: The rule subcommand group no longer validates rules
`taskless rule verify` SHALL NOT exist. Rule validation is addressed by path through the top-level `verify` and `test` commands, specified by the `cli-rule-validation` capability.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@claude /review |
|
Claude finished @thecodedrift's task in 3m 58s —— View job Review completeVerified structurally sound: I checked heading levels in all three edited spec files ( Findings posted inline — the theme across all of them is that this PR repathed/updated some requirements but left sibling text in the same file inconsistent:
None of these break No correctness/security/performance issues found in the mechanical parts of the diff (the heading restructuring, the |
Two self-contradictions the strict-validation pass left behind. The create requirements still wrote rules to the flat `.taskless/rules/<id>.yml` and tests to `.taskless/rule-tests/<id>.yml`, while delete had already been repathed to the rule directory. `files.ts` agrees with delete, so create was the stale one. The new "`taskless rule verify` SHALL NOT exist" requirement was contradicted three lines up, where the surface list still advertised it, and again where two scenarios named it as a live command. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
`pull_request: branches: [main]` matches the PR's base ref, and GitHub also resolves a stacked PR's eventual target and matches on that — so the filter did run on PRs based on another branch. Until it didn't. On the #71→#106 stack every PR up to #102 got a Validate run and #103/#106 got none, across 16 pull_request events that other workflows handled fine. #103 is a ~93-file change that has never been linted, typechecked, or tested in CI. Lint, typecheck, and tests have no interest in where a PR eventually merges, so the filter is dropped rather than repaired. `ready_for_review` is named explicitly because it is not in the default event set; without it a draft marked ready gets no fresh run until someone pushes again, which is the state #103 sat in. Committed directly to main: the fix restores CI coverage, and routing it through a PR would have it validated by the mechanism it repairs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
Three docs stated that GitHub's stacked-PR support makes `pull_request: branches: [main]` match every PR in a stack, and presented it as dependable. It is not. On the #71→#106 stack the filter matched through #102 and then silently stopped: #103 and #106 produced no `Validate` and no `Require a changeset` run across 16 pull_request events that filter-less workflows handled fine. That belief is why a ~93-file change reached "ready for review" having never been linted, typechecked, or tested in CI. The corrected rule is split by intent. A workflow that must run everywhere carries no `branches:` filter and names `ready_for_review` in `types:`, since it is absent from the default event set. A workflow that must act only on the PR merging to `main` establishes that inside the job, from the base ref or stack position. Also fixes a factual error: iterate-pr claimed `pr-check-openspec.yml` is scoped by `branches: [main]`. It has no `branches:` filter, which is the actual reason it runs on every PR. Adds the corollary worth internalizing: an absent check reads like a passing one, so a check you expected and cannot find is a reason to suspect the trigger, not to assume the PR is clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
…es' into openspec/spec-strict-cleanup
449a9c5
into
openspec/self-contained-vale-rules
Stack (root → tip):
Cleanup on top of the stack so
pnpm openspec validate --all --strictis green and the gate in #105 can be turned on without landing red.Two failures, and a third problem that wasn't failing
cli-update-engine— deleted. A tombstone: capability decommissioned, every requirement removed, file kept "for historical reference".--strictneeds at least one requirement.specs/describes what's true now, and the history is already in the2026-03-30-remove-scaffold-dependencyarchive, including that change's owncli-update-enginedelta. Nothing outside the archives referenced it.cli-rules— 18 errors. Scenarios and SHALL keywords added to 15 requirements. The five specifyingtaskless rule verifyare removed: this stack deleted that command in favour of the path-addressedverifyandtest, now owned bycli-rule-validation. A requirement stating the subcommand is gone replaces them. Two requirements named pre-layout paths (.taskless/rule-tests/<id>.yml, and deleting "rule and test files" rather than the rule directory); both repathed while being touched.The one worth reading. A second
##inside a requirements section ends it, so every requirement below stops being parsed:--strictbeforecli-rulesinfrastructureskillsinfrastructureandskillspassed throughout, because the single requirement each still exposed was well-formed. 35 requirements were unread while the validator reported success. This is the same shape as thecli-helpdefect repaired earlier in the stack, where a lost code fence turned a documentation template into real headings.The topical groupings are kept as bold lead-in lines instead of headings. Un-nesting
infrastructureimmediately exposed a real requirement with no SHALL, now fixed.skillsalso still told agents to fetch recipes vianpx @taskless/cli help <topic>.Result
23 specs, 0 failures, with every requirement actually visible to the parser. 594 tests, lint and typecheck unchanged: this PR touches only
openspec/specs/.Note that
--strictalone would not have caught the hidden-requirement class. Detecting it needs a separate check that every### Requirement:sits under## Requirements— noted on #105 for whoever wires the gate.Refs #105
🤖 Generated with Claude Code
https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3