Closes a finished story: verifies each acceptance criterion, checks for design or ADR deviations and updates its status. Use when the user says a story is done, finished or ready to close.
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
!bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,review_gate,automation,automation_always_ask,workflow,qa.level,gate_level,system_overrides
Resolved above — use as-is; --review overrides review_mode. No block →
defaults in .claude/docs/config-resolution.md.
Ask with the question tool. Without one, list the options numbered and end your turn to wait. A skipped or dismissed question is not an answer: ask again in plain text.
Closes a finished story. Every acceptance criterion is checked against evidence, deviations from the GDD, the ADRs and the story's own scope are reported as facts, and the story is marked Complete only on the user's yes.
Writes, after the user's yes: the story file (Status, Last Updated, a
## Completion Notes section) and its production/sprint-status.yaml entry;
docs/tech-debt-register.md only when the user picks that option. The session
checkpoint is written at the end of every run, whatever the verdict.
Next: the next story (Phase 8).
Asks follow .claude/docs/automation-modes.md (collaborative always asks, guided
asks on major choices, autonomous logs and goes on; automation_always_ask
categories always ask).
Checklist (copy it and tick as you go):
- [ ] Phase 1: story found, facts and settings read
- [ ] Phase 2: what the story is checked against, loaded for its tier
- [ ] Phase 3: each criterion verified, traceability table built
- [ ] Phase 4: test evidence and run result checked
- [ ] Phase 5: deviations and scope checked
- [ ] Phase 6: review gates run, or their skip noted
- [ ] Phase 7: report and verdict shown; close asked
- [ ] Phase 8: next story named, checkpoint written, closing block printedWhich story. The text typed after the skill name, with any --review <mode>
pair removed, is the story path. With nothing typed:
production/session-state/active.md: its Current task
line, when it names a story.bash .claude/scripts/story-facts.sh --all, rows
whose state is IN_REVIEW or IN_PROGRESS. Several: ask "Which story are we
closing?" with one option per story.production/epics/ holds no story file at all,
stop:
"No stories found in production/epics/ — run /create-stories [epic-slug] to make them (at standard and full, run /create-epics first if there is no epic yet)."Its facts. bash .claude/scripts/story-facts.sh <story-path> gives the status,
type, layer, TR-IDs, ADRs, criteria count, test-evidence status and dependencies.
Then read the story in full: the criteria text, the Test Evidence path, ## Files,
Out of Scope.
Tier. workflow for the story's system, keyed on the GDD filename stem of its
GDD: path (design/gdd/<stem>.md → <stem>; the [system] of its TR-ID only
when there is no GDD path): that system's system_overrides row if there is one,
else the project value.
What qa.level requires (the evidence rows of .claude/docs/coding-standards.md).
Take the value from the qa.level line above, never from workflow or rigor: the
two are set apart, so workflow: minimal with qa.level: standard still requires a
Logic story's unit test.
| Check | qa.level: minimal | qa.level: standard | qa.level: full |
|---|---|---|---|
| Logic, Integration test | waived | required | required |
| Config/Data smoke report | waived | required, advisory by default | required, blocking by default |
| Visual/Feel, UI retained screenshot | required | required | required |
| Untested criteria (Phase 3) | never escalate | more than half block | any blocks |
The look is never waived: a Visual/Feel or UI story needs its screenshot at every
level. Gate level per type is the gate_level line above. At full, a
Config/Data default (config=advisory(default…)) becomes blocking; an explicit
testing.strict.config: false still makes it advisory.
By the tier. Read every document by section, never whole.
full: the current requirement text of each TR-ID: in
docs/architecture/tr-registry.yaml, the lines matching id: <TR-ID>\s*$ and the
entry's text below (the anchor keeps TR-combat-001 from matching
TR-combat-0010; \s* takes a Windows line ending). Never use text quoted in the
story; the GDD's Acceptance Criteria and Detailed Design
(bash .claude/scripts/md-section.sh extract design/gdd/<file>.md "Acceptance Criteria",
then the same for "Detailed Design"; exit 3: try "Detailed Rules", the design
standard's name for the same section);
each ADR's status with bash .claude/scripts/adr-status.sh <ADR ids>, then its
Decision and Consequences sections.standard: the same GDD sections; the ADR sections only for a critical ADR
(adr-status.sh's layer column reads Foundation, or has no layer).minimal: none. The story's criteria are the spec.At every tier, when docs/architecture/control-manifest.md exists, note its
Manifest Version line.
Take each acceptance criterion in turn:
.claude/docs/code-root-resolution.md; unresolved, report NOT ASSESSED — code root unresolved, never zero hits).Not tested yet is UNTESTED, and
keeps the verdict at best NOT ASSESSED until someone checks it.production/qa/evidence/[story-slug]/ ([story-slug]: the story
file's name without .md) that you opened and saw it in.
Never describe an image you have not opened; a checkpoint's Run result: OBSERVED — <text> is /dev-story's description, to quote as such.DEFERRED — requires playtest session. It does not
block.Then map each criterion to what covers it: a test under the test root, a "Yes — passes", or a retained image.
| Criterion | Covered by | Status |
|-----------|------------|--------|
| AC-1: [text] | tests/unit/[system]/[file]::[test] | COVERED |
| AC-2: [text] | production/qa/evidence/[slug]/01-[what].png | COVERED |
| AC-3: [text] | — | UNTESTED |Untested criteria escalate by the Phase 1 table: blocking above the line; below it, advisory, listed in the Completion Notes as "Untested criteria: [AC-N list]".
By the story's type, at the Phase 1 gate level. Skip a check qa.level waives, and
say so: Test evidence: waived at qa.level minimal.
tests/unit/[system]/.tests/integration/[system]/, else a playtest
record naming this story in production/qa/playtests/ (/playtest-report
writes them there).production/qa/evidence/. No evidence doc or sign-off needed.production/qa/evidence/[story-slug]-evidence.md with every sign-off row
[x] Approved (one person may sign every role).production/qa/smoke-*.md report; none: "No smoke check
report found. Run /smoke-check."Type: to the story header."A missing item is a gap at the gate level: BLOCKING stops COMPLETE, ADVISORY goes in the notes. Name what is missing and where it goes. An evidence doc with no image beside it is not evidence: a described check is an assertion.
Is the evidence older than its code? For a retained image, run
bash .claude/scripts/review-receipts.sh check production/qa/evidence/[story-slug]/stamp.txt.
Each CHANGED: or GONE: file: "[file] changed after the evidence was captured —
re-capture it." RECEIPT: NONE: "no stamp — whether the evidence is older than the
code cannot be told". Report these lines; they never change the verdict.
Run result, every other type. Take the Run result: line from the /dev-story
checkpoint (only when its Current task names this story) or the story's Completion Notes.
OBSERVED with a path: note it. N/A — <reason>: accept only a reason that says
why nothing is observable ("it's a Logic story" is not one). NOT VERIFIED on a
story whose criteria name something on screen: a gap at the gate level. No line:
advisory, "confirm the build was launched and looked at". A user's "Yes — passes"
to an on-screen criterion with no retained image is an assertion, not an
observation: a gap at the gate level.
Run, by tier (minimal skips 1 and 3):
full; standard on its required sections): search the changed
files for the names the current GDD text and TR requirement use.Manifest Version older than the manifest's: ADVISORY,
"written against manifest v[story]; current is v[current] — run
/story-readiness to check". No manifest: skip. A Manifest-Note: line in the
story is carried into the deviations as written.full; standard for a critical ADR): search for the
patterns the ADR's Decision or the manifest forbids.## Files against the code and test
files changed (git status --porcelain). A changed file the list does not name
is OUT OF SCOPE. A story with no ## Files section: use the checkpoint's
Files in progress when its Current task names this story; else report
Scope: NOT ASSESSED — the story lists no files. A clean working tree: report
Scope: not checked — no uncommitted changes to compare.Each deviation is BLOCKING (contradicts the GDD or ADR), ADVISORY (drifts but works the same; the user decides) or OUT OF SCOPE (for awareness). State them as facts; the user judges them.
Read the review_gate line above.
skill-gates=skip: no agent. Note QL-TEST-COVERAGE skipped — [Solo | Lean] mode and LP-CODE-REVIEW skipped — [Solo | Lean] mode. In lean mode, ask: "Did
you run /code-review on the implemented files?" Options: Yes — it passed or was
approved with suggestions / No — skipping review for this story / No — I'll run
it before the sprint close-out. The answer sets Reviewed by.skill-gates=run: read references/review-gates.md and
.claude/docs/director-gates.md, and run both gates now. On a skip, do not load
it.Reviewed by is never blank: lead-programmer when LP-CODE-REVIEW ran;
/code-review (you said you ran it; not verified here) for the lean Yes; self, no independent review in solo mode, for either No, and when no implementation file
exists yet.
## Story Done: [title]
**Story**: [path] · **Type**: [type] · **Date**: [today]
### Acceptance Criteria: [X/Y passing]
- [x] [criterion] — [how verified]
- [ ] [criterion] — FAILS: [reason]
- [?] [criterion] — DEFERRED: requires playtest
### Traceability
[the Phase 3 table]
### Test Evidence
**Required**: [what the type needs at this qa.level, or "waived at qa.level minimal"]
**Found**: [YES — path | NO — BLOCKING | NO — ADVISORY]
### Deviations
[NONE, or each: BLOCKING / ADVISORY / OUT OF SCOPE — description — reference]
### Review
**Reviewed by**: [value]
### Verdict: [COMPLETE | COMPLETE WITH NOTES | NOT ASSESSED | BLOCKED]Verdicts, the first that matches wins:
Then ask, before writing anything: "How do you want to proceed?" Options:
Close the story — mark it Complete and log notes (Recommended) / Close and log the
advisory deviations as tech debt / Don't close yet — I'll fix things first / Close
anyway, accepting the deviations. On BLOCKED or NOT ASSESSED, recommend "Don't close
yet" and list what must change. Closing such a story is a scope_changes decision:
when the automation_always_ask line lists it, ask in every automation mode, even
when the user's own request is what got here. Write only on an explicit choice to
close.
On close:
bash .claude/scripts/md-section.sh set-field <story> Status Complete, then
set-field <story> "Last Updated" <YYYY-MM-DD> --after Status.## Completion Notes
**Completed**: [date]
**Criteria**: [X/Y passing] ([deferred items])
**Deviations**: [None, or the advisory ones]
**Test Evidence**: [path, or "waived at qa.level minimal", or "none required"]
**Reviewed by**: [value]references/tech-debt-row.md and add one
row per advisory deviation.production/sprint-status.yaml, when it exists: this story's entry gets
status: done and completed: [date], and the top-level updated gets today.
The close answer covers it.git add [the changed code and test files] [story path]
and git commit -m "feat: [story title] ([TR-ID])".On "Don't close yet": change no story file. List what the user flagged. Never fix a failing criterion yourself: report it and ask what to do.
The next story. With no sprint plan in production/sprints/ (always at
workflow: minimal): Run bash .claude/scripts/story-status.sh after the close, so
this story's new status is in it. It prints the unfinished stories in route order;
do not re-rank them. The first In Review story is next (the first IN_REVIEW
line), else the first In Progress one, else the first Ready or Not Started
one (TODO):
### Next Up
**[Story NNN: title]** — [one line]
Run `/story-done [path]` to close it (In Review) — else `/dev-story [path]` to implement it.When the workflow line above reads minimal, print no /story-readiness line at
all, not even as an option: it is not on that path. With no sprint plan at
workflow: standard or full, add "Run /story-readiness [path] first."
COMPLETE N of N: every story is built. Offer: play the build and note what
feels wrong; add stories from the brief with /create-stories; or /settings to
raise modes.rigor if the game has outgrown its brief.BLOCKED, OTHER or NO_STATUS lines left: there is no Next Up, and the
build order is not done. Name each story with its blocker, Draft or no status.With a sprint plan: read references/sprint-next.md.
The checkpoint, on every verdict, closed or not. Pipe the block to
bash .claude/scripts/session-state.sh checkpoint, which replaces the old block:
**Updated:** [date]
**Branch:** `[current git branch]`
**Current task:** /story-done — [story path]: [verdict], [closed | left open]
**Next step:** [the Next Up command, or the fix the verdict named]
**Blocked on:** [nothing, or what blocked the verdict]
**Files in progress:** none
**Open questions:** [tech debt logged: N items, or none]The run's last reply ends with this block (repeat it if you showed it earlier):
Verdict: [COMPLETE | COMPLETE WITH NOTES | NOT ASSESSED | BLOCKED] — [story path]
Story: [closed — Status: Complete | left open — Status: [status]]
Review: [Reviewed by value; the gates' skip notes]
Next step: [/dev-story [path] | /story-done [path] | the fix | play the build]Donchitos/Claude-Code-Game-Studios
05ad7c8
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.