Release 1.1.2 — the default path works end to end

Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
This commit is contained in:
Donchitos
2026-09-29 21:32:19 +10:00
co-authored by Claude Opus 5.5
parent 7ed2c3e9c4
commit b21fa0f7f2
383 changed files with 22888 additions and 10618 deletions
@@ -3,23 +3,33 @@
## Skill Summary
`/story-done` closes the loop between design and implementation. Run at the
end of implementing a story, it reads the story file and verifies each
acceptance criterion against the implementation. It checks for GDD and ADR
deviations, prompts a code review, updates the story status to `Complete`,
logs any tech debt, and surfaces the next ready story from the sprint. It
produces a COMPLETE / COMPLETE WITH NOTES / BLOCKED verdict and writes to
the story file and optionally to `docs/tech-debt-register.md`.
end of implementing a story, it reads the story file, re-reads the current
requirement text from `docs/architecture/tr-registry.yaml` (never the story's
quoted copy) and the governing ADR's `## Decision` / `## Consequences`, verifies
each acceptance criterion (automatically, by batched `AskUserQuestion`, or as
`DEFERRED — requires playtest session`), builds a criterion-to-test
traceability table, checks test evidence, and checks GDD/ADR/manifest/scope
deviations (categorised BLOCKING / ADVISORY / OUT OF SCOPE). Review mode then
decides the QA coverage gate (QL-TEST-COVERAGE) and the code review step
(LP-CODE-REVIEW in `full`, a `/code-review` question in `lean`, a noted skip in
`solo`). It produces a COMPLETE / COMPLETE WITH NOTES / NOT ASSESSED / BLOCKED
verdict and, only after an `AskUserQuestion` choice, updates the story file,
optionally appends to `docs/tech-debt-register.md`, and surfaces the next story —
with no sprint plan, from `bash .claude/scripts/story-status.sh`, the list `/help`
and `/sprint-status` read, run after the story file is written. It says what a
screenshot shows only after opening it, and asks about behaviour criteria rather
than reading them off the code.
---
## Static Assertions (Structural)
Verified automatically by `/skill-test static` — no fixture needed.
Checked against the SKILL.md by `/skill-test spec` — no fixture needed.
- [ ] Has required frontmatter fields: `name`, `description`, `argument-hint`, `user-invocable`, `allowed-tools`
- [ ] Has ≥5 phase headings (complex skill warranting `context: fork` if applicable)
- [ ] Contains verdict keywords: COMPLETE, BLOCKED
- [ ] Contains "May I write" collaborative protocol language (writes to story file and tech-debt register)
- [ ] Has ≥5 phase headings (complex multi-phase skill)
- [ ] Contains verdict keywords: COMPLETE, COMPLETE WITH NOTES, NOT ASSESSED, BLOCKED
- [ ] `allowed-tools` includes Write/Edit, so ask-before-write language is present ("Use `AskUserQuestion` before writing anything" — covering the story file and the tech-debt register)
- [ ] Has a next-step handoff (surfaces next story from sprint)
---
@@ -29,171 +39,260 @@ Verified automatically by `/skill-test static` — no fixture needed.
### Case 1: Happy Path — All acceptance criteria met, no deviations
**Fixture:**
- `project.yaml` sets `modes.rigor: standard` (→ `workflow: standard`,
`qa.level: standard`, `review_mode: lean`) and `engine.name: Godot`, so
`tests/unit/` is the test root
- Story file at `production/epics/core/story-light-pickup.md` with:
- 3 acceptance criteria, all implemented as described
- `TR-ID: TR-light-001` referencing a GDD requirement
- `ADR: docs/architecture/adr-003-inventory.md` (Accepted)
- `Type: Logic` and 3 acceptance criteria, all implemented as described:
AC-1 "Picking up a light adds it to the inventory", AC-2 "A pickup at the
carry limit is refused", AC-3 "The picked-up light leaves the world"
- `TR-light-001`; the story quotes an older wording of the requirement, while
`tr-registry.yaml` holds the current text, which the implementation matches
- `ADR: ADR-0003` (Accepted), whose guidance was followed
- A `## Test Evidence` section naming `tests/unit/light/pickup_test.gd`, which
exists with one test per criterion — `test_pickup_adds_to_inventory`,
`test_pickup_refused_at_limit`, `test_pickup_removes_world_light` — so every
criterion maps to a test
- `Status: In Progress`
- Implementation files listed in story exist in `src/`
- GDD requirement text at TR-light-001 matches how the feature was implemented
- ADR guidance was followed (no deviations)
- The `/dev-story` checkpoint in `production/session-state/active.md` names this
story as **Current task** and carries `Run result: OBSERVED — the light leaves
the floor and the inventory count rises —
production/qa/evidence/story-light-pickup/01-pickup.png`; that image exists
- Implementation files listed in the story exist in the code root
- A sprint plan in `production/sprints/` has other READY / NOT STARTED Must Have stories
**Input:** `/story-done production/epics/core/story-light-pickup.md`
**Expected behavior:**
1. Skill reads the story file and extracts all key fields
2. Skill reads the GDD requirement fresh from `tr-registry.yaml` (not from story's quoted text)
3. Skill reads the referenced ADR to understand implementation constraints
4. Skill evaluates each acceptance criterion (auto where possible, manual prompt where not)
5. Skill checks for GDD requirement deviations
6. Skill checks for ADR guideline deviations
7. Skill prompts user: "Please provide the code review outcome for this story"
8. Skill presents COMPLETE verdict
9. Skill asks "May I update story Status to Complete and add Completion Notes?"
10. If yes: skill updates the story file
11. Skill surfaces the next `Ready for Dev` story from the sprint
1. Skill reads the story and extracts its fields
2. Skill greps `tr-registry.yaml` for `TR-light-001` and uses that current text
3. Skill maps the ADR's headings and reads only `## Decision` and `## Consequences`
4. Skill verifies each criterion and builds the traceability table: AC-1..AC-3
each map to their test function, all COVERED
5. Test evidence found — reported as "Test file present at `<path>`" (existence,
not a pass claim); the checkpoint's `Run result: OBSERVED` is noted with its
retained path
6. No deviations
7. Phase 4b notes "QL-TEST-COVERAGE skipped — Lean mode."
8. Phase 5 (lean) asks "Code review is skipped in lean mode. Did you run `/code-review` on the implemented files?"
9. Completion report with verdict COMPLETE
10. `AskUserQuestion` "Verification complete. How do you want to proceed?"; on "Close the story", the file is updated
11. Skill surfaces the next ready stories from the sprint
**Assertions:**
- [ ] Skill reads `docs/architecture/tr-registry.yaml` for TR-ID requirement text (not just story)
- [ ] Skill reads the referenced ADR file (not just the story reference)
- [ ] Each acceptance criterion is listed with VERIFIED / DEFERRED / FAILED status
- [ ] Skill prompts the user for code review outcome (does not skip this step)
- [ ] Verdict is COMPLETE when all criteria are verified and no deviations exist
- [ ] Skill asks "May I write" before updating the story file
- [ ] Skill does NOT auto-update story status without user confirmation
- [ ] After completion, skill surfaces the next ready story from `production/sprints/`
- [ ] Requirement text comes from `tr-registry.yaml`, not the story's stale quote — the wording difference produces no deviation
- [ ] Skill reads only the ADR's `## Decision` and `## Consequences` spans, not the whole file
- [ ] Each criterion is listed with its status (`auto-verified` / `confirmed` / `FAILS` / `DEFERRED`) and appears in a Criterion | Test | Status traceability table
- [ ] Test evidence is reported as present, without claiming the tests pass
- [ ] In `lean` mode the skill asks whether `/code-review` was run, and records the answer in the Completion Notes `Code Review:` line
- [ ] The traceability table maps each of AC-1..AC-3 to its test function, with no UNTESTED row
- [ ] The `Run result:` line is read from the checkpoint (whose **Current task** names this story) and noted with its retained path
- [ ] Verdict is COMPLETE — every criterion maps to a test, the run was observed and retained, and no deviations exist
- [ ] No file is edited before the Phase 7 `AskUserQuestion`; on "Close the story" the story gets `Status: Complete`, a `Last Updated:` date and a `## Completion Notes` section
- [ ] After completion, skill surfaces the next READY / NOT STARTED Must Have or Should Have story from `production/sprints/` and suggests `/story-readiness [path]`
---
### Case 2: Blocked Path — Acceptance criterion cannot be verified
### Case 2: Criteria needing manual or playtest verification
**Fixture:**
- Story file has an acceptance criterion: "Player sees correct animation on pickup"
- No automated test for this criterion exists
- Manual verification has not been performed
- All other criteria are met
- As Case 1, plus two more criteria:
- (a) "Player sees correct animation on pickup" — no automated test; a frame of
the animation is retained at `production/qa/evidence/story-light-pickup/02-pickup-anim.png`
- (b) "Pickup state persists across a full level run" — needs a full game build
- 1 of the 5 criteria ends up with no covering test
**Input:** `/story-done production/epics/core/story-light-pickup.md`
**Expected behavior:**
1. Skill processes all acceptance criteria
2. Reaches the animation criterion — cannot auto-verify
3. Skill asks the user: "Acceptance criterion 'Player sees correct animation on
pickup' cannot be auto-verified. Has this been manually tested?"
4. If user says No: criterion is marked DEFERRED, verdict becomes COMPLETE WITH NOTES
5. Skill records the deferred criterion in completion notes
6. Asks "May I write updated story with deferred criterion noted?"
1. Criterion (a) is a subjective/gameplay criterion → skill asks via a batched
`AskUserQuestion` ("Does [criterion]?" — `Yes — passes` / `No — fails` / `Not tested yet`)
2. The user answers `Yes — passes`. The retained frame is the observation the
evidence rule requires; the answer covers the motion a still cannot show, and
counts as the manual test
3. Criterion (b) is marked `DEFERRED — requires playtest session` and does not block
4. The traceability table shows (b) UNTESTED; 1 of 5 (≤50%) → ADVISORY
5. The Completion Notes list the deferred item and "Untested criteria: [AC-N list]. Recommend adding tests in a follow-up story."
**Assertions:**
- [ ] Skill asks the user about unverifiable criteria rather than assuming PASS
- [ ] Deferred criteria result in COMPLETE WITH NOTES (not COMPLETE or BLOCKED)
- [ ] The deferred criterion is explicitly named in the completion notes
- [ ] Skill still asks "May I write" before updating the story file
- [ ] Skill asks the user about the unverifiable criterion rather than assuming it passes, batching up to 4 such questions per call — a behaviour criterion is never marked verified from reading the code
- [ ] Before the report says what `02-pickup-anim.png` shows, the image is opened with `Read`; the checkpoint's `Run result:` text is quoted as `/dev-story`'s description, never restated as the skill's own observation
- [ ] The playtest-only criterion is marked `DEFERRED — requires playtest session`
- [ ] Verdict is COMPLETE WITH NOTES, and the report lists the DEFERRED criterion — neither BLOCKED nor NOT ASSESSED, since a DEFERRED criterion does not block and does not fire the NOT ASSESSED trigger
- [ ] The deferred criterion is named in the Completion Notes `Criteria:` line, with the untested-criteria recommendation
- [ ] Variant — if the user answers `No — fails` for (a), the criterion is `FAILS`, the verdict is BLOCKED, and the skill does not proceed to Phase 7 on its own
- [ ] Variant — no image for this story is retained under `production/qa/evidence/` and the checkpoint carries no `Run result:` line: the user's `Yes — passes` for (a) is an assertion, not evidence, so the missing observation is flagged at the Logic gate level (BLOCKING by default) and the verdict is BLOCKED — never COMPLETE WITH NOTES on the confirmation alone
- [ ] Skill still asks via `AskUserQuestion` before updating the story file
---
### Case 3: Blocked Path — GDD deviation detected
**Fixture:**
- Story TR-ID points to requirement: "Player can carry max 3 light sources"
- Implementation in `src/` uses a variable `MAX_CARRIED_LIGHTS = 5`
- This is a deliberate deviation from the GDD
- `project.yaml` sets `modes.workflow: full`
- The current `tr-registry.yaml` text for the story's TR-ID: "Player can carry max 3 light sources"
- Implementation in the code root has `MAX_CARRIED_LIGHTS = 5` in gameplay code
**Input:** `/story-done production/epics/core/story-light-pickup.md`
**Expected behavior:**
1. Skill reads the GDD requirement text (max 3)
2. Skill detects discrepancy between requirement and implementation value (5)
3. Skill flags this as a GDD deviation and asks the user to classify it:
- INTENTIONAL: document the deviation and reason
- ERROR: implementation must be fixed before story can be marked Complete
- OUT OF SCOPE: requirement changed and GDD needs updating
4. If INTENTIONAL: skill records deviation in completion notes, verdict is COMPLETE WITH NOTES
5. If ERROR: verdict is BLOCKED until implementation is corrected
1. The GDD rules check (against the current registry text) finds the implementation contradicts "max 3"
2. The hardcoded-values check also flags the gameplay literal that belongs in a data file
3. The contradiction is categorised BLOCKING and cited with its GDD/TR reference
4. Verdict BLOCKED; skill lists what must be fixed and offers to help, and does not advance to Phase 7 on its own
5. If the user explicitly asks to close anyway, the Phase 7 menu appears (always asked, even in autonomous mode — `scope_changes`)
**Assertions:**
- [ ] Skill detects the mismatch between GDD requirement and implementation value
- [ ] Skill asks the user to classify the deviation (not auto-assumes either way)
- [ ] INTENTIONAL deviation → COMPLETE WITH NOTES (not BLOCKED)
- [ ] ERROR deviation → BLOCKED verdict until fixed
- [ ] Detected deviations are recorded in completion notes or tech debt register
- [ ] Skill detects the mismatch between the current requirement text and the implemented value
- [ ] The deviation is reported neutrally as BLOCKING with the GDD/TR reference — the skill does not edit code or the GDD to reconcile it
- [ ] Verdict is BLOCKED, and Phase 7 is not entered unless the user explicitly asks to close anyway
- [ ] Closing a BLOCKED story goes through the Phase 7 `AskUserQuestion` regardless of automation mode
- [ ] If closed via "Accept deviations as-is and close anyway", the deviation is recorded in the Completion Notes `Deviations:` line
---
### Case 4: Edge Case — No argument, auto-detect current story
**Fixture:**
- `production/session-state/active.md` contains a reference to
`production/epics/core/story-oxygen-drain.md` as the active story
- `production/session-state/active.md` names `production/epics/core/story-oxygen-drain.md` as the active story
- That story file exists with `Status: In Progress`
**Input:** `/story-done` (no argument)
**Expected behavior:**
1. Skill reads `production/session-state/active.md`
2. Skill finds the active story reference
3. Skill reads that story file and proceeds normally
4. Output confirms which story was auto-detected
1. Skill reads `production/session-state/active.md` and takes the active story
2. Skill reads that story file and proceeds normally
3. The completion report's `**Story**:` line names the auto-detected path
4. If `active.md` names no story, skill reads the newest sprint plan for IN PROGRESS stories;
with several, it asks "Which story are we completing?"; with none, it asks for the path
**Assertions:**
- [ ] Skill reads `production/session-state/active.md` when no argument is given
- [ ] Skill identifies and confirms the auto-detected story before proceeding
- [ ] If no story is found in session state, skill asks the user to provide a path
- [ ] Skill reads `production/session-state/active.md` first when no argument is given
- [ ] The report's `**Story**:` line names the auto-detected story file
- [ ] With several in-progress stories in the sprint, skill asks which one via `AskUserQuestion` instead of picking one
- [ ] If no story is found anywhere, skill asks the user to provide a path
---
---
### Case 5: Director Gate — LP-CODE-REVIEW behavior across review modes
### Case 5: Director Gate — LP-CODE-REVIEW across review modes
**Fixture:**
- Story file at `production/epics/core/story-light-pickup.md`
- All acceptance criteria verified, no GDD deviations
- `production/session-state/review-mode.txt` exists
- `project.yaml` sets `modes.workflow: full` and `qa.level: standard` (so the
QA coverage gate is not skipped for `qa.level: minimal`)
- Story file at `production/epics/core/story-light-pickup.md`, `Type: Logic`
- All acceptance criteria verified, no GDD deviations, implementation files exist,
and Case 1's run evidence (the `Run result: OBSERVED` checkpoint and its retained image)
- Review mode comes from `modes.review_mode` (legacy mirror `production/review-mode.txt`) or `--review`
**Case 5a — full mode:**
- `review-mode.txt` contains `full`
**Input:** `/story-done production/epics/core/story-light-pickup.md` (full mode)
**Case 5a — full mode:** `/story-done production/epics/core/story-light-pickup.md --review full`
**Expected behavior:**
1. Skill reads review mode — determines `full`
2. After implementation verification, skill invokes LP-CODE-REVIEW gate
3. Lead programmer reviews the implementation
4. If LP verdict is NEEDS CHANGES → story cannot be marked Complete
5. If LP verdict is APPROVED → skill proceeds to mark story Complete
1. After Phases 3–4, skill spawns `qa-lead` with gate QL-TEST-COVERAGE (unless `qa.level: minimal` or a Config/Data story)
2. Skill spawns `lead-programmer` with gate LP-CODE-REVIEW, passing the
implementation file paths, story path, relevant GDD section and governing ADR
3. The verdict (APPROVE / CONCERNS / REJECT) is presented to the user
4. CONCERNS → `AskUserQuestion`: `Revise flagged issues` / `Accept and proceed` / `Discuss further`
5. REJECT → no Phase 6 verdict until the issues are resolved
6. NOT ASSESSED (a gate input was missing) → the skill names the missing input and
never reads it as APPROVE: the input is supplied and the gate re-run, or the
Phase 6 verdict is at best NOT ASSESSED
**Assertions (5a):**
- [ ] Skill reads review mode before deciding whether to invoke LP-CODE-REVIEW
- [ ] LP-CODE-REVIEW gate is invoked in full mode after implementation check
- [ ] An LP NEEDS CHANGES verdict prevents story from being marked Complete
- [ ] Gate result is noted in output: "Gate: LP-CODE-REVIEW — [result]"
- [ ] Skill still asks "May I write" before updating story status even if LP approved
- [ ] Skill uses the resolved review mode before deciding whether to spawn LP-CODE-REVIEW
- [ ] LP-CODE-REVIEW is spawned in full mode after the implementation checks, with the four context items
- [ ] A REJECT verdict prevents the story from reaching a COMPLETE verdict until resolved
- [ ] A CONCERNS verdict produces the three-option `AskUserQuestion`
- [ ] A NOT ASSESSED answer from either gate is never treated as APPROVE / ADEQUATE: unless the missing input is supplied and the gate re-run, the verdict is NOT ASSESSED, not COMPLETE
- [ ] Skill still asks via the Phase 7 `AskUserQuestion` before updating story status, even after APPROVE
**Case 5b — lean or solo mode:**
- `review-mode.txt` contains `lean` or `solo`
**Expected behavior:**
1. Skill reads review mode — determines `lean` or `solo`
2. LP-CODE-REVIEW gate is SKIPPED
3. Output notes the skip: "[LP-CODE-REVIEW] skipped — Lean/Solo mode"
4. Story completion proceeds based on acceptance criteria check only
**Case 5b — lean mode:** `--review lean`
**Assertions (5b):**
- [ ] LP-CODE-REVIEW gate does NOT spawn in lean or solo mode
- [ ] Skip is explicitly noted in output
- [ ] Skill still requires "May I write" approval before marking story Complete
- [ ] LP-CODE-REVIEW does NOT spawn
- [ ] Skill asks "Did you run `/code-review` on the implemented files?" with the three listed options; all three proceed
- [ ] "QL-TEST-COVERAGE skipped — Lean mode." is noted
**Case 5c — solo mode:** `--review solo`
**Assertions (5c):**
- [ ] Neither LP-CODE-REVIEW nor QL-TEST-COVERAGE spawns, and no code-review question is asked
- [ ] Output notes "LP-CODE-REVIEW skipped — Solo mode." and "QL-TEST-COVERAGE skipped — Solo mode."
- [ ] Skill still requires the Phase 7 `AskUserQuestion` before marking the story Complete
---
### Case 6: UI story at `minimal`, no sprint plan — the screenshot closes it
**Fixture:**
- `project.yaml` sets `modes.rigor: minimal` (→ `workflow: minimal`,
`qa.level: minimal`, `review_mode: solo`); there is no sprint plan in
`production/sprints/` — the brief's build order is the plan
- `production/epics/mvp/` holds `story-001-*.md` (`Status: Complete`), this story
`story-002-shop-panel.md` (`Status: In Progress`) and `story-003-*.md` (`Status: Ready`)
- `story-002-shop-panel.md` has `Type: UI` and two criteria: "The shop panel shows
all 6 item slots inside the frame at 1280x720" and "Each slot shows its price"
- `production/qa/evidence/story-002-shop-panel/01-shop-open.png` exists and shows
both; the checkpoint carries `Run result: OBSERVED` with that path; there is no
evidence doc and no sign-off
**Input:** `/story-done production/epics/mvp/story-002-shop-panel.md`
**Expected behavior:**
1. At `qa.level: minimal` the Logic, Integration and Config/Data evidence checks,
the >50%-untested escalation and Phase 4b are skipped ("QL-TEST-COVERAGE
skipped — qa.level minimal.") — but the UI screenshot check runs
2. The retained screenshot satisfies the UI gate; no evidence doc or sign-off is asked for
3. Phase 4 runs the manifest, hardcoded-value and scope checks only (no GDD/ADR
traceability at `minimal`); Phase 5 notes "LP-CODE-REVIEW skipped — Solo mode."
4. Verdict COMPLETE; after the Phase 7 approval the story is marked Complete
5. Phase 8 takes the no-sprint branch: it runs `bash .claude/scripts/story-status.sh`
after the story file is written; `story-003` is on its first `TODO` line →
"Run `/dev-story [path]`"
**Assertions:**
- [ ] The UI screenshot check runs at `qa.level: minimal` and is satisfied by the retained image alone — no evidence doc or sign-off is required for a UI story
- [ ] Verdict is COMPLETE, not BLOCKED for a missing sign-off
- [ ] Phase 8 names `story-003` and recommends `/dev-story` directly — no `/story-readiness` line at `minimal`, and no Sprint Close-Out Sequence
- [ ] The next story comes from `bash .claude/scripts/story-status.sh`, run after this story's `Status: Complete` is written — not from a grep of one epic folder
- [ ] Variant — `production/epics/combat/story-001-arena.md` reads `**Status:** In Review`: it is Next Up (the script lists `IN_REVIEW` first, across every epic folder), and the Next Up line recommends `/story-done [path]` to close it, not `/dev-story`
- [ ] Variant — no image under `production/qa/evidence/` and no `Run result:` line: the UI gate is still BLOCKING at `qa.level: minimal`, so the verdict is BLOCKED
- [ ] Variant — `story-003` is `Blocked`, naming its blocker, and no other story is unfinished: Phase 8 prints no Next Up, names `story-003` with its blocker, suggests clearing it, and never says the build order is done
---
### Case 7: NOT ASSESSED — a criterion nobody could evaluate
**Fixture:**
- As Case 1, plus a fourth criterion, AC-4: "The pickup code is robust" — it
names no observable outcome, so no test, run or playtest could settle it
**Input:** `/story-done production/epics/core/story-light-pickup.md`
**Expected behavior:**
1. AC-1..AC-3 verify as in Case 1
2. AC-4 cannot be evaluated at all — not DEFERRED (no session could settle it as
written) and not failed
3. Verdict NOT ASSESSED, naming AC-4 and what would make it checkable (rewrite it
as an observable condition)
4. The skill does not proceed to Phase 7 on its own
**Assertions:**
- [ ] Verdict is NOT ASSESSED — not COMPLETE or COMPLETE WITH NOTES, and not BLOCKED (nothing is known to fail)
- [ ] Output names AC-4, why it cannot be evaluated, and what would make it checkable
- [ ] Phase 7 is entered only if the user explicitly asks to close anyway; it then always prompts (`scope_changes`), and the Completion Notes record AC-4 as never evaluated
- [ ] Variant — AC-4 is a checkable criterion that the user answers `Not tested yet`: it is UNTESTED in the traceability table and the verdict is NOT ASSESSED, naming what would settle it
- [ ] Variant — another criterion also FAILS: the verdict is BLOCKED (BLOCKED is evaluated before NOT ASSESSED)
---
## Protocol Compliance
- [ ] Uses "May I write" before updating the story file
- [ ] Uses "May I write" before adding entries to `docs/tech-debt-register.md`
- [ ] Presents complete findings (criteria check, deviation check) before asking approval
- [ ] Ends by surfacing the next ready story from the sprint plan
- [ ] Does not mark a story Complete if any criteria are in ERROR state
- [ ] Does not skip the code review prompt
- [ ] Asks via `AskUserQuestion` before updating the story file
- [ ] Appends to `docs/tech-debt-register.md` only when the user picks "Close and log advisory deviations as tech debt", as rows of `/tech-debt`'s register table with an `Added` date — never as free bullets
- [ ] Presents the complete report (criteria, traceability, test evidence, deviations, scope) before asking
- [ ] Ends by surfacing the next ready story (sprint plan) or the next story in the epic folder (no sprint plan)
- [ ] Never closes a BLOCKED or NOT ASSESSED story on its own — only on the user's explicit request, through Phase 7
- [ ] Never skips code review silently: `full` spawns LP-CODE-REVIEW, `lean` asks, `solo` notes the skip
---
@@ -201,9 +300,11 @@ Verified automatically by `/skill-test static` — no fixture needed.
- The full 8-phase flow of the skill is exercised across Cases 1-3; not all
edge cases within each phase are covered.
- Tech debt logging (deferred items written to `docs/tech-debt-register.md`)
is mentioned in Case 2 but not the primary assertion focus; dedicated
coverage deferred.
- The `sprint-status.yaml` update (Phase 7 in the skill) is implied by Case 1
but not the primary assertion; assumed to follow the same "May I write" pattern.
- Tech debt logging (`docs/tech-debt-register.md`) is covered only through the
Phase 7 option and the row-format line in Protocol Compliance; no case writes
a row.
- The `production/sprint-status.yaml` update and the session-state checkpoint
(both silent, after the Phase 7 approval) are not primary assertions.
- Case 6 covers the no-sprint-plan branch at `minimal`; the Sprint Close-Out
Sequence is not tested here.
- Stories with multiple TR-IDs or multiple ADRs are not explicitly tested.
@@ -3,22 +3,34 @@
## Skill Summary
`/story-readiness` validates that a story file is ready for a developer to
pick up and implement. It checks four dimensions: Design (embedded GDD
requirements), Architecture (ADR references and status), Scope (clear
boundaries and DoD), and Definition of Done (testable criteria). It produces
a READY / NEEDS WORK / BLOCKED verdict. It is a read-only skill and runs
before any developer picks up a story.
pick up and implement. It loads its reference context once (systems index,
the control manifest's `Manifest Version:` header, the TR registry, and every
ADR's status via a single Grep), then evaluates each story against six
checklist groups: Design Completeness, Architecture Completeness, Scope
Clarity, Open Questions, Asset References, and Definition of Done. The workflow
tier resolved for the story's system decides which groups block (`full`: all;
`standard`: architecture items advisory except a critical ADR; `minimal`:
architecture N/A) — except one rule at every tier: an ADR the story references that
is missing, `Proposed`, `Deprecated` or `Superseded` BLOCKS, because `/dev-story`
stops on it. At `minimal`, `design/game-brief.md` stands in for the GDD. It produces a READY / NEEDS WORK / BLOCKED / NOT ASSESSED
verdict. It is read-only — it never writes or edits a file. In `full` review
mode it then runs the QL-STORY-READY gate (`qa-lead`).
A fixture that sets neither `qa.level` nor `modes.rigor` resolves `qa.level:
minimal` (the `rigor: minimal` default). There the evidence item auto-passes for
Logic, Integration and Config/Data stories — never for UI or Visual/Feel, whose
retained screenshot is required at every `qa.level` (Case 6).
---
## Static Assertions (Structural)
Verified automatically by `/skill-test static` — no fixture needed.
Checked against the SKILL.md by `/skill-test spec` — no fixture needed.
- [ ] Has required frontmatter fields: `name`, `description`, `argument-hint`, `user-invocable`, `allowed-tools`
- [ ] Has ≥2 phase headings or numbered check sections
- [ ] Contains verdict keywords: READY, NEEDS WORK, BLOCKED
- [ ] Does NOT require "May I write" language (read-only skill)
- [ ] Contains verdict keywords: READY, NEEDS WORK, BLOCKED, NOT ASSESSED
- [ ] Does NOT require "May I write" language — `allowed-tools` has no Write or Edit
- [ ] Has a next-step handoff (what to do after verdict)
---
@@ -28,168 +40,234 @@ Verified automatically by `/skill-test static` — no fixture needed.
### Case 1: Happy Path — Fully ready story
**Fixture:**
- Story file exists at `production/epics/core/story-light-pickup.md`
- Story contains:
- `TR-ID: TR-light-001` (GDD requirement reference)
- `ADR: docs/architecture/adr-003-inventory.md`
- Referenced ADR exists and has status `Accepted`
- Referenced TR-ID exists in `docs/architecture/tr-registry.yaml`
- Story has `## Acceptance Criteria` with ≥3 testable items
- Story has `## Definition of Done` section
- Story has `Status: Ready for Dev`
- Manifest version in story header matches current `docs/architecture/control-manifest.md`
- `project.yaml` sets `modes.workflow: full` and `modes.review_mode: solo`
- Story file exists at `production/epics/core/story-light-pickup.md` containing:
- A `GDD: design/gdd/light-system.md` reference quoting the specific requirement
- `TR-light-001`, present with `status: active` in `docs/architecture/tr-registry.yaml`
- `ADR: ADR-0003`; `docs/architecture/adr-0003-inventory.md` has `## Status` Accepted
- `Type: Logic`, an `## Acceptance Criteria` section with 3 testable items, and a `## Test Evidence` section naming the test path
- An estimate, an Out of Scope statement, and `Dependencies: None`
- Engine notes (or "N/A — no engine API involved"), the relevant manifest rules, and a performance note
- A `Manifest Version:` equal to the one in `docs/architecture/control-manifest.md`
- No TBD / UNRESOLVED markers and no asset paths
- A sprint plan in `production/sprints/` lists other stories
**Input:** `/story-readiness production/epics/core/story-light-pickup.md`
**Expected behavior:**
1. Skill reads the story file
2. Skill reads the referenced ADR — verifies status is `Accepted`
3. Skill reads `docs/architecture/tr-registry.yaml` — verifies TR-ID exists
4. Skill reads `docs/architecture/control-manifest.md` — verifies manifest version matches
5. Skill evaluates all 4 dimensions (Design, Architecture, Scope, DoD)
6. Skill outputs READY verdict with all checks passing
1. Skill reports "Validating 1 story files."
2. Skill loads context once: greps `Manifest Version` from the control manifest,
indexes `tr-registry.yaml`, and resolves every ADR status with one
`Grep pattern="^## Status" glob="docs/architecture/adr-*.md"` scan
3. Skill evaluates all six checklist groups
4. Skill outputs READY with all checks passing
5. Phase 8 notes "QL-STORY-READY skipped — Solo mode."
6. Section 7 surfaces other ready stories from the sprint
**Assertions:**
- [ ] Skill reads the referenced ADR file (not just the story)
- [ ] Skill verifies ADR status is `Accepted` (not `Proposed`)
- [ ] Skill reads `tr-registry.yaml` to verify TR-ID exists
- [ ] Output includes check results for all 4 dimensions
- [ ] ADR status is resolved from the one-scan `^## Status` Grep over `docs/architecture/adr-*.md`, not by reading each ADR in full, and ADR-0003 is found Accepted
- [ ] Skill looks up `TR-light-001` in `tr-registry.yaml` and finds it active
- [ ] The current manifest version is taken from a Grep of the manifest header, not a full read
- [ ] The "Passing Checks (N/[total])" section names all six groups — Design Completeness, Architecture Completeness, Scope Clarity, Open Questions, Asset References ("no asset references"), Definition of Done — with the passing items under each
- [ ] Verdict is READY when all checks pass
- [ ] Skill does not write any files
- [ ] Section 7 lists up to 3 other ready sprint stories — or states "Next ready stories: no sprint file found" / "none ready in [sprint]" rather than omitting the section
---
### Case 2: Blocked Path — Referenced ADR is Proposed (not Accepted)
**Fixture:**
- Story file exists with `ADR: docs/architecture/adr-005-light-system.md`
- `adr-005-light-system.md` exists but has `Status: Proposed`
- All other story content is otherwise complete
- `project.yaml` sets `modes.workflow: full`
- Story `production/epics/core/story-light-system.md` references `ADR-0005`
- `docs/architecture/adr-0005-light-system.md` exists with `## Status` Proposed
- All other story content is complete
**Input:** `/story-readiness production/epics/core/story-light-system.md`
**Expected behavior:**
1. Skill reads the story
2. Skill reads `adr-005-light-system.md` — finds `Status: Proposed`
3. Skill flags this as a BLOCKING issue (cannot implement against unaccepted ADR)
4. Skill outputs BLOCKED verdict
5. Skill recommends: accept or reject the ADR before picking up the story
1. The status scan finds ADR-0005 `Proposed`
2. Skill flags it BLOCKED with the fix text "BLOCKED: ADR-0005 is Proposed — wait for acceptance before implementing."
3. Skill outputs BLOCKED, listing the ADR under Blockers
**Assertions:**
- [ ] Verdict is BLOCKED (not NEEDS WORK or READY) when ADR is Proposed
- [ ] Output explicitly names the Proposed ADR as the blocker
- [ ] Output recommends resolving ADR status before proceeding
- [ ] Verdict is BLOCKED (not NEEDS WORK or READY) when the ADR is Proposed at `full`
- [ ] Output explicitly names ADR-0005 as the blocker
- [ ] Output says to wait for the ADR's acceptance before implementing
- [ ] Skill does not output READY regardless of other checks passing
- [ ] Variant — same story at `modes.workflow: standard`, with `| **Layer** | Feature |` in ADR-0005's `## Engine Compatibility` table (non-critical): the story references the Proposed ADR, so the verdict is still BLOCKED — a referenced Proposed ADR blocks at every tier, because `/dev-story` stops on it
- [ ] Variant — the same non-critical ADR at `standard`, now `Accepted`, with the story's `Manifest Version:` older than the control manifest's: the stale version is listed under Gaps as advisory, with its `Fix:` line, and the verdict is READY — an advisory gap does not downgrade it
---
### Case 3: Needs Work — Missing Acceptance Criteria
### Case 3: Needs Work — Missing Acceptance Criteria (checked at every tier)
**Fixture:**
- Story file exists but has no `## Acceptance Criteria` section
- ADR reference exists and is `Accepted`
- TR-ID exists in registry
- Manifest version matches
- `project.yaml` sets `modes.workflow: minimal`
- Story `production/epics/core/story-oxygen-drain.md` has `Type: Logic` but no `## Acceptance Criteria` section
- The story references no ADR, no TR-ID and no manifest version
**Input:** `/story-readiness production/epics/core/story-oxygen-drain.md`
**Expected behavior:**
1. Skill reads the story
2. Skill finds no Acceptance Criteria section
3. Skill flags this as a NEEDS WORK issue (story is incomplete, not blocked)
4. Skill outputs NEEDS WORK verdict
5. Skill names the missing section and suggests adding measurable criteria
1. At `minimal`, skill evaluates Design Completeness and Scope Clarity and treats Architecture Completeness as N/A
2. Skill finds no acceptance criteria
3. Skill outputs NEEDS WORK, naming the gap with a `Fix:` line suggesting specific, observable criteria
**Assertions:**
- [ ] Verdict is NEEDS WORK (not BLOCKED or READY) when Acceptance Criteria section is absent
- [ ] Output identifies the missing Acceptance Criteria section specifically
- [ ] Output suggests adding testable/measurable criteria
- [ ] Skill distinguishes NEEDS WORK (fixable without external dependencies) from BLOCKED (requires outside action)
- [ ] Verdict is NEEDS WORK (not BLOCKED or READY) when the Acceptance Criteria section is absent
- [ ] Output identifies the missing Acceptance Criteria specifically, with a `Fix:` line proposing measurable criteria
- [ ] No ADR, TR-ID or manifest gap is flagged — Architecture Completeness is N/A at `minimal`
- [ ] The story is not BLOCKED: nothing requires outside action (no missing/DRAFT dependency, no unowned UNRESOLVED question)
- [ ] Variant — the same `minimal` story with acceptance criteria traced to `design/game-brief.md`'s MVP feature (no `design/gdd/` path): "GDD requirement referenced" passes — the brief stands in for the GDD at `minimal`
- [ ] Variant — the story also names `ADR-0005`, whose `## Status` is `Proposed`: the verdict is BLOCKED at `minimal` too — the referenced-ADR rule is the one Architecture Completeness item that is not N/A
---
### Case 4: Edge Case — Stale manifest version
**Fixture:**
- Story file has `Manifest Version: 2026-01-15` in its header
- `project.yaml` sets `modes.workflow: full`
- Story has `Manifest Version: 2026-01-15` in its header
- `docs/architecture/control-manifest.md` has `Manifest Version: 2026-03-10`
- Versions do not match (story was created before manifest was updated)
- Everything else in the story passes
**Input:** `/story-readiness production/epics/core/story-mirror-rotation.md`
**Expected behavior:**
1. Skill reads the story and extracts manifest version `2026-01-15`
2. Skill reads control manifest header and extracts current version `2026-03-10`
3. Skill detects version mismatch
4. Skill flags this as an ADVISORY issue (not blocking, but worth noting)
5. Verdict is NEEDS WORK with manifest staleness noted
1. Skill extracts `2026-01-15` from the story
2. Skill greps the manifest header and extracts `2026-03-10`
3. The story's version is older → the "Manifest version is current" item fails
4. Verdict is NEEDS WORK, with the fix to review the changed rules and update the story's `Manifest Version:`
**Assertions:**
- [ ] Skill reads `docs/architecture/control-manifest.md` to get current version
- [ ] Skill compares story's embedded manifest version against current manifest version
- [ ] Stale manifest version results in NEEDS WORK (not BLOCKED, not READY)
- [ ] Output explains that the story's embedded guidance may be outdated
---
- [ ] Skill gets the current version by grepping `Manifest Version` in `docs/architecture/control-manifest.md`
- [ ] Skill compares the story's embedded version against the current one
- [ ] At `full`, a stale manifest version results in NEEDS WORK (not BLOCKED, not READY)
- [ ] Output explains that new manifest rules may apply, and the `Fix:` says to review the changed rules, update the story if needed, then set its `Manifest Version:` to current
---
### Case 5: Director Gate — QL-STORY-READY behavior across review modes
**Fixture:**
- Story file exists and is READY (all 4 dimensions pass, ADR Accepted, criteria present)
- `production/session-state/review-mode.txt` exists
- `project.yaml` sets `modes.workflow: full`
- Story file exists and passes every checklist item
- Review mode comes from `modes.review_mode` (legacy mirror `production/review-mode.txt`) or `--review`
**Case 5a — full mode:**
- `review-mode.txt` contains `full`
**Input:** `/story-readiness production/epics/core/story-light-pickup.md` (full mode)
**Case 5a — full mode:** `/story-readiness production/epics/core/story-light-pickup.md --review full`
**Expected behavior:**
1. Skill reads review mode — determines `full`
2. After completing its own 4-dimension check, skill invokes QL-STORY-READY gate
3. QA lead reviews the story for readiness
4. If QA lead verdict is INADEQUATE → story verdict is BLOCKED regardless of 4-dimension result
5. If QA lead verdict is ADEQUATE → verdict proceeds normally
1. Skill completes its own checklist and verdict first
2. Skill spawns `qa-lead` via `Agent` with gate QL-STORY-READY, passing the story
file path, story type, acceptance criteria (verbatim), the GDD requirement
(TR-ID and text), dependency status and the Phase 4 verdict
3. ADEQUATE → story cleared
4. GAPS → `AskUserQuestion`: `Update story with suggested gaps` / `Accept and proceed anyway` / `Discuss further`
5. INADEQUATE → the gate says the story must be revised before sprint inclusion:
the checklist's READY is demoted to NEEDS WORK and the final verdict line is
restated with the gaps; the user is asked whether to update the story or
proceed anyway, and proceeding is recorded as an override, not as READY
6. NOT ASSESSED (a gate input was missing) → the missing input is named and never
read as ADEQUATE: it is supplied and the gate re-run, or READY becomes NOT ASSESSED
**Assertions (5a):**
- [ ] Skill reads review mode before deciding whether to invoke QL-STORY-READY
- [ ] QL-STORY-READY gate is invoked in full mode after the 4-dimension check completes
- [ ] A QA lead INADEQUATE verdict overrides a READY 4-dimension result → final verdict BLOCKED
- [ ] Gate invocation is noted in output: "Gate: QL-STORY-READY — [result]"
- [ ] Skill uses the resolved review mode before deciding whether to spawn QL-STORY-READY
- [ ] QL-STORY-READY is spawned only after the checklist verdict exists
- [ ] A GAPS result produces the three-option `AskUserQuestion`
- [ ] An INADEQUATE result overrides the checklist's READY: the final verdict is NEEDS WORK, restated with the gate's specific gaps
- [ ] If the user proceeds anyway, the verdict stays NEEDS WORK and the output states the override ("proceeding despite QL-STORY-READY: INADEQUATE (user override)") — never a silent READY
- [ ] A NOT ASSESSED answer from the gate names the missing input and never leaves READY standing: unless the input is supplied and the gate re-run, the verdict is NOT ASSESSED
**Case 5b — lean or solo mode:**
- `review-mode.txt` contains `lean` or `solo`
**Case 5b — lean or solo mode:** `--review lean` or `--review solo`
**Expected behavior:**
1. Skill reads review mode — determines `lean` or `solo`
2. QL-STORY-READY gate is SKIPPED
3. Output notes the skip: "[QL-STORY-READY] skipped — Lean/Solo mode"
4. Verdict is based on 4-dimension check only
1. QL-STORY-READY is skipped
2. Output notes "QL-STORY-READY skipped — Lean mode." or "QL-STORY-READY skipped — Solo mode."
3. Verdict is based on the checklist only
**Assertions (5b):**
- [ ] QL-STORY-READY gate does NOT spawn in lean or solo mode
- [ ] Skip is explicitly noted in output
- [ ] Verdict is based on 4-dimension check alone
- [ ] QL-STORY-READY does NOT spawn in lean or solo mode
- [ ] The skip is noted in the output with the mode named
- [ ] Verdict is based on the checklist alone
---
### Case 6: UI story at `qa.level: minimal` — the screenshot plan is never waived
**Fixture:**
- `project.yaml` sets `modes.workflow: standard` and `qa.level: minimal` (set on
its own, so only the test-evidence axis is at `minimal` and every checklist
group is evaluated)
- No `docs/architecture/control-manifest.md` and no `tr-registry.yaml` yet
- Story `production/epics/ui/story-003-shop-panel.md` has `Type: UI`, a
`GDD: design/gdd/shop.md` reference quoting the requirement it implements, two
testable acceptance criteria naming what the shop panel shows, "No ADR applies —
pure layout", engine notes, an estimate, an Out of Scope statement,
`Dependencies: None` and a performance note — and no `## Test Evidence` section,
nor any other mention of where a screenshot will go
- No TBD / UNRESOLVED markers and no asset paths
**Input:** `/story-readiness production/epics/ui/story-003-shop-panel.md`
**Expected behavior:**
1. The architecture items pass or auto-pass (explicit "No ADR applies"; no
TR-ID, manifest version or manifest to check)
2. The "Test evidence requirement is clear" item still applies — UI is the
exception to the `qa.level: minimal` auto-pass
3. `testing.strict.ui` is unset, so the item is strict by default: the missing
section makes the story NEEDS WORK
4. The `Fix:` asks for a `## Test Evidence` section naming where the retained
screenshot of each screen touched will go under `production/qa/evidence/`
**Assertions:**
- [ ] Verdict is NEEDS WORK, not READY — the evidence item does not auto-pass for a UI story at `qa.level: minimal`
- [ ] The gap names the missing screenshot plan, and its `Fix:` points at `production/qa/evidence/`
- [ ] The missing screenshot plan is the only gap — no ADR, TR-ID or manifest gap is flagged
- [ ] Variant — a `Type: Logic` story with three testable criteria and no `## Test Evidence` section, same config: the evidence item auto-passes at `qa.level: minimal`, so the missing section alone does not make it NEEDS WORK
---
### Case 7: NOT ASSESSED — nothing to evaluate, or an ADR nobody can read
**Case 7a — zero stories in scope:**
- `production/epics/` holds only `EPIC.md` index files, no story files
- **Input:** `/story-readiness all`
**Assertions (7a):**
- [ ] Output is `NOT ASSESSED — no stories in scope`, naming `production/epics/**/*.md` as the path searched
- [ ] It routes to `/create-epics [layer]` then `/create-stories [epic-slug]`
- [ ] No `Ready: 0 / Needs Work: 0 / Blocked: 0` summary is printed over an empty list
**Case 7b — a referenced ADR with no readable status:**
- `project.yaml` sets `modes.workflow: full`
- Story `production/epics/core/story-save-slots.md` passes every other item and
references `ADR-0007`; `docs/architecture/adr-0007-save-format.md` exists but has
no `## Status` section
- **Input:** `/story-readiness production/epics/core/story-save-slots.md`
**Assertions (7b):**
- [ ] The ADR check is NOT ASSESSED — the status is unknown, not failed — and the verdict is NOT ASSESSED: not BLOCKED, not READY
- [ ] Output names `docs/architecture/adr-0007-save-format.md` and routes to `/architecture-decision retrofit docs/architecture/adr-0007-save-format.md`
- [ ] Variant — the story names `ADR-0007` but no such file exists: that is a finding about the story, so the verdict is BLOCKED ("referenced ADR is missing"), not NOT ASSESSED
---
## Protocol Compliance
- [ ] Does NOT use Write or Edit tools (read-only skill)
- [ ] Presents complete check results before verdict
- [ ] Does not ask for approval (no file writes)
- [ ] Ends with recommended next step (fix issues or proceed to implementation)
- [ ] Distinguishes three verdict levels clearly (READY vs NEEDS WORK vs BLOCKED)
- [ ] Does NOT use Write or Edit tools; any help filling gaps is drafted in conversation only
- [ ] Single-story output follows the Section 5 template: Verdict line, "Passing Checks (N/[total])", Gaps each with a `Fix:` line, and Blockers when BLOCKED
- [ ] Does not ask for write approval (no file writes)
- [ ] Ends with a recommended next step (fix the gaps, or `/dev-story [story-path]` once READY)
- [ ] Keeps the verdict levels distinct — NOT ASSESSED (could not evaluate) is never reported as BLOCKED
---
## Coverage Notes
- Case where TR-ID is missing from the registry entirely is not explicitly
tested here; it follows the same NEEDS WORK pattern as Case 3.
- The "no argument" path (skill auto-detecting the current story) is not
tested because it depends on `production/session-state/active.md` content,
which is hard to fixture reliably.
- A TR-ID missing from the registry follows the same NEEDS WORK pattern as Case 4.
- The zero-story scope is Case 7a; the `sprint` / `all` aggregate output over real
stories and the Must Have sprint escalation warning are not tested here.
- The no-argument path (scope chosen via `AskUserQuestion`) is not tested.
- Stories with multiple ADR references are not tested; behavior is assumed to
be additive (all ADRs must be Accepted for READY verdict).