mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 10:17:06 +00:00
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
311 lines
19 KiB
Markdown
311 lines
19 KiB
Markdown
# 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-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)
|
||
|
||
---
|
||
|
||
## Test Cases
|
||
|
||
### 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:
|
||
- `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`
|
||
- 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 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:**
|
||
- [ ] 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: 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
|
||
- 1 of the 5 criteria ends up with no covering test
|
||
|
||
**Input:** `/story-done production/epics/core/story-light-pickup.md`
|
||
|
||
**Expected behavior:**
|
||
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 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:**
|
||
- `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. 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 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` 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` 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` 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 across review modes
|
||
|
||
**Fixture:**
|
||
- `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:** `/story-done production/epics/core/story-light-pickup.md --review full`
|
||
|
||
**Expected behavior:**
|
||
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 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 mode:** `--review lean`
|
||
|
||
**Assertions (5b):**
|
||
- [ ] 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
|
||
|
||
- [ ] 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
|
||
|
||
---
|
||
|
||
## 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.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.
|