mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 10:17:06 +00:00
Release 1.1.3 — long skills keep their later steps
Fix release for 1.1.2: the 14 longest skills keep their later phases after a compaction, a question nobody answered is never taken as an answer, settings read the same from a subfolder, the commit check works for a project in a subfolder of a larger repository, every skill opens with a title, and the shipped allow rules no longer approve deleting a branch or writing files without asking. Details in CHANGELOG.md; upgrade steps in UPGRADING.md (v1.1.2 → v1.1.3). Refs #83 Refs #133 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0185en4t76fPn7315q4c3nko
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b21fa0f7f2
commit
be8993bbc5
@@ -0,0 +1,246 @@
|
||||
# /story-done — Phase 3: Verify Acceptance Criteria
|
||||
|
||||
> Part of `/story-done`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 3: Verify Acceptance Criteria
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Automatic verification (run without asking)
|
||||
- Manual verification with confirmation (use `AskUserQuestion`)
|
||||
- Unverifiable (flag without blocking)
|
||||
- Test-Criterion Traceability
|
||||
- Test Evidence Requirement
|
||||
|
||||
For each acceptance criterion in the story, attempt verification using one of
|
||||
three methods:
|
||||
|
||||
### Automatic verification (run without asking)
|
||||
|
||||
- **File existence check**: `Glob` for files the story said would be created.
|
||||
- **Test file check**: if a test file path is mentioned, confirm the file exists
|
||||
with `Glob`. Do not run it — this skill establishes existence only (see the
|
||||
note under Test Evidence Requirement), so report "test file present", never
|
||||
"test passes".
|
||||
- **No hardcoded values check**: `Grep` for numeric literals in gameplay code
|
||||
paths that should be in config files.
|
||||
- **No hardcoded strings check**: `Grep` for player-facing strings in the **code root** (resolve per `.claude/docs/code-root-resolution.md`). **If the code root is unresolved, report `NOT ASSESSED — code root unresolved` rather than zero hits.**
|
||||
that should be in localization files.
|
||||
- **Dependency check**: if a criterion says "depends on X", check that X exists.
|
||||
|
||||
### Manual verification with confirmation (use `AskUserQuestion`)
|
||||
|
||||
- Criteria about subjective qualities ("feels responsive", "animations play correctly")
|
||||
- Criteria about gameplay behaviour ("player takes damage when...", "enemy responds to...")
|
||||
— these are asked, never marked verified from reading the code: the code says
|
||||
what should happen, not what the build does
|
||||
- Performance criteria ("completes within Xms") — ask if profiled or accept as assumed
|
||||
|
||||
Batch up to 4 manual verification questions into a single `AskUserQuestion` call:
|
||||
|
||||
```
|
||||
question: "Does [criterion]?"
|
||||
options: "Yes — passes", "No — fails", "Not tested yet"
|
||||
```
|
||||
|
||||
Map each answer: `Yes — passes` → confirmed; `No — fails` → FAILS;
|
||||
`Not tested yet` → not evaluated — UNTESTED in the traceability table below, and
|
||||
the verdict is NOT ASSESSED (Phase 6) until someone checks it. If the criterion
|
||||
genuinely needs a full-build playtest, mark it `DEFERRED — requires playtest
|
||||
session` instead.
|
||||
|
||||
### Unverifiable (flag without blocking)
|
||||
|
||||
- Criteria that require a full game build to test (end-to-end gameplay scenarios)
|
||||
- Mark as: `DEFERRED — requires playtest session`
|
||||
|
||||
### Test-Criterion Traceability
|
||||
|
||||
After completing the pass/fail/deferred check above, map each acceptance
|
||||
criterion to the test that covers it:
|
||||
|
||||
For each acceptance criterion in the story:
|
||||
|
||||
1. Ask: is there a test — unit, integration, or confirmed manual playtest — that
|
||||
directly verifies this criterion?
|
||||
- **Unit test**: check `tests/unit/` for a test file or function name that
|
||||
matches the criterion's subject (use `Glob` and `Grep`)
|
||||
- **Integration test**: check `tests/integration/` similarly
|
||||
- **Manual confirmation**: if the criterion was verified via `AskUserQuestion`
|
||||
above with a "Yes — passes" answer, count that as a manual test
|
||||
- **Retained screenshot**: if the criterion names something on screen and a
|
||||
retained image under `production/qa/evidence/[story-slug]/` shows it (the
|
||||
`Run result: OBSERVED` from `/dev-story` Phase 6 step 4), count that as
|
||||
covered — put the image path in the Test column. A visual criterion
|
||||
verified by looking is not UNTESTED; without this row every UI story
|
||||
reads as >50% untested and false-escalates. "Shows it" means you opened
|
||||
the image with `Read` and saw it; a checkpoint's `Run result: OBSERVED —
|
||||
<text>` is `/dev-story`'s description, to quote as such, not yours.
|
||||
**Never describe an image you have not opened.**
|
||||
|
||||
2. Produce a traceability table:
|
||||
|
||||
```
|
||||
| Criterion | Test | Status |
|
||||
|-----------|------|--------|
|
||||
| AC-1: [criterion text] | tests/unit/test_foo.gd::test_bar | COVERED |
|
||||
| AC-2: [criterion text] | Manual playtest confirmation | COVERED |
|
||||
| AC-3: [criterion text] | production/qa/evidence/[slug]/01-shop-open.png | COVERED |
|
||||
| AC-4: [criterion text] | — | UNTESTED |
|
||||
```
|
||||
|
||||
3. Apply these escalation rules (skip entirely at `qa.level: minimal` — no
|
||||
evidence is required, so untested criteria never escalate):
|
||||
|
||||
- If **>50% of criteria are UNTESTED**: escalate to **BLOCKING** — test
|
||||
coverage is insufficient to confirm the story is actually done. The verdict
|
||||
in Phase 6 cannot be COMPLETE until coverage improves.
|
||||
- If **some (≤50%) criteria are UNTESTED**: remain ADVISORY — does not block
|
||||
completion, but must appear in Completion Notes.
|
||||
- If **all criteria are COVERED**: no action needed beyond including the
|
||||
table in the report.
|
||||
|
||||
4. For any ADVISORY untested criteria, add to the Completion Notes in Phase 7:
|
||||
`"Untested criteria: [AC-N list]. Recommend adding tests in a follow-up story."`
|
||||
|
||||
### Test Evidence Requirement
|
||||
|
||||
**First apply `qa.level` (resolved in Phase 1).** At `minimal`, no *test*
|
||||
evidence is required — skip the Logic, Integration and Config/Data checks below.
|
||||
But still run the Visual/Feel and UI check and the `Run result:` check: the look
|
||||
is not waived at minimal, only the tests are. At `standard`, require evidence
|
||||
for the story's own type. At `full`, require evidence for every story type. The
|
||||
`testing.strict` resolution below applies to every check that runs.
|
||||
|
||||
Based on the Story Type extracted in Phase 2, check for required evidence.
|
||||
|
||||
**Resolve the gate level for this story's type.** A gate level is either
|
||||
BLOCKING (a gap prevents the COMPLETE verdict in Phase 6) or ADVISORY (a gap is
|
||||
noted in the Completion Notes but does not block). Resolve it from the
|
||||
`testing.strict` block **already resolved in the resolved-config block at the top of this skill** — not by reading
|
||||
`project.yaml` yourself:
|
||||
|
||||
1. Map the Story Type to a `testing.strict` key — Logic→`logic`,
|
||||
Integration→`integration`, Visual/Feel→`visual`, UI→`ui`, Config/Data→`config`.
|
||||
Take `testing.strict.<key>` from that resolved block. If its value is `true`
|
||||
(case-insensitive) → BLOCKING; if `false` → ADVISORY; `unset` → fall through.
|
||||
2. Else read `testing.strict` as a plain boolean (legacy single-value form). If
|
||||
its value is `true` → BLOCKING or `false` → ADVISORY, it applies to every type.
|
||||
3. Else use the default in the table below.
|
||||
|
||||
> **Use that resolved block, never `project.yaml` directly.** `testing.strict.*` is
|
||||
> on the `/settings --local` whitelist, so a developer can set
|
||||
> `testing.strict.logic=false` in `project.local.yaml` for fast WIP commits —
|
||||
> `effects-map.md` specifies exactly this ("stricter dev's local `/story-done`
|
||||
> blocks earlier"). Reading `project.yaml` alone silently ignores that file: the
|
||||
> setting is accepted, displayed by `/settings`, and has no effect. The
|
||||
> `resolve_config` block at the top of this skill already merges local over base.
|
||||
|
||||
Only `true` and `false` (case-insensitive) are recognized at steps 1–2. A key
|
||||
that is present but holds any other value — `maybe`, `1`, `yes`, etc. — is
|
||||
treated as unset: continue to the next step, and surface the unrecognized value
|
||||
to the user.
|
||||
|
||||
| Story Type | Required Evidence | Default Gate Level |
|
||||
|---|---|---|
|
||||
| **Logic** | Automated unit test in `tests/unit/[system]/` — must exist and pass (this skill verifies **existence**; see the note below Phase 3) | BLOCKING |
|
||||
| **Integration** | Integration test in `tests/integration/[system]/` OR playtest doc | BLOCKING |
|
||||
| **Visual/Feel** | Retained screenshot + sign-off in `production/qa/evidence/` | BLOCKING |
|
||||
| **UI** | Retained screenshot of each screen touched, in `production/qa/evidence/` | BLOCKING |
|
||||
| **Config/Data** | Smoke check pass report in `production/qa/smoke-*.md` | ADVISORY |
|
||||
|
||||
The **Default Gate Level** column applies when `testing.strict` is unset (the
|
||||
common case). When `testing.strict` is configured, the resolved value from
|
||||
steps 1–2 overrides it. Visual/Feel and UI default to BLOCKING because for a
|
||||
game the rendered result is the product; set `testing.strict.visual` or
|
||||
`testing.strict.ui` to `false` for an advisory gate.
|
||||
|
||||
> **Exception — `/smoke-check`.** The ADVISORY default for **Config/Data** above
|
||||
> governs *per-story evidence* gates, which is what this skill checks.
|
||||
> `/smoke-check` is a build-health gate, not a per-story evidence gate, so its own
|
||||
> unset default for `testing.strict.config` is **BLOCKING** — see
|
||||
> `.claude/skills/smoke-check/SKILL.md` § "Resolve the gate enforcement level".
|
||||
> The divergence is intentional; do not "fix" either side to match the other.
|
||||
|
||||
> **This phase checks that evidence EXISTS. It does not run anything.** The
|
||||
> `Default Gate Level` table above, and `.claude/docs/coding-standards.md`, both
|
||||
> say a Logic story's test "must exist **and pass**". The checks below establish
|
||||
> only the first half — every one of them is a `Glob` or a `Grep`. A unit test
|
||||
> that exists and fails, or that contains no assertions, satisfies them.
|
||||
>
|
||||
> Say which half you verified when you report. "Test file present at `<path>`"
|
||||
> is the honest claim; "tests pass" is not one this phase can make. Pass/fail is
|
||||
> established by `/gate-check` (runs the suite at a phase gate) and
|
||||
> `/smoke-check` (runs it before QA hand-off), both of which do execute.
|
||||
>
|
||||
> Unlike `/regression-suite` and `/launch-checklist`, which stop at existence
|
||||
> and carry no general `Bash` pre-approval, this skill has `Bash` pre-approved —
|
||||
> the limit here is the instruction, not the grant (a pre-approval never
|
||||
> restricts). Running the story's own test before closing it is a live option;
|
||||
> it is not enabled because it needs a configured runner and a decision about
|
||||
> what a missing runner should mean.
|
||||
|
||||
**For Logic stories**: first read the story's **Test Evidence** section to extract the
|
||||
exact required file path. Use `Glob` to check that exact path. If the exact path is not
|
||||
found, also search `tests/unit/[system]/` broadly (the file may have been placed at a
|
||||
slightly different location). If no test file is found at either location:
|
||||
- Flag at the resolved gate level: "Logic story has no unit test file. Story
|
||||
requires it at `[exact-path-from-Test-Evidence-section]`. Create and run the
|
||||
test before marking this story Complete."
|
||||
|
||||
**For Integration stories**: read the story's **Test Evidence** section for the exact
|
||||
required path. Use `Glob` to check that exact path first, then search
|
||||
`tests/integration/[system]/` broadly, then check `production/session-logs/` for a
|
||||
playtest record referencing this story.
|
||||
If none found: flag at the resolved gate level (same rule as Logic).
|
||||
|
||||
**For Visual/Feel and UI stories**: glob `production/qa/evidence/` for a
|
||||
retained screenshot for this story (`*.png`, `*.jpg`, `*.gif`) and for an
|
||||
evidence doc referencing it. What closes the story follows the evidence table
|
||||
in `.claude/docs/coding-standards.md`, the same at every `qa.level`:
|
||||
- A **UI** story is satisfied by the retained screenshot of each screen it
|
||||
touched. No evidence doc or sign-off is required; note one if it exists.
|
||||
- A **Visual/Feel** story also needs the sign-off: the evidence doc
|
||||
(`production/qa/evidence/[story-slug]-evidence.md`, from the test-evidence
|
||||
template) with every sign-off row `[x] Approved`.
|
||||
|
||||
Flag at the resolved gate level:
|
||||
- No screenshot: "No visual evidence found. Capture a screenshot of each screen or effect this story touched and save it under `production/qa/evidence/` before final closure." For Visual/Feel add: "then record sign-off in `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template."
|
||||
- An evidence doc but no screenshot retained beside it: "Evidence doc found at `[path]` but no screenshot is retained. A described check is an assertion, not evidence — capture the screen and save the image under `production/qa/evidence/` before final closure."
|
||||
- Visual/Feel with a screenshot but no evidence doc: "Screenshot found but no sign-off is recorded. Create `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template and obtain sign-off before final closure."
|
||||
- Visual/Feel sign-off rows still unchecked — grep the doc for `| .* | .* | .* | \[ \] Approved`: "Evidence file found at `[path]` but [N] sign-off(s) are still pending (shown as `[ ] Approved` in the sign-off table). Obtain required sign-offs before final closure. Note: for solo developers, all roles may be signed off by the same person."
|
||||
|
||||
Otherwise note "Retained screenshot found[, sign-offs complete] — gate satisfied."
|
||||
|
||||
The retained image **is** the `Run result: OBSERVED` from `/dev-story` Phase 6
|
||||
step 4 (`.claude/docs/run-and-observe.md`); its absence means the run was
|
||||
`NOT VERIFIED` or never happened, and the flag above is the consequence. The
|
||||
run is not waived at `qa.level: minimal`.
|
||||
|
||||
**For every other story type**, read the `Run result:` line from the
|
||||
`/dev-story` checkpoint in `production/session-state/active.md` — only when its
|
||||
**Current task** names this story; a later `/dev-story` overwrites it — or from
|
||||
the story's `## Completion Notes`. `OBSERVED` with a retained path: note
|
||||
it. `N/A — <reason>`: accept only if the reason names why nothing is
|
||||
observable — "it's a Logic story" is not a reason. `NOT VERIFIED — <reason>`
|
||||
on a story whose acceptance criteria name anything on screen: flag at the
|
||||
resolved gate level for the story's type. No `Run result:` line at all: flag
|
||||
as ADVISORY — "the implementation summary carries no run result; confirm the
|
||||
build was launched and looked at before closure." The exception: when the
|
||||
acceptance criteria name something on screen and no retained image for this
|
||||
story is under `production/qa/evidence/`, nothing observed the story — a user's
|
||||
`Yes — passes` to such a criterion is an assertion, not the retained observation
|
||||
`.claude/docs/run-and-observe.md` requires — so flag it at the resolved gate
|
||||
level for the story's type, as for `NOT VERIFIED`.
|
||||
|
||||
**For Config/Data stories**: check for any `production/qa/smoke-*.md` file.
|
||||
If none: flag at the resolved gate level — "No smoke check report found. Run `/smoke-check`."
|
||||
|
||||
**If no Story Type is set**: flag as **ADVISORY** —
|
||||
"Story Type not declared. Add `Type: [Logic|Integration|Visual/Feel|UI|Config/Data]`
|
||||
to the story header to enable test evidence gate enforcement in future stories."
|
||||
|
||||
Any BLOCKING test evidence gap prevents the COMPLETE verdict in Phase 6.
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user