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
19 KiB
Skill Test Spec: /story-done
Skill Summary
/story-done closes the loop between design and implementation. Run at the
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)
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 multi-phase skill)
- Contains verdict keywords: COMPLETE, COMPLETE WITH NOTES, NOT ASSESSED, BLOCKED
allowed-toolsincludes Write/Edit, so ask-before-write language is present ("UseAskUserQuestionbefore writing anything" — covering the story file and the tech-debt register)- Has a next-step handoff (surfaces next story from sprint)
Test Cases
Case 1: Happy Path — All acceptance criteria met, no deviations
Fixture:
project.yamlsetsmodes.rigor: standard(→workflow: standard,qa.level: standard,review_mode: lean) andengine.name: Godot, sotests/unit/is the test root- Story file at
production/epics/core/story-light-pickup.mdwith:Type: Logicand 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, whiletr-registry.yamlholds the current text, which the implementation matchesADR: ADR-0003(Accepted), whose guidance was followed- A
## Test Evidencesection namingtests/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
- The
/dev-storycheckpoint inproduction/session-state/active.mdnames this story as Current task and carriesRun 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:
- Skill reads the story and extracts its fields
- Skill greps
tr-registry.yamlforTR-light-001and uses that current text - Skill maps the ADR's headings and reads only
## Decisionand## Consequences - Skill verifies each criterion and builds the traceability table: AC-1..AC-3 each map to their test function, all COVERED
- Test evidence found — reported as "Test file present at
<path>" (existence, not a pass claim); the checkpoint'sRun result: OBSERVEDis noted with its retained path - No deviations
- Phase 4b notes "QL-TEST-COVERAGE skipped — Lean mode."
- Phase 5 (lean) asks "Code review is skipped in lean mode. Did you run
/code-reviewon the implemented files?" - Completion report with verdict COMPLETE
AskUserQuestion"Verification complete. How do you want to proceed?"; on "Close the story", the file is updated- Skill surfaces the next ready stories from the sprint
Assertions:
- 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
## Decisionand## Consequencesspans, 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
leanmode the skill asks whether/code-reviewwas run, and records the answer in the Completion NotesCode 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 getsStatus: Complete, aLast Updated:date and a## Completion Notessection - 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: Criteria needing manual or playtest verification
Fixture:
- 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
- (a) "Player sees correct animation on pickup" — no automated test; a frame of
the animation is retained at
- 1 of the 5 criteria ends up with no covering test
Input: /story-done production/epics/core/story-light-pickup.md
Expected behavior:
- Criterion (a) is a subjective/gameplay criterion → skill asks via a batched
AskUserQuestion("Does [criterion]?" —Yes — passes/No — fails/Not tested yet) - 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 - Criterion (b) is marked
DEFERRED — requires playtest sessionand does not block - The traceability table shows (b) UNTESTED; 1 of 5 (≤50%) → ADVISORY
- 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 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.pngshows, the image is opened withRead; the checkpoint'sRun 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 — failsfor (a), the criterion isFAILS, 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 noRun result:line: the user'sYes — passesfor (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
AskUserQuestionbefore updating the story file
Case 3: Blocked Path — GDD deviation detected
Fixture:
project.yamlsetsmodes.workflow: full- The current
tr-registry.yamltext for the story's TR-ID: "Player can carry max 3 light sources" - Implementation in the code root has
MAX_CARRIED_LIGHTS = 5in gameplay code
Input: /story-done production/epics/core/story-light-pickup.md
Expected behavior:
- The GDD rules check (against the current registry text) finds the implementation contradicts "max 3"
- The hardcoded-values check also flags the gameplay literal that belongs in a data file
- The contradiction is categorised BLOCKING and cited with its GDD/TR reference
- Verdict BLOCKED; skill lists what must be fixed and offers to help, and does not advance to Phase 7 on its own
- 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 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
AskUserQuestionregardless 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.mdnamesproduction/epics/core/story-oxygen-drain.mdas the active story- That story file exists with
Status: In Progress
Input: /story-done (no argument)
Expected behavior:
- Skill reads
production/session-state/active.mdand takes the active story - Skill reads that story file and proceeds normally
- The completion report's
**Story**:line names the auto-detected path - If
active.mdnames 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.mdfirst 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
AskUserQuestioninstead of picking one - If no story is found anywhere, skill asks the user to provide a path
Case 5: Director Gate — LP-CODE-REVIEW across review modes
Fixture:
project.yamlsetsmodes.workflow: fullandqa.level: standard(so the QA coverage gate is not skipped forqa.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: OBSERVEDcheckpoint and its retained image) - Review mode comes from
modes.review_mode(legacy mirrorproduction/review-mode.txt) or--review
Case 5a — full mode: /story-done production/epics/core/story-light-pickup.md --review full
Expected behavior:
- After Phases 3–4, skill spawns
qa-leadwith gate QL-TEST-COVERAGE (unlessqa.level: minimalor a Config/Data story) - Skill spawns
lead-programmerwith gate LP-CODE-REVIEW, passing the implementation file paths, story path, relevant GDD section and governing ADR - The verdict (APPROVE / CONCERNS / REJECT) is presented to the user
- CONCERNS →
AskUserQuestion:Revise flagged issues/Accept and proceed/Discuss further - REJECT → no Phase 6 verdict until the issues are resolved
- 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 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
AskUserQuestionbefore updating story status, even after APPROVE
Case 5b — lean mode: --review lean
Assertions (5b):
- LP-CODE-REVIEW does NOT spawn
- Skill asks "Did you run
/code-reviewon 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
AskUserQuestionbefore marking the story Complete
Case 6: UI story at minimal, no sprint plan — the screenshot closes it
Fixture:
project.yamlsetsmodes.rigor: minimal(→workflow: minimal,qa.level: minimal,review_mode: solo); there is no sprint plan inproduction/sprints/— the brief's build order is the planproduction/epics/mvp/holdsstory-001-*.md(Status: Complete), this storystory-002-shop-panel.md(Status: In Progress) andstory-003-*.md(Status: Ready)story-002-shop-panel.mdhasType: UIand 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.pngexists and shows both; the checkpoint carriesRun result: OBSERVEDwith that path; there is no evidence doc and no sign-off
Input: /story-done production/epics/mvp/story-002-shop-panel.md
Expected behavior:
- At
qa.level: minimalthe 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 - The retained screenshot satisfies the UI gate; no evidence doc or sign-off is asked for
- 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." - Verdict COMPLETE; after the Phase 7 approval the story is marked Complete
- Phase 8 takes the no-sprint branch: it runs
bash .claude/scripts/story-status.shafter the story file is written;story-003is on its firstTODOline → "Run/dev-story [path]"
Assertions:
- The UI screenshot check runs at
qa.level: minimaland 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-003and recommends/dev-storydirectly — no/story-readinessline atminimal, and no Sprint Close-Out Sequence - The next story comes from
bash .claude/scripts/story-status.sh, run after this story'sStatus: Completeis written — not from a grep of one epic folder - Variant —
production/epics/combat/story-001-arena.mdreads**Status:** In Review: it is Next Up (the script listsIN_REVIEWfirst, 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 noRun result:line: the UI gate is still BLOCKING atqa.level: minimal, so the verdict is BLOCKED - Variant —
story-003isBlocked, naming its blocker, and no other story is unfinished: Phase 8 prints no Next Up, namesstory-003with 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:
- AC-1..AC-3 verify as in Case 1
- AC-4 cannot be evaluated at all — not DEFERRED (no session could settle it as written) and not failed
- Verdict NOT ASSESSED, naming AC-4 and what would make it checkable (rewrite it as an observable condition)
- 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
- Asks via
AskUserQuestionbefore updating the story file - Appends to
docs/tech-debt-register.mdonly when the user picks "Close and log advisory deviations as tech debt", as rows of/tech-debt's register table with anAddeddate — 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:
fullspawns LP-CODE-REVIEW,leanasks,solonotes the skip
Coverage Notes
- 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 (
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.yamlupdate 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.