Release 1.1.0 — one config file, and a process weight you choose

`project.yaml` at the repo root is now the single source of truth for a
project's configuration, replacing `production/stage.txt`,
`production/review-mode.txt` and `.claude/docs/technical-preferences.md` (all
three still read as a fallback; nothing is force-deleted).

**`modes.rigor` — one question instead of six.** `minimal`, `standard` or
`full` fronts six knobs: `modes.workflow`, `docs.density`, `qa.level`,
`modes.story_granularity`, `modes.review_mode` and `team.size`. It defaults to
`minimal`, which is a change from 1.0's behaviour: the heavier tier was
measured costing several times more to reach working code without producing a
better result, and returning nothing when a fresh developer inherited the
project. Pin `modes.rigor: standard` to keep 1.0's process level.

Also in this release:

- `/settings` to view or change any setting, and `project.local.yaml` for
  per-developer preferences that should not be committed.
- `system_overrides` to hold one system to a higher standard than the rest of
  the project, and `testing.strict` to set per test type whether missing
  evidence blocks a story or warns.
- A story that changes anything the player sees is not closed until the game
  has been launched, observed, and a screenshot retained in
  `production/qa/evidence/`. A parse check is not a run. This holds at every
  rigor level, including `minimal`, where automated tests are waived but the
  look is not.
- The code root is engine-specific and enforced as such: Godot `src/`, Unity
  `Assets/`, Unreal `Source/<Module>/`. Two of the three will not build a
  project laid out any other way.
- Migration tooling for existing projects: `.claude/scripts/migrate-v1-config.sh`
  converts a 1.0 layout, non-destructively by default, with a report to review
  before `--finalize` deletes anything.
- Ask-before-write holds regardless of personal automation settings.

Upgrading from 1.0 or earlier: see UPGRADING.md. Full list of changes:
CHANGELOG.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016xvzG3i7pWQg4LjyDwWMXd
This commit is contained in:
Donchitos
2026-09-23 12:25:11 +10:00
co-authored by Claude Opus 5
parent 984023ddac
commit d05699707f
291 changed files with 24374 additions and 7740 deletions
+154 -47
View File
@@ -1,13 +1,19 @@
---
name: adopt
description: "Brownfield onboarding — audits existing project artifacts for template format compliance (not just existence), classifies gaps by impact, and produces a numbered migration plan. Run this when joining an in-progress project or upgrading from an older template version. Distinct from /project-stage-detect (which checks what exists) — this checks whether what exists will actually work with the template's skills."
description: "Brownfield audit — do existing artifacts actually work? Numbered migration plan. Unlike /project-stage-detect, checks compliance not existence."
argument-hint: "[focus: full | gdds | adrs | stories | infra]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion
allowed-tools: Read, Glob, Grep, Bash, Write, AskUserQuestion
model: sonnet
agent: technical-director
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,automation_always_ask,workflow`
Resolved above — use as-is. `/adopt` also inspects `project.yaml` and the legacy
config files directly when reporting and writing migration state; that raw
inspection is deliberate and separate from the resolved values above.
# Adopt — Brownfield Template Adoption
This skill audits an existing project's artifacts for **format compliance** with
@@ -35,6 +41,16 @@ wrong internal format.
---
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** (per `.claude/docs/workflow-modes.md`). It scopes the Phase 2 audit and
Phase 3 severity: `full` audits all doc types at full structure; `standard` audits
only the required docs/sections (optional sections are informational, not gaps);
`minimal` is a `design/game-brief.md` format check — GDDs/ADRs/UX are not expected. See Phase 2.
## Phase 1: Detect Project State
Emit one line before reading: `"Scanning project artifacts..."` — this confirms the
@@ -43,23 +59,23 @@ skill is running during the silent read phase.
Then read silently before presenting anything else.
### Existence check
- `production/stage.txt` — if present, read it (authoritative phase)
- `design/gdd/game-concept.md` — concept exists?
- `project.stage` in `project.yaml` (fallback `production/stage.txt`) — if either is present, use that value (authoritative phase)
- `design/gdd/game-concept.md` (or, at the minimal tier, `design/game-brief.md`) — concept exists?
- `design/gdd/systems-index.md` — systems index exists?
- Count GDD files: `design/gdd/*.md` (excluding game-concept.md and systems-index.md)
- Count ADR files: `docs/architecture/adr-*.md`
- Count story files: `production/epics/**/*.md` (excluding EPIC.md)
- `.claude/docs/technical-preferences.md` — engine configured?
- `project.yaml` (`engine.name`) / `.claude/docs/technical-preferences.md` — engine configured?
- `docs/engine-reference/` — engine reference docs present?
- Glob `docs/adoption-plan-*.md` — note the filename of the most recent prior plan if any exist
### Infer phase (if no stage.txt)
### Infer phase (if no project.stage / stage.txt)
Use the same heuristic as `/project-stage-detect`:
- 10+ source files in `src/` → Production
- 10+ source files in the code root → Production
- Stories in `production/epics/` → Pre-Production
- ADRs exist → Technical Setup
- systems-index.md exists → Systems Design
- game-concept.md exists → Concept
- game-concept.md (or `design/game-brief.md`) exists → Concept
- Nothing → Fresh (not a brownfield project — suggest `/start`)
If the project appears fresh (no artifacts at all), use `AskUserQuestion`:
@@ -78,32 +94,61 @@ Report: "Detected phase: [phase]. Found: [N] GDDs, [M] ADRs, [P] stories."
## Phase 2: Format Audit
For each artifact type in scope (based on argument mode), check not just that
the file exists but that it contains the internal structure the template requires.
For each artifact type in scope (based on argument mode **and the resolved
workflow tier**), check not just that the file exists but that it contains the
internal structure the template requires. At `minimal`, scope the audit to
`design/game-brief.md` — do not audit for GDDs, ADRs, or UX specs (they are not expected).
### 2a: GDD Format Audit
For each GDD file found, check for the 8 required sections by scanning headings:
**Gather section presence deterministically — do not read the GDDs to count
headings.** For each GDD discovered in Phase 1, pass its path explicitly to the
structure-check script:
| Required Section | Heading pattern to look for |
|---|---|
| Overview | `## Overview` |
| Player Fantasy | `## Player Fantasy` |
| Detailed Rules / Design | `## Detailed` or `## Core Rules` or `## Detailed Design` |
| Formulas | `## Formulas` or `## Formula` |
| Edge Cases | `## Edge Cases` |
| Dependencies | `## Dependencies` or `## Depends` |
| Tuning Knobs | `## Tuning` |
| Acceptance Criteria | `## Acceptance` |
```
Bash: bash .claude/scripts/gdd-structure-check.sh [path-to-gdd]
```
For each GDD, record:
- Which sections are present
- Which sections are missing
- Whether it has any content in present sections or just placeholder text
(`[To be designed]` or equivalent)
**Pass paths one at a time; do not invoke it bare.** The no-argument form sweeps
`design/gdd/` only, and a brownfield project's GDDs are not guaranteed to live
there — pass whatever paths Phase 1 found. The script prints a `PRESENT:` list
and, when applicable, an `ABSENT:` list per file. It reports **presence only**
and makes no REQUIRED/ADVISORY judgment (that is the tier logic below), and it
already accepts `## Detailed Design` as satisfying the `Detailed Rules`
requirement, so do not flag that alias as missing.
Also check: does each GDD have a `**Status**:` field in its header block?
Valid values: `In Design`, `Designed`, `In Review`, `Approved`, `Needs Revision`.
If the script prints `Not found:` for a path or errors, that is a **discovery
failure, not a format gap** — report it as "could not audit [path]" and do not
count it as a missing-sections finding.
**Then apply the workflow tier** resolved above to each file's PRESENT/ABSENT
lists. Which sections are **required** (a miss = gap) vs **advisory** (a miss =
informational):
- **`full`** — all 8 sections are required.
- **`standard`** — the 5 required (Overview, Detailed Rules, Edge Cases,
Dependencies, Acceptance Criteria) + Formulas for any system that defines
numeric rules (rates, curves, thresholds, costs — the system's `Category` is a
hint, not the test); Player Fantasy and Tuning Knobs are advisory.
- **`minimal`** — GDDs are not expected; audit `design/game-brief.md` instead. Any GDD
that does exist is checked at the `standard` bar, advisorily.
The script's 8 canonical labels are: Overview, Player Fantasy, Detailed Rules,
Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria.
A section reported PRESENT can still be an empty heading. For each GDD, also
record with a targeted grep (not a full read):
- Placeholder-only sections — `Grep pattern="\[To be designed\]"` (or an
equivalent empty/single-line body) marks a present-but-unwritten section.
- The `**Status**:` header field — `Grep pattern="^>?[[:space:]]*\*\*Status\*\*:"`.
Valid values: `Draft`, `In Design`, `Designed`, `In Review`, `Approved`,
`Implemented`, `Needs Revision`.
> **The `>?` is load-bearing, and so are `Draft`/`Implemented`.** Both emitters
> write this field inside a blockquote — `.claude/docs/templates/game-design-document.md`
> and `/design-system` produce `> **Status**: …` — so an anchor of
> `^\*\*Status\*\*:` matches nothing and reports *every* template-compliant GDD
> as missing its Status. The template's own value list offers `Draft` and
> `Implemented`, so both must count as valid.
### 2b: ADR Format Audit
@@ -154,17 +199,69 @@ For each story file found:
| Control manifest | `docs/architecture/control-manifest.md` | HIGH — no layer rules for stories |
| Manifest version stamp | In manifest header: `Manifest Version:` | MEDIUM — staleness checks blind |
| Sprint status | `production/sprint-status.yaml` | MEDIUM — `/sprint-status` falls back to markdown |
| Stage file | `production/stage.txt` | MEDIUM — phase auto-detect unreliable |
| Stage file | `project.stage` in `project.yaml` (fallback `production/stage.txt`) | MEDIUM — phase auto-detect unreliable |
| Engine reference | `docs/engine-reference/[engine]/VERSION.md` | HIGH — ADR engine checks blind |
| Architecture traceability | `docs/architecture/architecture-traceability.md` | MEDIUM — no persistent matrix |
| Architecture traceability | `docs/architecture/requirements-traceability.md` | MEDIUM — no persistent matrix |
### 2f: Technical Preferences Audit
### 2f: Project Config Audit
Read `.claude/docs/technical-preferences.md`. Check each field for `[TO BE CONFIGURED]`:
- Engine, Language, Rendering, Physics → HIGH if unconfigured (ADR skills fail)
- Naming conventions → MEDIUM
- Performance budgets → MEDIUM
- Forbidden Patterns, Allowed Libraries → LOW (starts empty by design)
Read `project.yaml` (the primary config store) and `.claude/docs/technical-preferences.md` (legacy mirror). A setting counts as configured if EITHER source has a real value (in technical-preferences.md, `[TO BE CONFIGURED]` means unconfigured):
- `engine.name`/`version`/`language`/`rendering`/`physics` (else the Engine/Language/Rendering/Physics fields) → HIGH if unconfigured in both (ADR skills fail)
- `naming.*` (else Naming conventions) → MEDIUM
- `performance.*` (else Performance budgets) → MEDIUM
- Forbidden Patterns, Allowed Libraries (technical-preferences.md only — not migrated to project.yaml) → LOW (starts empty by design)
### 2g: v1.0 Migration Check
A project is a **v1.0 project needing migration** when `project.yaml` does NOT
exist at the repo root AND at least one legacy file does: `production/stage.txt`,
`production/review-mode.txt`, or a `.claude/docs/technical-preferences.md` with
real values.
"Real values" means one of the keys the converter actually migrates — Engine,
Language, Rendering, Physics, the naming, platform and performance fields,
Framework, or the specialists. Not merely "some bullet is filled in": the
shipped template ships one prose default (`- **Required Tests**: …`) that is
never migrated, and counting it made every fresh clone read as a v1.0 project.
Do not hand-migrate. Run the converter, which is deterministic and covered by
the framework's own test suite:
```bash
bash .claude/scripts/migrate-v1-config.sh --dry-run
```
Report what it lists. If the user approves, run it without `--dry-run`. It
writes `project.yaml` plus `production/migration-report.md` and **deletes
nothing** — the whole operation stays reversible with `git checkout`.
Then tell the user to read `production/migration-report.md` before running:
```bash
bash .claude/scripts/migrate-v1-config.sh --finalize
```
`--finalize` deletes a legacy file only after proving its value is present in
`project.yaml`; on mismatch it deletes nothing and exits 4. It never deletes
`technical-preferences.md`, which still holds Forbidden Patterns and Allowed
Libraries.
**If the script refuses with exit 3**, do not work around it. Exit 3 means one
of two things, and the message says which:
- **the values DISAGREE** — two sources of truth and no way to know which the
user edited last. Surface it and let them decide.
- **a `production/migration-report.md` is already present** — a migration ran
here, so these are post-migration leftovers and `--finalize` is the next step,
not a second `migrate`.
Both files merely *existing* is not exit 3 and must not be reported as a
conflict: `/start` writes `production/stage.txt` on every new v1.1 project as a
mirror, so agreement is the normal state. The script says
`the legacy files mirror it (values agree)` and exits 0 for that.
Classify as **BLOCKING** in Phase 3: until migration runs, every skill reads
config through the legacy fallback chain, and v1.1 settings are unavailable.
---
@@ -226,7 +323,7 @@ For each affected GDD, list which sections are missing and the fix:
2. Run `/architecture-review` → bootstraps `tr-registry.yaml`
3. Run `/create-control-manifest` → creates manifest with version stamp
4. Run `/sprint-plan update` → creates `sprint-status.yaml`
5. Run `/gate-check [phase]` → writes `stage.txt` authoritatively
5. Run `/gate-check [phase]` → writes `project.stage` in `project.yaml` (and legacy `stage.txt`) authoritatively
**Existing stories** — note explicitly:
> "Existing stories continue to work with all template skills — all new format
@@ -330,7 +427,7 @@ Run `/sprint-plan update`
### 3d. Set authoritative project stage
Run `/gate-check [current-phase]`
**Time**: 5 min
- [ ] production/stage.txt written
- [ ] `project.stage` in `project.yaml` written (legacy `production/stage.txt` also updated)
---
@@ -365,12 +462,13 @@ are resolved. The new run will reflect the current state of the project.
## Phase 6b: Set Review Mode
After writing the adoption plan (or if the user cancels writing), check whether
`production/review-mode.txt` exists.
After writing the adoption plan (or if the user cancels writing), check whether a
review mode is already set — read `modes.review_mode` from `project.yaml` first,
then legacy `production/review-mode.txt`.
**If it exists**: Read it and note the current mode — "Review mode is already set to `[current]`." — skip the prompt.
**If a mode is already set**: Note the current mode — "Review mode is already set to `[current]`." — skip the prompt.
**If it does not exist**: Use `AskUserQuestion`:
**If no mode is set**: Use `AskUserQuestion`:
- **Prompt**: "One more setup step: how much design review would you like as you work through the workflow?"
- **Options**:
@@ -378,10 +476,15 @@ After writing the adoption plan (or if the user cancels writing), check whether
- `Lean (recommended)` — Directors only at phase gate transitions (/gate-check). Skips per-skill reviews. Balanced for solo devs and small teams.
- `Solo` — No director reviews at all. Maximum speed. Best for game jams, prototypes, or if reviews feel like overhead.
Write the choice to `production/review-mode.txt` immediately after selection — no separate "May I write?" needed:
- `Full` → write `full`
- `Lean (recommended)` → write `lean`
- `Solo` → write `solo`
Write the choice immediately after selection — no separate "May I write?" needed.
Dual-write:
1. Set `modes.review_mode` in `project.yaml` (primary; add the `modes:` block if absent).
2. Also write the single word to `production/review-mode.txt` (legacy fallback).
Value mapping:
- `Full` → `full`
- `Lean (recommended)` → `lean`
- `Solo` → `solo`
Create the `production/` directory if it does not exist.
@@ -433,6 +536,10 @@ Use `AskUserQuestion`:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Read silently** — complete the full audit before presenting anything
2. **Show the summary first** — let the user see scope before asking to write
3. **Ask before writing** — always confirm before creating the adoption plan file
@@ -0,0 +1,94 @@
# /architecture-decision — Handoff Contract
## Role in Pipeline
Authors a new Architecture Decision Record (ADR) by guiding a collaborative design session, cross-referencing the engine reference library and existing architectural stances, and writing a fully-structured ADR file to `docs/architecture/` — which then unblocks stories and epics that depend on the decision.
Two checks inside the run emit `NOT ASSESSED` rather than passing silently, and
a reader of the resulting ADR should expect them: **engine validation** when no
engine is configured (`engine.name` unset and no legacy fallback), and **GDD
sync** when the referenced design docs cannot be read. A skipped check that says
nothing is indistinguishable from a check that passed.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `docs/engine-reference/[engine]/VERSION.md` | Engine name + version, LLM knowledge cutoff date, post-cutoff risk levels per domain | Yes |
| `docs/engine-reference/[engine]/modules/[domain].md` | Domain-specific API reference (read if exists for the decision's domain) | Yes |
| `docs/engine-reference/[engine]/breaking-changes.md` | Post-cutoff breaking changes in the relevant domain | Yes |
| `docs/engine-reference/[engine]/deprecated-apis.md` | APIs that must not be referenced in the new ADR | Yes |
| `docs/registry/architecture.yaml` | All existing architectural stances (state ownership, interface contracts, forbidden patterns, performance budgets) — checked for conflicts before the design begins | Yes |
| `docs/architecture/` (existing ADRs) | Scanned to determine the next sequential ADR number | Yes |
| `design/gdd/[system].md` (GDDs relevant to the decision) | Specific rules, formulas, performance constraints, or integration points that motivate the decision | Yes |
| `project.yaml` | `engine.name` — derives the primary specialist (`<engine>-specialist`) to spawn for validation (Step 4.5) | Yes |
| `.claude/docs/technical-preferences.md` | `Engine Specialists` section — legacy fallback, used only when `engine.name` is absent or empty in `project.yaml` | Yes — required only when `engine.name` is absent |
### Preconditions
- An engine must be configured (`docs/engine-reference/[engine]/VERSION.md` must exist) — if not, the skill prompts to run `/setup-engine` first
- The title or subject of the decision must be provided by the user before Step 0 proceeds (if no argument is given, the skill asks)
- If in **retrofit mode** (`retrofit [path]` argument), the target ADR file must already exist on disk
- Any conflict with a registered architectural stance in `docs/registry/architecture.yaml` must be resolved or explicitly accepted as an exception before the ADR is drafted (Step 2a is a BLOCKING gate)
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `docs/architecture/adr-NNNN-[slug].md` | `## Status`, `## Date`, `## Engine Compatibility` (table with engine, domain, knowledge risk, post-cutoff APIs, verification required), `## ADR Dependencies` (table with depends-on, enables, blocks, ordering note), `## Context` (problem statement, constraints, requirements), `## Decision` (+ architecture diagram + key interfaces), `## Alternatives Considered`, `## Consequences` (positive, negative, risks), `## GDD Requirements Addressed` (table), `## Performance Implications`, `## Migration Plan`, `## Validation Criteria`, `## Related Decisions` | created after user approves ("May I write this ADR to docs/architecture/adr-NNNN-[slug].md?") |
| `docs/registry/architecture.yaml` | New stance entries (state ownership, interface contracts, performance budgets, forbidden patterns) derived from the ADR; existing entries marked `status: superseded_by` if overridden | appended after separate user approval ("May I update docs/registry/architecture.yaml with these N new stances?") |
### Output Guarantees
- The ADR number is the next sequential integer after the highest existing `adr-NNNN-*` filename in `docs/architecture/`
- `## Status` is always present and set to `Proposed` unless the user explicitly confirms `Accepted` during the session
- `## Engine Compatibility` is always populated using verified data from the engine reference docs — never from training data alone when the domain carries MEDIUM or HIGH risk
- `## GDD Requirements Addressed` is always present (if no GDD motivated the decision, it documents which GDDs the decision will constrain or enable)
- `## ADR Dependencies` is always present (fields set to "None" if no ordering constraints exist)
- Engine specialist validation (Step 4.5) runs before the file is written if an engine specialist is configured; blocking issues found by the specialist cause the Decision section to be revised before saving
## Immutability Rules
- READS but does NOT modify: all existing ADR files in `docs/architecture/` (including in retrofit mode — existing sections are never touched), all GDD files in `design/gdd/`, `docs/engine-reference/**`, `project.yaml`, `.claude/docs/technical-preferences.md` (legacy fallback)
- MODIFIES: `docs/architecture/adr-NNNN-[slug].md` (new file created; or missing sections appended in retrofit mode), `docs/registry/architecture.yaml` (append only; existing entries get `status: superseded_by` annotation, never deleted or rewritten)
- In retrofit mode: appends only the missing sections — never modifies any section that is already present in the target ADR file
## Hard Constraints (Never Violate)
- Never sets `Status: Accepted` without explicit user confirmation — the default on creation is always `Status: Proposed`
- **Acceptance route: `/architecture-decision accept ADR-NNNN`** — the only path that sets `Accepted`. It refuses when a dependency is still Proposed, and prompts for confirmation regardless of `modes.automation`. Without this route acceptance would be enforced by ten skills, owned per the authority below, and reachable by nobody.
- **Acceptance authority: the user, or `technical-director` on the user's explicit confirmation — no other agent, and not this skill on its own.** Recorded here because every consumer enforces the consequences of acceptance, and without this line nothing would say who can produce it. This narrows *who* may set the field; it does not relax the confirmation rule above.
- Never assigns an ADR number that is already in use — always scan `docs/architecture/` first and use the next sequential number
- Never proceeds past the architectural stance conflict check (Step 2a) if a conflict exists — surface the conflict and require resolution or explicit exception acknowledgment before drafting
- Never references APIs listed in `docs/engine-reference/[engine]/deprecated-apis.md` in the Decision or Key Interfaces sections
- Never writes the ADR file without asking: "May I write this ADR to docs/architecture/adr-NNNN-[slug].md?"
- Never writes to `docs/registry/architecture.yaml` without a separate ask: "May I update docs/registry/architecture.yaml with these N new stances?"
- In retrofit mode: never modifies any existing section — only appends absent sections
## Downstream Skill Expects
**Next skills:** `/create-epics`, `/create-stories`, `/dev-story`, `/architecture-review`
### `/create-epics` reads ADRs expecting:
- `## Status` field — value must be `Accepted` for epics to reference it
- `## GDD Requirements Addressed` table — used to link epics to GDD traceability
- `## Engine Compatibility` section — checked during the Technical Setup → Pre-Production gate
### `/create-stories` reads ADRs expecting:
- `## Implementation Guidelines` section — provides the concrete patterns programmer agents must follow (note: this section is generated during `/create-stories`, not by `/architecture-decision` itself; the ADR must have a Decision section detailed enough to derive these guidelines)
- `## ADR Dependencies` table — stories referencing a `Depends On` ADR that is still `Proposed` are automatically set `Status: Blocked`
### `/dev-story` reads ADRs expecting:
- `## Decision` (full text, verbatim — not summarized)
- `## Implementation Guidelines` (verbatim)
- `## Engine Compatibility` (post-cutoff API risks, verification required)
- `## ADR Dependencies` (to detect if this ADR's dependencies are unresolved)
### `/architecture-review` reads ADRs expecting:
- All required sections present (it flags gaps)
- `## Status` is set (required for coverage matrix)
- `## Engine Compatibility` is stamped with the correct engine version
## Known Fragile Points
- If the ADR number scan misses a file (e.g., a file in a subdirectory of `docs/architecture/` or with a non-standard naming pattern), a duplicate number can be assigned — all ADR files must follow the `adr-NNNN-[slug].md` naming convention at the top level of `docs/architecture/`
- Stories that were `Status: Blocked` pending this ADR must be manually updated to `Status: Ready` after the ADR reaches `Accepted` — the skill surfaces a reminder but does not automatically update story files
- The `## GDD Requirements Addressed` table is populated based on what the user tells the skill during the collaborative session; if the user does not know which GDDs motivated the decision, this table may be incomplete — `/create-epics` and `/gate-check` both rely on this linkage for traceability
- Engine specialist validation (Step 4.5) is skipped only when **both** sources are unset — `engine.name` absent or empty in `project.yaml` **and** `.claude/docs/technical-preferences.md` still reading `[TO BE CONFIGURED]`. A project configured solely via `project.yaml` **does** get specialist validation. When both are unset, post-cutoff engine API risks are not caught before the ADR is written
- `docs/registry/architecture.yaml` is append-only by design; if a stance entry becomes permanently invalid (not superseded by another ADR), it must be manually removed — there is no cleanup mechanism
- In retrofit mode, if the existing ADR has sections present but empty (e.g., a `## Status` heading with no value), the skill treats the section as present and does not fill it — an empty Status is effectively invisible to downstream skills like `/story-readiness`
+203 -23
View File
@@ -1,22 +1,50 @@
---
name: architecture-decision
description: "Creates an Architecture Decision Record (ADR) documenting a significant technical decision, its context, alternatives considered, and consequences. Every major technical choice should have an ADR."
argument-hint: "[title] [--review full|lean|solo]"
description: "Create an ADR documenting a technical decision: context, alternatives considered, consequences."
argument-hint: "[title | retrofit <path> | accept <ADR-id>] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density,team.size`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
When this skill is invoked:
## 0. Parse Arguments — Detect Retrofit Mode
## 0. Parse Arguments — Detect Retrofit / Acceptance Mode
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`team.size`**: which agents validate this ADR (orthogonal to review_mode/workflow).
- **`individual`** (default): `technical-director` + `lead-programmer` + the engine-specialist.
- **`small`**: + an engine sub-specialist where applicable.
- **`studio`**: + an adversarial review by an alternate engine-specialist.
Any non-core agent needed at `individual` routes through the nearest active core agent with a note.
**`docs.density`** — it controls the *depth* of the ADR's prose sections, not
which sections the skeleton emits (that is fixed). `modes.rigor` sets it
alongside `workflow`; set `docs.density` explicitly to vary ADR verbosity alone:
`terse` = decision + alternatives as bullets, one line of rationale each;
`balanced` = paragraph per section with light rationale (default); `thorough` =
full prose with trade-offs and worked rationale in Decision, Alternatives, and
Consequences. Apply it to the prose sections; the Engine Compatibility, ADR
Dependencies, and GDD Requirements tables are structural and stay whole at every
density.
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — all ADRs on the required ADR list must be completed.
- `standard` — critical ADRs only (Foundation-layer systems).
- `minimal` — not required. Can still be run voluntarily.
**If the argument starts with `retrofit` followed by a file path**
(e.g., `/architecture-decision retrofit docs/architecture/adr-0001-event-system.md`):
@@ -59,7 +87,74 @@ Enter **retrofit mode**:
7. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
has its Status and Dependencies fields."
If NOT in retrofit mode, proceed to Step 1 below (normal ADR authoring).
**If the argument starts with `accept` followed by an ADR id**
(e.g., `/architecture-decision accept ADR-0005`):
Enter **acceptance mode**. This is the *only* path in the framework that moves an
ADR from `Proposed` to `Accepted`. Authoring always produces `Proposed`
(Step 5), while
`/create-control-manifest`, `/create-epics`, `/create-stories` and `/gate-check`
all require `Accepted` — so without this mode the pipeline had a state it could
enter and never leave.
1. **Resolve the id to a file, then read it.** Glob
`docs/architecture/adr-NNNN-*.md` for the given number. If **no** file matches,
or **more than one** does, stop and say which — do not pick one. If the file
has no `## Status` section, stop and say so; a missing Status is exactly what
retrofit mode is for.
2. **Check the current status.** If it is already `Accepted`, say so and stop.
If it is `Deprecated` or `Superseded`, refuse: reviving a superseded decision
is a new ADR, not a status edit.
3. **Check its dependencies first.** Read `## ADR Dependencies`.
**If that section is absent, empty, or reads `UNKNOWN`, do not read it as
"no dependencies" — refuse and say which:**
> "ADR-0005's dependency section is [absent / UNKNOWN], so I cannot tell what
> this decision rests on. An empty dependency list and an unexamined one look
> identical here, and only one of them is safe to accept. Run
> `/architecture-decision retrofit <path>` to establish it."
A dependency check reading a field that defaults to empty is the vacuous-pass
shape this gate exists to prevent — the check would examine nothing and report
clean.
If it depends on any ADR that is not itself `Accepted`, **refuse and name them**:
> "ADR-0005 depends on ADR-0002, which is still Proposed. Accept ADR-0002
> first — an accepted decision resting on an unaccepted one is not a decision,
> it is a deferral with a different label."
This is the same dependency rule `/architecture-review` already flags; here it
is enforced rather than reported.
4. **Confirm with the user, always.** Per `CONTRACT.md`, acceptance authority is
**the user, or `technical-director` on the user's explicit confirmation — no
other agent, and never this skill on its own.** Use `AskUserQuestion`:
- Prompt: "Accept ADR-NNNN — [title]? This is what unblocks stories and epics
that depend on it."
- Options: `[A] Yes — accept it` / `[B] Not yet — leave it Proposed`
**This prompt fires regardless of `modes.automation`, including `autonomous`.**
Acceptance is the decision the whole architecture pipeline gates on; it is not
a step to be inferred.
5. **Find the stories this will unblock, BEFORE the prompt in step 4.** Grep
`production/epics/[epic-slug]/story-*.md` — the one place stories live — for
files containing **both** `Status: Blocked` and this ADR's id.
> **Stories live only under `production/epics/`.** A flat top-level stories
> directory does not exist and no skill creates one — never write or match a
> path outside `production/epics/`. `/dev-story` matches entries *by file
> path*, so a story recorded under any other path silently fails to match and
> never gets picked up. That pairing is what "blocked pending this
ADR" means — a story blocked for an unrelated reason will not name it. Feed the
count into step 4's prompt so it reads *"3 stories become Ready"* rather than a
generic claim: **the user is being asked to authorise an effect, and should be
shown the effect.** If none match, say "no stories are waiting on this" — that
is useful information, not an empty result to omit.
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Set the date in the
ADR's `## Date` section; **if that section is absent, add it** — retrofit mode
already owns this shape, and acceptance must not fail on a template that
predates the field.
7. Then set each story found in step 5 from `Blocked` to `Ready`. Unblocking is a
consequence of acceptance, never of authoring — see Step 6's note below.
8. Report what moved: the ADR, its new date, and every story that became Ready.
If NOT in retrofit or acceptance mode, proceed to Step 1 below (normal ADR authoring).
**No-argument guard**: If no argument was provided (title is empty), ask before
running Phase 0:
@@ -123,12 +218,13 @@ Scan `docs/architecture/` for existing ADRs to find the next number.
## 3. Gather context
Read related code, existing ADRs, and relevant GDDs from `design/gdd/`.
### 3a: Architecture Registry Check (BLOCKING gate)
### 3a: Architecture Registry Check (BLOCKING gate) — do this FIRST
Read `docs/registry/architecture.yaml`. Extract entries relevant to this ADR's
domain and decision (grep by system name, domain keyword, or state being touched).
Run this before reading any existing ADR — the registry exists specifically so a
new ADR's author does not need to open prior ADRs to learn their binding facts
(state ownership, interface contracts, forbidden patterns).
Present any relevant stances to the user **before** the collaborative design
begins, as locked constraints:
@@ -164,6 +260,34 @@ the conflict immediately:
Do not proceed to Step 4 (collaborative design) until any conflict is resolved
or explicitly accepted as an intentional exception.
### 3b: Existing ADRs and Related GDDs — registry-scoped, never unbounded
The registry (3a) covers *what* prior decisions bind — not always *why*. If the
registry surfaced a directly relevant ADR and its reasoning matters here (not
just its stated facts), read that specific ADR — never glob-and-read every
ADR in `docs/architecture/` on the chance one is relevant:
1. **Map its headings first** (cheap):
```
Grep pattern="^## " path="docs/architecture/[adr-file].md" output_mode="content" -n
```
2. **Under ~50KB** (`Bash: wc -c "docs/architecture/[adr-file].md"`) — one full
`Read` is fine; per-call overhead exceeds the savings from bounded reads at
this size (measured elsewhere in this project).
3. **~50KB or larger** — bounded-read only `## Context`, `## Decision`, and
`## Consequences` (the sections that carry reasoning, not just facts) via
`Read(offset, limit)` from the heading map.
Read GDDs the same way `/design-system` Step 2b does: only GDDs the registry
or the ADR list names as directly relevant, and only their `## Dependencies`,
`## Formulas`, and `## Edge Cases` sections
(`Grep pattern="^## (Dependencies|Formulas|Edge Cases)" ... -A 40`) — never a
speculative full read of `design/gdd/*.md` looking for anything that might
relate.
Skip 3b entirely if the registry already answers everything this decision
needs — most ADRs will.
---
## 4. Guide the decision collaboratively
@@ -175,7 +299,16 @@ a **confirm/adjust** prompt using `AskUserQuestion` — not open-ended questions
**Derive assumptions first:**
- **Problem**: Infer from the title + GDD context what decision needs to be made
- **Alternatives**: Propose 2-3 concrete options from engine reference + GDD requirements
- **Dependencies**: Scan existing ADRs for upstream dependencies; assume None if unclear
- **Dependencies**: Scan existing ADRs for upstream dependencies. **If the scan is
inconclusive, present `UNKNOWN — scan inconclusive, please confirm`, never
`None`.** The two are not interchangeable: `None` asserts that nothing upstream
constrains this decision, and a user confirming a prefilled list cannot tell an
assertion from a guess. This field is load-bearing — `/architecture-review`
flags unaccepted dependencies, `/dev-story` reads it, and the acceptance route
in Phase 0 **refuses to accept an ADR whose dependencies are not themselves
Accepted**. A dependency list that defaulted to empty makes that check pass
while examining nothing. `UNKNOWN` must be resolved during the confirm/adjust
prompt; it is a prompt state, never a value written to the file
- **GDD linkage**: Extract which GDD systems the title directly relates to
- **Status**: Always `Proposed` for new ADRs — never ask the user what the status is
@@ -239,6 +372,20 @@ Following this format:
## Date
[Date of decision]
## Last Verified
[YYYY-MM-DD — when this ADR was last confirmed accurate against the current
engine version and design. Update this date when you re-read and confirm it is
still correct, even if nothing changed.]
## Decision Makers
[Who was involved in this decision]
## Summary
[2 sentences: what problem this ADR solves, and what was decided. Written for
tiered context loading — a skill scanning 20 ADRs uses this to decide whether to
read the full decision. Be specific: name the system, the problem, and the
chosen approach.]
## Engine Compatibility
| Field | Value |
@@ -286,6 +433,11 @@ to implement it.]
### Key Interfaces
[API contracts or interface definitions this decision creates]
### Implementation Guidelines
[Specific guidance for the programmer implementing this decision — the rules a
`/create-control-manifest` or `/dev-story` run should follow. State mandates as
"must / must never" so they extract cleanly.]
## Alternatives Considered
### Alternative 1: [Name]
@@ -308,7 +460,7 @@ to implement it.]
### Negative
- [Trade-offs and costs accepted]
### Risks
## Risks
- [Things that could go wrong]
- [Mitigation for each risk]
@@ -330,14 +482,14 @@ to implement it.]
## Validation Criteria
[How will we know this decision was correct? What metrics or tests?]
## Related Decisions
- [Links to related ADRs]
## Related
- [Links to related ADRs — note if supersedes, contradicts, or depends on]
- [Links to related design documents]
```
5.5. **Engine Specialist Validation** — Before saving, spawn the **primary engine specialist** via Task to validate the drafted ADR:
- Read `.claude/docs/technical-preferences.md` `Engine Specialists` section to get the primary specialist
- If no engine is configured (`[TO BE CONFIGURED]`), skip this step
5.5. **Engine Specialist Validation** — Before saving, spawn the **primary engine specialist** via `Agent` to validate the drafted ADR:
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
- If no engine is configured (neither source yields an engine), skip this step **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
- Spawn `subagent_type: [primary specialist]` with: the ADR's Engine Compatibility section, Decision section, Key Interfaces, and the engine reference docs path. Ask them to:
1. Confirm the proposed approach is idiomatic for the pinned engine version
2. Flag any APIs or patterns that are deprecated or changed post-training-cutoff
@@ -350,7 +502,7 @@ to implement it.]
- `lean` → skip (not a PHASE-GATE). Note: "TD-ADR skipped — Lean mode." Proceed to Step 5.7 (GDD sync check).
- `full` → spawn as normal.
5.6. **Technical Director Strategic Review** — After the engine specialist validation, spawn `technical-director` via Task using gate **TD-ADR** (`.claude/docs/director-gates.md`):
5.6. **Technical Director Strategic Review** — After the engine specialist validation, spawn `technical-director` via `Agent` using gate **TD-ADR** (`.claude/docs/director-gates/td-adr.md`):
- Pass: the ADR file path (or draft content), engine version, domain, any existing ADRs in the same domain
- The TD validates architectural coherence (is this decision consistent with the whole system?) — distinct from the engine specialist's API-level check
- If CONCERNS or REJECT: revise the Decision or Alternatives sections accordingly before proceeding
@@ -370,7 +522,21 @@ The GDD must be updated before or alongside writing this ADR to prevent
developers reading the GDD from implementing the wrong interface.
```
If no inconsistencies: skip this block silently.
**This check has three outcomes, not two.** The two above are "found" and "none
found"; the third is **could not check**, and until now it fell through the
silent branch and rendered exactly like a clean result.
- **None found** — print one line, do not stay silent:
`GDD sync: checked [N] referenced GDD(s), no naming inconsistencies.`
A silent pass is indistinguishable from a check that never ran, and this one
guards against developers implementing the wrong interface from a stale GDD.
- **Could not check** — the ADR has no `GDD Requirements Addressed` section, it
names no GDDs, or a named GDD does not exist on disk. Print:
`GDD sync: NOT ASSESSED — [which reason, and which files]`
Do **not** treat an ADR that references no GDDs as one whose GDDs are
consistent. Nothing was compared.
Only the warning block itself is conditional; the check always reports.
5. **Write approval** — Use `AskUserQuestion`:
@@ -453,4 +619,18 @@ If there are no remaining priority ADRs and no undesigned GDD systems, offer onl
> The reviewing agent must be independent of the authoring context to give an unbiased
> assessment. Running it here would invalidate the review.
Update any stories that were `Status: Blocked` pending this ADR to `Status: Ready`.
**Do NOT unblock stories here.** This ADR is `Proposed` — Step 5 guarantees it,
and a story blocked *pending this decision* is still pending it. Unblocking on
authoring is how the deadlock stayed invisible: it defeated the guard at the
moment the guard became relevant, so the pipeline appeared to flow while running
on decisions nobody had accepted.
Instead, tell the user what is now waiting on acceptance:
> "ADR-NNNN is written and `Proposed`. [N] stories remain `Blocked` pending it.
> Run `/architecture-decision accept ADR-NNNN` when the decision is settled —
> that is what moves them to `Ready`."
List the blocked stories by path so the cost of leaving it Proposed is visible.
(Acceptance has consequences enforced across many skills and an authority
recorded in only a few, so the route between them must stay explicit.)
+232 -44
View File
@@ -1,13 +1,16 @@
---
name: architecture-review
description: "Validates completeness and consistency of the project architecture against all GDDs. Builds a traceability matrix mapping every GDD technical requirement to ADRs, identifies coverage gaps, detects cross-ADR conflicts, verifies engine compatibility consistency across all decisions, and produces a PASS/CONCERNS/FAIL verdict. The architecture equivalent of /design-review."
description: "Traceability matrix mapping GDD requirements to ADRs. Finds gaps, cross-ADR conflicts, engine compatibility. PASS/CONCERNS/NOT ASSESSED/FAIL."
argument-hint: "[focus: full | coverage | consistency | engine | single-gdd path/to/gdd.md]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
agent: technical-director
allowed-tools: Read, Glob, Grep, Bash, Write, Agent, AskUserQuestion
model: opus
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow`
# Architecture Review
The architecture review validates that the complete body of architectural decisions
@@ -29,10 +32,48 @@ and Pre-Production.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — full traceability matrix across all GDDs and all ADRs.
- `standard` — reduced scope: architecture doc + critical ADRs only.
- `minimal` — not applicable (no architecture doc required).
## Phase 1: Load Everything
### Phase 1a — L0: Summary Scan (fast, low tokens)
**Freshness check before any scan.** Locate the latest prior report — Glob
`docs/architecture/architecture-review-*.md` and take the newest — then:
```
Bash: bash .claude/scripts/review-receipts.sh check "[latest-report]" docs/architecture/adr-*.md design/gdd/*.md
```
- **Any `UNRESOLVED`** — check this FIRST; it disqualifies every option
below. One of the two globs matched no file, so that whole document class
was never examined and the comparison covered less than it appears to.
Say which pattern came back unresolved and stop: an ADR or GDD directory
that is empty, renamed or misspelled is a finding about the project, not a
reason to stand on a prior report. Never read a set of `UNCHANGED` lines as
"everything is current" while an `UNRESOLVED` line is present — the set
compared was not the set requested.
- **Everything `UNCHANGED`** (and no `UNRESOLVED`) — nothing this review
reads has changed since that report; re-running reproduces it. Surface the
prior report's date and verdict and offer via `AskUserQuestion`: `[A] Stand
on the prior report (Recommended)` / `[B] Re-run the full review anyway` —
`guided` proceeds with [A] and notes it; `autonomous` logs via
`log_decision` and stands on the prior report.
- **Some `CHANGED`/`NEW`** — name them, then scope instead of re-running
everything: recommend `/architecture-review [system]` (single-system mode)
for just the changed systems. A full re-run stays available on request,
and structural changes (a `NEW` ADR, a deleted file) warrant one.
- **`RECEIPT: NONE`** — no prior report, or one written before receipts
existed. Proceed with the full review; this run's report will carry the
first stamps.
Before reading any full document, use Grep to extract `## Summary` sections
from all GDDs and ADRs:
@@ -41,34 +82,92 @@ Grep pattern="## Summary" glob="design/gdd/*.md" output_mode="content" -A 4
Grep pattern="## Summary" glob="docs/architecture/adr-*.md" output_mode="content" -A 3
```
**Fail open on a missing Summary.** Establish the denominator: glob
`design/gdd/*.md` and count **N**. A scan matching fewer than N means those GDDs
predate `## Summary` (`/design-system` emits it, but older GDDs lack it) — never
treat an absent Summary as a system out of scope. A zero-match scan means "no GDD
carries a Summary yet", not "nothing to review": full-read the unmatched set.
For `single-gdd [path]` mode: use the target GDD's summary to identify which
ADRs reference the same system (Grep ADRs for the system name), then full-read
only those ADRs. Skip full-reading unrelated GDDs entirely.
ADRs reference the same system (Grep ADRs for the system name), then load only
those ADRs' sections per Phase 1b. Skip unrelated GDDs entirely.
For `engine` mode: only full-read ADRs — GDDs are not needed for engine checks.
For `engine` mode: load ADR sections only — GDDs are not needed for engine checks.
In practice this is the `## Engine Compatibility` scan alone.
For `coverage` or `full` mode: proceed to full-read everything below.
For `coverage` or `full` mode: proceed to Phase 1b for the full in-scope set.
**This is a section load, not a full-file load** — see below for why, and for the
narrow cases that still justify escalating to a whole document.
### Phase 1b — L1/L2: Full Document Load
### Phase 1b — L1/L2: Targeted Section Load
Read all inputs appropriate to the mode:
Load the sections the later phases actually consume — **not whole files**. This
skill reads the two largest document sets in the project (every GDD *and* every
ADR); at realistic sizes a full load of both exhausts the context window before
Phase 2 starts, and most of what it loads is narrative this skill never uses.
**Establish the denominator first.** Glob `design/gdd/*.md` and count **N_gdd**;
glob `docs/architecture/adr-*.md` and count **N_adr**. Report both. A section
scan matching fewer than the denominator means those documents lack the section —
**never treat an absent section as an absent document.** The scan narrows the
*read* set; it never shrinks the *in-scope* set.
### Design Documents
- All in-scope GDDs in `design/gdd/` — read every file completely
- `design/gdd/systems-index.md` — the authoritative list of systems
Phase 2 extracts *technical requirements* — data structures, performance
constraints, engine capabilities, cross-system communication, persistence,
threading, platform needs. Those live in a known set of sections; Overview and
Player Fantasy are narrative and yield none.
```
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
```
Accept **either** `## Detailed Rules` or `## Detailed Design` — the design
standard and the GDD template disagree on the name and they denote the same
required section. Full-read a single GDD only when a scanned section
cross-references material outside itself, or when a GDD matched zero sections
(it predates the template — read it whole and say so).
- `design/gdd/systems-index.md` — the authoritative list of systems; read whole (small, and it is an index)
### Architecture Documents
- All in-scope ADRs in `docs/architecture/` — read every file completely
Phases 3–5 need the traceability table, the decision itself, engine claims, and
the dependency edges — not Context, Consequences, Alternatives, Migration Plan or
Validation Criteria, which explain *why* a decision was made.
```
Grep pattern="^## (Status|Decision|GDD Requirements Addressed|Engine Compatibility|ADR Dependencies|Performance Implications)" glob="docs/architecture/adr-*.md" output_mode="content" -A 30
```
Interpret against **N_adr**, and distinguish the two zero-match cases — they are
not the same finding:
| Result | Meaning | Action |
|---|---|---|
| N_adr matches | Normal. | Proceed on the scanned sections. |
| Some ADRs match, some do not | Those ADRs are missing sections. | Record each as a **structural gap** in the Phase 7 report — a missing `## GDD Requirements Addressed` is itself a traceability finding. |
| **0 matches, N_adr > 0** | **Malformed ADRs**, not "no architecture". | "[N_adr] ADRs found, none carries a scannable section — run `/architecture-decision [file] retrofit` on each." Do **not** report zero coverage; that would read as a design failure when it is a format failure. |
Escalate to a full read of one ADR only when judging a conflict needs its
reasoning (Phase 4) — that is a per-ADR decision, not a blanket load.
- `docs/architecture/architecture.md` if it exists
### Engine Reference
- `docs/engine-reference/[engine]/VERSION.md`
- `docs/engine-reference/[engine]/breaking-changes.md`
- `docs/engine-reference/[engine]/deprecated-apis.md`
- All files in `docs/engine-reference/[engine]/modules/`
- **Only the module docs the in-scope ADRs actually name** — take the union of
each ADR's `References Consulted` and `Post-Cutoff APIs Used` fields (already
captured by the `## Engine Compatibility` scan above) and read those files.
Reading the whole `modules/` directory loads engine subsystems the project may
not use at all. If no ADR names any module, read none and note it: Phase 5
cannot cross-check engine claims that were never made.
### Project Standards
- `.claude/docs/technical-preferences.md`
- `project.yaml` — `naming.*` and `performance.*`; plus `.claude/docs/technical-preferences.md` for those keys when absent and for forbidden patterns / allowed libraries
Report a count: "Loaded [N] GDDs, [M] ADRs, engine: [name + version]."
@@ -137,16 +236,36 @@ architecture must cover.
For each technical requirement extracted in Phase 2, search the ADRs:
1. Read every ADR's "GDD Requirements Addressed" section
1. Use the ADRs **already loaded in Phase 1b** — do not re-read them. Extract each
ADR's "GDD Requirements Addressed" section from what is already in context.
(If Phase 1b ran in a mode that did not load every ADR, `Grep pattern="## GDD
Requirements Addressed" glob="docs/architecture/adr-*.md" output_mode="content"
-A 15` fills the gap without a full re-read.)
2. Check if it explicitly references the requirement or its GDD
3. Check if the ADR's decision text implicitly covers the requirement
4. Mark coverage status:
| Status | Meaning |
|--------|---------|
| ✅ **Covered** | An ADR explicitly addresses this requirement |
| ✅ **Covered** | An **Accepted** ADR explicitly addresses this requirement |
| 🟡 **Covered (Proposed)** | An ADR addresses it, but that ADR is still `Proposed` |
| ⚠️ **Partial** | An ADR partially covers this, or coverage is ambiguous |
| ❌ **Gap** | No ADR addresses this requirement |
| ❓ **Not assessed** | The ADR is unreadable, or has no `## Status` section |
> **Read each ADR's `## Status` before marking coverage — an unaccepted decision
> is not coverage.** If `✅` meant only that *an ADR addresses this*, with no
> status qualification, a requirement covered entirely by `Proposed` ADRs would
> count as covered and this review could return **PASS: All requirements
> covered** over an architecture nobody had accepted. Four skills downstream
> (`create-control-manifest`, `create-epics`, `create-stories`, `gate-check`)
> require `Accepted`, so a PASS on that basis sends work forward that every one
> of them will refuse.
>
> `🟡` is **not** a pass state: it caps the verdict at **CONCERNS**, and names the
> route out — `/architecture-decision accept ADR-NNNN`. That route is the only
> thing that moves an ADR to `Accepted`; without it, grading `Proposed` as
> covered would be the only option, which is why it must never be graded so.
Build the full matrix:
@@ -174,11 +293,22 @@ Requirements Traceability Matrix (RTM).
### Step 3b-1 — Load stories
Glob `production/epics/**/*.md` (excluding EPIC.md index files). For each
story file:
- Extract `TR-ID` from the story's Context section
- Extract story file path, title, Status
- Extract `## Test Evidence` section — the stated test file path
Glob `production/epics/**/*.md` (excluding EPIC.md index files) to establish the
denominator. Then collect the fields with **targeted section greps, not a full
read of each story** — the same two-grep form `/test-evidence-review` uses for
this identical extraction:
```
Grep pattern="## Test Evidence" glob="production/epics/**/story-*.md" output_mode="content" -A 8
Grep pattern="TR-" glob="production/epics/**/story-*.md" output_mode="content"
```
- **TR-ID** — from the second grep.
- **Test file path** — under `## Test Evidence`, captured by the first grep's `-A 8`.
- **Status** — from the story header; add `Grep pattern="^> \*\*Status\*\*"` if not already captured.
- **Story path and title** — from the file name and path; no read at all.
Full-read a story only when its Test Evidence section is missing or ambiguous.
### Step 3b-2 — Load test files
@@ -250,24 +380,41 @@ Resolution options:
### ADR Dependency Ordering
After conflict detection, analyse the dependency graph across all ADRs:
After conflict detection, analyse the dependency graph across all ADRs.
1. **Collect all `Depends On` fields** from every ADR's "ADR Dependencies" section
2. **Topological sort**: Determine the correct implementation order — ADRs with no
**Build the graph deterministically — do not trace it by hand:**
```
Bash: bash .claude/scripts/adr-dep-graph.sh
```
It collects every `Depends On` edge, runs Kahn's algorithm, and emits
`ADRS:` / `EDGES:` / `NO_DEPS_SECTION:` / `CYCLE:`. A model tracing A→B→C→A across
a dozen ADRs eventually misses an edge; the algorithm cannot. It reports
observations, not a verdict — you apply the meaning below.
**`NO_DEPS_SECTION` is load-bearing**: it makes "no cycles because the graph is
clean" distinguishable from "no cycles because half the ADRs declare no
dependencies". Report the second case as a structural gap, never as a clean graph.
Then interpret:
1. **Topological sort**: the emitted order — ADRs with no
dependencies come first (Foundation), ADRs that depend on those come next, etc.
3. **Flag unresolved dependencies**: If ADR-A's "Depends On" field references an ADR
that is still `Proposed` or does not exist, flag it:
2. **Flag unresolved dependencies**: cross the `EDGES:` list against the `## Status`
values already scanned in Phase 1b. If ADR-A depends on an ADR that is still
`Proposed` or does not exist, flag it:
```
⚠️ ADR-0005 depends on ADR-0002 — but ADR-0002 is still Proposed.
ADR-0005 cannot be safely implemented until ADR-0002 is Accepted.
```
4. **Cycle detection**: If ADR-A depends on ADR-B and ADR-B depends on ADR-A (directly
or transitively), flag it as a `DEPENDENCY CYCLE`:
3. **Cycle detection**: every `CYCLE:` line the script emitted is a
`DEPENDENCY CYCLE` — report each one. Do not re-derive them by hand:
```
🔴 DEPENDENCY CYCLE: ADR-0003 → ADR-0006 → ADR-0003
This cycle must be broken before either can be implemented.
```
5. **Output recommended implementation order**:
4. **Output recommended implementation order**:
```
### Recommended ADR Implementation Order (topologically sorted)
Foundation (no dependencies):
@@ -323,9 +470,9 @@ Post-Cutoff API Conflicts:
### Engine Specialist Consultation
After completing the engine audit above, spawn the **primary engine specialist** via Task for a domain-expert second opinion:
- Read `.claude/docs/technical-preferences.md` `Engine Specialists` section to get the primary specialist
- If no engine is configured, skip this consultation
After completing the engine audit above, spawn the **primary engine specialist** via `Agent` for a domain-expert second opinion:
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
- If no engine is configured (neither source yields an engine), skip this consultation **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
- Spawn `subagent_type: [primary specialist]` with: all ADRs that contain engine-specific decisions or `Post-Cutoff APIs Used` fields, the engine reference docs, and the Phase 5 audit findings. Ask them to:
1. Confirm or challenge each audit finding — specialists may know of engine nuances not captured in the reference docs
2. Identify engine-specific anti-patterns in the ADRs that the audit may have missed (e.g., using the wrong Godot node type, Unity component coupling, Unreal subsystem misuse)
@@ -385,7 +532,16 @@ If [B]: display the complete proposed systems-index section, then re-ask with `A
## Phase 6: Architecture Document Coverage
If `docs/architecture/architecture.md` exists, validate it against GDDs:
**If `docs/architecture/architecture.md` does not exist, say so in the report** —
`Architecture document coverage: NOT ASSESSED — no docs/architecture/architecture.md`
— and carry it into the Phase 7 verdict per the trigger list below. Phase 5
already models this for the engine consultation (*"A skipped check that says
nothing is indistinguishable from a check that passed"*); this phase is the one
that did not. Silently producing no Phase 6 findings reads as an architecture
document that was checked and found clean, which is the opposite of what
happened.
If it exists, validate it against GDDs:
- Does every system from `systems-index.md` appear in the architecture layers?
- Does the data flow section cover all cross-system communication defined in GDDs?
@@ -404,6 +560,10 @@ Engine: [name + version]
GDDs Reviewed: [N]
ADRs Reviewed: [M]
[output of: Bash: bash .claude/scripts/review-receipts.sh hash docs/architecture/adr-*.md design/gdd/*.md
— one Reviewed-Content-Hash line per file reviewed; Phase 1a's freshness
check reads these on the next run to skip or scope an unchanged re-review]
---
### Traceability Summary
@@ -438,13 +598,34 @@ For each gap:
---
### Verdict: [PASS / CONCERNS / FAIL]
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
PASS: All requirements covered, no conflicts, engine consistent
CONCERNS: Some gaps or partial coverage, but no blocking conflicts
PASS: All requirements covered by **Accepted** ADRs, no conflicts, engine consistent
NOT ASSESSED: The review could not be performed over its stated scope — name why
CONCERNS: Some gaps, partial coverage, or coverage resting on `Proposed` ADRs,
but no blocking conflicts
FAIL: Critical gaps (Foundation/Core layer requirements uncovered),
or blocking cross-ADR conflicts detected
**`NOT ASSESSED` ranks above PASS and below CONCERNS and FAIL.** Emit it when:
- **No ADRs exist, or none could be read.** Zero requirements traced is not full
coverage — it is an untraced architecture, and a matrix of `❌ Gap` rows at
least says so while an empty matrix says nothing.
- **The requirement source is missing** — no `tr-registry.yaml` and no GDD
requirements to trace *from*. A review with no left-hand column cannot report
coverage; it can only report that it had nothing to compare.
- **An ADR is unreadable or has no `## Status`**, so its rows are `❓` and their
coverage is unknown rather than absent.
- **Phase 6 could not run** — no `docs/architecture/architecture.md`. This does
not by itself force NOT ASSESSED for the whole review (ADR traceability is the
primary scope and can still be complete), but it must appear as a named
`NOT ASSESSED` **line item** in the report rather than as absent findings. Emit
the overall NOT ASSESSED verdict only if Phase 6 was the review's stated scope.
Do not resolve any of these to PASS on the grounds that no gap was *found*. No
gap was looked for.
### Blocking Issues (must resolve before PASS)
[List items that must be resolved — FAIL verdict only]
@@ -634,20 +815,27 @@ Then close with `AskUserQuestion` tailored to the pre-gate checklist state:
## Error Recovery Protocol
If any spawned agent returns BLOCKED, errors, or fails to complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "fails to complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" before continuing
2. **Assess dependencies**: If the blocked agent's output is required by a later phase, do not proceed past that phase without user input
3. **Offer options** via AskUserQuestion with three choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope (fewer GDDs, single-system focus)
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed so work is not lost
If any spawned agent returns BLOCKED, errors, or fails to complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report** (retry scope here = fewer GDDs / single-system). Full procedure:
`.claude/docs/error-recovery-protocol.md`.
---
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Read silently** — do not narrate every file read
2. **Show the matrix** — present the full traceability matrix before asking for
anything; let the user see the state
+126 -25
View File
@@ -1,20 +1,41 @@
---
name: art-bible
description: "Guided, section-by-section Art Bible authoring. Creates the visual identity specification that gates all asset production. Run after /brainstorm is approved and before /map-systems or any GDD authoring begins."
description: "Author the Art Bible — visual identity gating asset production. Run before /map-systems."
argument-hint: "[--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
## Phase 0: Parse Arguments and Context Check
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which sections exist. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = each section a bulleted list of
constraints + references; `balanced` = paragraphs explaining each visual choice
(default); `thorough` = full prose including style explorations, references, and
rationale per choice. Apply it to every section you author.
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — all 9 art bible sections required.
- `standard` — required only if visual asset stories exist in the project;
sections 1–4 are the minimum when required. `workflow_overrides.art_bible_strict:
true` forces all 9 sections regardless of tier.
- `minimal` — not required. Can still be run voluntarily.
Read `design/gdd/game-concept.md`. If it does not exist, fail with:
> "No game concept found. Run `/brainstorm` first — the art bible is authored after the game concept is approved."
@@ -26,9 +47,24 @@ Extract from game-concept.md:
- **Visual Identity Anchor** section if present (from brainstorm Phase 4 art-director output)
- Target platform (if noted)
**Retrofit mode detection**: Glob `design/art/art-bible.md`. If the file exists:
- Read it in full
- For each of the 9 sections, check whether the body contains real content (more than a `[To be designed]` placeholder or similar) vs. is empty/placeholder
**Retrofit mode detection**: Glob `design/art/art-bible.md`. If the file exists,
build the status table **without reading the document** — you are about to author
only the *incomplete* sections, so loading the complete ones is loading exactly
what you will not touch:
```
Grep pattern="^## " path="design/art/art-bible.md" output_mode="content" -n
Grep pattern="\[To be designed\]|\[TBD\]|\[To be written\]|^_?TODO" path="design/art/art-bible.md" output_mode="content" -n
```
- The first grep gives the section headings and their line numbers — the gap
between consecutive headings is that section's size.
- The second gives placeholder markers and where they fall.
- A section is **Complete** if it has substantive distance to the next heading and
no placeholder marker inside it; **Placeholder** if a marker falls in its range;
**Empty** if consecutive headings sit adjacent.
- Where the two greps leave a section genuinely ambiguous, read *that section's*
line range with `Read(offset, limit)` — never the whole file.
- Build a section status table:
```
@@ -51,7 +87,7 @@ Section | Status
If the file does not exist, this is a fresh authoring session — proceed normally.
Read `.claude/docs/technical-preferences.md` if it exists — extract performance budgets and engine for asset standard constraints.
Extract performance budgets and the engine for asset standard constraints: read `performance.*` and `engine.name` from `project.yaml`; for any key absent or empty (including when `project.yaml` has no `performance` or `engine` block), fall back to `.claude/docs/technical-preferences.md`.
---
@@ -62,6 +98,21 @@ Present the session context and ask two questions before authoring anything:
Use `AskUserQuestion` with two tabs:
- Tab **"Scope"** — "Which sections need to be authored today?"
Options: `Full bible — all 9 sections` / `Visual identity core (sections 1–4 only)` / `Asset standards only (section 8)` / `Resume — fill in missing sections`
**Mark the option the resolved `workflow` tier actually requires as
(Recommended), and say why** — the tier already decides this and the user
should not have to know the tier table to answer:
- `full` → **Full bible** — all 9 sections are required at this tier.
- `standard` → **Visual identity core (sections 1–4 only)** — that is the
documented minimum when an art bible is required at all. Say: "Sections 1–4
are what `standard` requires; 5–9 are available if you want them."
- `minimal` → no art bible is required. Say so before asking, and offer
sections 1–4 as the useful-if-you-want-it option rather than defaulting to 9.
- `workflow_overrides.art_bible_strict: true` → **Full bible** regardless of tier.
This is the single biggest cost lever in this skill: every authored section
carries a specialist spawn, so authoring 9 sections where the tier requires 4
more than doubles the run for artifacts nothing downstream will check.
- Tab **"References"** — "Do you have reference games, films, or art that define the visual direction?"
(Free text — let the user type specific titles. Do NOT preset options here.)
@@ -74,6 +125,21 @@ If the game-concept.md has a Visual Identity Anchor section, note it:
These four sections define the core visual language. **All other sections flow from them.** Author and write each to file before moving to the next.
> **Spawn policy for this phase.** Section 1 is delegated on its own — it is
> foundational and the user chooses between anchor directions before anything
> else can build on it. Sections 2–4 are then delegated in **one** `art-director`
> call, not three: they are the same agent receiving the same inputs (Visual
> Identity Statement + pillars), and mood, shape and colour are interdependent —
> an art director defines them together, not in isolation. Three separate calls
> re-sent the same context three times and asked the agent to reason about
> colour without knowing the shape language it had just written.
>
> **This is not reduced specialist involvement** — every section is still
> authored by the specialist, which is the point `.claude/docs/effects-map.md`
> makes about art-bible delegation being mandatory. It is one call instead of
> three for the same three sections. Per-section user approval and
> write-to-file-immediately are unchanged.
### Section 1: Visual Identity Statement
**Goal**: A one-line visual rule plus 2–3 supporting principles that resolve visual ambiguity.
@@ -83,7 +149,7 @@ If a visual anchor exists from game-concept.md: present it and ask:
- "Revise it before expanding?"
- "Start fresh with new options?"
**Agent delegation (MANDATORY)**: Spawn `art-director` via Task:
**Agent delegation (MANDATORY)**: Spawn `art-director` via `Agent`:
- Provide: game concept (elevator pitch, core fantasy), full pillar set, platform target, any reference games/art from Phase 1 framing, the visual anchor if it exists
- Ask: "Draft a Visual Identity Statement for this game. Provide: (1) a one-line visual rule that could resolve any visual decision ambiguity, (2) 2–3 supporting visual principles, each with a one-sentence design test ('when X is ambiguous, this principle says choose Y'). Anchor all principles directly in the stated pillars — each principle must serve a specific pillar."
@@ -102,9 +168,21 @@ For each major game state (e.g., exploration, combat, victory, defeat, menus —
- Atmospheric descriptors (3–5 adjectives)
- Energy level (frenetic / measured / contemplative / etc.)
**Agent delegation**: Spawn `art-director` via Task with the Visual Identity Statement and pillar set. Ask: "Define mood and atmosphere targets for each major game state in this game. Be specific — 'dark and foreboding' is not enough. Name the exact emotional target, the lighting character (warm/cool, high/low contrast, time of day direction), and at least one visual element that carries the mood. Each game state must feel visually distinct from the others."
**Agent delegation for Sections 2–4 — one call, issued here.** Spawn
`art-director` via `Agent` with the locked Visual Identity Statement and pillar set,
and ask for all three sections in a single brief:
Write the approved section to file immediately.
1. **Mood & atmosphere** — "Define mood and atmosphere targets for each major game state in this game. Be specific — 'dark and foreboding' is not enough. Name the exact emotional target, the lighting character (warm/cool, high/low contrast, time of day direction), and at least one visual element that carries the mood. Each game state must feel visually distinct from the others."
2. **Shape language** — "Define the shape language for this game. Connect each shape principle back to the visual identity statement and a specific game pillar. Explain what these shape choices communicate to the player emotionally."
3. **Colour system** — "Design the color system for this game. Every semantic color assignment must be explained — why does this color mean danger/safety/reward in this world? Identify which color pairs might fail colorblind players and specify what backup cues are needed."
Require the three to be **mutually consistent** — the palette must serve the mood
targets and the shape hierarchy — and returned as three separately labelled
blocks so each can be approved and written on its own.
Then present **Section 2** to the user, approve it, and write it to file
immediately before moving to Section 3. Do not present all three at once: the
batching is in the delegation, not in the review.
### Section 3: Shape Language
@@ -116,7 +194,8 @@ Cover:
- UI shape grammar (does UI echo the world aesthetic, or is it a distinct HUD language?)
- Hero shapes vs. supporting shapes (what draws the eye, what recedes?)
**Agent delegation**: Spawn `art-director` via Task with Visual Identity Statement and mood targets. Ask: "Define the shape language for this game. Connect each shape principle back to the visual identity statement and a specific game pillar. Explain what these shape choices communicate to the player emotionally."
**Draft source**: the Sections 2–4 delegation issued under Section 2 — use the
shape-language block it returned. Do not spawn again.
Write the approved section to file immediately.
@@ -131,7 +210,8 @@ Cover:
- UI palette (may differ from world palette — define the divergence explicitly)
- Colorblind safety: which semantic colors need shape/icon/sound backup
**Agent delegation**: Spawn `art-director` via Task with Visual Identity Statement and mood targets. Ask: "Design the color system for this game. Every semantic color assignment must be explained — why does this color mean danger/safety/reward in this world? Identify which color pairs might fail colorblind players and specify what backup cues are needed."
**Draft source**: the Sections 2–4 delegation issued under Section 2 — use the
colour-system block it returned. Do not spawn again.
Write the approved section to file immediately.
@@ -143,13 +223,25 @@ These sections translate the visual identity into concrete production rules. The
### Section 5: Character Design Direction
**Agent delegation**: Spawn `art-director` via Task with sections 1–4. Ask: "Define character design direction for this game. Cover: visual archetype for the player character (if any), distinguishing feature rules per character type (how do players tell enemies/NPCs/allies apart at a glance?), expression/pose style targets (stiff/expressive/realistic/exaggerated), and LOD philosophy (how much detail is preserved at game camera distance?)."
**Agent delegation for Sections 5–6 — one call, issued here.** Both sections
were separate spawns of the **same agent with the same input** (`sections 1–4`),
which is pure duplication: the second call re-sent the whole visual identity to
an agent that had just been given it. Spawn `art-director` once with sections
1–4 and ask for both:
Write the approved section to file.
1. **Character design direction** — "Cover: visual archetype for the player character (if any), distinguishing feature rules per character type (how do players tell enemies/NPCs/allies apart at a glance?), expression/pose style targets (stiff/expressive/realistic/exaggerated), and LOD philosophy (how much detail is preserved at game camera distance?)."
2. **Environment design language** — "Cover: architectural style and its relationship to the world's culture/history, texture philosophy (painted vs. PBR vs. stylized — why this choice for this game?), prop density rules (sparse/dense — what drives the choice per area type?), and environmental storytelling guidelines (what visual details should tell the story without text?)."
Require characters and environments to be **legible against each other** — a
character silhouette must read against the environment texture density the same
brief defines. Return two separately labelled blocks.
Present **Section 5** first, approve, write to file, then Section 6.
### Section 6: Environment Design Language
**Agent delegation**: Spawn `art-director` via Task with sections 1–4. Ask: "Define the environment design language for this game. Cover: architectural style and its relationship to the world's culture/history, texture philosophy (painted vs. PBR vs. stylized — why this choice for this game?), prop density rules (sparse/dense — what drives the choice per area type?), and environmental storytelling guidelines (what visual details should tell the story without text?)."
**Draft source**: the Sections 5–6 delegation issued under Section 5 — use the
environment block it returned. Do not spawn again.
Write the approved section to file.
@@ -167,7 +259,7 @@ Write the approved section to file.
**Agent delegation**: Spawn in parallel:
- **`art-director`**: File format preferences, naming convention direction, texture resolution tiers, LOD level expectations, export settings philosophy
- **`technical-artist`**: Engine-specific hard constraints — poly count budgets per asset category, texture memory limits, material slot counts, importer constraints, anything from the performance budgets in `.claude/docs/technical-preferences.md`
- **`technical-artist`**: Engine-specific hard constraints — poly count budgets per asset category, texture memory limits, material slot counts, importer constraints, anything from the performance budgets (`performance.*` in `project.yaml`, falling back to `.claude/docs/technical-preferences.md`)
If any art preference conflicts with a technical constraint (e.g., art-director wants 4K textures but performance budget requires 2K for mobile), resolve the conflict explicitly — note both the ideal and the constrained standard, and explain the tradeoff. Ambiguity in asset standards is where production costs are born.
@@ -179,7 +271,7 @@ Write the approved section to file.
**Goal**: A curated reference set that is specific about what to take and what to avoid from each source.
**Agent delegation**: Spawn `art-director` via Task with the completed sections 1–8. Ask: "Compile a reference direction for this game. Provide 3–5 reference sources (games, films, art styles, or specific artists). For each: name it, specify exactly what visual element to draw from it (not 'the general aesthetic' — a specific technique, color choice, or compositional rule), and specify what to explicitly avoid or diverge from (to prevent the 'trying to copy X' reading). References should be additive — no two references should be pointing in exactly the same direction."
**Agent delegation**: Spawn `art-director` via `Agent` with the completed sections 1–8. Ask: "Compile a reference direction for this game. Provide 3–5 reference sources (games, films, art styles, or specific artists). For each: name it, specify exactly what visual element to draw from it (not 'the general aesthetic' — a specific technique, color choice, or compositional rule), and specify what to explicitly avoid or diverge from (to prevent the 'trying to copy X' reading). References should be additive — no two references should be pointing in exactly the same direction."
Write the approved section to file.
@@ -192,7 +284,7 @@ Write the approved section to file.
- `lean` → skip (not a PHASE-GATE). Note: "AD-ART-BIBLE skipped — Lean mode." Proceed to Phase 6.
- `full` → spawn as normal.
After all sections are complete (or the scoped set from Phase 1 is complete), spawn `creative-director` via Task using gate **AD-ART-BIBLE** (`.claude/docs/director-gates.md`).
After all sections are complete (or the scoped set from Phase 1 is complete), spawn `creative-director` via `Agent` using gate **AD-ART-BIBLE** (`.claude/docs/director-gates/ad-art-bible.md`).
Pass: art bible file path, game pillars, visual identity anchor.
@@ -205,7 +297,7 @@ Handle verdict per standard rules in `director-gates.md`. Record the verdict in
Before presenting next steps, check project state:
- Does `design/gdd/systems-index.md` exist? → map-systems is done, skip that option
- Does `.claude/docs/technical-preferences.md` contain a configured engine (not `[TO BE CONFIGURED]`)? → setup-engine is done, skip that option
- Is an engine configured — `engine.name` present in `project.yaml`, or a configured Engine field (not `[TO BE CONFIGURED]`) in `.claude/docs/technical-preferences.md`? → setup-engine is done, skip that option
- Does `design/gdd/` contain any `*.md` files? → design-system has been run, skip that option
- Does `design/gdd/gdd-cross-review-*.md` exist? → review-all-gdds is done
- Do GDDs exist (check above)? → include /consistency-check option
@@ -230,10 +322,19 @@ Assign letters A, B, C… only to the options actually included. Mark the most l
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
Every section follows: **Question → Options → Decision → Draft (from art-director agent) → Approval → Write to file**
- Never draft a section without first spawning the relevant agent(s)
- Write each section to file immediately after approval — do not batch
- Never draft a section yourself — every section's content comes from the
relevant specialist. One delegation may cover several sections (2–4 share a
call, as do 5–6), but no section may be written from the orchestrator's own
judgement instead of an agent's.
- Write each section to file immediately after approval — do not batch **the
writes or the approvals**. Batching applies only to the delegation call; the
user still sees, approves and commits one section at a time.
- Surface all agent disagreements to the user — never silently resolve conflicts between art-director and technical-artist
- The art bible is a constraint document: it restricts future decisions in exchange for visual coherence. Every section should feel like it narrows the solution space productively.
+49 -4
View File
@@ -1,13 +1,58 @@
---
name: asset-audit
description: "Audits game assets for compliance with naming conventions, file size budgets, format standards, and pipeline requirements. Identifies orphaned assets, missing references, and standard violations."
description: "Audit assets against naming conventions, file size budgets, format standards. Finds orphaned assets, missing references."
argument-hint: "[category|all]"
user-invocable: true
allowed-tools: Read, Glob, Grep
allowed-tools: Read, Glob, Grep, Bash
model: sonnet
# Read-only diagnostic skill — no specialist agent delegation needed
---
## Measuring file sizes and formats requires Bash
This skill's report asks for **file sizes against budgets**, **texture dimensions**
(power-of-two), **audio sample rates**, and **last-modified times** for orphan
detection. None of those are obtainable from `Read`/`Glob`/`Grep` — they need
`stat` or a binary header read, so `Bash` is declared above for exactly that.
**If you cannot take a measurement, the cell is `NOT ASSESSED`, never an
estimate.** A size budget table filled from guesses is worse than an empty one:
it looks like evidence. This is a live fabrication vector even on a project full
of real assets: if the template demands tables of numbers the tool allowlist
cannot produce, the only way to complete it is to invent them.
---
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1: Read Standards
Read the art bible or asset standards from the relevant design docs and the CLAUDE.md naming conventions.
@@ -56,7 +101,7 @@ Scan the target asset directory using Glob:
- **Format violations**: [N]
- **Orphaned assets**: [N]
- **Missing assets**: [N]
- **Overall health**: [CLEAN / MINOR ISSUES / NEEDS ATTENTION]
- **Overall health**: [NOT ASSESSED / CLEAN / MINOR ISSUES / NEEDS ATTENTION]
## Naming Violations
| File | Expected Pattern | Issue |
@@ -81,7 +126,7 @@ Scan the target asset directory using Glob:
## Recommendations
[Prioritized list of fixes]
## Verdict: [COMPLIANT / WARNINGS / NON-COMPLIANT]
## Verdict: [NOT ASSESSED / COMPLIANT / WARNINGS / NON-COMPLIANT]
```
This skill is read-only — it produces a report but does not write files.
+42 -11
View File
@@ -1,12 +1,16 @@
---
name: asset-spec
description: "Generate per-asset visual specifications and AI generation prompts from GDDs, level docs, or character profiles. Produces structured spec files and updates the master asset manifest. Run after art bible and GDD/level design are approved, before production begins."
description: "Per-asset visual specs plus AI generation prompts from GDDs and character profiles. After the art bible."
argument-hint: "[system:<name> | level:<name> | character:<name>] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation`
If no argument is provided, check whether `design/assets/entity-inventory.md` exists:
- If it exists: read it, find the first entity or screen with status "Needed" but no spec file yet, and use `AskUserQuestion`:
- Prompt: "The next unspecced item is **[name]**. Generate specs for it?"
@@ -16,6 +20,15 @@ If no argument is provided, check whether `design/assets/entity-inventory.md` ex
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt). **Note**: actually invoking an external image
generator (calling an image API) always prompts regardless of
`modes.automation` — it is an irreversible external action guarded
unconditionally, independent of whether `external_calls` is listed in
`automation_always_ask`. (Today this skill only emits generation-prompt
*text*; the guard applies if live generation is ever wired in.)
## Phase 0b: Entity & Screen Inventory (runs when no arguments and no existing inventory)
This flow produces `design/assets/entity-inventory.md` — the master list of everything
@@ -24,7 +37,16 @@ the game needs visually. Run once before asset spec work begins.
### Step 1 — Gather from docs
Read all available source material in parallel:
- `design/gdd/systems-index.md` — extract every system listed
- All GDDs in `design/gdd/` — extract: Visual/Audio Requirements sections, UI elements mentioned, VFX events, any named entities (characters, enemies, buildings, items)
- GDD asset content — do **not** full-read every GDD. The two wanted sections are
standard headings, and named entities live in the registry:
```
Grep pattern="## (Visual/Audio Requirements|UI Requirements)" glob="design/gdd/*.md" output_mode="content" -A 25
```
For named entities (characters, enemies, buildings, items), read
`design/registry/entities.yaml` (`entities`/`items`) if it exists and has
entries; otherwise grep the GDDs for named content. Full-read a GDD only when
its Visual/Audio section is missing or reads `[To be designed]` (Phase 1 already
handles that case). VFX events surface in the Visual/Audio grep context.
- `design/art/art-bible.md` — extract: any named visual categories, asset type expectations
- `design/narrative/` — scan for any character or world entity documents if they exist (optional — not required)
@@ -108,8 +130,13 @@ Extract:
- **Target name**: the name after the colon (normalize to kebab-case)
- **Review mode**: `--review [full|lean|solo]` if present
The effective mode is the one already resolved at the top of this skill via
`resolve_config --keys review_mode`, which applies the full chain and
defaults to `lean` — not `full`. A `--review` argument overrides it for this
run only.
**Mode behavior:**
- `full` (default): spawn both `art-director` and `technical-artist` in parallel
- `full`: spawn both `art-director` and `technical-artist` in parallel
- `lean`: spawn `art-director` only — faster, skips technical constraint pass
- `solo`: no agent spawning — main session writes specs from art bible rules alone. Use for simple asset categories or when speed matters more than depth.
@@ -122,9 +149,9 @@ Read all source material **before** asking the user anything.
### Required reads:
- **Art bible**: Read `design/art/art-bible.md` — fail if missing:
> "No art bible found. Run `/art-bible` first — asset specs are anchored to the art bible's visual rules and asset standards."
Extract: Visual Identity Statement, Color System (semantic colors), Shape Language, Asset Standards (Section 8 — dimensions, formats, polycount budgets, texture resolution tiers).
Extract: Visual Identity Statement, Color System (semantic colors), Shape Language, Asset Standards (art bible Section 8 — dimensions, formats, polycount budgets, texture resolution tiers).
- **Technical preferences**: Read `.claude/docs/technical-preferences.md` — extract performance budgets and naming conventions.
- **Project config**: Read `performance.*` and `naming.*` from `project.yaml`; for any key absent or empty (including when `project.yaml` has no `performance` or `naming` block), fall back to `.claude/docs/technical-preferences.md`. Extract performance budgets and naming conventions.
### Source doc reads (by target type):
- **system**: Read `design/gdd/[target-name].md`. Extract the **Visual/Audio Requirements** section. If it doesn't exist or reads `[To be designed]`:
@@ -179,17 +206,17 @@ Do NOT proceed to Phase 3 without user confirmation of the asset list.
## Phase 3: Spec Generation
Spawn specialist agents based on review mode. **Issue all Task calls simultaneously — do not wait for one before starting the next.**
Spawn specialist agents based on review mode. **Issue all `Agent` calls simultaneously — do not wait for one before starting the next.**
### Full mode — spawn in parallel:
**`art-director`** via Task:
**`art-director`** via `Agent`:
- Provide: full asset list from Phase 2, art bible Visual Identity Statement, Color System, Shape Language, the source doc's visual requirements, and any reference games/art mentioned in the art bible Section 9
- Ask: "For each asset in this list, produce: (1) a 2–3 sentence visual description anchored to the art bible's shape language and color system — be specific enough that two different artists would produce consistent results; (2) a generation prompt ready for use with AI image tools (Midjourney/Stable Diffusion style — include style keywords, composition, color palette anchors, negative prompts); (3) which art bible rules directly govern this asset (cite by section). For audio assets, describe the sonic character instead of a generation prompt."
**`technical-artist`** via Task:
- Provide: full asset list, art bible Asset Standards (Section 8), technical-preferences.md performance budgets, engine name and version
- Ask: "For each asset in this list, specify: (1) exact dimensions or polycount (match the art bible Asset Standards tiers — do not invent new sizes); (2) file format and export settings; (3) naming convention (from technical-preferences.md); (4) any engine-specific constraints this asset type must respect; (5) LOD requirements if applicable. Flag any asset type where the art bible's preferred standard conflicts with the engine's constraints."
**`technical-artist`** via `Agent`:
- Provide: full asset list, art bible Asset Standards (Section 8), performance budgets (`performance.*` from `project.yaml`, else `technical-preferences.md`), engine name and version
- Ask: "For each asset in this list, specify: (1) exact dimensions or polycount (match the art bible Asset Standards tiers — do not invent new sizes); (2) file format and export settings; (3) naming convention (`naming.*` from `project.yaml`, else `technical-preferences.md`); (4) any engine-specific constraints this asset type must respect; (5) LOD requirements if applicable. Flag any asset type where the art bible's preferred standard conflicts with the engine's constraints."
### Lean mode — spawn art-director only (skip technical-artist).
@@ -336,6 +363,10 @@ If any spawned agent returns BLOCKED or cannot complete:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
Every phase follows: **Identify → Confirm → Generate → Review → Approve → Write**
- Never spec assets without first confirming the asset list with the user
+56 -5
View File
@@ -1,11 +1,48 @@
---
name: balance-check
description: "Analyzes game balance data files, formulas, and configuration to identify outliers, broken progressions, degenerate strategies, and economy imbalances. Use after modifying any balance-related data or design. Use when user says 'balance report', 'check game balance', 'run a balance check'."
description: "Find balance outliers, broken progressions, degenerate strategies, economy imbalances in formulas and data. 'Check game balance'."
argument-hint: "[system-name|path-to-data-file]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion
model: sonnet
agent: economy-designer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1: Identify Balance Domain
@@ -31,8 +68,22 @@ Note every file read — they will appear in the Data Sources section of the rep
## Phase 3: Read Design Document
Read the GDD for the system from `design/gdd/` to understand intended design targets,
tuning knobs, and expected value ranges. This is the baseline for "correct" behaviour.
**Registry first.** If `design/registry/entities.yaml` exists, read it before the
GDD. Its `constants` and `formulas` sections hold the cross-GDD named values and
output ranges — the balance targets — already distilled, each with a `source:`
GDD and any `revised:` date:
```
Grep pattern="^ - name:" path="design/registry/entities.yaml" output_mode="content" -A 6
```
Take the intended values from the registry for any constant or formula it lists
(the `constants:` and `formulas:` blocks); these are the authoritative cross-doc
figures a GDD must not contradict. **If `design/registry/entities.yaml` does not
exist or has no entries** (it ships as an empty stub until `/design-system`
populates it), skip this and use the GDD alone.
Then read the GDD for the system from `design/gdd/` to understand intended design
targets, tuning knobs, and expected value ranges — for anything the registry did
not already supply. This is the baseline for "correct" behaviour.
---
@@ -77,7 +128,7 @@ Run domain-specific checks:
### Data Sources Analyzed
- [List of files read]
### Health Summary: [HEALTHY / CONCERNS / CRITICAL ISSUES]
### Health Summary: [NOT ASSESSED / HEALTHY / CONCERNS / CRITICAL ISSUES]
### Outliers Detected
| Item/Value | Expected Range | Actual | Issue |
+119 -16
View File
@@ -1,22 +1,99 @@
---
name: brainstorm
description: "Guided game concept ideation — from zero idea to a structured game concept document. Uses professional studio ideation techniques, player psychology frameworks, and structured creative exploration."
description: "Guided concept ideation using professional studio techniques, player psychology, creative exploration."
argument-hint: "[genre or theme hint, or 'open'] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, WebSearch, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, WebSearch, Agent, AskUserQuestion
model: sonnet
---
When this skill is invoked:
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,docs.density,workflow`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
`--review` overrides `review_mode`; store it for all gate spawns this run. See
`.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which sections exist. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = pillar bullets + concept bullets;
`balanced` = pillars + concept with brief rationale (default); `thorough` =
pillars + concept + extensive rationale + alternatives. Apply it to every section
you author.
---
## Tier branch — check `workflow` FIRST
The `workflow` tier resolved above governs this skill's output:
- **`standard` / `full`** → run the full flow ("When this skill is invoked" through
Phase 5 and the concept-document generation). No change.
- **`minimal`** → run the **Lean Brief flow** immediately below and **STOP** — skip
Phases 1–5, the director gates (CD-PILLARS / AD-CONCEPT-VISUAL / TD-FEASIBILITY /
PR-SCOPE), and the full-length concept document entirely. Output is the one-page
`design/game-brief.md`, not `game-concept.md`.
### Lean Brief flow (`workflow: minimal` only)
A jam / small-scope session: capture the load-bearing thinking in one page, then get
to code. Keep prompting light — a few exchanges, not fifteen. Author from the
one-page template `.claude/docs/templates/game-brief.md` (6 required fields + 2
one-liners). If `design/game-brief.md` already exists, read it and resume/refine
rather than restart.
1. **Concept** — from the argument hint (or one quick open question if none), propose
**2–3 one-line concepts** (verb-first or mashup, per Phase 2's techniques). One
`AskUserQuestion` to pick or combine — the only guaranteed creative prompt.
2. **Fill the brief fields** conversationally (not one prompt each):
- **One-sentence pitch** — the excited one-liner.
- **Core loop** — the 2–4 step cycle the player repeats.
- **MVP** — the ruthlessly short feature list that makes it *the game* (each becomes
a story downstream). If it runs past ~7, push back on scope.
- **Out of scope** — what they're deliberately NOT building.
- **Build order** — sequence to build the MVP, risky / core-fun thing first.
- **Who it's for / what they feel** and **Art & audio direction** — one line each
(offer, don't force).
Present the filled brief back in full for a single confirmation.
3. **Write approval** — `AskUserQuestion`: "Brief is ready. May I write it to
`design/game-brief.md`?" → `[A] Yes — write it` / `[B] Revise a field first`. On
[B], revise the named field, show before/after, re-ask; repeat until [A]. Then
write `design/game-brief.md` from the template, creating directories as needed.
Honor `modes.automation` for this write as elsewhere in the framework.
4. **Next steps** (short — this is the point). **Read `engine.name` from
`project.yaml` first and list `/setup-engine` only if it is absent or empty:**
1. *(only when `engine.name` is absent or empty)* "`/setup-engine` — configure
the engine (required before code)"
2. "`/create-stories` — turn the brief's MVP list into implementable stories. The
epic is implicit at `minimal`; there is no separate `/create-epics` or
`/sprint-plan` — the brief's build order is the plan."
3. "`/dev-story` — first line of game code"
> **Why the condition.** `/start`'s `minimal` path runs `/setup-engine`
> *before* `/brainstorm`, and `/setup-engine` Section 2 states that a missing
> brief is expected because the brief is authored afterwards. Listing engine
> setup unconditionally here tells a user who just followed that path to go
> back and redo step one — the only skill in the four-step path that assumes
> it runs first.
Then output a one-line summary (pitch + MVP feature count + `design/game-brief.md`).
Verdict: **COMPLETE** — game brief created; next stop is code. Do NOT run Phases 1–5,
spawn any director gate, or write `game-concept.md` at this tier.
---
When this skill is invoked (`standard` / `full` tier — `minimal` uses the Lean Brief
flow above):
1. **Parse the argument** for an optional genre/theme hint (e.g., `roguelike`,
`space survival`, `cozy farming`). If `open` or no argument, start from
scratch. Also resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
scratch.
2. **Check for existing concept work**:
- Read `design/gdd/game-concept.md` if it exists (resume, don't restart)
@@ -109,6 +186,13 @@ For each concept, present:
Present all three. Then use `AskUserQuestion` to capture the selection.
**This decision asks regardless of `modes.automation`.** Concept selection
is the creative heart of `/brainstorm` and has no defensible autonomous
default — there is no algorithmic way to pick which creative direction
resonates with the user. Per `.claude/docs/automation-modes.md`, treat
this site as exempt (it overrides the mode the same way
`automation_always_ask` categories do).
**CRITICAL**: This MUST be a plain list call — no tabs, no form fields. Use exactly this structure:
```
@@ -195,19 +279,26 @@ If the user selects B, C, or D, make the revision, then use `AskUserQuestion` ag
- Prompt: "Pillars updated. Ready to lock these in?"
- Options: `[A] Lock these in` / `[B] Revise another pillar` / `[C] Something else`
Repeat until the user selects [A] Lock these in.
**At `collaborative`** — repeat until the user selects [A] Lock these in.
**At `guided`** — pillars are a major decision, so ask once; apply the chosen
revision and lock them in without a second confirmation round.
**At `autonomous`** — do not ask. Lock in the drafted pillars and record them via
`log_decision` with the alternatives considered.
> An `autonomous` run never issues the question, so "repeat until [A]" has no
> exit condition (`automation-modes.md:56`).
**Review mode check** — apply before spawning CD-PILLARS and AD-CONCEPT-VISUAL:
- `solo` → skip both. Note: "CD-PILLARS skipped — Solo mode. AD-CONCEPT-VISUAL skipped — Solo mode." Proceed to Phase 5.
- `lean` → skip both (not PHASE-GATEs). Note: "CD-PILLARS skipped — Lean mode. AD-CONCEPT-VISUAL skipped — Lean mode." Proceed to Phase 5.
- `full` → spawn as normal.
**After pillars and anti-pillars are agreed, spawn BOTH `creative-director` AND `art-director` via Task in parallel before moving to Phase 5. Issue both Task calls simultaneously — do not wait for one before starting the other.**
**After pillars and anti-pillars are agreed, spawn BOTH `creative-director` AND `art-director` via `Agent` in parallel before moving to Phase 5. Issue both `Agent` calls simultaneously — do not wait for one before starting the other.**
- **`creative-director`** — gate **CD-PILLARS** (`.claude/docs/director-gates.md`)
- **`creative-director`** — gate **CD-PILLARS** (`.claude/docs/director-gates/cd-pillars.md`)
Pass: full pillar set with design tests, anti-pillars, core fantasy, unique hook.
- **`art-director`** — gate **AD-CONCEPT-VISUAL** (`.claude/docs/director-gates.md`)
- **`art-director`** — gate **AD-CONCEPT-VISUAL** (`.claude/docs/director-gates/ad-concept-visual.md`)
Pass: game concept elevator pitch, full pillar set with design tests, target platform (if known), any reference games or visual touchstones the user mentioned.
Collect both verdicts, then present them together using a two-tab `AskUserQuestion`:
@@ -246,6 +337,12 @@ Ground the concept in reality:
- **Engine experience**: Use `AskUserQuestion` — "Do you already have an engine you work in?"
Options: `Godot` / `Unity` / `Unreal Engine 5` / `No preference — help me decide`
- **This decision always prompts regardless of `modes.automation` —
including `autonomous` mode.** Engine choice is a project-wide
architectural commitment that downstream tooling depends on and is
effectively irreversible mid-project, so this skill guards it
unconditionally (it is NOT left to the configurable
`automation_always_ask` list). The model must NOT silently pick an engine.
- If they pick an engine → record it as their preference and move on. Do NOT second-guess it.
- If "No preference" → tell them: "Run `/setup-engine` after this session — it will walk you through the full decision based on your concept and platform target." Do not make a recommendation here.
- **Art pipeline**: What's the art style and how labor-intensive is it?
@@ -260,7 +357,7 @@ Ground the concept in reality:
- `lean` → skip (not a PHASE-GATE). Note: "TD-FEASIBILITY skipped — Lean mode." Proceed directly to scope tier definition.
- `full` → spawn as normal.
**After identifying biggest technical risks, spawn `technical-director` via Task using gate TD-FEASIBILITY (`.claude/docs/director-gates.md`) before scope tiers are defined.**
**After identifying biggest technical risks, spawn `technical-director` via `Agent` using gate TD-FEASIBILITY (`.claude/docs/director-gates/td-feasibility.md`) before scope tiers are defined.**
Pass: core loop description, platform target, engine choice (or "undecided"), list of identified technical risks.
@@ -271,7 +368,7 @@ Present the assessment to the user. If HIGH RISK, offer to revisit scope before
- `lean` → skip (not a PHASE-GATE). Note: "PR-SCOPE skipped — Lean mode." Proceed to document generation.
- `full` → spawn as normal.
**After scope tiers are defined, spawn `producer` via Task using gate PR-SCOPE (`.claude/docs/director-gates.md`).**
**After scope tiers are defined, spawn `producer` via `Agent` using gate PR-SCOPE (`.claude/docs/director-gates/pr-scope.md`).**
Pass: full vision scope, MVP definition, timeline estimate, team size.
@@ -301,7 +398,13 @@ If [B]: ask which section to revise using `AskUserQuestion` with options: `Eleva
After revising, show the updated section as a diff or clear before/after, then use `AskUserQuestion` — "Ready to write the updated concept document?"
Options: `[A] Yes — write it` / `[B] Revise another section`
Repeat until the user selects [A].
**At `collaborative`** — repeat until the user selects [A].
**At `guided`** — ask once; apply the requested revision and write the document
without a further confirmation round.
**At `autonomous`** — do not ask; write the document and record the decision via
`log_decision`.
> Same exit-condition problem as the pillars loop above (`automation-modes.md:56`).
If yes, generate the document using the template at `.claude/docs/templates/game-concept.md`, fill in ALL sections from the brainstorm conversation, and write the file, creating directories as needed.
+18 -3
View File
@@ -1,12 +1,20 @@
---
name: bug-report
description: "Creates a structured bug report from a description, or analyzes code to identify potential bugs. Ensures every bug report has full reproduction steps, severity assessment, and context."
description: "Structured bug report from a description, or analyze code for potential bugs. Reproduction steps, severity."
argument-hint: "[description] | analyze [path-to-file]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Phase 1: Parse Arguments
Determine the mode from the argument:
@@ -35,7 +43,14 @@ If no argument is provided, ask the user for a bug description before proceeding
**Title**: [Concise, descriptive title]
**ID**: BUG-[NNNN]
**Severity**: [S1-Critical / S2-Major / S3-Minor / S4-Trivial]
**Priority**: [P1-Immediate / P2-Next Sprint / P3-Backlog / P4-Wishlist]
**Priority**: [P1-Fix this sprint / P2-Fix soon / P3-Backlog / P4-Won't fix]
> **These labels must match `/bug-triage`'s priority table exactly** — it parses
> this field out of the file you are writing. P4 is the easiest to get wrong:
> `P4-Wishlist` ("would be nice someday") and `P4 — Won't fix / Deferred`
> ("accepted risk, not doing it") mean opposite things, and nothing at runtime
> surfaces a disagreement between the producer and consumer of the field. If you change this ladder, change
> `.claude/skills/bug-triage/SKILL.md` in the same commit.
**Status**: Open
**Reported**: [Date]
**Reporter**: [Name]
+21 -1
View File
@@ -1,12 +1,20 @@
---
name: bug-triage
description: "Read all open bugs in production/qa/bugs/, re-evaluate priority vs. severity, assign to sprints, surface systemic trends, and produce a triage report. Run at sprint start or when the bug count grows enough to need re-prioritization."
description: "Re-evaluate open bugs — priority vs severity, assign to sprints, surface systemic trends. Run when the count grows."
argument-hint: "[sprint | full | trend]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Bug Triage
This skill processes the open bug backlog into a prioritised, sprint-assigned
@@ -50,6 +58,18 @@ If no bug files found:
Stop and report. Do not proceed if no bugs exist.
**In `trend` mode, do not read full bug bodies.** Trend metrics (volume, severity
mix, by-system, by-date) are computable from the header fields alone:
```
Grep pattern="\*\*(Severity|Priority|Status|System|Category|Reported)\*\*" glob="production/qa/bugs/*.md" output_mode="content"
```
(Bug-report fields are bolded — `**Severity**:`, `- **System**:` — so match the
`**field**` form, not a bare line-start `Field:`.)
Full bug bodies are needed only for the priority-vs-severity **re-evaluation** in
`sprint`/`full` modes; `trend` is a read-only report and skips it. (The one
deviation check that needs a story's status — "bug filed against a Complete
story" — is a targeted story-status grep either way, not a bug-body read.)
### Step 2b — Load sprint context
Read the most recently modified file in `production/sprints/` to understand:
+79 -6
View File
@@ -1,13 +1,82 @@
---
name: changelog
description: "Auto-generates a changelog from git commits, sprint data, and design documents. Produces both internal and player-facing versions."
description: "Auto-generate a changelog from git commits and sprint data. Internal and player-facing versions."
argument-hint: "[version|sprint-number]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write
context: |
!git log --oneline -30 2>/dev/null
!git tag --list --sort=-v:refname 2>/dev/null | head -5
model: haiku
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Recent History
Recent commits:
!`git log --oneline -30 2>/dev/null`
Recent tags (newest first):
!`git tag --list --sort=-v:refname 2>/dev/null | head -5`
## Provenance check — before trusting the history above
**The commits above may not belong to this game.** This skill's history blocks are
auto-resolved *before* the body runs, so the read has already happened — what this
check governs is whether that output is usable, not whether it is fetched.
1. Read the injected commit subjects above.
2. **Classify each one** as **Game** (mechanics, content, balance, art, audio,
UI, or a bug in those), **Framework / maintenance** (subjects naming skills,
hooks, agents, the test plan, CI, or the framework's own docs), or **Unclear**
— and treat Unclear as Framework.
3. Decide from the counts:
- **At least one Game commit** → proceed using only those, and state how many
of how many you used.
- **Zero Game commits** → stop, using the message below.
> **Filter per commit; a repo containing maintenance work is not a wrong repo.**
> Every project on this framework accumulates commits touching hooks, CI and
> skills — the game repo *is* the framework repo. Listing those as a hard STOP
> fires on virtually every real project and contradicts step 2 whenever the
> history is mostly the game's. The harm is those commits becoming release copy,
> and excluding them prevents that precisely.
>
> This rule is kept identical to `/patch-notes`' on purpose — the two read the
> same history for different audiences, and they must not disagree about whose
> history it is. Change both together.
The genuine wrong-history signal is different: Game commits naming a product that
`design/` and `src/` never mention. If you see that, stop.
If **no** commit in the range is this game's, say so and stop:
> "The git history in this repo does not appear to belong to [game]. The recent
> commits describe [what they actually describe]. I cannot generate a changelog
> from it — point me at the right history, or supply the change list directly."
**Why this is a hard stop, not a warning.** This exact failure is real, not
hypothetical: a batch of framework-internal commits produced player-facing copy
reading *"Fixed an issue where progress from your last session could be lost on
launch"* — a
session-hook timeout rendered as a gameplay fix for a game with **no save
system**. It was fluent, plausible, and entirely false. A reader cannot tell the
difference; only this check can.
**Do not treat the preamble's existence as evidence.** Injected output means the
command ran, never that its subject is your game.
---
Both blocks are resolved before this skill runs. Use them as the starting point
for Phase 2 rather than re-running the same commands.
---
## Phase 1: Parse Arguments
@@ -26,7 +95,11 @@ Read the git log since the last tag or release:
git log --oneline [last-tag]..HEAD
```
If no tags exist, read the full log or a reasonable recent range (last 100 commits).
If no tags exist, bound the range explicitly — `git log --oneline -n 100`. Do not
fall back to the full log: on an established repo that is thousands of lines for
a changelog covering one release, and the oldest of them are the least relevant.
If 100 commits does not reach far enough back, say so and ask for a start ref
rather than widening blindly.
Read sprint reports from `production/sprints/` for the relevant period to understand planned work and context behind changes.
+86 -17
View File
@@ -1,11 +1,48 @@
---
name: code-review
description: "Performs an architectural and quality code review on a specified file or set of files. Checks for coding standard compliance, architectural pattern adherence, SOLID principles, testability, and performance concerns."
description: "Architectural code review — coding standards, SOLID, testability, performance concerns."
argument-hint: "[path-to-file-or-directory]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Bash, Agent, AskUserQuestion
model: sonnet
agent: lead-programmer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1: Load Target Files
@@ -16,14 +53,22 @@ Read the target file(s) in full. Read CLAUDE.md for project coding standards.
## Phase 2: Identify Engine Specialists
Read `.claude/docs/technical-preferences.md`, section `## Engine Specialists`. Note:
Read the `specialists` block from `project.yaml`; if it is absent, fall back to the `## Engine Specialists` section of `.claude/docs/technical-preferences.md`. Note:
- The **Primary** specialist (used for architecture and broad engine concerns)
- The **Language/Code Specialist** (used when reviewing the project's primary language files)
- The **Shader Specialist** (used when reviewing shader files)
- The **UI Specialist** (used when reviewing UI code)
- The **Primary** specialist — `<engine>-specialist` derived from `engine.name` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); used for architecture and broad engine concerns
- The **Language/Code Specialist** — `specialists.code` — used when reviewing the project's primary language files
- The **Shader Specialist** — `specialists.shader` — used when reviewing shader files
- The **UI Specialist** — `specialists.ui` — used when reviewing UI code
If the section reads `[TO BE CONFIGURED]`, no engine is pinned — skip engine specialist steps.
**A value of `null` means UNSET — treat that key as absent and skip its
specialist. Never spawn it as an agent name.** The v1.0 migration writes `null`
for any specialist the legacy file did not name, and it writes the whole block
whenever *one* member is set — so a project that configured only its code
specialist carries `shader: null` and `ui: null`. The config reader returns the
four-character string `"null"` for these, which is not empty and therefore reads
as configured. `null`, empty, and missing are the same state here.
If no engine is configured (no `engine.name` in `project.yaml`, and `technical-preferences.md` reads `[TO BE CONFIGURED]` or is missing), skip engine specialist steps. **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
---
@@ -40,7 +85,12 @@ Look for patterns like `ADR-NNN` or `docs/architecture/ADR-`.
If no ADR references found, note: "No ADR references found — ADR compliance check skipped. For full ADR compliance review, provide the story path: `/code-review [files] [story-path]`."
For each referenced ADR: read the file, extract the **Decision** and **Consequences** sections, then classify any deviation:
For each referenced ADR, load **only the sections this check needs — never an unbounded full read.** A substantial ADR exceeds the 25k-token `Read` cap, and a capped read's only recovery is paging the remainder — the most expensive way to read a file (measured ~103k vs ~54k tokens on a 34k-token ADR). Use the same pattern as `/dev-story` and `/create-stories`:
1. **Map the headings** (cheap — line numbers only): `Grep pattern="^## " path="[adr-file]" output_mode="content" -n`
2. **Bounded-read only `## Decision` and `## Consequences`**, using the line numbers to set `Read(offset, limit)` spans that end where the next heading begins. If the heading map is empty (a nonstandard ADR predating the template), fall back to one full `Read`; if that truncates at the cap, grep for the decision/consequence content directly rather than paging the remainder.
From those two sections, classify any deviation:
- **ARCHITECTURAL VIOLATION** (BLOCKING): Uses a pattern explicitly rejected in the ADR
- **ADR DRIFT** (WARNING): Meaningfully diverges from the chosen approach without using a forbidden pattern
@@ -91,7 +141,26 @@ Identify the system category (engine, gameplay, AI, networking, UI, tools) and e
## Phase 7: Specialist Reviews (Parallel)
Spawn all applicable specialists simultaneously via Task — do not wait for one before starting the next.
Spawn all applicable specialists simultaneously via `Agent` — do not wait for one before starting the next.
> **Verify every specialist finding before reporting it. Do not pass findings
> through unchecked.** For each finding, record in the report:
>
> - **File and line** it refers to.
> - **Evidence** — the quoted code, or the concrete input/state that triggers it.
> - **Confidence** — `VERIFIED` (you checked it yourself) or `UNVERIFIED —
> specialist claim` (you could not).
>
> A finding you could not verify is reported as unverified or dropped, never
> promoted to a defect on the strength of confident phrasing.
>
> **Why this is mandatory.** Agents are reliable when deriving and unreliable when
> diagnosing existing code. Measured in practice: three separate agents
> produced three different **wrong** claims about the same six-line function,
> every one fluent enough to pass a skim — including a spawned specialist here
> alleging a float-precision bug that enumerating the inputs disproves. Without
> this step the parent review is a laundering channel: a guess enters as a
> specialist finding and leaves as a reviewed defect.
### Engine Specialists
@@ -106,7 +175,7 @@ Also spawn the **Primary Specialist** for any file touching engine architecture
### QA Testability Review
For Logic and Integration stories, also spawn `qa-tester` via Task in parallel with the engine specialists. Pass:
For Logic and Integration stories, also spawn `qa-tester` via `Agent` in parallel with the engine specialists. Pass:
- The implementation files being reviewed
- The story's `## QA Test Cases` section (the pre-written test specs from qa-lead)
- The story's `## Acceptance Criteria`
@@ -136,16 +205,16 @@ Collect all specialist findings before producing output.
[qa-tester findings: test hooks, coverage gaps, untestable paths, new edge cases]
[If BLOCKING: implementation must expose [X] before tests in ## QA Test Cases can run]
### ADR Compliance: [NO ADRS FOUND / COMPLIANT / DRIFT / VIOLATION]
### ADR Compliance: [NOT ASSESSED / NO ADRS FOUND / COMPLIANT / DRIFT / VIOLATION]
[List each ADR checked, result, and any deviations with severity]
### Standards Compliance: [X/6 passing]
[List failures with line references]
### Architecture: [CLEAN / MINOR ISSUES / VIOLATIONS FOUND]
### Architecture: [NOT ASSESSED / CLEAN / MINOR ISSUES / VIOLATIONS FOUND]
[List specific architectural concerns]
### SOLID: [COMPLIANT / ISSUES FOUND]
### SOLID: [NOT ASSESSED / COMPLIANT / ISSUES FOUND]
[List specific violations]
### Game-Specific Concerns
@@ -160,7 +229,7 @@ Collect all specialist findings before producing output.
### Suggestions
[Nice-to-have improvements]
### Verdict: [APPROVED / APPROVED WITH SUGGESTIONS / CHANGES REQUIRED]
### Verdict: [NOT ASSESSED / APPROVED / APPROVED WITH SUGGESTIONS / CHANGES REQUIRED]
```
This skill is read-only — no files are written.
@@ -170,7 +239,7 @@ This skill is read-only — no files are written.
## Phase 9: Next Steps
Use `AskUserQuestion`:
- Prompt: "Code review complete — verdict: [APPROVED / CHANGES REQUIRED / MAJOR REVISION]. How would you like to proceed?"
- Prompt: "Code review complete — verdict: [NOT ASSESSED / APPROVED / CHANGES REQUIRED / MAJOR REVISION]. How would you like to proceed?"
- Options (adjust based on verdict):
- If APPROVED:
- `[A] Run /story-done to mark the story complete`
+24 -3
View File
@@ -1,12 +1,16 @@
---
name: consistency-check
description: "Scan all GDDs against the entity registry to detect cross-document inconsistencies: same entity with different stats, same item with different values, same formula with different variables. Grep-first approach — reads registry then targets only conflicting GDD sections rather than full document reads."
description: "Scan GDDs against the entity registry for cross-document conflicts. Grep-first approach targets conflicting sections, different stats."
argument-hint: "[full | since-last-review | entity:<name> | item:<name>]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow`
# Consistency Check
Detects cross-document inconsistencies by comparing all GDDs against the
@@ -28,6 +32,15 @@ catches too late.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — full entity-registry cross-check against all GDD sections.
- `standard` — cross-check against the required sections only.
- `minimal` — not meaningful (no GDDs to check).
## Phase 1: Parse Arguments and Load Registry
**Modes:**
@@ -281,9 +294,15 @@ Then append the new conflict entries. Never skip logging — a missing file is n
Silently append to `production/session-state/active.md` (create the file if it does not exist):
```
<!-- CONSISTENCY-CHECK: [date] | GDDs checked: [N] | Conflicts found: [N] | Report: docs/consistency-report-[date].md -->
<!-- CONSISTENCY-CHECK: [date] | GDDs checked: [N] | Conflicts found: [N] | Log: docs/consistency-failures.md -->
```
> **Point at `docs/consistency-failures.md` — the file Phase 6 actually appends
> to.** A breadcrumb is a pointer left for a future session to follow. One that
> names a file nothing writes sends that session looking for conflict history it
> will never find, and nothing errors along the way. Never invent a report
> filename here.
Then close with an `AskUserQuestion` widget:
- **Prompt**: "Consistency check complete — [N] conflicts found. What next?"
@@ -293,7 +312,9 @@ Then close with an `AskUserQuestion` widget:
- `[C] Run /design-review on the most conflicted GDD`
- `[D] Stop here`
Never end the skill with plain text. Always close with this widget.
In collaborative and guided modes, never end the skill with plain text — always
close with this widget. In autonomous mode, print the findings and recommended
next step, then record via `log_decision` (no widget).
---
+101 -11
View File
@@ -1,13 +1,31 @@
---
name: content-audit
description: "Audit GDD-specified content counts against implemented content. Identifies what's planned vs built."
description: "Audit GDD content counts against what's implemented — planned vs built."
argument-hint: "[system-name | --summary | (no arg = full audit)]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
agent: producer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys workflow,automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Resolved above — use as-is. No block → defaults in `.claude/docs/config-resolution.md`.
> This skill declares tier-dependent behaviour ("audit only specs in the required
> sections"), which is unreachable unless the tier is actually resolved — without
> it the skill applies whatever tier it assumed. Resolve `modes.workflow` before
> auditing, and
> when a required input such as `design/gdd/systems-index.md` is absent, report
> **`NOT ASSESSED — NO DATA`** rather than computing a gap percentage (which
> divides by zero when nothing is specified).
When this skill is invoked:
Parse the argument:
@@ -17,25 +35,97 @@ Parse the argument:
---
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — full content-count audit against all GDD specs.
- `standard` — audit only specs in the required sections.
- `minimal` — cannot run (no systems index exists).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1 — Context Gathering
1. **Read `design/gdd/systems-index.md`** for the full list of systems, their
categories, and MVP/priority tier.
2. **L0 pre-scan**: Before full-reading any GDDs, Grep all GDD files for
`## Summary` sections plus common content-count keywords:
2. **Registry-first count**: If `design/registry/entities.yaml` exists, read it
first. Its `entities` and `items` sections are the cross-GDD named content
the audit is counting, already distilled with a `source:` GDD per entry:
```
Grep pattern="(## Summary|N enemies|N levels|N items|N abilities|enemy types|item types)" glob="design/gdd/*.md" output_mode="files_with_matches"
Grep pattern="^ - name:" path="design/registry/entities.yaml" output_mode="content" -A 2
```
`- name:` appears in all four registry sections; keep only the names whose
`-A 2` context shows they sit under `entities:` or `items:` (the named
content this audit counts — not `formulas:`/`constants:`). Use those as the
**planned** named-content set without full-reading the GDDs that own them.
**If `design/registry/entities.yaml` does not exist or has no entries** (it
ships as an empty stub until `/design-system` populates it), skip this step
and rely on the GDD scan below — behaviour is unchanged, only more expensive.
3. **L0 pre-scan**: Before full-reading any GDDs, run **two** greps — they
answer different questions and must not share a pattern:
a. Which GDDs carry a Summary (the denominator / fail-open check):
```
Grep pattern="^## Summary" glob="design/gdd/*.md" output_mode="files_with_matches"
```
b. Which GDDs actually declare content counts (the narrowing step):
```
Grep pattern="[0-9]+[[:space:]]+(enemies|enemy types|levels|areas|maps|stages|items|weapons|equipment|abilities|skills|spells|cutscenes|conversations|dialogue scenes|bosses|quests)|(enemy|item|weapon|ability|level) types:" glob="design/gdd/*.md" output_mode="files_with_matches"
```
> **These were one grep, and it narrowed nothing.** The old pattern was
> `(## Summary|N enemies|N levels|N items|N abilities|enemy types|item types)`.
> `N enemies` and friends are un-substituted placeholders copied from the
> template — no real GDD contains the literal letter `N` as a count — while
> `## Summary` matches every compliant GDD. So the union returned *all* GDDs
> and step 3's whole purpose (read-avoidance) saved zero tokens. Pattern (b)
> matches digits followed by the content nouns step 5 actually extracts.
**Fail open on a missing Summary.** Establish the denominator: glob
`design/gdd/*.md` and count **N**. **Scan (a)** matching fewer than N means
those GDDs predate `## Summary` — never treat an absent Summary as a system
out of scope; a zero-match (a) means "no GDD carries a Summary yet", not "no
auditable content". Full-read the unmatched in-scope GDDs.
For a single-system audit: skip this step and go straight to full-read.
For a full audit: full-read only the GDDs that matched content-count keywords.
For a full audit: full-read only the GDDs that **scan (b)** matched
**and are not already fully covered by the registry entries from step 2**.
GDDs with no content-count language (pure mechanics GDDs) are noted as
"No auditable content counts" without a full read.
3. **Full-read in-scope GDD files** (or the single system GDD if a system
4. **Full-read in-scope GDD files** (or the single system GDD if a system
name was given).
4. **For each GDD, extract explicit content counts or lists.** Look for patterns
5. **For each GDD, extract explicit content counts or lists.** Look for patterns
like:
- "N enemies" / "enemy types:" / list of named enemies
- "N levels" / "N areas" / "N maps" / "N stages"
@@ -45,7 +135,7 @@ Parse the argument:
- "N quests" / "N missions" / "N objectives"
- Any explicit enumerated list (bullet list of named content pieces)
4. **Build a content inventory table** from the extracted data:
6. **Build a content inventory table** from the extracted data:
| System | Content Type | Specified Count/List | Source GDD |
|--------|-------------|---------------------|------------|
@@ -62,14 +152,14 @@ what has been implemented. Use Glob and Grep to locate files.
**Levels / Areas / Maps:**
- Glob `assets/**/*.tscn`, `assets/**/*.unity`, `assets/**/*.umap`
- Glob `src/**/*.tscn`, `src/**/*.unity`
- Glob the **code root** for scene files: `*.tscn` (Godot), `*.unity` (Unity), `*.umap` (Unreal). Resolve the root per `.claude/docs/code-root-resolution.md`. **If the code root is unresolved, report `NOT ASSESSED — code root unresolved` rather than zero hits.**
- Look for scene files in subdirectories named `levels/`, `areas/`, `maps/`,
`worlds/`, `stages/`
- Count unique files that appear to be level/scene definitions (not UI scenes)
**Enemies / Characters / NPCs:**
- Glob `assets/data/**/enemies/**`, `assets/data/**/characters/**`
- Glob `src/**/enemies/**`, `src/**/characters/**`
- Glob `<code root>/**/enemies/**`, `<code root>/**/characters/**`
- Look for `.json`, `.tres`, `.asset`, `.yaml` data files defining entity stats
- Look for scene/prefab files in character subdirectories
+104 -18
View File
@@ -1,13 +1,18 @@
---
name: create-architecture
description: "Guided, section-by-section authoring of the master architecture document for the game. Reads all GDDs, the systems index, existing ADRs, and the engine reference library to produce a complete architecture blueprint before any code is written. Engine-version-aware: flags knowledge gaps and validates decisions against the pinned engine version."
description: "Author the architecture blueprint before code is written. Validates decisions against the pinned engine, flags knowledge gaps."
argument-hint: "[focus-area: full | layers | data-flow | api-boundaries | adr-audit] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion, Task
allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion, Agent
model: sonnet
agent: technical-director
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Create Architecture
This skill produces `docs/architecture/architecture.md` — the master architecture
@@ -17,12 +22,26 @@ It sits between design and implementation, and must exist before sprint planning
**Distinct from `/architecture-decision`**: ADRs record individual point decisions.
This skill creates the whole-system blueprint that gives ADRs their context.
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which sections exist. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = layer diagrams + decision bullets,
no essays; `balanced` = diagrams + paragraph explanations of layer choices
(default); `thorough` = full prose with rationale, trade-offs, and alternatives
considered per layer. Apply it to every section you author.
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — full architecture: all layers, module ownership, data flow, API
boundaries, full ADR audit.
- `standard` — simplified: system layer map + critical ADR list only.
- `minimal` — not required. Can still be run voluntarily.
**Argument modes:**
- **No argument / `full`**: Full guided walkthrough — all sections, start to finish
@@ -39,7 +58,8 @@ Before anything else, load the full project context in this order:
### 0a. Engine Context (Critical)
Read the engine reference library completely:
Read the four project-wide engine documents in full — they are small, and every
part of each is used:
1. `docs/engine-reference/[engine]/VERSION.md`
→ Extract: engine name, version, LLM cutoff, post-cutoff risk levels
@@ -49,22 +69,75 @@ Read the engine reference library completely:
→ Extract: APIs to avoid
4. `docs/engine-reference/[engine]/current-best-practices.md`
→ Extract: post-cutoff best practices that differ from training data
5. All files in `docs/engine-reference/[engine]/modules/`
Then read **only the module docs whose domain this game actually uses** —
not the whole `modules/` directory:
5. `docs/engine-reference/[engine]/modules/` — glob it to establish what exists,
then match against the domains present in `design/gdd/systems-index.md`
(the same domain vocabulary the ADR template uses: Physics, Rendering, UI,
Audio, Navigation, Animation, Networking, Core, Input). Read the matching
modules; skip the rest.
→ Extract: current API patterns per domain
A game with no multiplayer system does not need the networking module loaded
to write its architecture, and loading it costs the same as one that does.
**If the domain match is ambiguous, read the module** — a missed engine
constraint is far more expensive here than a redundant read, because this
phase is where those constraints get baked into the architecture.
If no engine is configured, stop and prompt:
> "No engine is configured. Run `/setup-engine` first. Architecture cannot be
> written without knowing which engine and version you are targeting."
### 0b. Design Context + Technical Requirements Extraction
Read all approved design documents and extract technical requirements from each:
Load the approved design documents and extract technical requirements from each:
1. `design/gdd/game-concept.md` — game pillars, genre, core loop
2. `design/gdd/systems-index.md` — all systems, dependencies, priority tiers
3. `.claude/docs/technical-preferences.md` — naming conventions, performance budgets,
allowed libraries, forbidden patterns
4. **Every GDD in `design/gdd/`** — for each, extract technical requirements:
**Check both exist before reading either. Neither is optional here, and both
need an absence branch** — §0a stops for an unconfigured engine, and these two
matter just as much:
- **`systems-index.md` absent** — stop:
> "No systems index found. Run `/map-systems` first. An architecture written
> without it invents layers for systems nobody mapped, and every ADR, epic and
> story downstream inherits that invention."
At `minimal` the index is not required (§ tier note above) — say so and proceed
from the brief instead.
- **`game-concept.md` absent** — at `standard`/`full`, stop and point at
`/brainstorm`. At `minimal`, read `design/game-brief.md` in its place; if that
is absent too, stop — there is no design record to architect against.
- **Either present but empty or still template placeholders** — treat as absent.
Present-but-empty is the case that most looks like present.
Do not proceed on a partial read and note it later. This phase is where design
assumptions get baked into ADRs, and an assumption made here is re-derived by
everything downstream rather than re-checked.
3. Project config — `naming.*` and `performance.*` from `project.yaml` (for any
key absent or empty, fall back to `.claude/docs/technical-preferences.md`);
allowed libraries and forbidden patterns from
`.claude/docs/technical-preferences.md` (not migrated to project.yaml)
4. **Every GDD in `design/gdd/`** — extract technical requirements from the
sections that carry them, **not from whole files**. Establish the denominator
first (glob `design/gdd/*.md`, count **N**), then:
```
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
```
Overview and Player Fantasy are narrative and imply no architecture; the
scanned set is where rules, numbers, and cross-system contracts live. Accept
either `## Detailed Rules` or `## Detailed Design` — the design standard and
the GDD template disagree on the name and they denote the same section.
Full-read a GDD when it matched **zero** sections (it predates the template —
a zero-match means "unstructured", never "no requirements") or when a scanned
section refers to material outside itself. **Never treat an absent section as
an absent requirement**: report any GDD that contributed nothing, rather than
letting it drop silently out of the baseline below.
For each, extract:
- Data structures implied by the game rules
- Performance constraints stated or implied
- Engine capabilities the system requires
@@ -92,8 +165,17 @@ left without an architectural decision to support it by the end of this session.
### 0c. Existing Architecture Decisions
Read all files in `docs/architecture/` to understand what has already been decided.
List any ADRs found and their domains.
To learn **what has already been decided and in which domain**, scan the ADR
headers — do not full-read every ADR to produce a list of numbers and domains:
```
Grep pattern="^## (Status|Summary)" glob="docs/architecture/adr-*.md" output_mode="content" -A 4
Grep pattern="\*\*Domain\*\*" glob="docs/architecture/adr-*.md" output_mode="content"
```
`## Summary` (a 2-sentence what-and-why) plus `## Status` and the Engine
Compatibility `Domain` field are exactly "what was decided and its domain". List
the ADRs found, their status, and their domains from the scan. Full-read a
specific ADR only when a new decision this session would collide with it and you
need its reasoning — not to build the inventory.
### 0d. Generate Knowledge Gap Inventory
@@ -346,14 +428,14 @@ After writing the master architecture document, perform an explicit sign-off bef
**Step 1 — Technical Director self-review** (this skill runs as technical-director):
Apply gate **TD-ARCHITECTURE** (`.claude/docs/director-gates.md`) as a self-review. Check all four criteria from that gate definition against the completed document.
Apply gate **TD-ARCHITECTURE** (`.claude/docs/director-gates/td-architecture.md`) as a self-review. Check all four criteria from that gate definition against the completed document.
**Review mode check** — apply before spawning LP-FEASIBILITY:
- `solo` → skip. Note: "LP-FEASIBILITY skipped — Solo mode." Proceed to Phase 8 handoff.
- `lean` → skip (not a PHASE-GATE). Note: "LP-FEASIBILITY skipped — Lean mode." Proceed to Phase 8 handoff.
- `full` → spawn as normal.
**Step 2 — Spawn `lead-programmer` via Task using gate LP-FEASIBILITY (`.claude/docs/director-gates.md`):**
**Step 2 — Spawn `lead-programmer` via `Agent` using gate LP-FEASIBILITY (`.claude/docs/director-gates/lp-feasibility.md`):**
Pass: architecture document path, technical requirements baseline summary, ADR list.
@@ -439,6 +521,10 @@ Omit this section entirely if there are no open QQs.
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
This skill follows the collaborative design principle at every phase:
1. **Load context silently** — do not narrate file reads
+80 -27
View File
@@ -1,13 +1,16 @@
---
name: create-control-manifest
description: "After architecture is complete, produces a flat actionable rules sheet for programmers — what you must do, what you must never do, per system and per layer. Extracted from all Accepted ADRs, technical preferences, and engine reference docs. More immediately actionable than ADRs (which explain why)."
description: "Flat must-do/never-do rules sheet per system and layer, extracted from Accepted ADRs. ADRs explain why; this is actionable."
argument-hint: "[update — regenerate from current ADRs]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
agent: technical-director
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
# Create Control Manifest
The Control Manifest is a flat, actionable rules sheet for programmers. It
@@ -22,18 +25,37 @@ status. Re-run whenever new ADRs are accepted or existing ADRs are revised.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## 1. Load All Inputs
### ADRs
- Glob `docs/architecture/adr-*.md` and read every file
- Filter to only Accepted ADRs (Status: Accepted) — skip Proposed, Deprecated,
Superseded
- Note the ADR number and title for every rule sourced
**Establish the denominator first.** Glob `docs/architecture/adr-*.md`. Call the
count **N**. If N is 0: "No ADRs found — run `/architecture-decision` before
building a control manifest." Stop.
### Technical Preferences
- Read `.claude/docs/technical-preferences.md`
- Extract: naming conventions, performance budgets, approved libraries/addons,
forbidden patterns
**Resolve status without reading the ADRs** — the filter must precede the read,
not follow it:
```
Grep pattern="^## Status" glob="docs/architecture/adr-*.md" output_mode="content" -A 3
```
Interpret against N:
| Result | Meaning | Action |
|---|---|---|
| **N matches, some read `Accepted`** | Normal. | The Accepted set is **A**; proceed with A. |
| **N matches, none `Accepted`** | Genuinely no Accepted ADRs. | "[N] ADRs found, none Accepted. A manifest built from Proposed ADRs would encode decisions that may still change." Ask whether to proceed with Proposed or stop. **Do not silently emit an empty manifest.** |
| **0 matches, N > 0** | **Malformed ADRs — not an empty Accepted set.** `## Status` is BLOCKING-if-missing. | "[N] ADRs found, none has a `## Status` section — acceptance cannot be determined. Run `/architecture-decision [file] retrofit` on each." **Stop.** Do not treat all ADRs as Accepted; do not emit a manifest. |
- Note the ADR number and title for every rule sourced.
### Project Config
- Read `naming.*` and `performance.*` from `project.yaml`; for any key absent or
empty, fall back to `.claude/docs/technical-preferences.md`
- Read approved libraries/addons and forbidden patterns from
`.claude/docs/technical-preferences.md` (not migrated to project.yaml)
### Engine Reference
- Read `docs/engine-reference/[engine]/VERSION.md` for engine + version
@@ -47,10 +69,28 @@ Report: "Loaded [N] Accepted ADRs, engine: [name + version]."
## 2. Extract Rules from Each ADR
Read **only these four sections** per Accepted ADR — not the whole file. Context,
Consequences, Migration Plan and Validation Criteria explain *why* a decision was
made; the manifest records *what to do*, so they are not needed here:
```
Grep pattern="^## (Decision|Alternatives Considered|Performance Implications|Engine Compatibility)" glob="docs/architecture/adr-*.md" output_mode="content" -A 30
```
Filter the results to the Accepted set **A** resolved above. If a section is
absent for a given ADR, note it per ADR and continue; if a section is absent
across **all** of A, report "No Accepted ADR contains a `[section]` section — the
manifest's [category] rules will be empty. Verify this is intended." Escalate to
a full read of one ADR only when its scanned sections cross-reference material
outside them (e.g. a Decision that says "subject to the constraints in Context").
For each Accepted ADR, extract:
### Required Patterns (from "Implementation Guidelines" section)
- Every "must", "should", "required to", "always" statement
### Required Patterns (from the `## Decision` section)
- Every "must", "should", "required to", "always" statement in the Decision body
— including any `### Implementation Guidelines` sub-heading when the ADR has one
(newer ADRs emit it; older ones state mandates directly in `## Decision`). Never
scan for `### Implementation Guidelines` alone — it is absent from many
skill-authored ADRs, and scanning for it yields an empty Required Patterns
section on a manifest that should have been full.
- Every specific pattern or approach mandated
### Forbidden Approaches (from "Alternatives Considered" sections)
@@ -82,12 +122,21 @@ If an ADR spans multiple layers, duplicate the rule into each relevant layer.
Combine rules that apply to all layers:
### From technical-preferences.md:
- Naming conventions (classes, variables, signals/events, files, constants)
- Performance budgets (target framerate, frame budget, draw call limits, memory ceiling)
### From project config (`project.yaml`, else `technical-preferences.md`):
- Naming conventions — `naming.*`: classes, variables, signals/events, files, constants
- Performance budgets — `performance.*`: target framerate, frame budget, draw call limits, memory ceiling
### From deprecated-apis.md:
- All deprecated APIs → Forbidden API entries
- Deprecated APIs → Forbidden API entries, **filtered for relevance to this
project**. Do not copy the deprecation table wholesale.
> Each entry must apply to what this project actually builds. `deprecated-apis.md`
> mixes dimensions and subsystems: its `GodotPhysics3D → Jolt Physics 3D` row is
> **3D-only**, so emitting it unqualified gives a 2D project a global rule about
> a physics engine it never uses. If you cannot tell whether an entry applies —
> 2D vs 3D, a module the project does not include — either scope the rule
> ("when using 3D physics: ...") or omit it and note it as unresolved. A manifest
> of rules that do not apply is one nobody reads, and `/create-stories` consumes
> this file.
### From current-best-practices.md (if available):
- Engine-recommended patterns → Required entries
@@ -130,7 +179,7 @@ Use `AskUserQuestion`:
- `lean` → skip. Note: "TD-MANIFEST skipped — Lean mode." Proceed to Phase 5.
- `full` → spawn as normal.
Spawn `technical-director` via Task using gate **TD-MANIFEST** (`.claude/docs/director-gates.md`).
Spawn `technical-director` via `Agent` using gate **TD-MANIFEST** (`.claude/docs/director-gates/td-manifest.md`).
Pass: the Control Manifest Preview from Phase 4 (rule counts per layer, full extracted rule list), the list of ADRs covered, engine version, and any rules sourced from technical-preferences.md or engine reference docs.
@@ -238,19 +287,19 @@ rule, see the referenced ADR.
### Naming Conventions
| Element | Convention | Example |
|---------|-----------|---------|
| Classes | [from technical-preferences] | [example] |
| Variables | [from technical-preferences] | [example] |
| Signals/Events | [from technical-preferences] | [example] |
| Files | [from technical-preferences] | [example] |
| Constants | [from technical-preferences] | [example] |
| Classes | [from naming.* in project.yaml, else technical-preferences.md] | [example] |
| Variables | [from naming.* in project.yaml, else technical-preferences.md] | [example] |
| Signals/Events | [from naming.* in project.yaml, else technical-preferences.md] | [example] |
| Files | [from naming.* in project.yaml, else technical-preferences.md] | [example] |
| Constants | [from naming.* in project.yaml, else technical-preferences.md] | [example] |
### Performance Budgets
| Target | Value |
|--------|-------|
| Framerate | [from technical-preferences] |
| Frame budget | [from technical-preferences] |
| Draw calls | [from technical-preferences] |
| Memory ceiling | [from technical-preferences] |
| Framerate | [from performance.* in project.yaml, else technical-preferences.md] |
| Frame budget | [from performance.* in project.yaml, else technical-preferences.md] |
| Draw calls | [from performance.* in project.yaml, else technical-preferences.md] |
| Memory ceiling | [from performance.* in project.yaml, else technical-preferences.md] |
### Approved Libraries / Addons
- [library] — approved for [purpose]
@@ -279,6 +328,10 @@ After writing the manifest:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Load silently** — read all inputs before presenting anything
2. **Show the summary first** — let the user see the scope before writing
3. **Ask before writing** — always confirm before creating or overwriting the manifest. On write: Verdict: **COMPLETE** — control manifest written. On decline: Verdict: **BLOCKED** — user declined write.
+76
View File
@@ -0,0 +1,76 @@
# /create-epics — Handoff Contract
## Role in Pipeline
Translates approved GDDs and architecture documents into one EPIC.md file per
architectural module, defining scope, ADR governance, engine risk, and requirement
traceability — sits between architecture review and story decomposition.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `design/gdd/systems-index.md` | System list, layer assignments, priority order | Yes |
| `design/gdd/[system].md` | `## Summary`, `## Acceptance Criteria`, `## Overview` (all 8 required sections) | Yes |
| `docs/architecture/architecture.md` | Module ownership, API boundaries | Yes |
| `docs/architecture/adr-NNNN-[slug].md` (all governing ADRs) | `Status:`, `GDD Requirements Addressed`, `Decision`, `Engine Compatibility` | Yes |
| `docs/architecture/control-manifest.md` | `Manifest Version:` date in header | Yes |
| `docs/architecture/tr-registry.yaml` | TR-IDs with `id`, `system`, requirement text | Yes |
| `docs/engine-reference/[engine]/VERSION.md` | Engine name, version, risk levels | Yes |
### Preconditions
- `/create-control-manifest` has been run and `docs/architecture/control-manifest.md` exists
- `/architecture-review` has passed (at minimum Foundation and Core ADRs are Accepted)
- All in-scope GDDs have status `Approved` or `Designed` in `systems-index.md`
- The target layer's GDDs are stable — do not run for Feature layer until Core is nearly complete
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `production/epics/[epic-slug]/EPIC.md` | `Layer`, `GDD` path, `Architecture Module`, `Status: Ready`, `## Governing ADRs` table, `## GDD Requirements` table with TR-IDs and ADR coverage, `## Definition of Done`, `## Overview` | Created per approved epic |
| `production/epics/index.md` | `Epic`, `Layer`, `System`, `GDD`, `Stories`, `Status` columns | Created or appended |
### Output Guarantees
- Every EPIC.md contains a `## Governing ADRs` table with at least one row (or a documented note if none apply)
- Every EPIC.md contains a `## GDD Requirements` table where each row has a `TR-ID` and an `ADR Coverage` cell (either `ADR-NNNN ✅` or `❌ No ADR`)
- The `GDD:` field in the EPIC.md header is a valid relative path to the source GDD
- The `Layer:` field is one of: Foundation, Core, Feature, Presentation
- The `Status:` field is set to `Ready`
- The `Stories:` field reads `Not yet created — run /create-stories [epic-slug]`
- Untraced requirements (TR-IDs with no ADR) are flagged in the GDD Requirements table with `❌ No ADR`
- `production/epics/index.md` has an entry for every epic written in this run
## Immutability Rules
- READS but does NOT modify: `design/gdd/systems-index.md`, all GDD files, `docs/architecture/architecture.md`, all ADR files in `docs/architecture/adr-NNNN-[slug].md` pattern, `docs/architecture/control-manifest.md`, `docs/architecture/tr-registry.yaml`, `docs/engine-reference/[engine]/VERSION.md`
- MODIFIES: `production/epics/[epic-slug]/EPIC.md` (creates), `production/epics/index.md` (creates or updates)
## Hard Constraints (Never Violate)
- Never create story files — this skill stops at the epic level
- Never invent content not sourced from GDDs, ADRs, or architecture docs
- Never skip the per-epic approval prompt before writing
- Never write an EPIC.md without first presenting the epic definition to the user
- Never mark a TR-ID as covered by an ADR unless that ADR's `Status:` is `Accepted`
- Never create epics for a layer whose dependency layer is not yet substantially complete
## Downstream Skill Expects
**Next skill:** /create-stories
It will read:
- `production/epics/[epic-slug]/EPIC.md` — specifically: `Layer:`, `GDD:` path, `Architecture Module:`, the full `## Governing ADRs` table (ADR IDs and summaries), and the full `## GDD Requirements` table (TR-IDs and ADR coverage status)
- `production/epics/index.md` — to enumerate available epics when no argument is given
It assumes:
- The `GDD:` path in EPIC.md resolves to a readable file
- Every ADR listed in `## Governing ADRs` exists as a file and has an `Accepted` status
- TR-IDs in `## GDD Requirements` match entries in `docs/architecture/tr-registry.yaml`
- The epic slug used in the directory name matches the slug referenced in `index.md`
- `Status: Ready` means stories have NOT yet been created (it will replace this line)
## Known Fragile Points
- If the EPIC.md template structure changes (section names, header field names, table column order), `/create-stories` will silently fail to parse governance data and may produce incomplete or incorrect stories
- If `tr-registry.yaml` is regenerated with renumbered IDs after EPIC.md files are written, the TR-IDs in existing EPIC.md files become stale and mislead `/create-stories`
- If an ADR is retroactively changed from `Accepted` to `Proposed` after the epic is written, the EPIC.md will still show it as governing — `/create-stories` will embed it without a BLOCKED flag
- If `systems-index.md` layer assignments change after epics are created, the `Layer:` field in existing EPIC.md files will be incorrect and `/create-stories` will use the wrong layer context
- `production/epics/index.md` is append-updated — if an epic is regenerated, a duplicate row may appear
+116 -18
View File
@@ -1,13 +1,18 @@
---
name: create-epics
description: "Translate approved GDDs + architecture into epics — one epic per architectural module. Defines scope, governing ADRs, engine risk, and untraced requirements. Does NOT break into stories — run /create-stories [epic-slug] after each epic is created."
description: "Turn GDDs plus architecture into epics — one per architectural module, with untraced requirements. Then /create-stories [epic-slug]."
argument-hint: "[system-name | layer: foundation|core|feature|presentation | all] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
agent: technical-director
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density,story_granularity,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Create Epics
An epic is a named, bounded body of work that maps to one architectural module.
@@ -22,18 +27,52 @@ will have changed.
**Next step after each epic:** `/create-stories [epic-slug]`
**When to run:** After `/create-control-manifest` and `/architecture-review` pass.
**When to run:** After `/create-control-manifest` and `/architecture-review` pass
(at `full`). At `standard`, critical ADRs + a control manifest suffice. At
`minimal`, this skill is **optional and not part of the path** — `/create-stories`
synthesizes the epic from `design/game-brief.md` itself (Option A). If run anyway,
it decomposes directly from the brief with no GDD/ADR/manifest prerequisite.
> **At `minimal`, this skill is optional — `/create-stories` synthesizes the epic**
> (Option A). At that tier `/create-stories` reads `design/game-brief.md`
> directly, writes a lightweight implicit `production/epics/<slug>/EPIC.md`, and
> generates stories from the MVP list — so the path is `/brainstorm` →
> `/create-stories` → `/dev-story`, with no separate `/create-epics` or
> `/sprint-plan` step. **At `standard`/`full` an epic IS required**:
> `/create-stories` reads `production/epics/[slug]/EPIC.md`, and skipping this
> skill there leaves `/dev-story` with no story to implement — a dead end, not a
> shortcut.
---
## 1. Parse Arguments
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** (per `.claude/docs/workflow-modes.md`):
create-epics runs project-wide: it uses the project-level tier for its
prerequisite expectations and consults
`workflow_overrides.system_overrides.<system>` per-system when reading each
in-scope GDD. See "Workflow tier adjustment" in Step 2.
**`story_granularity`** — it sizes the
epic's story breakdown: expect **3–5** child stories per epic at `coarse`, **5–10**
at `balanced` (default), **10–20** at `fine`.
**`docs.density`** — it controls the *depth* of each epic's written scope and
rationale, not the story count (that is `story_granularity`). `modes.rigor` sets
it alongside `workflow`; set `docs.density` explicitly to vary epic prose alone:
`terse` = scope as bullets, one-line rationale; `balanced` = a scope paragraph
with light rationale (default); `thorough` = full scope prose with governing-ADR
rationale and risk discussion. The EPIC.md tables (GDD requirements, governing
ADRs) are structural and stay whole at every density.
**Modes:**
- `/create-epics all` — process all systems in layer order
@@ -48,16 +87,34 @@ See `.claude/docs/director-gates.md` for the full check pattern.
## 2. Load Inputs
### Step 2a — Summary scan (fast)
### Step 2a — Summary scan (fast, fail-open)
Grep all GDDs for their `## Summary` sections before reading anything fully:
**Establish the denominator first.** Glob `design/gdd/*.md`, excluding the
non-system docs (`game-concept.md`, `systems-index.md`, `game-pillars.md`,
`gameplay-tags.md`, `entity-registry.md`, `fixture-swap-ledger.md`, and any
`gdd-cross-review-*.md` — the same set `gdd-structure-check.sh` skips). Call the
count **N**. If N is 0, there are no system GDDs — report "No system GDDs found
in `design/gdd/` — run `/design-system` first" and stop.
Scan for Summary sections:
```
Grep pattern="## Summary" glob="design/gdd/*.md" output_mode="content" -A 5
Grep pattern="^## Summary" glob="design/gdd/*.md" output_mode="content" -A 5
```
For `layer:` or `[system-name]` modes: filter to only in-scope GDDs based on
the Summary quick-reference. Skip full-reading anything out of scope.
Interpret the **M** matches against N. These are three different outcomes, and
a zero-match scan is **never** the same as "nothing in scope":
| Result | Meaning | Action |
|---|---|---|
| **M = N** | Every GDD has a Summary. | For `layer:`/`[system-name]` modes, use the Summary Quick-reference (Layer/Priority) to pick the in-scope set; skip full-reading the rest. |
| **0 < M < N** | Partial adoption — older GDDs predate `## Summary`. | Scope the M by their Summaries; determine the scope of the **N − M** unmatched from `systems-index.md` (layer/priority) and full-read those. |
| **0 matches, N > 0** | Expected for GDDs authored before `/design-system` emitted `## Summary`. | Determine scope for **all N** from `systems-index.md` and full-read the in-scope set. This is the pre-optimization behaviour — correct, only more expensive. Note once: "No `## Summary` sections found across [N] GDDs — scoping from `systems-index.md` instead of Summary." |
**Never treat an absent `## Summary` as an absent system.** The scan narrows the
*read* set when it succeeds; it never shrinks the *in-scope* set. In `all` mode
every system is in scope regardless of Summary, so the scan is a convenience
only — never a filter.
### Step 2b — Full document load (in-scope systems only)
@@ -68,13 +125,38 @@ Read for in-scope systems:
- `design/gdd/systems-index.md` — authoritative system list, layers, priority
- In-scope GDDs only (Approved or Designed status, filtered by Step 2a results)
- `docs/architecture/architecture.md` — module ownership and API boundaries
- Accepted ADRs **whose domains cover in-scope systems only** — read the "GDD Requirements Addressed", "Decision", and "Engine Compatibility" sections; skip ADRs for unrelated domains
- Accepted ADRs **whose domains cover in-scope systems only** — skip ADRs for
unrelated domains entirely. For each in-scope ADR, load only the "GDD
Requirements Addressed", "Decision", and "Engine Compatibility" sections —
never an unbounded full read:
```
Grep pattern="^## (GDD Requirements Addressed|Decision|Engine Compatibility)" path="docs/architecture/[adr-file].md" output_mode="content" -n
```
then `Read(offset, limit)` bounded to each match through the next `## `
heading (or to end of file for the last match). This matters most on a
large ADR — measured at 47k tokens this way vs. 103k for an unbounded
read of the same size file.
- `docs/architecture/control-manifest.md` — manifest version date from header
- `docs/architecture/tr-registry.yaml` — for tracing requirements to ADR coverage
- `docs/engine-reference/[engine]/VERSION.md` — engine name, version, risk levels
Report: "Loaded [N] GDDs, [M] ADRs, engine: [name + version]."
> **Workflow tier adjustment** (resolved in Step 1; per-system via
> `system_overrides`). The inputs above are the `full` baseline:
> - **`full`** — every in-scope GDD must be Approved with all 8 sections; TR
> registry + control manifest are required inputs; untraced requirements
> (Step 4) are flagged before proceeding.
> - **`standard`** — GDDs need the 5 required sections (+ conditional Formulas)
> approved; only **critical (Foundation-layer) ADRs** are expected; the control
> manifest is read if present, not required. A system pinned higher via
> `system_overrides` must still meet its higher bar.
> - **`minimal`** — decompose against `design/game-brief.md` +
> acceptance criteria. Do not require GDDs, ADRs, the TR registry, or the
> manifest; skip the untraced-requirement gate. If run, the epic is still
> produced — but note `/create-stories` also synthesizes one from the brief when
> this skill is skipped (the default `minimal` path).
---
## 3. Processing Order
@@ -87,15 +169,27 @@ Process in dependency-safe layer order:
Within each layer, use the order from `systems-index.md`.
> **At `minimal` there is no `systems-index.md`** — `/map-systems` is not required
> at that tier, so nothing has produced one. Derive the layer split and ordering
> from `design/game-brief.md` instead: its **Build order** field names what must
> exist first. Do not stop, and do not send the user to `/map-systems` to satisfy
> an ordering hint — the tier deliberately skips it.
---
## 4. Define Each Epic
For each system, map it to an architectural module from `architecture.md`.
Check ADR coverage against the TR registry:
Check ADR coverage against the TR registry **per the resolved tier** (Step 1):
- **`full`** — trace every TR-ID; warn on each untraced requirement (below).
- **`standard`** — only **critical (Foundation-layer) ADRs** are expected; trace
those. Treat untraced non-critical requirements as informational (list them, do
not block or emit the Blocked-story warning).
- **`minimal`** — skip this check entirely (no TR registry / ADR expected).
- **Traced requirements**: TR-IDs that have an Accepted ADR covering them
- **Untraced requirements**: TR-IDs with no ADR — warn before proceeding
- **Untraced requirements**: TR-IDs with no ADR — warn before proceeding (full only)
Present to user before writing anything:
@@ -132,7 +226,7 @@ Use `AskUserQuestion`:
- `lean` → skip (not a PHASE-GATE). Note: "PR-EPIC skipped — Lean mode." Proceed to Step 5 (write epic files).
- `full` → spawn as normal.
After all epics for the current layer are defined (Step 4 completed for all in-scope systems), and before writing any files, spawn `producer` via Task using gate **PR-EPIC** (`.claude/docs/director-gates.md`).
After all epics for the current layer are defined (Step 4 completed for all in-scope systems), and before writing any files, spawn `producer` via `Agent` using gate **PR-EPIC** (`.claude/docs/director-gates/pr-epic.md`).
Pass: the full epic structure summary (all epics, their scope summaries, governing ADR counts), the layer being processed, milestone timeline and team capacity.
@@ -233,6 +327,10 @@ After writing all epics for the requested scope:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **One epic at a time** — present each epic definition before asking to create it
2. **Warn on gaps** — flag untraced requirements before proceeding
3. **Ask before writing** — per-epic approval before writing any file
+81
View File
@@ -0,0 +1,81 @@
# /create-stories — Handoff Contract
## Role in Pipeline
Decomposes a single epic into implementable story files by tracing GDD acceptance
criteria through ADR decisions and manifest rules — sits between `/create-epics`
and `/story-readiness` + `/dev-story`.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `production/epics/[epic-slug]/EPIC.md` | `Layer:`, `GDD:` path, `Architecture Module:`, `## Governing ADRs` table, `## GDD Requirements` table with TR-IDs | Yes |
| `design/gdd/[filename].md` | All 8 required sections, especially `## Acceptance Criteria`, `## Formulas`, `## Edge Cases` | Yes |
| `docs/architecture/adr-NNNN-[slug].md` (all governing ADRs) | `Status:`, `Decision`, `Implementation Guidelines`, `Engine Compatibility`, `Engine Notes` | Yes |
| `docs/architecture/control-manifest.md` | Layer rules (required patterns, forbidden patterns, guardrails), `Manifest Version:` date in header | Yes |
| `docs/architecture/tr-registry.yaml` | All TR-IDs for the epic's system, with stable `id` values | Yes |
### Preconditions
- `/create-epics` has been run and the target `EPIC.md` has `Status: Ready`
- The EPIC.md contains a populated `## GDD Requirements` table (not empty)
- All governing ADRs listed in the EPIC.md exist as files
- Foundation epics have stories created before Core epics are started; Core before Feature; Feature before Presentation
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `production/epics/[epic-slug]/story-NNN-[slug].md` | `Epic:`, `Status:`, `Layer:`, `Type:`, `Manifest Version:`, `## Context` (GDD path + `TR-[system]-NNN` + ADR reference + ADR Decision Summary + Engine/Risk + Engine Notes + Control Manifest Rules), `## Acceptance Criteria`, `## Implementation Notes`, `## Out of Scope`, `## Test Evidence`, `## Dependencies` | Created per story |
| `production/epics/[epic-slug]/EPIC.md` | `## Stories` table replacing the "Not yet created" placeholder | Updated in-place |
### Output Guarantees
- Every story file contains a `TR-[system]-NNN` reference in its `## Context` section (or `TR-[system]-???` with a warning if the registry has no match)
- Every story file contains an `ADR Governing Implementation:` line referencing at least one ADR, or an explicit `No ADR applies` note
- Every story file has a `Status:` field — either `Ready` or `Blocked` (if the governing ADR is `Proposed`)
- Every story file has a `Type:` field — one of: Logic, Integration, Visual/Feel, UI, Config/Data
- Every story file has a `Manifest Version:` field matching the date from `docs/architecture/control-manifest.md`'s header at time of writing
- Every story file has a `## Test Evidence` section stating the expected evidence location for its type
- Every story file has a `## Acceptance Criteria` section with at least one checkbox item copied from the GDD
- Every story file has a `## Dependencies` section (may say "None" but is never omitted)
- The EPIC.md `## Stories` table is updated with a row per story including `#`, `Story` title, `Type`, `Status`, and `ADR`
- Stories with a `Proposed` ADR have `Status: Blocked` and a note: `BLOCKED: ADR-NNNN is Proposed — run /architecture-decision to advance it`
- Every story file has an `Engine` and a `Risk` field. `Risk` is taken from `docs/engine-reference/<engine>/VERSION.md`; when that file is missing or assigns no level, `Risk` is **`NOT ASSESSED (no VERSION.md risk rating)`** — never a guessed level
- **`NOT ASSESSED` is an emittable value of the `Risk` field**, and downstream readers must handle it. `/dev-story` treats it as HIGH when deciding whether to spawn the engine specialist: an unknown risk is not a low one
## Immutability Rules
- READS but does NOT modify: the epic's GDD, all ADR files, `docs/architecture/tr-registry.yaml`, `docs/architecture/control-manifest.md`
- MODIFIES: `production/epics/[epic-slug]/story-NNN-[slug].md` (creates), `production/epics/[epic-slug]/EPIC.md` (updates Stories section only)
## Hard Constraints (Never Violate)
- Never start implementation — this skill stops at the story file level
- Never invent acceptance criteria — all criteria must come from the GDD
- Never invent implementation notes — all guidance must come from the referenced ADR
- Never write story files without presenting the full story list for approval first
- Never mark a story `Status: Ready` if its governing ADR has `Status: Proposed`
- Never omit the `Manifest Version:` field — downstream readiness checks depend on it
- Never reuse a story number (NNN) that already exists in the epic directory
## Downstream Skill Expects
**Next skill:** /story-readiness (then /dev-story)
It will read:
- Each `story-NNN-[slug].md` file — specifically: `Status:`, `Type:`, `Manifest Version:` (header), `TR-[system]-NNN` (in `## Context`), `ADR Governing Implementation:` line, `## Acceptance Criteria` section, `## Test Evidence` section, `## Dependencies` section
- `docs/architecture/control-manifest.md` — to compare its `Manifest Version:` against the story's embedded version
- The referenced ADR file — to verify its `Status:` field is still `Accepted`
It assumes:
- `Manifest Version:` in the story header is a date string that can be compared against the manifest's current `Manifest Version:` date
- `TR-[system]-NNN` IDs are resolvable in `docs/architecture/tr-registry.yaml`
- The ADR referenced by name in `ADR Governing Implementation:` exists as a file in `docs/architecture/` (pattern: `adr-NNNN-[slug].md`)
- `Status: Ready` means the story is a candidate for assignment (not Draft, not in progress)
- `## Acceptance Criteria` contains checkbox items that are directly testable
- `## Test Evidence` specifies an exact file path or evidence doc path where proof will be stored
## Known Fragile Points
- If the story file format (header field names, section names, checkbox syntax) changes, `/story-readiness` will silently skip checks for fields it cannot parse — stories may pass readiness that should fail
- If `control-manifest.md` is regenerated with a new `Manifest Version:` date after stories are written, all existing stories will show a stale manifest version and fail the readiness manifest check — every story in the epic will need its `Manifest Version:` updated
- If a governing ADR is renumbered or its file is renamed after stories are written, the `ADR Governing Implementation:` reference in story files will point to a missing file and `/story-readiness` will BLOCK those stories
- If `tr-registry.yaml` deprecates or supersedes a TR-ID that is already embedded in story files, `/story-readiness` will flag those stories as NEEDS WORK
- The EPIC.md Stories table update is append-style — if `/create-stories` is run twice for the same epic, duplicate rows will appear in the table
+170 -37
View File
@@ -1,13 +1,18 @@
---
name: create-stories
description: "Break a single epic into implementable story files. Reads the epic, its GDD, governing ADRs, and control manifest. Each story embeds its GDD requirement TR-ID, ADR guidance, acceptance criteria, story type, and test evidence path. Run after /create-epics for each epic."
description: "Break one epic into implementable stories embedding TR-ID, ADR guidance, acceptance criteria. Reads the control manifest. After /create-epics."
argument-hint: "[epic-slug | epic-path] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
agent: lead-programmer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density,story_granularity,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Create Stories
A story is a single implementable behaviour — small enough to complete in one
@@ -27,38 +32,135 @@ then Core, and so on — matching the dependency order.
## 1. Parse Argument
Extract `--review [full|lean|solo]` if present and store as the review mode
override for this run. If not provided, read `production/review-mode.txt`
(default `lean` if missing). This resolved mode applies to all gate spawns
in this skill — apply the check pattern from `.claude/docs/director-gates.md`
before every gate invocation.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** for this epic's system (per `.claude/docs/workflow-modes.md`) —
use the `system_overrides` row for `<system>` if the block lists one, else the
project value. `<system>` is the epic slug / its GDD system. The tier sets which prerequisites block — see the note in Step 2.
**`story_granularity`** — it sets each
story's AC load: **5–10 ACs covering a whole feature** at `coarse`, **2–4 ACs
covering one task** at `balanced` (default), **1 AC** at `fine` (the story name is
the AC restatement). Group or split ACs into stories to hit the target.
**`docs.density`** — it controls the *depth* of each story's prose (context,
implementation notes, ADR summary), not the AC count (that is
`story_granularity`) and never the AC text itself. `modes.rigor` sets it
alongside `workflow`; set `docs.density` explicitly to vary story prose alone:
`terse` = notes as bullets, no preamble; `balanced` = short context paragraph +
notes (default); `thorough` = full context, implementation guidance, and ADR
rationale. The embedded TR-ID reference, ADR Version stamp, and acceptance
criteria are structural and are never trimmed by density.
- `/create-stories [epic-slug]` — e.g. `/create-stories combat`
- `/create-stories production/epics/combat/EPIC.md` — full path also accepted
- No argument — ask: "Which epic would you like to break into stories?"
Glob `production/epics/*/EPIC.md` and list available epics with their status.
- No argument — at `minimal` there are no epics yet (Option A): skip to Step 2's
`minimal` branch and synthesize the epic from `design/game-brief.md`. At
`standard`/`full`, ask "Which epic would you like to break into stories?" and
Glob `production/epics/*/EPIC.md` to list available epics with their status.
> **If that glob returns nothing at `standard`/`full`, stop — do not build a
> question with no options.** Report:
> "No epics found under `production/epics/`. Run `/create-epics layer: foundation`
> first — an epic is what this skill decomposes."
>
> **The zero-epic path is load-bearing.** Asking which epic *and* globbing to
> list them leaves an `AskUserQuestion` with nothing to offer when the glob is
> empty. Route to `/create-epics` instead — it is named as **Previous step**
> in this skill's own header.
>
> Note what this skill guarded and what it did not. Step 2's ADR validation is
> thorough: three tiers, each with its own stop condition, and an explicit
> message naming the missing file. That is the **deepest** input. The **first**
> input — does an epic exist at all — went unchecked. Guarding the far end of a
> chain while leaving the near end open is the shape to watch for.
>
> At `minimal` this does not apply: there are deliberately no epics, and the
> branch above synthesizes one from the brief.
---
## 2. Load Everything for This Epic
Read in full:
> **`minimal` tier — synthesize the epic from the brief** (Option A). At
> `minimal` there is no `/create-epics` step and no `EPIC.md`. Instead:
> 1. Read `design/game-brief.md` in full (it is one page).
> 2. Synthesize an implicit epic: write a lightweight
> `production/epics/<slug>/EPIC.md`, where `<slug>` is the brief's slugified
> working title (`mvp` if untitled) — goal = the brief's one-sentence pitch,
> scope = its MVP feature list, ordering = its **Build order**. Keep it terse;
> this is the container `/dev-story` and `/sprint-status` expect.
> 3. Generate **one coarse story per MVP feature** (Step 3+), in Build-order
> sequence, each traced to the brief (not a GDD/TR-ID). Leave stories unblocked
> on ADR grounds — none exist at this tier.
> Skip the GDD, control-manifest, TR-registry, and ADR reads below (none exist at
> `minimal`), then continue to Step 3 with the synthesized epic.
For `standard`/`full` (a `/create-epics` epic exists), read in full (these are small):
- `production/epics/[epic-slug]/EPIC.md` — epic overview, governing ADRs, GDD requirements table
- The epic's GDD (`design/gdd/[filename].md`) — read all 8 sections, especially Acceptance Criteria, Formulas, and Edge Cases
- All governing ADRs listed in the epic — read the Decision, Implementation Guidelines, Engine Compatibility, and Engine Notes sections
- `docs/architecture/control-manifest.md` — extract rules for this epic's layer; note the Manifest Version date from the header
- `docs/architecture/tr-registry.yaml` — load all TR-IDs for this system
- The epic's GDD (`design/gdd/[filename].md`) — at `full` read all 8 sections; at `standard` the 5 required sections (+ conditional Formulas); at `minimal` the GDD may not exist — work from the epic brief + acceptance criteria. Always prioritise Acceptance Criteria, Formulas, and Edge Cases where present.
- `docs/architecture/control-manifest.md` — grep only this epic's layer (`Grep pattern="^## <layer> Layer Rules" path="docs/architecture/control-manifest.md" output_mode="content" -A 40`) plus the header Manifest Version date, not a full read of all layers
- `docs/architecture/tr-registry.yaml` — grep only this system's entries (`Grep pattern="system: <slug>" path="docs/architecture/tr-registry.yaml" output_mode="content" -B1 -A5`, or `id: TR-<slug>-`), not the whole cross-system registry
**ADR existence validation**: After reading the governing ADRs list from the epic, confirm each ADR file exists on disk. If any ADR file cannot be found, **stop immediately** before decomposing any story:
**Load each governing ADR by section — never with an unbounded full read.** A
substantial ADR exceeds the 25k-token `Read` cap, and a capped read's only
recovery is paging through the remainder — the most expensive possible way to
read a file (measured at 103k tokens on a 34k-token ADR vs ~54k for targeted
reads of the same file). Per ADR:
1. **Map the headings** (cheap — line numbers only):
```
Grep pattern="^## |^### Implementation Guidelines" path="docs/architecture/[adr-file].md" output_mode="content" -n
```
2. **Bounded-read exactly the sections this skill consumes**, using the line
numbers from the map to set `Read(offset, limit)` spans that end where the
next section begins:
- `## Summary` and `## Decision` (including its `### Implementation
Guidelines` subsection) — these feed the story's ADR Decision Summary
and Implementation Notes.
- `## Engine Compatibility` — feeds the story's Engine, Risk, and Engine
Notes fields. (Engine Notes is a *story* field derived from this
section — it is not an ADR section name; do not search for one.)
3. **Capture the `## Last Verified` date**:
```
Grep pattern="^## (Last Verified|Date)" path="docs/architecture/[adr-file].md" output_mode="content" -A 1
```
Use `Last Verified`, falling back to `Date`, then to `unversioned` if both
are absent. This becomes the story's `ADR Version` stamp — `/dev-story`
uses it to decide whether it can trust this story's distilled summary
instead of re-opening the ADR.
Skip Context, Alternatives Considered, Consequences, Risks, and any
Amendments Log unless a section you loaded explicitly cross-references one of
their entries — then take only the referenced entry with one more bounded
read. If the heading map comes back empty (a nonstandard ADR predating the
template), fall back to one full `Read` — and if that read truncates at the
cap, do **not** page through the remainder; grep for the story-relevant
content directly and flag the ADR for `/architecture-decision [file]
retrofit`.
**ADR existence validation** (tier-gated — resolved in Step 1): After reading the governing ADRs list from the epic, confirm each referenced ADR file exists on disk.
- **`full`** — if **any** referenced ADR file cannot be found, **stop immediately** before decomposing any story.
- **`standard`** — stop only if a **critical (Foundation-layer) ADR** is missing; for a missing non-critical ADR, **warn and continue** (the story embeds the ADR reference and is set `Status: Blocked` until the ADR exists).
- **`minimal`** — no ADR requirement; do **not** stop. Embed any ADR references that do exist; otherwise decompose against the brief + acceptance criteria and leave stories unblocked on ADR grounds.
When stopping (full / standard-critical):
> "Epic references [ADR-NNNN: title] but `docs/architecture/[adr-file].md` was not found.
> Check the filename in the epic's Governing ADRs list, or run `/architecture-decision`
> to create it. Cannot create stories until all referenced ADR files are present."
Do not proceed to Step 3 until all referenced ADR files are confirmed present.
At `full`, do not proceed to Step 3 until all referenced ADR files are confirmed present.
Report: "Loaded epic [name], GDD [filename], [N] governing ADRs (all confirmed present), control manifest v[date]."
Report: "Loaded epic [name], GDD [filename], [N] governing ADRs [ADR status], [manifest status]." State the **actual** situation for the resolved tier — e.g. "all confirmed present, control manifest v[date]" at full; "M present, K missing non-critical (embedded + Blocked)" at standard; "no ADRs / manifest required" at minimal. Do not assert "all confirmed present" if any referenced ADR was missing, or name a manifest version when none exists.
---
@@ -87,8 +189,11 @@ For each GDD acceptance criterion:
2. Each group = one story
3. Order stories: foundational behaviour first, edge cases last, UI last
**Story sizing rule:** one story = one focused session (~2-4 hours). If a
group of criteria would take longer, split into two stories.
**Story sizing rule:** size each story to the resolved `modes.story_granularity`
target (above). The "~2-4 hours / one focused session" heuristic is the
`balanced` default — at `coarse` a story spans a whole feature (5–10 ACs,
multi-day), at `fine` a story is a single AC. Split or group criteria to hit the
resolved target, not a fixed session length.
For each story, determine:
- **GDD requirement**: which acceptance criterion(ia) does this satisfy?
@@ -110,24 +215,17 @@ For each story, determine:
- `lean` → skip (not a PHASE-GATE). Note: "QL-STORY-READY skipped — Lean mode." Proceed to Step 5 (present stories for review).
- `full` → spawn as normal.
After decomposing all stories (Step 4 complete) but before presenting them for write approval, spawn `qa-lead` via Task using gate **QL-STORY-READY** (`.claude/docs/director-gates.md`).
After decomposing all stories (Step 4 complete) but before presenting them for write approval, spawn `qa-lead` **once** via `Agent` using gate **QL-STORY-READY** (`.claude/docs/director-gates/ql-story-ready.md`). A single call returns **both** the readiness verdict and the test-case specs — do not spawn `qa-lead` a second time to generate specs.
Pass: the full story list with acceptance criteria, story types, and TR-IDs; the epic's GDD acceptance criteria for reference.
Pass: the full story list with acceptance criteria, story types, and TR-IDs; the epic's GDD acceptance criteria for reference. Require in the return:
1. The QL-STORY-READY verdict per story (ADEQUATE / GAPS / INADEQUATE).
2. For every story it marks **ADEQUATE**, its test-case spec block (formats below) — one Given/When/Then per acceptance criterion for Logic and Integration stories, or manual verification steps for Visual/Feel and UI stories.
Present the QA lead's assessment. For each story flagged as GAPS or INADEQUATE, revise the acceptance criteria before proceeding — stories with untestable criteria cannot be implemented correctly. Once all stories reach ADEQUATE, proceed.
Present the assessment. For each story flagged GAPS or INADEQUATE, revise the acceptance criteria before proceeding — untestable criteria cannot be implemented correctly; those stories carry no specs until they reach ADEQUATE (re-request specs for just those in a follow-up call only if a revision was needed). Once all stories are ADEQUATE, proceed with the returned specs.
**Before generating test specs**: Glob `production/qa/qa-plan-*.md` for the most recently modified file. If found, read it and check whether it contains test case specifications for the stories in this epic (look for story titles or slugs in the plan's Automated Tests Required section). If matching specs exist:
- Use `AskUserQuestion`:
- Prompt: "A QA plan exists at [path] with test specs for some of these stories. How do you want to proceed?"
- Options:
- `Use existing specs from the QA plan — embed them into the story files (Recommended)`
- `Ask qa-lead to generate fresh specs — override the QA plan`
- `Skip test spec generation — I'll fill in ## QA Test Cases manually`
- If "Use existing specs": extract the test case specs from the qa-plan for each matching story and embed them directly into the `## QA Test Cases` section. No qa-lead spawn needed for those stories. Only spawn qa-lead for stories with no coverage in the qa-plan.
- If "Generate fresh": proceed with the qa-lead spawn below as normal.
- If "Skip": leave `## QA Test Cases` with a placeholder: `*Test cases not yet defined — run /qa-plan to generate them.*`
**Prefer an existing QA plan when one already covers a story** — this substitutes for the qa-lead's specs, it does not add a spawn. Glob `production/qa/qa-plan-*.md` for the most recent file; if it holds test specs for stories in this epic (match titles/slugs in its Automated Tests Required section) that differ from the qa-lead's, use `AskUserQuestion` (Use QA-plan specs / Use qa-lead specs / Skip and leave `*Test cases not yet defined — run /qa-plan to generate them.*`). Either way no additional `qa-lead` spawn occurs.
**After ADEQUATE** (or after qa-plan import): for every Logic and Integration story, ask the qa-lead to produce concrete test case specifications — one per acceptance criterion — in this format:
The spec block formats — Logic/Integration:
```
Test: [criterion text]
@@ -181,6 +279,34 @@ Use `AskUserQuestion`:
For each story, write `production/epics/[epic-slug]/story-[NNN]-[slug].md`:
> **At `minimal` tier the Context/traceability inputs do not exist** (no GDD, ADR,
> TR registry, or control manifest). Fill the template from the brief instead —
> apply this mapping exactly, so every run is deterministic rather than improvised:
> - **GDD** → `design/game-brief.md`
> - **Requirement** → `Brief MVP feature N` (the feature this story implements — NOT a `TR-[system]-NNN` ID)
> - **ADR Governing Implementation / ADR Decision Summary / ADR Version** → `N/A (minimal — no ADRs)`
> - **Manifest Version** and **Control Manifest Rules (this layer)** → `N/A (minimal — no control manifest)`
> - **Engine** and **Risk** → read `docs/engine-reference/<engine>/VERSION.md`
> (engine from `engine.name`). **Engine** is `engine.name` + `engine.version`.
> **Risk** is the risk level that file assigns to the pinned version — its
> post-cutoff timeline row, or its stated overall risk. If the file is missing
> or assigns no level, write `NOT ASSESSED (no VERSION.md risk rating)` — never
> guess a level.
>
> > **This field is load-bearing and had no rule, so it was improvised.**
> > `/dev-story` Phase 3 spawns the engine specialist as a mandatory secondary
> > "when engine risk is HIGH (from the ADR or VERSION.md)". At `minimal` there
> > is no ADR, so `VERSION.md` is the *only* source — and nothing here told this
> > skill to read it. A story written with an invented `Risk: MEDIUM` against a
> > `VERSION.md` rating of HIGH silently disables the specialist review. In the
> > run that found this, that review was what caught two wrong engine defaults.
> > Treat `NOT ASSESSED` as HIGH for the spawn decision: an unknown risk is not
> > a low one.
> - **Engine Notes** → `none (no ADR engine-compatibility analysis at minimal)`
> - The Acceptance-Criteria source line → "From `design/game-brief.md` (the **Player goal & fail state** field + the MVP feature this story implements), scoped to this story" — derive concrete, testable ACs from what the user wrote there rather than inventing them from a bare MVP bullet
> - The **`## QA Test Cases`** section → at any tier where the QL-STORY-READY / qa-lead gate is skipped (`minimal`, or `lean`/`solo` review mode) no qa-lead specs are authored; write "*N/A — no qa-lead specs at this tier; implement against the Acceptance Criteria above*" rather than improvising test cases.
> - Any **Test Evidence / DoD** line is governed by `qa.level`, not this template — at `qa.level: minimal` it is **waived** (advisory, never "must exist and pass").
```markdown
# Story [NNN]: [title]
@@ -200,6 +326,7 @@ For each story, write `production/epics/[epic-slug]/story-[NNN]-[slug].md`:
**ADR Governing Implementation**: [ADR-NNNN: title]
**ADR Decision Summary**: [1-2 sentence summary of what the ADR decided]
**ADR Version**: [the ADR's `## Last Verified` date, else its `## Date`, else `unversioned`]
**Engine**: [name + version] | **Risk**: [LOW / MEDIUM / HIGH]
**Engine Notes**: [from ADR Engine Compatibility section — post-cutoff APIs, verification required]
@@ -240,7 +367,7 @@ change meaning. This is what the programmer reads instead of the ADR.]
## QA Test Cases
*Written by qa-lead at story creation. The developer implements against these — do not invent new test cases during implementation.*
*Written by qa-lead at story creation. The developer implements against these — do not invent new test cases during implementation. (At tiers where the QL-STORY-READY gate is skipped — `minimal`, or `lean`/`solo` review mode — no qa-lead specs exist; see the `minimal` mapping note above.)*
**[For Logic / Integration stories — automated test specs]:**
@@ -261,9 +388,11 @@ change meaning. This is what the programmer reads instead of the ADR.]
## Test Evidence
*Governed by `qa.level`: at `qa.level: minimal` the evidence below is **waived** (advisory, never "must exist and pass").*
**Story Type**: [type]
**Required evidence**:
- Logic: `tests/unit/[system]/[story-slug]_test.[ext]` — must exist and pass
- Logic: `tests/unit/[system]/[story-slug]_test.[ext]` — must exist and pass (`/story-done` checks that it EXISTS; pass/fail is established by `/gate-check` and `/smoke-check`, both later)
- Integration: `tests/integration/[system]/[story-slug]_test.[ext]` OR playtest doc
- Visual/Feel: `production/qa/evidence/[story-slug]-evidence.md` + sign-off
- UI: `production/qa/evidence/[story-slug]-evidence.md` or interaction test
@@ -294,7 +423,7 @@ Replace the "Stories: Not yet created" line with a populated table:
### Also update `production/epics/index.md`
Find the row in the index table matching this epic (by epic name or slug). Update its `Stories` column from `Not yet created` to `[N] stories` (where N is the count just written). If the index file does not exist, skip silently.
Find the row in the index table matching this epic (by epic name or slug). Update its `Stories` column from `Not yet created` to `[N] stories` (where N is the count just written). If the index file does not exist, say so in one line — `Systems index not updated: design/gdd/systems-index.md absent` — and continue. Do not skip silently: the index is what a reader consults to learn which epics have stories, so an un-updated one keeps reporting `Not yet created` for work that now exists, and nothing else would ever reveal the gap.
---
@@ -320,6 +449,10 @@ Note in output: "Work through stories in order — each story's `Depends on:` fi
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Read before presenting** — load all inputs silently before showing the story list
2. **Ask once** — present all stories for the epic in one summary, not one at a time
3. **Warn on blocked stories** — flag any story with a Proposed ADR before writing
+36 -9
View File
@@ -1,9 +1,10 @@
---
name: day-one-patch
description: "Prepare a day-one patch for a game launch. Scopes, prioritises, implements, and QA-gates a focused patch addressing known issues discovered after gold master but before or immediately after public launch. Treats the patch as a mini-sprint with its own QA gate and rollback plan."
description: "Day-one launch patch — focused fix for known issues found after gold master. Mini-sprint with QA gate and rollback."
argument-hint: "[scope: known-bugs | cert-feedback | all]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
---
@@ -33,15 +34,32 @@ ships. It is a mini-sprint — not a hotfix, not a full sprint.
## Phase 1: Load Release Context
Read:
- `production/stage.txt` — confirm project is in Release stage
- `project.stage` in `project.yaml` (fallback `production/stage.txt`) — confirm project is in Release stage
- The most recent file in `production/gate-checks/` — read the release gate verdict
- `production/qa/bugs/*.md` — load all bugs with Status: Open or Fixed — Pending Verification
- `production/sprints/` most recent — understand what shipped
- `production/security/security-audit-*.md` most recent — check for any open security items
If `production/stage.txt` is not `Release` or `Polish`:
If the resolved stage (project.yaml → stage.txt) is not `Release` or `Polish`:
> "Day-one patch prep is for Release-stage projects. Current stage: [stage]. This skill is not appropriate until you are approaching launch."
**Check the premise, do not assume it.** This whole skill rests on there being a
gold master that already passed a release gate — that premise is what justifies
its lightweight QA pass instead of a full one. So verify it rather than inferring
it from the stage value:
- **No file in `production/gate-checks/`**, or none recording a release-gate
verdict: report `Release gate: NOT ASSESSED — no gate-check record found`. Do
not proceed silently. Say plainly that the reduced QA scope below is justified
by a gate nobody can find, and ask whether to run `/gate-check` first or
proceed with a full QA pass instead.
- **The most recent record is FAIL, CONCERNS or NOT ASSESSED**: name it and stop.
A day-one patch on top of a build that never passed its gate is not a day-one
patch; it is the release gate, arriving late and scoped to the wrong changes.
- `project.stage: Release` on its own does **not** establish this. The stage is a
claim about where the project is; the gate record is the evidence that it earned
the position.
---
## Phase 2: Scope the Patch
@@ -84,7 +102,7 @@ Use `AskUserQuestion` to confirm proceeding or reduce scope.
Before any code is written, define the rollback procedure. This is non-negotiable.
Spawn `release-manager` via Task. Ask them to produce a rollback plan covering:
Spawn `release-manager` via `Agent`. Ask them to produce a rollback plan covering:
- How to revert to the gold master build on each target platform
- Platform-specific rollback constraints (some platforms cannot roll back cert builds)
- Who is responsible for triggering the rollback
@@ -100,14 +118,14 @@ Do not proceed to Phase 4 until the rollback plan is written.
For each bug in the approved scope, spawn a focused implementation loop:
1. Spawn `lead-programmer` via Task with:
1. Spawn `lead-programmer` via `Agent` with:
- The bug report (exact reproduction steps and root cause if known)
- The constraint: minimum viable fix only, no cleanup
- The affected files (from bug report Technical Context section)
2. The lead-programmer implements and runs targeted tests.
3. Spawn `qa-tester` via Task to verify: does the bug reproduce after the fix?
3. Spawn `qa-tester` via `Agent` to verify: does the bug reproduce after the fix?
For config/data-only fixes: make the change directly (no programmer agent needed). Confirm the value changed and re-run any relevant smoke test.
@@ -117,7 +135,7 @@ For config/data-only fixes: make the change directly (no programmer agent needed
This is a lightweight QA pass — not a full `/team-qa`. The patch is already QA-approved from the release gate; we are only re-verifying the changed areas.
Spawn `qa-lead` via Task with:
Spawn `qa-lead` via `Agent` with:
- List of all changed files
- List of bugs fixed (with verification status from Phase 4)
- The smoke check scope for the affected systems
@@ -130,6 +148,14 @@ Run the required QA scope:
QA verdict must be PASS or PASS WITH WARNINGS before proceeding. If FAIL: scope the failing fix out of the day-one patch and defer to 1.1.
**If the QA verdict is `NOT ASSESSED`, that is not a pass.** `/smoke-check` returns
it when the suite never ran — no build, no runner, or a result nobody confirmed.
Do not proceed on it and do not re-read it as PASS WITH WARNINGS: the warnings
value means somebody looked and saw something minor, and this means nobody looked.
Either obtain the result (the verdict names what would make it runnable) or defer
the fix to 1.1. A day-one patch ships to every player who buys the game on day
one, which is the worst possible audience for an unverified change.
---
## Phase 6: Generate Patch Record
@@ -161,10 +187,11 @@ QA verdict must be PASS or PASS WITH WARNINGS before proceeding. If FAIL: scope
## QA Sign-Off
**QA scope**: [Targeted smoke / Broader regression]
**Verdict**: [PASS / PASS WITH WARNINGS]
**Verdict**: [PASS / PASS WITH WARNINGS / NOT ASSESSED]
**QA lead**: qa-lead agent
**Date**: [date]
**Warnings (if any)**: [list or "None"]
**Not assessed (if any)**: [what could not be checked, and why — or "None"]
---
+172 -25
View File
@@ -1,17 +1,40 @@
---
name: design-review
description: "Reviews a game design document for completeness, internal consistency, implementability, and adherence to project design standards. Run this before handing a design document to programmers."
argument-hint: "[path-to-design-doc] [--depth full|lean|solo]"
description: "Reviews one design document for completeness, internal consistency, implementability, and design standards. Before handing to programmers."
argument-hint: "[path-to-design-doc] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
## Phase 0: Parse Arguments
Extract `--depth [full|lean|solo]` if present. Default is `full` when no flag is given.
**Note**: `--depth` controls the *analysis depth* of this skill (how many specialist agents are spawned). It is independent of the global review mode in `production/review-mode.txt`, which controls director gate spawning. These are two different concepts — `--depth` is about how thoroughly *this* skill analyses the document.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`workflow`** for the GDD under review — use the `system_overrides` row for `<system>` if the block lists one, else the project value. Validation scope follows the tier:
- `full` — all 8 sections validated; any missing section blocks approval.
- `standard` — the 5 required sections (Overview, Detailed Rules, Edge Cases,
Dependencies, Acceptance Criteria) block if missing; Formulas blocks only when
the system defines numeric rules (rates, curves, thresholds, costs — the
category is a hint, not the test); Player Fantasy and
Tuning Knobs are advisory (warn, never block) unless `workflow_overrides`
require them.
- `minimal` — no GDD is expected; if one exists, validate the 5 standard
sections advisorily.
Resolved mode controls how thorough this review is:
- **`full`**: Complete review — all phases + specialist agent delegation (Phase 3b)
- **`lean`**: All phases, no specialist agents — faster, single-session analysis
@@ -21,7 +44,68 @@ Extract `--depth [full|lean|solo]` if present. Default is `full` when no flag is
## Phase 1: Load Documents
Read the target design document in full. Read CLAUDE.md to understand project context and standards. Read related design documents referenced or implied by the target doc (check `design/gdd/` for related systems).
**Freshness check first — a re-review of an unchanged document costs full
price (~46k tokens, measured) and reproduces the same verdict.** Run:
```
Bash: bash .claude/scripts/review-receipts.sh check "design/gdd/reviews/[doc-name]-review-log.md" "[target-doc-path]" "design/registry/entities.yaml"
```
The registry is in the check because this review consults it for
cross-document facts — an unchanged GDD reviewed against a *changed*
registry can reach different conclusions, so the skip is only safe when
**every** listed line reads `UNCHANGED` (an absent registry simply doesn't
appear in the output and doesn't block the skip).
- **All `UNCHANGED`** and the log's latest entry carries a verdict — surface it:
*"This document is byte-identical to its last review on [date] (verdict:
[verdict])."* If that verdict was APPROVED, offer via `AskUserQuestion`:
`[A] Use the prior verdict (Recommended)` / `[B] Re-review anyway` —
`guided` proceeds with [A] and notes it; `autonomous` logs via
`log_decision` and uses the prior verdict. If it was NEEDS REVISION or
MAJOR REVISION NEEDED, say so plainly: the document has not changed since
it failed review — the prior findings stand; revising the document is the
next step, not re-reviewing it. Offer to display the prior findings from
the log.
- **Only the registry line reads `CHANGED`** (doc `UNCHANGED`) — the prior
verdict stands except for cross-document facts: re-verify the doc's
registry-sourced values against the new registry and re-issue the verdict;
escalate to a full re-review only if a conflict appears.
- **Target doc `CHANGED` or `NEW`, or `RECEIPT: NONE`** — proceed with the
full review below. **Do not offer a partial/delta re-review that skips
reading or re-analyzing unchanged sections.** Measured against a full review:
three independent designs (a straightforward section-scoped pass, one with
an explicit forced whole-document scan step, and one gated on a
genuinely thorough two-round prior review) each caught only 2 of 6 real
defects a full review found on the same document, and the most
careful version cost *more* tokens than the full review while catching
the same reduced fraction. "Unchanged since last review" only means
byte-identical to what was reviewed then — it says nothing about whether
that prior pass was itself complete, and no amount of "scan everything
anyway" instruction reliably overcame a model's attention naturally
narrowing to the flagged change.
Read the target design document in full. Read CLAUDE.md to understand project context and standards.
**For cross-document facts, prefer the registry over sibling GDDs.** If
`design/registry/entities.yaml` exists **and lists entries for this system**,
grep it — these are the established facts this GDD must not contradict, and they
replace reading sibling GDDs to rediscover them:
```
Grep pattern="source: design/gdd/[system].md" path="design/registry/entities.yaml" output_mode="content" -A 6
Grep pattern="design/gdd/[system].md" path="design/registry/entities.yaml" output_mode="content" -B 8
```
The first finds entries this system **owns** — the `-A 6` context includes their
`referenced_by:` block. The second finds entries that **reference** this system —
`referenced_by:` is a block sequence (the key and its paths are on separate
lines), so match the path with `-B 8` context to see the owning entry, not a
`referenced_by.*name` one-liner (which never matches the block form).
**If `design/registry/entities.yaml` does not exist, or lists no entry for this
system** — the file ships as an empty stub, so this is the default until
`/design-system` has populated it — fall back to reading the related GDDs the
target doc names in its Dependencies section. Bound the read to those, not to
everything "implied". Do not glob-read all of `design/gdd/`.
**Dependency graph validation:** For every system listed in the Dependencies section, use Glob to check whether its GDD file exists in `design/gdd/`. Flag any that don't exist yet — these are broken references that downstream authors will hit.
@@ -33,16 +117,34 @@ Read the target design document in full. Read CLAUDE.md to understand project co
## Phase 2: Completeness Check
Evaluate against the Design Document Standard checklist:
**Step 2a — gather section presence deterministically (no document read):**
- [ ] Has Overview section (one-paragraph summary)
- [ ] Has Player Fantasy section (intended feeling)
- [ ] Has Detailed Rules section (unambiguous mechanics)
- [ ] Has Formulas section (all math defined with variables)
- [ ] Has Edge Cases section (unusual situations handled)
- [ ] Has Dependencies section (other systems listed)
- [ ] Has Tuning Knobs section (configurable values identified)
- [ ] Has Acceptance Criteria section (testable success conditions)
```
Bash: bash .claude/scripts/gdd-structure-check.sh [target-doc-path]
```
It prints a `PRESENT:` list and, when applicable, an `ABSENT:` list. It reports
**presence only** and makes no REQUIRED/ADVISORY judgment — that is Step 2b's
job. It already accepts `## Detailed Design` as satisfying the `Detailed Rules`
requirement, so do not flag that as missing.
**Step 2b — apply the tier.** Using the Step 2a lists, evaluate against the
Design Document Standard checklist below. **Mark each section REQUIRED or
ADVISORY per the resolved workflow tier (Phase 0).** A missing REQUIRED section
blocks approval; a missing ADVISORY section is surfaced as a recommendation but
does not block.
A section reported PRESENT can still fail review if it is an empty heading —
spot-read any section the verdict actually turns on.
- [ ] Has Overview section (one-paragraph summary) — REQUIRED at all tiers
- [ ] Has Player Fantasy section (intended feeling) — REQUIRED at `full`; ADVISORY at `standard`
- [ ] Has Detailed Rules section (unambiguous mechanics) — REQUIRED at `full`/`standard`. The GDD template titles this section `## Detailed Design` (it carries Core Rules / States / Interactions sub-headings); accept **either** heading as satisfying this requirement — do not flag "Detailed Rules" as missing when a `## Detailed Design` section is present.
- [ ] Has Formulas section (all math defined with variables) — REQUIRED at `full`; at `standard` REQUIRED whenever the system defines numeric rules (rates, curves, thresholds, costs, damage, drop weights), else ADVISORY. The system's `Category` is a hint, not the test — do not clear this on a category token alone
- [ ] Has Edge Cases section (unusual situations handled) — REQUIRED at `full`/`standard`
- [ ] Has Dependencies section (other systems listed) — REQUIRED at `full`/`standard`
- [ ] Has Tuning Knobs section (configurable values identified) — REQUIRED at `full`; ADVISORY at `standard` unless `workflow_overrides.tuning_knobs`
- [ ] Has Acceptance Criteria section (testable success conditions) — REQUIRED at `full`/`standard`
---
@@ -76,7 +178,7 @@ Evaluate against the Design Document Standard checklist:
### Step 1 — Identify all domains the GDD touches
Read the GDD and identify every domain present. A GDD can touch multiple domains simultaneously — be thorough. Common signals:
Using the GDD **already loaded in Phase 1** — do not re-read it — identify every domain present. A GDD can touch multiple domains simultaneously — be thorough. Common signals:
| If the GDD contains... | Spawn these agents |
|------------------------|-------------------|
@@ -91,7 +193,7 @@ Read the GDD and identify every domain present. A GDD can touch multiple domains
| Multiplayer, sync, replication | `network-programmer` |
| Audio cues, music triggers | `audio-director` |
| Performance, draw calls, memory | `performance-analyst` |
| Engine-specific patterns or APIs | Primary engine specialist (from `.claude/docs/technical-preferences.md`) |
| Engine-specific patterns or APIs | Primary engine specialist (`<engine>-specialist` from `engine.name` — Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`; fall back to the Primary line of `## Engine Specialists` in `technical-preferences.md`) |
| Acceptance criteria, test coverage | `qa-lead` |
| Data schema, resource structure | `systems-designer` |
| Any gameplay system | `game-designer` (always) |
@@ -102,12 +204,12 @@ These are the most common baselines — but not required for pure UI specs, audi
### Step 2 — Spawn all relevant specialists in parallel
**CRITICAL: Task in this skill spawns a SUBAGENT — a separate independent Claude session
**CRITICAL: `Agent` in this skill spawns a SUBAGENT — a separate independent Claude session
with its own context window. It is NOT task tracking. Do NOT simulate specialist
perspectives internally. Do NOT reason through domain views yourself. You MUST issue
actual Task calls. A simulated review is not a specialist review.**
actual `Agent` calls. A simulated review is not a specialist review.**
Issue all Task calls simultaneously. Do NOT spawn one at a time.
Issue all `Agent` calls simultaneously. Do NOT spawn one at a time.
**Prompt each specialist adversarially:**
> "Here is the GDD for [system] and the main review's structural findings so far.
@@ -146,8 +248,18 @@ Mark every finding with its source: `[game-designer]`, `[economy-designer]`, `[c
Specialists consulted: [list agents spawned]
Re-review: [Yes — prior verdict was X on YYYY-MM-DD / No — first review]
### Completeness: [X/8 sections present]
[List missing sections]
### Completeness: [X/N sections present, where N is the count REQUIRED at this project's `modes.workflow`]
[List only sections missing that are REQUIRED at this tier. Mark ADVISORY gaps
separately as "advisory at `standard`" — do not list them as missing.]
> **N is not 8 unless `workflow: full`.** The tier table earlier in this skill is
> authoritative: 8 required at `full`, 5 at `standard` (+ Formulas when the system
> defines numeric rules), 0 at `minimal`. Hardcoding `/8` here
> reintroduces the tier confusion in the presentation layer after the logic
> layer already handles it — reporting a `standard` project as "5/8 missing Player
> Fantasy, Formulas, Tuning Knobs" warns about three sections that project's own
> configuration says it does not need, which trains the reader to ignore the
> review.
### Dependency Graph
[List each declared dependency and whether its GDD file exists on disk]
@@ -179,7 +291,20 @@ systems touched, and whether new ADRs are required.
- **XL** — cross-cutting concern, 5+ dependencies, multiple new ADRs likely
Label clearly: "Rough scope signal: M (producer should verify before sprint planning)"
### Verdict: [APPROVED / NEEDS REVISION / MAJOR REVISION NEEDED]
### Verdict: [APPROVED / NEEDS REVISION / MAJOR REVISION NEEDED / NOT ASSESSED]
> **`NOT ASSESSED` when the review could not actually be performed.**
> The other three verdicts are all claims about the design's quality, so each one
> asserts that the document was read and judged. Use `NOT ASSESSED` instead when
> the target document is absent, unreadable, or empty of the sections being
> reviewed, or when a document it depends on is missing so the criteria cannot be
> applied. **Name what was unavailable and which skill produces it.**
>
> `APPROVED` is the dangerous default here: a review that could not find its
> input has not approved anything, and this verdict is consumed downstream as a
> sign-off. `NOT ASSESSED` outranks `APPROVED` in any aggregate — it does not
> outrank the two revision verdicts, because a known problem is more actionable
> than an unknown one.
```
This skill is read-only — no files are written during Phase 4.
@@ -213,7 +338,9 @@ After all revisions are complete, show a summary table (blocker → fix applied)
- `[C] Move to next system — /design-system [next-system] (#N in design order)`
- `[D] Stop here`
Never end the revision flow with plain text. Always close with this widget.
In collaborative and guided modes, never end the revision flow with plain text —
always close with this widget. In autonomous mode, summarize the outcome and
record via `log_decision`.
**Second widget — tracking records (combined, for APPROVED path):**
@@ -243,8 +370,26 @@ Specialists: [list]
Blocking items: [count] | Recommended: [count]
Summary: [2-3 sentence summary of key findings from creative-director verdict]
Prior verdict resolved: [Yes / No / First review]
Findings:
- [BLOCKING] [section]: [one-line finding]
- [RECOMMENDED] [section]: [one-line finding]
[output of: Bash: bash .claude/scripts/review-receipts.sh hash "[target-doc-path]" — plus "design/registry/entities.yaml" if the registry file exists]
```
Findings rules: one line per finding, named by the section it lives in;
write `- none` when the verdict carried no findings. This is documentation
for a human reader of the revision history, not a mechanism the skill reads
back — a delta re-review that skipped re-analyzing unchanged sections was
tried and reverted (see Phase 1) after measuring it against a full review.
The hash line is the receipt Phase 1 reads on the next run to detect a
byte-identical re-review — the one form of skip that's actually safe,
because the input is provably the same, not merely believed to be adequately
covered by a prior pass. Always include it, whatever the verdict — an
unchanged document that previously FAILED review is exactly the case where
skipping a redundant re-review saves the most (the prior findings stand
verbatim).
---
**Final closing widget — always show after all file writes complete:**
@@ -265,4 +410,6 @@ Build the option list dynamically — only include options that are genuinely ne
Assign letters A, B, C… only to included options. Mark the most pipeline-advancing option as `(recommended)`.
Never end the skill with plain text after file writes. Always close with this widget.
In collaborative and guided modes, never end the skill with plain text after
file writes — always close with this widget. In autonomous mode, print the next
step and record via `log_decision`.
+478 -74
View File
@@ -1,22 +1,39 @@
---
name: design-system
description: "Guided, section-by-section GDD authoring for a single game system. Gathers context from existing docs, walks through each required section collaboratively, cross-references dependencies, and writes incrementally to file."
description: "Section-by-section GDD authoring for one system — walks through each required section, cross-references dependencies."
argument-hint: "<system-name> [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
When this skill is invoked:
## 1. Parse Arguments & Validate
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which sections exist. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = bullet points, 2–5 lines per section,
skip rationale and preambles; `balanced` = paragraphs with light rationale
(default); `thorough` = full prose with rationale, examples, and alternatives
considered. Apply it to every section you author. Mandated structures (the
Formulas variable table, Given-When-Then acceptance criteria) are correctness
requirements at every density — `terse` trims the surrounding prose, never the
required structure itself.
A system name or retrofit path is **required**. If missing:
@@ -35,9 +52,15 @@ If the argument starts with `retrofit` or the argument is a file path to an
existing `.md` file in `design/gdd/`, enter **retrofit mode**:
1. Read the existing GDD file.
2. Identify which of the 8 required sections are present (scan for section headings).
Required sections: Overview, Player Fantasy, Detailed Design/Rules, Formulas,
2. Identify which of the 8 **possible** sections are present (scan for section
headings): Overview, Player Fantasy, Detailed Design/Rules, Formulas,
Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria.
**Which of them are *required* depends on the effective tier** (§1) — at
`standard` only 5 are, plus Formulas for math categories, and Player Fantasy
and Tuning Knobs are skipped **by design**. Report an absent section as a gap
only when the tier requires it; otherwise list it as available-to-add. Calling
all 8 required here reports two by-design-absent sections as gaps on every
`standard` project.
3. Identify which sections contain only placeholder text (`[To be designed]` or
equivalent — blank, a single line, or obviously incomplete).
4. Present to the user before doing anything:
@@ -64,6 +87,46 @@ existing `.md` file in `design/gdd/`, enter **retrofit mode**:
If NOT in retrofit mode, normalize the system name to kebab-case for the
filename (e.g., "combat system" becomes `combat-system`).
**`workflow`** for this system (per `.claude/docs/workflow-modes.md`) — use the
`system_overrides` row for this system if the block lists one, else the project
value.
The resolved tier determines which GDD sections are **required** (applied in §4).
**`## Summary` is required at every tier and is not one of the 8** — §5-pre
authors it unconditionally (*"This runs at every tier"*), but it appeared in none
of the per-tier lists below, and these lists are what other skills and gates
apply. A GDD checked against a tier list alone would pass with no Summary, the
one section `/review-all-gdds` and the tiered-loading readers depend on. Read
every list below as "`## Summary`, plus:".
- `full` — all 8 sections
- `standard` — Overview, Detailed Design, Edge Cases, Dependencies, Acceptance
Criteria (5 required); **Formulas conditional** — required when the system
**defines numeric rules**: rates, curves, thresholds, costs, damage, drop
weights, or any value a balance pass would tune. Optional only when the system
defines no such value. **The `Category` in `systems-index.md` is a hint, not
the test** — `Gameplay`, `Economy` and `Progression` systems almost always
qualify, and a `Core`, `UI` or `Persistence` system that defines a numeric rule
qualifies too. If the Detailed Design states a quantity that is not a constant
of the engine, Formulas is required. **Player Fantasy and Tuning Knobs skipped**
unless `workflow_overrides` force them (`tuning_knobs: true` forces Tuning Knobs)
> **Do not gate this on a category token.** A rule of the form "required when
> the system category is combat / economy / progression / AI" does not work:
> those four tokens are not what `/map-systems` writes — `templates/systems-index.md`
> defines the categories as `Core · Gameplay · Progression · Economy ·
> Persistence · UI · Audio · Narrative · Meta` and lists **combat and AI as
> example systems under `Gameplay`**. A combat system categorised exactly as the
> template instructs matches none of the four, and Formulas would be dropped for
> the system most likely to need it.
- `minimal` — a GDD is not required (the game brief replaces it). If invoked
voluntarily at minimal, author exactly the 5 standard sections (Overview,
Detailed Design, Edge Cases, Dependencies, Acceptance Criteria) — the
conditional Formulas rule does NOT re-apply at minimal — and tell the user
the GDD is optional at this workflow level.
Retrofit mode is unaffected — it fills whatever sections are missing regardless
of tier.
---
## 2. Gather Context (Read Phase)
@@ -73,6 +136,48 @@ primary advantage over ad-hoc design — it arrives informed.
### 2a: Required Reads
> **At `minimal`** (design-system is voluntary at this tier): read
> `design/game-brief.md` in place of the game concept, and **skip the systems-index
> read** — neither `game-concept.md` nor `systems-index.md` exists at `minimal`.
> Author from the brief's relevant MVP feature and its core loop.
>
> **This callout keys on the PROJECT tier, not this system's effective tier.**
> The two differ whenever `workflow_overrides.system_overrides` bumps one system
> above a `minimal` project — the configuration `.claude/docs/settings-guidance.md`
> advertises as the reason the override exists ("bump one deep system"). Those two
> files are absent because the *project* is `minimal`; raising *this system* to
> `standard` or `full` does not create them. So on a `minimal` project, take this
> branch **even for an overridden system**, and read the brief.
>
> The effective tier still governs everything downstream — the required section
> set (§1), the skeleton (§3), the section cycle (§4) and §5a. Only the
> required-*reads* branch here follows the project tier.
>
> **Then derive `Category`, `Layer` and `Priority` from the brief, once, here.**
> Six later steps are keyed on the systems index you just skipped — §2e's engine
> domain, Section A's and Section B's recommended options, the Visual/Audio
> REQUIRED table, §6 specialist routing, and §5-pre's Quick reference — and none
> of them has an absent-index branch. An overridden system reaches all six at
> `standard` or `full`, so "skip the index" leaves them with no input at all.
> Derive from the brief instead:
>
> - **`Category`** — one of the nine in `templates/systems-index.md`
> (`Core · Gameplay · Progression · Economy · Persistence · UI · Audio ·
> Narrative · Meta`), chosen from what the brief says the system *does*.
> - **`Layer`** — `Foundation` if other systems depend on it, else `Feature`.
> - **`Priority`** — `MVP` if the brief's build order lists it, else `Post-MVP`.
>
> Carry all three for the rest of the run and treat them as the index's answer.
> **Mark them inferred** in §5-pre's Quick reference (*"Category: Gameplay
> (inferred from the brief — no systems index at this tier)"*) so a later reader
> does not mistake a derivation for an indexed fact. Do **not** write a systems
> index to hold them: `/map-systems` owns that file (§5d).
>
> Read literally without this rule, an overridden system resolves to `full`, falls
> through to the fail-fast reads below, and aborts with *"No game concept found.
> Run `/brainstorm` first"* — killing the escape hatch on step one of the very
> configuration it was built for.
- **Game concept**: Read `design/gdd/game-concept.md` — fail if missing:
> "No game concept found. Run `/brainstorm` first."
- **Systems index**: Read `design/gdd/systems-index.md` — fail if missing:
@@ -94,25 +199,36 @@ primary advantage over ad-hoc design — it arrives informed.
### 2b: Dependency Reads
From the systems index, identify:
- **Upstream dependencies**: Systems this one depends on. Read their GDDs if they
exist (these contain decisions this system must respect).
- **Downstream dependents**: Systems that depend on this one. Read their GDDs if
they exist (these contain expectations this system must satisfy).
- **Upstream dependencies**: Systems this one depends on (decisions this system
must respect).
- **Downstream dependents**: Systems that depend on this one (expectations this
system must satisfy).
For each dependency GDD that exists, extract and hold in context:
- Key interfaces (what data flows between the systems)
For each dependency GDD that exists, read **only the four sections that carry the
cross-system contract** — not the whole GDD:
```
Grep pattern="## (Dependencies|Formulas|Edge Cases|Tuning Knobs)" glob="design/gdd/[dep].md" output_mode="content" -A 20
```
- Key interfaces and data flow (from Dependencies)
- Formulas that reference this system's outputs
- Edge cases that assume this system's behavior
- Tuning knobs that feed into this system
Much of this is already in `entities.yaml` (loaded in 2a) — the registry's
`formula_map`/`constant_map` carry the owned values with their `source:`. Use the
registry first; the section grep fills what it does not hold.
### 2c: Optional Reads
- **Game pillars**: Read `design/gdd/game-pillars.md` if it exists
- **Existing GDD**: Read `design/gdd/[system-name].md` if it exists (resume, don't
restart from scratch)
- **Related GDDs**: Glob `design/gdd/*.md` and read any that are thematically related
(e.g., if designing a system that overlaps with another in scope, read the related GDD
even if it's not a formal dependency)
- **Related systems**: do **not** glob-and-read `design/gdd/*.md` hunting for
"thematically related" systems — there is no deterministic proxy for that and it
is the read the registry exists to replace. `entities.yaml` (2a) already holds
the cross-system facts a related GDD would supply. If a specific overlap is
known, treat it as a dependency above and section-grep it; otherwise rely on the
registry.
### 2d: Present Context Summary
@@ -147,26 +263,55 @@ constraints or knowledge gaps that will shape the design.
**Step 1 — Determine the engine domain for this system:**
Map the system's category (from systems-index.md) to an engine domain:
| System Category | Engine Domain |
|----------------|--------------|
| Combat, physics, collision | Physics |
| Rendering, visual effects, shaders | Rendering |
| UI, HUD, menus | UI |
| Audio, sound, music | Audio |
| AI, pathfinding, behavior trees | Navigation / Scripting |
| Animation, IK, rigs | Animation |
| Networking, multiplayer, sync | Networking |
| Input, controls, keybinding | Input |
| Save/load, persistence, data | Core |
| Dialogue, quests, narrative | Scripting |
Keyed on the `Category` column of `systems-index.md`. All nine categories
`templates/systems-index.md` defines appear here; where a category spans several
engine domains, pick the row matching what the system actually does and say
which you picked.
| `Category` | Engine Domain |
|-----------|--------------|
| `Gameplay` | **Physics** for combat / collision / movement; **Navigation** for AI and pathfinding; **Scripting** for rule-only systems with no engine surface |
| `Core` | **Core** — scene management, state, resource loading; **Input** for controls and keybinding |
| `UI` | UI |
| `Audio` | Audio |
| `Narrative` | Scripting — dialogue, quests, cutscenes |
| `Progression` | Scripting — save-adjacent rule logic, no dedicated domain |
| `Economy` | Scripting — data and rule logic, no dedicated domain |
| `Persistence` | Core — save/load, settings, serialization |
| `Meta` | Core — analytics, tutorials, accessibility plumbing |
> Animation, Rendering and Networking are engine domains with no category of
> their own: a system needing them will be `Gameplay` or `Core`. Name the domain
> you read the reference for, whichever row you came in on.
**Step 2 — Read engine context (if available):**
- Read `.claude/docs/technical-preferences.md` to identify the engine and version
- Identify the engine and version: read `engine.name` and `engine.version` from `project.yaml`. Resolve each field independently — if its key is absent or empty (including when `project.yaml` has no `engine:` block), fall back to `.claude/docs/technical-preferences.md` (a `[TO BE CONFIGURED]` value means not set)
- If engine is configured, read `docs/engine-reference/[engine]/VERSION.md`
- Read `docs/engine-reference/[engine]/modules/[domain].md` if it exists
- Read `docs/engine-reference/[engine]/modules/[domain].md` if it exists.
**If it does not exist, say so by name** — *"no engine reference for `[domain]`
under `docs/engine-reference/[engine]/modules/`; feasibility not checked against
the pinned engine"* — and carry that into §5-pre. A silent skip here is
indistinguishable from a feasibility check that ran and found nothing wrong,
which is the failure `.claude/rules/skill-authoring.md` obligation 3 exists to
stop.
> **This is not a rare branch.** The domain table above names `Scripting` and
> `Core` for five of the nine categories (`Narrative`, `Progression`, `Economy`
> → Scripting; `Persistence`, `Meta` → Core), plus a sub-row each under
> `Gameplay` and `Core`. The Godot reference ships `animation, audio, input,
> navigation, networking, physics, rendering, ui` — **there is no
> `scripting.md` and no `core.md`**. So the majority of non-`Gameplay` systems
> hit the absent branch every time, and `if it exists` turned that into
> silence. Either the reference gains those two files or the check reports it;
> until the former, do the latter.
- Read `docs/engine-reference/[engine]/breaking-changes.md` for domain-relevant entries
- Glob `docs/architecture/adr-*.md` and read any ADRs whose domain matches
(check the Engine Compatibility table's "Domain" field)
- Find the domain-matching ADRs without reading every ADR to learn the field you
filter on — grep the Domain field first, then read only the matches:
```
Grep pattern="\*\*Domain\*\*" glob="docs/architecture/adr-*.md" output_mode="content"
```
Read only the ADRs whose Domain matches this system's category (its `## Decision`
and `## Engine Compatibility` sections); skip the rest.
**Step 3 — Present the Feasibility Brief:**
@@ -215,6 +360,18 @@ Use `AskUserQuestion`:
Once the user confirms, **immediately** create the GDD file with empty section
headers. This ensures incremental writes have a target.
**Scaffold only the sections required at the resolved tier** (§1): at
`standard`, omit Player Fantasy and Tuning Knobs (and Formulas only when the
system defines no numeric rule — see §1; the category is a hint, not the test);
at `full`, scaffold all 8.
**Only the sections §1 named as omitted are skipped** — do not leave empty
`[To be designed]` placeholders for those. Every other section in the template
is scaffolded with its placeholder, including the ones §4 has not decided yet.
This sentence governs the three tier omissions above (Player Fantasy, Tuning
Knobs, and Formulas when no numeric rule exists) and nothing else: it is not a
licence to strip a section because it looks optional, and §4 cannot fill a
section §3 never created.
Use the template structure from `.claude/docs/templates/game-design-document.md`:
```markdown
@@ -223,8 +380,15 @@ Use the template structure from `.claude/docs/templates/game-design-document.md`
> **Status**: In Design
> **Author**: [user + agents]
> **Last Updated**: [today's date]
> **Last Verified**: [today's date]
> **Implements Pillar**: [from context]
## Summary
[To be designed]
> **Quick reference** — Layer: `[Foundation | Core | Feature | Presentation]` · Priority: `[MVP | Vertical Slice | Alpha | Full Vision]` · Key deps: `[System names or "None"]`
## Overview
[To be designed]
@@ -267,10 +431,18 @@ Use the template structure from `.claude/docs/templates/game-design-document.md`
[To be designed]
## Game Feel
[To be designed]
## UI Requirements
[To be designed]
## Cross-References
[To be designed]
## Acceptance Criteria
[To be designed]
@@ -280,6 +452,15 @@ Use the template structure from `.claude/docs/templates/game-design-document.md`
[To be designed]
```
> **This skeleton and the template must stay identical in section set and
> order.** They diverged once and it was invisible: the skeleton omitted
> `## Game Feel` and `## Cross-References`, so §3's own rule — *"§4 cannot fill a
> section §3 never created"* — made both unreachable **at every tier, `full`
> included**, while §3's prose above still said *"every other section in the
> template is scaffolded"*. Two agents authoring a combat GDD noticed the gap
> only by opening the template. If you add a section to one file, add it to the
> other in the same commit.
Ask: "May I create the skeleton file at `design/gdd/[system-name].md`?"
If the user declines: Stop with the following message:
@@ -300,7 +481,16 @@ File content:
## 4. Section-by-Section Design
Walk through each section in order. For **each section**, follow this cycle:
**Author only the sections required at the resolved tier** (§1). At `standard`,
the walk covers A (Overview), C (Detailed Design), E (Edge Cases),
F (Dependencies), H (Acceptance Criteria) — plus D (Formulas) when the system
defines numeric rules (see §1; the category is a hint, not the test); skip B (Player Fantasy) and
G (Tuning Knobs) unless `workflow_overrides.tuning_knobs: true` forces G. At
`full`, walk all eight (A–H). At `minimal`, the GDD is optional — if authoring
voluntarily, walk the standard set. Any `system_overrides.<system>` tier was
already folded into the resolved tier in §1.
Walk through each required section in order. For **each section**, follow this cycle:
### The Section Cycle
@@ -324,14 +514,26 @@ Context -> Questions -> Options -> Decision -> Draft -> Approval ->
5. **Draft**: Write the section content in conversation text for review. Flag any
provisional assumptions about undesigned dependencies.
6. **Approval**: Immediately after the draft — in the SAME response — use
`AskUserQuestion`. **NEVER use plain text. NEVER skip this step.**
6. **Approval**: Per the resolved `modes.automation` mode
(`.claude/docs/automation-modes.md`):
**In `collaborative` mode**: Immediately after the draft — in the SAME
response — use `AskUserQuestion`. **NEVER use plain text. NEVER skip
this step.**
- Prompt: "Approve the [Section Name] section?"
- Options: `[A] Approve — write it to file` / `[B] Make changes — describe what to fix` / `[C] Start over`
**The draft and the approval widget MUST appear together in one response.
If the draft appears without the widget, the user is left at a blank prompt
with no path forward — this is a protocol violation.**
with no path forward — this is a protocol violation in collaborative mode.**
**In `guided` mode**: Write the section immediately after the draft with
a brief one-line summary of what was decided. Skip the per-section widget;
the multi-section authoring rule (no per-section confirmation) applies.
**In `autonomous` mode**: Write the section directly and call
`log_decision` with `Decision point: Approve [Section Name] section`,
`Chosen: [A] Approve`, `Category: minor`.
7. **Write**: Use the Edit tool to replace the placeholder with the approved content.
**CRITICAL**: Always include the section heading in the `old_string` to ensure
@@ -369,7 +571,7 @@ Each section has unique design considerations and may benefit from specialist ag
**Goal**: One paragraph a stranger could read and understand.
**Derive recommended options before building the widget**: Read the system's category and layer from the systems index (already in context from Phase 2), then determine the recommended option for each tab:
- **Framing tab**: Foundation/Infrastructure layer → `[A]` recommended. Player-facing categories (Combat, UI, Dialogue, Character, Animation, Visual Effects, Audio) → `[C] Both` recommended.
- **Framing tab**: keyed on the `Category` column (`Core · Gameplay · Progression · Economy · Persistence · UI · Audio · Narrative · Meta`). Player-facing — `Gameplay`, `UI`, `Audio`, `Narrative` → `[C] Both` recommended. Internal — `Core`, `Persistence`, `Meta` → `[A]` recommended. Mixed — `Economy`, `Progression` → `[C] Both`. **Tiebreak, when Layer and Category disagree** (a `Foundation`-layer `Gameplay` system is the common case): **Category wins** — the framing describes what the section is *about*, and a player-facing system stays player-facing wherever it sits in the dependency graph.
- **ADR ref tab**: Glob `docs/architecture/adr-*.md` and grep for the system name in the GDD Requirements section of any ADR. If a matching ADR is found → `[A] Yes — cite the ADR` recommended. If none found → `[B] No` recommended.
- **Fantasy tab**: Foundation/Infrastructure layer → `[B] No` recommended. All other categories → `[A] Yes` recommended.
@@ -380,7 +582,12 @@ Append `(Recommended)` to the appropriate option text in each tab.
- Tab "ADR ref" — "Should the overview reference the existing ADR for this system?" Options: `[A] Yes — cite the ADR for implementation details` / `[B] No — keep the GDD at pure design level`
- Tab "Fantasy" — "Does this system have a player fantasy worth stating?" Options: `[A] Yes — players feel it directly` / `[B] No — pure infrastructure, players feel what it enables`
Use the user's answers to shape the draft. Do NOT answer these questions yourself and auto-draft.
Use the answers to shape the draft. **In `collaborative` mode, do NOT answer
these questions yourself and auto-draft** — the widget must appear. In `guided`
and `autonomous`, this is a MINOR framing decision: select the recommended
option derived above, state it in one line, and proceed (that is the whole
point of pre-deriving recommendations). Applies to every "ask BEFORE drafting"
widget in this section walk, not just this one.
**Questions to ask**:
- What is this system in one sentence?
@@ -404,9 +611,13 @@ describes the technical approach used to achieve it.
**Goal**: The emotional target — what the player should *feel*.
**Derive recommended option before building the widget**: Read the system's category and layer from Phase 2 context:
- Player-facing categories (Combat, UI, Dialogue, Character, Animation, Audio, Level/World) → `[A] Direct` recommended
- Foundation/Infrastructure layer → `[B] Indirect` recommended
- Mixed categories (Camera/input, Economy, AI with visible player effects) → `[C] Both` recommended
Keyed on the `Category` column (`Core · Gameplay · Progression · Economy · Persistence · UI · Audio · Narrative · Meta`):
- Player-facing — `Gameplay`, `UI`, `Audio`, `Narrative` → `[A] Direct` recommended
- Internal — `Core`, `Persistence`, `Meta` → `[B] Indirect` recommended
- Mixed — `Economy`, `Progression` → `[C] Both` recommended
**When Layer and Category disagree, Category wins** — same tiebreak as the
Framing tab above.
Append `(Recommended)` to the appropriate option text.
@@ -430,7 +641,7 @@ quote the relevant pillar text.
- `full` → spawn as described below.
**Agent delegation (MANDATORY)**: After the framing answer is given but before drafting,
spawn `creative-director` via Task:
spawn `creative-director` via `Agent`:
- Provide: system name, framing answer (direct/indirect/both), game pillars, any reference games the user mentioned, the game concept summary
- Ask: "Shape the Player Fantasy for this system. What emotion or power fantasy should it serve? What player moment should we anchor to? What tone and language fits the game's established feeling? Be specific — give me 2-3 candidate framings."
- Collect the creative-director's framings and present them to the user alongside the draft.
@@ -464,7 +675,7 @@ This is usually the largest section. Break it into sub-sections:
- `lean` → skip unless this is a section with HIGH implementation risk (Sections D and H only). For other sections, draft without the agent.
- `full` → spawn as described below.
**Agent delegation (MANDATORY)**: Before drafting Section C, spawn specialist agents via Task in parallel:
**Agent delegation (MANDATORY)**: Before drafting Section C, spawn specialist agents via `Agent` in parallel:
- Look up the system category in the routing table (Section 6 of this skill)
- Spawn the Primary Agent AND Supporting Agent(s) listed for this category
- Provide each agent: system name, game concept summary, pillar set, dependency GDD excerpts, the specific section being worked on
@@ -493,9 +704,9 @@ The [formula_name] formula is defined as:
`[formula_name] = [expression]`
**Variables:**
| Variable | Symbol | Type | Range | Description |
|----------|--------|------|-------|-------------|
| [name] | [sym] | float/int | [min–max] | [what it represents] |
| Variable | Type | Range | Source | Description |
|----------|------|-------|--------|-------------|
| [name] | float/int | [min–max] | data file / calculated / constant | [what it represents] |
**Output Range:** [min] to [max] under normal play; [behaviour at extremes]
**Example:** [worked example with real numbers]
@@ -504,6 +715,16 @@ The [formula_name] formula is defined as:
Do NOT write `[Formula TBD]` or describe a formula in prose without the variable
table. A formula without defined variables cannot be implemented without guesswork.
> **These columns must match `templates/game-design-document.md` exactly.** They
> did not: this block said `Symbol` where the template says `Source`, so a
> correctly-authored GDD was wrong against whichever of the two its reader
> happened to hold. `Source` is the column that stays, because it is what carries
> the coding-standards rule *"gameplay values must be data-driven (external
> config), never hardcoded"* into the design document — a variable marked
> `data file` is a tuning knob, one marked `constant` is a deliberate exception,
> and the distinction is invisible under a `Symbol` column. Put a symbol, where
> one helps, in the expression itself.
**Questions to ask**:
- What are the core calculations this system performs?
- Should scaling be linear, logarithmic, or stepped?
@@ -514,7 +735,7 @@ table. A formula without defined variables cannot be implemented without guesswo
- `lean` → skip unless this is a section with HIGH implementation risk (Sections D and H only). For other sections, draft without the agent.
- `full` → spawn as described below.
**Agent delegation (MANDATORY)**: Before proposing any formulas or balance values, spawn specialist agents via Task in parallel:
**Agent delegation (MANDATORY)**: Before proposing any formulas or balance values, spawn specialist agents via `Agent` in parallel:
- **Always spawn `systems-designer`**: provide Core Rules from Section C, tuning goals from user, balance context from dependency GDDs. Ask them to propose formulas with variable tables and output ranges.
- **For economy/cost systems, also spawn `economy-designer`**: provide placement costs, upgrade cost intent, and progression goals. Ask them to validate cost curves and ratios.
- Present the specialists' proposals to the user for review via `AskUserQuestion`
@@ -551,7 +772,7 @@ design question, not a specification.
- `lean` → skip unless this is a section with HIGH implementation risk (Sections D and H only). For other sections, draft without the agent.
- `full` → spawn as described below.
**Agent delegation (MANDATORY)**: Spawn `systems-designer` via Task before finalising edge cases. Provide: the completed Sections C and D, and ask them to identify edge cases from the formula and rule space that the main session may have missed. For narrative systems, also spawn `narrative-director`. Present their findings and ask the user which to include.
**Agent delegation (MANDATORY)**: Spawn `systems-designer` via `Agent` before finalising edge cases. Provide: the completed Sections C and D, and ask them to identify edge cases from the formula and rule space that the main session may have missed. For narrative systems, also spawn `narrative-director`. Present their findings and ask the user which to include.
**Cross-reference**: Check edge cases against dependency GDDs. If a dependency
defines a floor, cap, or resolution rule that this system could violate, flag it.
@@ -584,9 +805,20 @@ system]". Flag any one-directional dependencies for correction.
- For each knob, what breaks if it's set too high? Too low?
- Which knobs interact with each other? (Changing A makes B irrelevant)
**Review mode check** (apply before spawning):
- `solo` → skip this agent spawn. Derive the knobs from Section D's variable table yourself. Add a note: "`systems-designer` not consulted — Solo mode. Review manually before production."
- `lean` → skip unless Section D defines a formula whose knobs interact (changing one makes another inert).
- `full` → delegate as described below.
**Agent delegation**: If formulas are complex, delegate to `systems-designer`
to derive tuning knobs from the formula variables.
> The guard above was missing here while Sections B, C, D, E and H all carried
> one — and this delegation names `systems-designer`, the same agent Section D's
> guard has already told a `solo` run to skip. Read without it, `solo` skips the
> specialist for the formulas and then consults it for the knobs derived from
> those same formulas.
**Cross-reference**: If a dependency GDD lists tuning knobs that affect this system,
reference them here. Don't create duplicate knobs — point to the source of truth.
@@ -607,12 +839,30 @@ Include at least: one criterion per core rule from Section C, and one per formul
from Section D. Do NOT write "the system works as designed" — every criterion must
be independently verifiable by a QA tester without reading the GDD.
> **When Section D was not authored** (Formulas optional at this tier because the
> system defines no numeric rule), there are no formulas to cover and the
> criteria come from Section C alone — say so in one line rather than silently
> writing fewer criteria. **If Section D was skipped but Section C states a
> quantity** — a rate, threshold, cost or curve — that is the §1 test being met
> after the fact: stop, tell the user Formulas is required for this system, and
> author it before finalising the criteria. A criterion cannot verify a number
> the GDD never defines.
>
> **That escalation applies at `standard` only.** It re-runs §1's *conditional*
> Formulas test, and §1 disables that conditional at `minimal` outright — *"the
> conditional Formulas rule does NOT re-apply at minimal"*. At `minimal` a
> Section C quantity is expected and does **not** pull Formulas back in: state
> the value inline in Core Rules so it stays implementable, and move on. At
> `full`, Section D is unconditionally required, so the case cannot arise. Read
> without this scope, the two rules contradict each other for any `minimal`
> system that defines a rate — which is most of them.
**Review mode check** (apply before spawning):
- `solo` → skip this agent spawn. Draft the section without the specialist. Add a note: "`qa-lead` not consulted — Solo mode. Review manually before production."
- `lean` → skip unless this is a section with HIGH implementation risk (Sections D and H only). For other sections, draft without the agent.
- `full` → spawn as described below.
**Agent delegation (MANDATORY)**: Spawn `qa-lead` via Task before finalising acceptance criteria. Provide: the completed GDD sections C, D, E, and ask them to validate that the criteria are independently testable and cover all core rules and formulas. Surface any gaps or untestable criteria to the user.
**Agent delegation (MANDATORY)**: Spawn `qa-lead` via `Agent` before finalising acceptance criteria. Provide: the completed GDD sections C, D, E, and ask them to validate that the criteria are independently testable and cover all core rules and formulas. Surface any gaps or untestable criteria to the user.
**Questions to ask**:
- What's the minimum set of tests that prove this works?
@@ -624,27 +874,91 @@ not just this system in isolation.
---
### Optional Sections: Visual/Audio, UI Requirements, Open Questions
### Optional Sections: Visual/Audio, Game Feel, UI Requirements, Cross-References, Open Questions
These sections are included in the template. Visual/Audio is **REQUIRED** for visual system categories — not optional. Determine the requirement level before asking:
These five are the template sections that are **not** among §1's eight. They are
governed here, not by the tier: §1's per-tier lists decide the *required* set,
and this block decides the rest independently. Adding a section here therefore
never changes a tier's section count.
**Visual/Audio is REQUIRED (mandatory — do not offer to skip) for these system categories:**
- Combat, damage, health
- UI systems (HUD, menus)
- Animation, character movement
- Visual effects, particles, shaders
- Character systems
- Dialogue, quests, lore
- Level/world systems
Visual/Audio and Game Feel are **REQUIRED** for some categories — not optional.
Determine the requirement level before asking:
For required systems: **spawn `art-director` via Task** before drafting this section. Provide: system name, game concept, game pillars, art bible sections 1–4 if they exist. Ask them to specify: (1) VFX and visual feedback requirements for this system's events, (2) any animation or visual style constraints, (3) which art bible principles most directly apply to this system. Present their output; do NOT leave this section as `[To be designed]` for visual systems.
**Keyed on the `Category` column of `systems-index.md`** — the nine values
`templates/systems-index.md` defines. Every one of the nine appears below
exactly once, so nothing falls through:
For **all other system categories** (Foundation/Infrastructure, Economy, AI/pathfinding, Camera/input), offer the optional sections after the required sections:
**Visual/Audio is REQUIRED (mandatory — do not offer to skip) for:**
- `Gameplay` — combat, AI, stealth, movement, interaction: everything the player
sees resolve
- `UI` — HUD, menus, inventory screens, dialogue UI
- `Narrative` — dialogue, quests, cutscenes, lore delivery
- `Audio` — by definition
> **`Gameplay` is the row this table was missing.** It is the category
> `/map-systems` assigns to combat, AI and movement — the largest bucket in most
> action games. If it appears in **neither** this list nor the "all other" list
> below, the skill has no defined behaviour for it and the author has to guess.
> All nine categories must be covered between the two lists.
For required systems: **spawn `art-director` via `Agent`** before drafting this section. Provide: system name, game concept, game pillars, art bible sections 1–4 if they exist. Ask them to specify: (1) VFX and visual feedback requirements for this system's events, (2) any animation or visual style constraints, (3) which art bible principles most directly apply to this system. Present their output; do NOT leave this section as `[To be designed]` for visual systems.
**Review mode check** (apply before spawning):
- `solo` → skip this agent spawn. Draft the section without the specialist. Add a note: "`art-director` not consulted — Solo mode. Review manually before production."
- `lean` → skip unless this system's visual feedback is central to it (a `Gameplay` or `UI` system whose events the player reads to play). Otherwise draft without the agent.
- `full` → spawn as described above.
> Sections B, C, D, E and H each carry this block and this spawn did not, while
> being worded as mandatory (*"do NOT leave this section as `[To be designed]`"*).
> Two agents in `solo` skipped it anyway, on the strength of the other five, and
> both flagged the guess. `director-gates.md`'s *"solo → no director gates
> anywhere"* governs director **gates**, not specialist spawns, so it did not
> settle it — this block does.
**Game Feel is REQUIRED (mandatory — do not offer to skip) for `Gameplay` and
`UI`** — the categories whose systems the player directly operates, where
responsiveness, weight and snap are design targets rather than polish. It is
optional for the other seven. The template argues the point itself: feel *"drives
animation budgets, input handling architecture, and hitbox timing. Retrofitting
feel targets after implementation is expensive."*
**Cross-References is REQUIRED whenever the Dependencies section names another
GDD.** The rule is derived, not category-keyed: if this document references
another system's mechanic, value or rule anywhere, that reference belongs in the
table. Where Dependencies names nothing, write *"None — this system references no
other GDD"* rather than leaving the placeholder. `/review-all-gdds` Phase 2c
reads this table when it exists.
For the remaining five categories — `Core`, `Progression`, `Economy`,
`Persistence`, `Meta` — Visual/Audio is optional: offer the optional sections
after the required sections.
> **At `minimal`, force nothing.** §1 says a voluntary `minimal` GDD is *"exactly
> the 5 standard sections"*, which contradicts a category rule that makes
> Visual/Audio or Game Feel mandatory. §1 wins: at `minimal` both drop to
> optional and the whole set goes through the widget below. The contradiction is
> real — an agent authoring a `minimal` inventory GDD hit it and had to choose.
Use `AskUserQuestion`:
- "The 8 required sections are complete. Do you want to also define Visual/Audio
requirements, UI requirements, or capture open questions?"
- Options: "Yes, all three", "Just open questions", "Skip — I'll add these later"
- "The required sections for this workflow tier are complete. Which of the
remaining template sections do you want to define?"
- Options: "All of them", "Just Cross-References and open questions", "Skip — I'll add these later"
- List in the question only the ones still outstanding: Visual/Audio, Game
Feel, UI Requirements, Cross-References, Open Questions **minus** any this
system's category or dependencies already made mandatory above. Offering to
skip a section the rules just made required is how a mandatory section gets
skipped.
- **Recommended option**: "All of them" when the system has any dependency,
UI surface or player-facing feedback; "Just Cross-References and open
questions" otherwise. `autonomous` needs a marked recommendation to pick —
the three options previously carried none, unlike the Section A/B widgets,
so an unattended run had nothing to choose by and defaulted to skipping.
Do **not** state a section count here. The required set is tier-dependent
(§1: 8 at `full`, 5 + conditional Formulas at `standard`, 5 at a voluntary
`minimal`), so the previous hardcoded "8 required sections are complete" was
false on every run below `full` — it told a `standard`-tier user that 8
sections existed when 6 had been authored.
For **Visual/Audio** (non-required systems): Coordinate with `art-director` and `audio-director` if detail is needed. Often a brief note suffices at the GDD stage.
@@ -672,11 +986,35 @@ fully resolved. Each question should have an owner and target resolution date.
After all sections are written:
### 5-pre: Author the Summary
Write `## Summary` and its `> **Quick reference**` line now — after the design
exists, so the summary distils real content rather than intentions. This runs
**at every tier**, including `standard` and a voluntary `minimal` GDD: the
Summary is what lets a later skill scan 20 GDDs and decide which to read in full
(`/create-epics`, `/architecture-review`, `/review-all-gdds` all grep it), so a
GDD without it silently forces those consumers back to full reads.
- **Summary body**: 2–3 sentences — what this system is, what it does for the
player, why it exists in this game. No jargon; a reader who has not seen the
GDD should learn whether it is relevant to their task.
- **Quick reference**: `Layer` and `Priority` from the systems index
(`design/gdd/systems-index.md`); `Key deps` from the Dependencies section just
written (system names, or `None`).
Replace the `[To be designed]` Summary placeholder in the skeleton. Then apply
the section cycle's Write step as for any other section.
### 5a: Self-Check
Read back the complete GDD from file (not from conversation memory — the file is
the source of truth). Verify:
- All 8 required sections have real content (not placeholders)
- The `## Summary` and its Quick reference are populated (not the placeholder)
- Every section **required at this system's effective tier** has real content
(not placeholders) — §1: 8 at `full`, 5 + conditional Formulas at `standard`,
5 at a voluntary `minimal`. Do not verify against a fixed count of 8: below
`full` that reports a correctly-authored GDD as incomplete, which is the same
error already corrected in the optional-sections prompt above
- Formulas reference defined variables
- Edge cases have resolutions
- Dependencies are listed with interfaces
@@ -689,7 +1027,7 @@ the source of truth). Verify:
- `lean` → skip (not a PHASE-GATE). Note: "CD-GDD-ALIGN skipped — Lean mode." Proceed to Step 5b.
- `full` → spawn as normal.
Before finalizing the GDD, spawn `creative-director` via Task using gate **CD-GDD-ALIGN** (`.claude/docs/director-gates.md`).
Before finalizing the GDD, spawn `creative-director` via `Agent` using gate **CD-GDD-ALIGN** (`.claude/docs/director-gates/cd-gdd-align.md`).
Pass: completed GDD file path, game pillars (from `design/gdd/game-concept.md` or `design/gdd/game-pillars.md`), MDA aesthetics target.
@@ -706,7 +1044,27 @@ Scan the completed GDD for cross-system facts that should be registered:
- Named formulas with defined variables and output ranges
- Named constants referenced by value in more than one place
For each candidate, check if it already exists in `design/registry/entities.yaml`:
**First check the registry exists** — §2a reads it *"if it exists"*, and this
step never carried the same guard. At `standard` and below the file is often
absent, and a grep against a missing path returns nothing, which is
indistinguishable from "no candidate is registered yet":
- **Absent** — say so, and ask whether to create it:
*"`design/registry/entities.yaml` does not exist. May I create it with these
[N] entries?"* If the user declines, skip 5b and say the registry was not
written — do not treat the skip as a clean pass.
- **Present but empty** — every list is `[]`, or the only matches are inside
comment blocks. Treat it as present, register the candidates, but say which
state you found: *"registry exists and is empty — all [N] entries are new."*
The shipped template's comments carry fully-formed examples referencing
`design/gdd/inventory.md` with real-looking values (`base_inventory_slots: 20`,
`gold_carry_limit: 9999`), so §2a's prescribed
`grep referenced_by.*[system-name]` returns **comment lines** on an empty
registry — and §2d would then present those invented numbers to the user as
*"These values are locked."* Match entries under a live `entities:`/`items:`/
`formulas:`/`constants:` key, never a commented example.
- **Present** — for each candidate, check whether it is already registered:
```
Grep pattern=" - name: [candidate_name]" path="design/registry/entities.yaml"
```
@@ -723,7 +1081,9 @@ Registry candidates from this GDD:
```
Ask: "May I update `design/registry/entities.yaml` with these [N] new entries
and update `referenced_by` for the existing entries?"
and update `referenced_by` for the existing entries?" (If the file was absent
and the user approved creating it, the wording is *create*, not *update*, and
there are no `referenced_by` arrays to merge.)
If yes: append new entries and update `referenced_by` arrays. Never modify
existing `value` / attribute fields without surfacing it as a conflict first.
@@ -750,6 +1110,18 @@ Present a completion summary:
After the GDD is complete (and optionally reviewed):
**First check the systems index exists.** §2a skips it at `minimal` because it is
never written at that tier, and this step never carried the same guard — the same
class of bug §5b was patched for. It bites hardest on a `minimal` project with a
`system_overrides` bump, where the effective tier is `standard` or `full` and
nothing else in §5 hints the file may be absent.
- **Absent** — say so in one line (*"no `design/gdd/systems-index.md` at this
workflow tier; nothing to update"*) and skip to §5e. Do **not** offer to create
one: `/map-systems` owns that file, and a stub written here would be a systems
index listing exactly one system.
- **Present** — continue:
- Read the systems index
- Update the target system's row:
- If design-review was run and verdict is APPROVED: Status → "Approved"
@@ -767,7 +1139,11 @@ Update `production/session-state/active.md` with:
- Task: [system-name] GDD
- Status: Complete (or In Review if design-review was run)
- File: design/gdd/[system-name].md
- Sections: All 8 written
- Sections: [list the sections actually authored, by name] — **never a fixed
count**; §5a forbids verifying against `/8`, and the same reasoning applies to
recording it. Below `full` a correctly-authored GDD has fewer than 8 sections,
and writing "All 8 written" into session state makes the next reader believe
a complete GDD is incomplete
- Next: [suggest next system from design order]
### 5f: Suggest Next Steps
@@ -788,7 +1164,27 @@ Use `AskUserQuestion`:
This skill delegates to specialist agents for domain expertise. The main session
orchestrates the overall flow; agents provide expert content.
| System Category | Primary Agent | Supporting Agent(s) |
**Rows here are finer-grained than the nine `Category` values on purpose** — the
right specialist for combat is not the right specialist for pathfinding, and both
are `Gameplay`. Resolve in two steps: take the system's `Category` from
`systems-index.md`, then pick the row within it that matches what the system
actually does. Every category has at least one row, so nothing falls through.
| `Category` | Rows below to choose from |
|---|---|
| `Gameplay` | Combat/damage/health · AI/pathfinding/behavior · Animation/character movement · Character systems · Camera/input/controls |
| `Core` | Foundation/Infrastructure · Camera/input/controls |
| `Persistence` | Foundation/Infrastructure |
| `Economy` | Economy/loot/crafting |
| `Progression` | Progression/XP/skills |
| `UI` | UI systems · Visual effects (when the system is HUD-adjacent VFX) |
| `Audio` | Audio systems |
| `Narrative` | Dialogue/quests/lore |
| `Meta` | Foundation/Infrastructure (analytics, tutorial plumbing) · UI systems (accessibility options screens) |
If two rows fit, spawn the union of their Primary agents and say why.
| System type | Primary Agent | Supporting Agent(s) |
|----------------|---------------|---------------------|
| **Foundation/Infrastructure** (event bus, save/load, scene mgmt, service locator) | `systems-designer` | `gameplay-programmer` (feasibility), `engine-programmer` (engine integration) |
| Combat, damage, health | `game-designer` | `systems-designer` (formulas), `ai-programmer` (enemy AI), `art-director` (hit feedback visual direction, VFX intent) |
@@ -804,7 +1200,7 @@ orchestrates the overall flow; agents provide expert content.
| Visual effects, particles, shaders | `game-designer` | `art-director` (VFX visual direction), `technical-artist` (performance budget, shader complexity), `systems-designer` (trigger/state integration) |
| Character systems (stats, archetypes) | `game-designer` | `art-director` (character visual archetype), `narrative-director` (character arc alignment), `systems-designer` (stat formulas) |
**When delegating via Task tool**:
**When delegating via the `Agent` tool**:
- Provide: system name, game concept summary, dependency GDD excerpts, the specific
section being worked on, and what question needs expert input
- The agent returns analysis/proposals to the main session
@@ -831,6 +1227,11 @@ disruption.
## Collaborative Protocol
**In `collaborative` mode (the default).** For `guided` and `autonomous`
modes, see the per-mode rules in `.claude/docs/automation-modes.md` — the
"Never" lines below describe what collaborative mode requires, not what
applies universally.
This skill follows the collaborative design principle at every step:
1. **Question -> Options -> Decision -> Draft -> Approval** for every section
@@ -838,7 +1239,10 @@ This skill follows the collaborative design principle at every step:
- Phase 2: "Ready to start, or need more context?"
- Phase 3: "May I create the skeleton?"
- Phase 4 (each section): Design questions, approach options, draft approval
- Phase 5: "Run design review? Update systems index? What's next?"
- Phase 5: "May I update the entity registry? May I update the systems
index? What's next?" — **not** "Run design review?": §5c forbids offering
`/design-review` inline, because the reviewing agent must not inherit this
session's design history. Phase 5c presents the hand-off; it never asks.
3. **"May I write to [filepath]?"** before the skeleton and before each section write
4. **Incremental writing**: Each section is written to file immediately after approval
5. **Session state updates**: After every section write
+78
View File
@@ -0,0 +1,78 @@
# /dev-story — Handoff Contract
## Role in Pipeline
Bridges planning and code by loading the full context for a single story (story file, TR registry, ADR, control manifest, engine prefs), routing to the correct programmer agent, implementing source code and tests, and leaving the story ready for `/code-review` then `/story-done`.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `production/epics/**/*.md` (the story file) | `Status: Ready`, `TR-ID`, `Governing ADR`, `Manifest Version`, `## Acceptance Criteria`, `## Test Evidence`, `## Dependencies`, `## Out of Scope` | **Partially mutable.** This skill sets `Status:` to `In Progress` and updates `Last Updated:` before spawning any agent (Phase 2) — at `minimal` the story file is the only record of progress, since `sprint-status.yaml` is absent. Everything else in the story file is read-only to this skill |
| `docs/architecture/tr-registry.yaml` | Entry matching the story's TR-ID with current `requirement` text | Yes |
| `docs/architecture/adr-NNNN-[slug].md` (referenced ADR) | `## Decision`, `## Implementation Guidelines`, `## Engine Compatibility`, `## ADR Dependencies` | Yes |
| `docs/architecture/control-manifest.md` | `Manifest Version:` header, layer rules (required patterns, forbidden patterns, performance guardrails) | Yes |
| `project.yaml` | `engine.name`, `engine.version`, `naming.*`, `performance.*` — the primary source for each of these fields | Yes |
| `.claude/docs/technical-preferences.md` | Legacy fallback for any field above that is absent or empty in `project.yaml`; **sole** source for forbidden patterns and allowed libraries (deliberately never migrated), plus the `Engine Specialists` section | Yes — required only for fields absent from `project.yaml`, and always for forbidden patterns |
| `docs/engine-reference/[engine]/VERSION.md` | Engine version, LLM knowledge cutoff, post-cutoff risk levels | Yes |
| `production/session-state/active.md` | (read to find active story when no argument given; created if absent) | No |
### Preconditions
- The target story must have `Status: Ready` (validated by `/story-readiness` before invocation)
- The ADR referenced in the story must have `Status: Accepted` — if `Status: Proposed`, do not implement; surface this as a blocker and direct user to `/architecture-decision`
- All `## Dependencies` stories listed in the story file must already have `Status: Complete` (or `Status: Done`)
- An engine must be configured — `engine.name` in `project.yaml`, or as legacy fallback an `**Engine**:` value in `.claude/docs/technical-preferences.md` that is not `[TO BE CONFIGURED]`
- `docs/architecture/tr-registry.yaml` must contain the story's TR-ID
- `docs/architecture/control-manifest.md` must exist (required for layer rule enforcement)
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `<code root>/[system]/[file].[ext]` | Doc-commented public APIs; no hardcoded gameplay values; follows ADR Implementation Guidelines and control-manifest required patterns | created or modified by sub-agent; code root resolved per `.claude/docs/code-root-resolution.md` |
| `tests/unit/[system]/[story-slug]_test.[ext]` OR `tests/integration/[system]/[story-slug]_test.[ext]` | One test function per acceptance criterion (Logic/Integration stories only); naming: `test_[scenario]_[expected_outcome]`; no random seeds; no external I/O | created by sub-agent; path matches `## Test Evidence` in story |
| `production/session-state/active.md` | `## Session Extract — /dev-story [date]` block: story path, files changed, test written path, blockers, next steps | appended (created if absent) |
### Output Guarantees
- All source files follow the naming conventions in `project.yaml` (`naming.*`), falling back to `.claude/docs/technical-preferences.md` for any convention absent there
- Test file path matches exactly the path declared in the story's `## Test Evidence` section
- Every acceptance criterion is mapped to a test function (Logic/Integration), an `OBSERVED` retained screenshot (the *look* half of Visual/Feel and UI), or flagged `DEFERRED` (the *feel* half only — timing, weight, responsiveness) in the implementation summary
- No files are written outside the story's `## Out of Scope` boundary without surfacing the conflict to the user first
- Session state records files changed and the next recommended invocations (`/code-review` then `/story-done`)
- The implementation summary states a **verification** result — what was run against the written code (`commands.test`, `commands.smoke`, or the engine's headless import) and its outcome. When the engine binary is unavailable this is **`NOT VERIFIED — <reason>`**, never an inference that the code is fine because it reads correctly
- The implementation summary states a **run result** — `OBSERVED — <what was on screen>` with a retained screenshot under `production/qa/evidence/[story-slug]/`, `NOT VERIFIED — <reason>`, or `N/A — <reason>` (only for a story with genuinely nothing observable). `NOT VERIFIED` is a blocker at the default gate level for Visual/Feel and UI stories. The run is **not waived at `qa.level: minimal`** — tests are, the look is not. Procedure: `.claude/docs/run-and-observe.md`
- At `qa.level: minimal` no test file is written, and the summary says so explicitly (`Test evidence: waived at qa.level: minimal`). A waived run and a run where tests were forgotten must not produce the same artifact
- **`NOT ASSESSED` is an accepted inbound value of the story's `Risk` field** (`/create-stories` emits it when `VERSION.md` assigns no level). This skill treats it as HIGH for the engine-specialist spawn decision
- **Completion is not assumed.** If the programmer agent stopped early or its output fails to parse, the story is reported **INCOMPLETE** with the specific breakage named, and `Implementation Complete` is not emitted
## Immutability Rules
- READS but does NOT modify: `project.yaml`, `docs/architecture/tr-registry.yaml`, `docs/architecture/adr-NNNN-[slug].md`, all GDD files in `design/gdd/`, `docs/architecture/control-manifest.md`, `.claude/docs/technical-preferences.md` (legacy fallback), `docs/engine-reference/[engine]/VERSION.md`
- MODIFIES: `<code root>/**` (new/updated source files, via sub-agent; code root resolved per `.claude/docs/code-root-resolution.md`), `tests/**` (new test file, via sub-agent), `production/session-state/active.md` (append only)
- Updates the story file's `Status` field to `In Progress` only (Phase 2, before
spawning any agent). It writes no other `Status` value: advancing a story to
`Complete` is the exclusive responsibility of `/story-done`
## Hard Constraints (Never Violate)
- Never marks a story `Status: Done` or `Status: Complete` — that belongs to `/story-done`
- Never begins implementation without loading the full context package (story, TR-ID from registry, ADR Decision + Implementation Guidelines, control-manifest layer rules, engine prefs)
- Never implements a story whose referenced ADR has `Status: Proposed` — surface as a blocker
- Never writes a Logic or Integration story as complete without a test file at the path declared in `## Test Evidence`
- Never touches files listed in the story's `## Out of Scope` section without explicit user approval
- Never deviates from the ADR's Implementation Guidelines silently — deviations must be flagged in the summary
- Never modifies ADR files or GDD files under any circumstances
- All file writes are delegated to sub-agents via Task; this orchestrator does not write source or test files directly
## Downstream Skill Expects
**Next skill:** `/story-done`
- It will read: the story file (to check `Status`, `## Acceptance Criteria`, `## Test Evidence` path, `Type:`, referenced ADR, TR-ID)
- It assumes: the test file declared in `## Test Evidence` already exists on disk (for Logic/Integration stories)
- It assumes: `production/session-state/active.md` records the story path and files changed (used to locate the in-progress story when no argument is given)
- It assumes: source files under the resolved code root are present and match the criterion descriptions, so Grep-based deviation checks can run
## Known Fragile Points
- If the story's embedded `Manifest Version` differs from the current `docs/architecture/control-manifest.md` header date, rules may have changed since the story was authored — the skill surfaces this, but silently proceeding would produce code that violates newer manifest rules
- The test file path in `## Test Evidence` must be exact: `/story-done` uses that literal path for Glob checks; a typo here causes a false BLOCKING result downstream
- If `docs/architecture/tr-registry.yaml` has a stale `requirement` text that diverges from the GDD, the implementation may satisfy the registry but fail the GDD — always treat the registry as authoritative per design, but flag if a visible discrepancy is noticed
- Sub-agent task failures are non-fatal by design (partial reports are surfaced), but a blocked programmer sub-agent means no source files are written — `/story-done` will then fail its file-existence checks
- Config/Data stories produce no test file; `/story-done` must see `Type: Config/Data` in the story header to classify the story correctly — otherwise it resolves the test-evidence gate for the wrong type (e.g. Logic, which is BLOCKING by default) and may flag a missing test
+346 -70
View File
@@ -1,12 +1,19 @@
---
name: dev-story
description: "Read a story file and implement it. Loads the full context (story, GDD requirement, ADR guidelines, control manifest), routes to the right programmer agent for the system and engine, implements the code and test, and confirms each acceptance criterion. The core implementation skill — run after /story-readiness, before /code-review and /story-done."
description: "Implement a story: ADR guidelines, right programmer agent, code plus test. After /story-readiness, before /code-review and /story-done."
argument-hint: "[story-path]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash, Task, AskUserQuestion
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,story_granularity,qa.level,testing.strict,system_overrides`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
# Dev Story
This skill bridges planning and code. It reads a story file in full, assembles
@@ -24,10 +31,33 @@ drives implementation to completion — including writing the test.
**After all sprint stories are done:** run `/team-qa sprint` to execute the full QA cycle and get a sign-off verdict before advancing the project stage.
**Output:** Source code + test file in the project's `src/` and `tests/` directories.
**Output:** Source code under the project's **code root** + test file in `tests/`. Resolve the code root from `engine.name` (`src/` Godot, `Assets/` Unity, `Source/<Module>/` Unreal) per `.claude/docs/code-root-resolution.md`.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Workflow tier**: resolved per the story's system (per
`.claude/docs/workflow-modes.md`) — **the GDD filename stem** of the story's
`GDD:` path (`design/gdd/<stem>.md` → `<stem>`), with the `[system]` segment of
its `TR-[system]-NNN` ID accepted only as a fallback alias: use the
`system_overrides` row for that system if the block lists one, else the
project value. Resolve it at the start of Phase 2 (the story header is
read there) and apply it to the prerequisite gate.
**`story_granularity`** — it sets the
expected implementation cycle: **multi-day** at `coarse` (give the programmer
subagent longer working context), **1–2 days** at `balanced` (default), **hours**
at `fine` (tighter context). It does not change the prerequisite gate.
**`qa.level`**: controls whether the programmer brief carries
a test requirement. At `minimal`, omit the "Test requirement" line (Phase 4 item 7)
— tests are not required; at `standard`, include the per-type test requirement; at
`full`, also pass a coverage target. Distinct from `workflow: minimal`. When tests
are not required (`minimal`), the Phase 5 `testing.strict` gate is a no-op.
## Phase 1: Find the Story
**If a path is provided**: read that file directly.
@@ -41,23 +71,32 @@ If not found, ask: "Which story are we implementing?" Glob
## Phase 2: Load Full Context
**Before loading any context, verify required files exist.** Extract the ADR path from the story's `ADR Governing Implementation` field, then check:
**Before loading any context, resolve the workflow tier for this story's system** (see the Workflow tier note above), then **verify required files exist.** Extract the ADR path from the story's `ADR Governing Implementation` field. The "If missing — `full`" column is the baseline; the tier columns relax it:
| File | Path | If missing |
|------|------|------------|
| TR registry | `docs/architecture/tr-registry.yaml` | **STOP** — "TR registry not found at `docs/architecture/tr-registry.yaml`. Run `/architecture-review` to bootstrap the registry from your GDDs and ADRs." |
| Governing ADR | path from story's ADR field | **STOP** — "ADR file [path] not found. Run `/architecture-decision` to create it, or correct the filename in the story's ADR field." |
| Control manifest | `docs/architecture/control-manifest.md` | **WARN and continue** — "Control manifest not found — layer rules cannot be checked. Run `/create-control-manifest`." |
| File | Path | If missing — `full` | `standard` | `minimal` |
|------|------|---------------------|-----------|-----------|
| TR registry | `docs/architecture/tr-registry.yaml` | **STOP** — "TR registry not found at `docs/architecture/tr-registry.yaml`. Run `/architecture-review` to bootstrap the registry from your GDDs and ADRs." | optional — proceed without it | not expected — proceed |
| Governing ADR | path from story's ADR field | **STOP** — "ADR file [path] not found. Run `/architecture-decision` to create it, or correct the filename in the story's ADR field." | **STOP only if the story references an ADR** and its file is missing/Proposed; if it references none, proceed | no ADR required — proceed |
| Control manifest | `docs/architecture/control-manifest.md` | **WARN and continue** — "Control manifest not found — layer rules cannot be checked. Run `/create-control-manifest`." | WARN and continue | skip — not expected |
If the TR registry or governing ADR is missing, set the story status to **BLOCKED** in the session state and do not spawn any programmer agent.
At `full`, if the TR registry or governing ADR is missing, set the story status to **BLOCKED** in the session state and do not spawn any programmer agent. At `standard`/`minimal`, only a story that references an ADR whose file is **missing or `Proposed`** is set BLOCKED; a missing TR registry, or an absent-by-design ADR, does **not** block — implement against the story's acceptance criteria + the GDD/brief.
Read all of the following simultaneously — these are independent reads. Do not start implementation until all context is loaded:
Read the story file and the TR registry simultaneously — these two are
genuinely independent, unconditional reads. **The governing ADR is not part
of this batch — do not include it in the same parallel tool-call group as
these two.** Its own section below is a gate, not a read: whether the ADR
gets opened at all depends on a freshness check that itself depends on the
story file already being read. Do not start implementation until this phase
is fully resolved:
### The story file
Extract and hold:
- **Story title, ID, layer, type** (Logic / Integration / Visual/Feel / UI / Config/Data)
- **TR-ID** — the GDD requirement identifier
- **Governing ADR** reference
- **ADR Version** stamp embedded in story header (absent on pre-stamp stories)
- **ADR Decision Summary** and **Implementation Notes** — the distilled ADR
guidance; this is the primary source for what the ADR decided
- **Manifest Version** embedded in story header
- **Acceptance Criteria** — every checkbox item, verbatim
- **Implementation Notes** — the ADR guidance section in the story
@@ -66,19 +105,74 @@ Extract and hold:
- **Dependencies** — what must be DONE before this story
### The TR registry
Read `docs/architecture/tr-registry.yaml`. Look up the story's TR-ID.
Read the current `requirement` text — this is the source of truth for what the
GDD requires now. Do not rely on any inline text in the story file (may be stale).
Grep the story's TR-ID from `docs/architecture/tr-registry.yaml`
(`Grep pattern="id: <TR-ID>" path="docs/architecture/tr-registry.yaml" output_mode="content" -A 6`)
rather than reading the whole cross-system registry. Read the matched entry's current
`requirement` text — this is the source of truth for what the GDD requires now. Do not
rely on any inline text in the story file (may be stale).
### The governing ADR
Read `docs/architecture/[adr-file].md`. Extract:
- The full Decision section
- The Implementation Guidelines section (this is what the programmer follows)
- The Engine Compatibility section (post-cutoff APIs, known risks)
- The ADR Dependencies section
**Do not open the ADR by default.** `/create-stories` already distilled it into
this story's `**ADR Decision Summary**` + `## Implementation Notes`, and its
template states the contract outright: *"This is what the programmer reads
instead of the ADR."* Re-reading the source here discards that work and, on an
ADR past the 25k `Read` cap, costs a failed read plus offset/limit retries
before implementation even starts.
**Check freshness with one line, not one file.** Resolve the ADR path from the
story, then:
```
Grep pattern="^## Last Verified" path="docs/architecture/[adr-file].md" output_mode="content" -A 1
```
Compare that date against the story's `**ADR Version**` field:
| Result | Meaning | Action |
|---|---|---|
| Dates **match** | The summary was distilled from the ADR as it stands. | **Trust the story.** Do not read the ADR. |
| Story has **no `ADR Version`** field | A story written before the stamp existed — *not* evidence of staleness. | **Trust the story**, and note in the Phase 6 summary: "Story predates the ADR Version stamp; summary trusted unverified." |
| Grep returns **no match** and the story reads `unversioned` | The ADR carries no `## Last Verified`. Consistent, not stale. | **Trust the story**; recommend `/architecture-decision [file] retrofit` to add the field. |
| Grep returns **no match** but the story names a date | Ambiguous — the ADR may have lost the field. | Treat as **mismatch** (below). |
| Dates **differ** | The ADR changed after this story was written. | **Mismatch** — resolve below. |
**Never treat an absent stamp as a stale one.** A missing field means "unknown",
and the fallback for unknown is the story, not a 35k-token re-read — the two
staleness gates that already exist (`/story-readiness` on Manifest Version,
`/code-review` post-implementation) are what make that safe.
**On mismatch**, use `AskUserQuestion` — same shape as the Manifest Version
check below:
- Prompt: "Story was written against ADR v[story-date]. The ADR is now
v[current-date]. Its decision may have changed. How do you want to proceed?"
- Options:
- `[A] Re-read the changed ADR sections and implement against current guidance (Recommended)`
- `[B] Implement from the story's summary — I accept the drift risk`
- `[C] Stop — I want to review the ADR diff first`
If **[A]**: first check the ADR's size — `Bash: wc -c "docs/architecture/[adr-file].md"`:
- **Under ~50KB** — read the whole file with one `Read` call. Measured on this
branch: at this size one read is *cheaper* than the multi-grep path (48.4k
vs 52.1k tokens on a 16KB fixture) — per-call overhead outweighs the
content saved. Targeted reading only pays for itself on files big enough
to threaten the 25k-token `Read` cap.
- **~50KB or larger** — read *only* the sections that govern implementation,
never the whole file:
```
Grep pattern="^## (Decision|Engine Compatibility|ADR Dependencies)" path="docs/architecture/[adr-file].md" output_mode="content" -A 40
```
Escalate to a bounded `Read(offset, limit)` on one section only if a scanned
section cross-references material outside itself.
Then update the story's `ADR Version` to the current date so the next run is clean.
If **[B]**: proceed on the summary; record it in the Phase 6 "Deviations" summary.
If **[C]**: stop. Do not spawn any agent.
### The control manifest
Read `docs/architecture/control-manifest.md`. Extract the rules for this story's layer:
Read only this story's layer from `docs/architecture/control-manifest.md` — grep that one
section (`Grep pattern="^## <layer> Layer Rules" path="docs/architecture/control-manifest.md" output_mode="content" -A 40`) rather than a full read of every layer. Extract the rules for this story's layer:
- Required patterns
- Forbidden patterns
- Performance guardrails
@@ -117,26 +211,29 @@ If a dependency file cannot be found: warn "Dependency story not found: [path].
---
### Engine reference
Read `.claude/docs/technical-preferences.md`:
- `Engine:` value — determines which programmer agents to use
- Naming conventions (class names, file names, signal/event names)
- Performance budgets (frame budget, memory ceiling)
- Forbidden patterns
Read from `project.yaml` first, falling back to `.claude/docs/technical-preferences.md` for any key absent or empty:
- `specialists.*` — the project's chosen specialist agents; **read before**
`engine.name` when selecting an agent (see Phase 3)
- `engine.name` (else the `Engine:` value) — the generic engine specialist, and
the fallback when `specialists` is absent
- `naming.*` (else Naming conventions) — class names, file names, signal/event names
- `performance.*` (else Performance budgets) — frame budget, memory ceiling
- Forbidden patterns — from `.claude/docs/technical-preferences.md` (not migrated to project.yaml)
### Mark Story In Progress
Silently update two things before spawning any agent:
1. **`production/sprint-status.yaml`** (if it exists): find the entry matching this story's file path and set `status: in_progress`. Update the top-level `updated` field to today's date. If the file does not exist, skip silently.
1. **`production/sprint-status.yaml`** (if it exists): find the entry matching this story's file path and set `status: in_progress`. Update the top-level `updated` field to today's date. If the file does not exist, say so in one line — `Sprint status not updated: production/sprint-status.yaml absent` — and continue. Do not skip silently: `/sprint-status` reads that file to report progress, so a story that never gets marked `in_progress` is invisible to the very command a producer uses to ask what is moving.
2. **The story file itself**: edit the `Last Updated:` field in the story header to today's date (format: `YYYY-MM-DD`). If the field does not exist in the story header, add it after the `Status:` line. This enables sprint-status staleness detection for this story.
2. **The story file itself**: set the story header's `Status:` field to `In Progress`, and edit its `Last Updated:` field to today's date (format: `YYYY-MM-DD`; if the field does not exist, add it after the `Status:` line). Setting `Status:` here is what actually marks the story In Progress — at `minimal` the `sprint-status.yaml` in step 1 is absent, so the story file is the only record of progress at that tier.
---
## Phase 3: Route to the Right Programmer
Based on the story's **Layer**, **Type**, and **system name**, determine which
specialist to spawn via Task.
specialist to spawn via `Agent`.
**Config/Data stories — skip agent spawning entirely:**
If the story's Type is `Config/Data`, no programmer agent or engine specialist is needed. Jump directly to Phase 4 (Config/Data note). The implementation is a data file edit — no routing table evaluation, no engine specialist.
@@ -155,40 +252,111 @@ If the story's Type is `Config/Data`, no programmer agent or engine specialist i
### Engine specialist — always spawn as secondary for code stories
Read the `Engine Specialists` section of `.claude/docs/technical-preferences.md`
to get the configured primary specialist. Spawn them alongside the primary agent
when the story involves engine-specific APIs, patterns, or the ADR has HIGH
engine risk.
**Read the `specialists` block from `project.yaml` directly — it is not in
the `resolve_config` output at the top of this skill..** `resolve_config` does not emit
`specialists.*`; the five skills that already consume it (`/adopt`,
`/code-review`, `/design-system`, `/gate-check`, `/team-ui`) all read the block
out of `project.yaml` themselves, and so does this one. Adding it to the
frontmatter key list would fail the gate that asserts every requested key is one
`resolve_config` actually emits.
`/setup-engine` writes the block, and it is the project's own answer to "which
specialist implements here" — resolved from the engine *and the language*, which
`engine.name` alone cannot tell you. Resolve in this order:
1. **`specialists.code`** — the language/code specialist, and the right secondary
for an implementation story. This is the value that distinguishes a Godot C#
project (`godot-csharp-specialist`) from a Godot GDScript one
(`godot-gdscript-specialist`); `engine.name` is `Godot` for both.
2. **`specialists.shader`** when the story touches shaders or materials, and
**`specialists.ui`** when the story's Type is `UI` — in addition to, not
instead of, `specialists.code`.
3. **The generic `<engine>-specialist`** — derived from `engine.name`
(Godot→`godot-specialist`, Unity→`unity-specialist`,
Unreal→`unreal-specialist`) — for architecture-level and broad engine
concerns, and as the fallback when the `specialists` block is absent.
4. If `engine.name` is also absent or empty, read the Primary line of the
`## Engine Specialists` section of `.claude/docs/technical-preferences.md`.
**A value of `null` means UNSET — treat that key as absent and fall through to
the generic specialist. Never spawn it as an agent name.** The config reader
returns the four-character string `"null"`, which is not empty and therefore
reads as configured; `null`, empty and missing are the same state here. (This is
the same caveat `/code-review` Phase 2 carries, for the same reason.)
Spawn the resolved specialist alongside the primary agent when the story involves
engine-specific APIs, patterns, or the ADR has HIGH engine risk.
The full roster, for reference when no `specialists` block exists:
| Engine | Specialist agents available |
|--------|----------------------------|
| Godot 4 | `godot-specialist`, `godot-gdscript-specialist`, `godot-shader-specialist` |
| Unity | `unity-specialist`, `unity-ui-specialist`, `unity-shader-specialist` |
| Godot 4 | `godot-specialist`, `godot-gdscript-specialist`, `godot-csharp-specialist`, `godot-shader-specialist`, `godot-gdextension-specialist` |
| Unity | `unity-specialist`, `unity-ui-specialist`, `unity-shader-specialist`, `unity-dots-specialist`, `unity-addressables-specialist` |
| Unreal Engine | `unreal-specialist`, `ue-gas-specialist`, `ue-blueprint-specialist`, `ue-umg-specialist`, `ue-replication-specialist` |
> **Do not pick from this table when `specialists` is set.** The table lists what
> *exists* for an engine; the block records what this project *chose*. Reading the
> table instead of the block is how a Godot C# project ends up reviewed by the
> GDScript specialist.
**When engine risk is HIGH** (from the ADR or VERSION.md): always spawn the engine
specialist, even for non-engine-facing stories. High risk means the ADR records
assumptions about post-cutoff engine APIs that need expert verification.
> **Read the risk, do not trust the story card alone.** If the story's `Risk`
> field is absent, or says `NOT ASSESSED`, **or disagrees with
> `docs/engine-reference/<engine>/VERSION.md`, the VERSION.md rating wins** and an
> unknown counts as HIGH. At `minimal` there is no ADR, so VERSION.md is the only
> source; a story card carrying an improvised `MEDIUM` against a VERSION.md
> rating of HIGH would skip this spawn without saying so — which is how two wrong engine
> defaults reached a project unreviewed. `/create-stories` now derives the field
> from the same file, so the two should agree; this check is what catches it when
> they do not.
---
## Phase 4: Implement
Spawn the chosen programmer agent(s) via Task with the full context package:
Spawn the chosen programmer agent(s) via `Agent` with the full context package:
Brief the agent with file paths and targeted reading instructions — do not serialize document content into the Task prompt. The agent reads what it needs directly:
Brief the agent with file paths and targeted reading instructions — do not serialize document content into the `Agent` prompt. The agent reads what it needs directly.
1. **Story file**: `[story-path]` — read in full
> **Tier note (from Phase 2):** items 2–4 below assume the `full` baseline. At
> `standard`, include the TR registry only if it exists and the governing ADR
> only where the story references one. At `minimal`, the TR registry, ADR, and
> control manifest are typically absent — **omit items 2–4 and brief the agent to
> implement against the story's Acceptance Criteria and the GDD/brief** (the
> story file from item 1). Never instruct the agent to read a file Phase 2
> confirmed missing.
>
> **Say which items you dropped, and say it to both readers.** The rule item 7
> already carries applies unchanged to items 2–4: *an omitted item and a
> forgotten one are indistinguishable to the agent.* They are equally
> indistinguishable to the user reading the Phase 6 summary.
> - **To the agent**, in the prompt: *"No TR registry entry is passed for this
> story — `docs/architecture/tr-registry.yaml` does not exist at this tier.
> Implement against the story's Acceptance Criteria and the GDD/brief. Do not
> go looking for it."* Same form for an absent ADR or control manifest.
> - **To the user**, one line before spawning: `Briefing omits: TR registry
> (absent), control manifest (absent) — implementing against acceptance
> criteria + GDD.`
>
> Without this, a `standard` run where the registry legitimately does not exist
> and one where `/architecture-review` was supposed to bootstrap it and nobody
> did produce **identical output**.
1. **Story file**: `[story-path]` — the agent reads this one file; it carries the acceptance criteria, Out of Scope boundaries, and QA test cases
2. **GDD requirement**: look up TR-ID `[TR-XXX-NNN]` in `docs/architecture/tr-registry.yaml` — use the `requirement` field as source of truth
3. **ADR**: `docs/architecture/[adr-file].md` — read the **Decision** and **Implementation Guidelines** sections only
3. **ADR guidance**: pass the story's `**ADR Decision Summary**` and `## Implementation Notes` **inline in the prompt** — do not pass the ADR path. Phase 2 already established that this summary is current; handing the agent a path makes it re-read the whole ADR in its own context, paying the cost this skill just avoided. Pass the path *only* if Phase 2 hit the mismatch branch and the user chose `[C]`-style deferral, in which case say which sections to grep.
4. **Control manifest**: `docs/architecture/control-manifest.md` — read rules for the **[layer]** layer only
5. **Engine preferences**: `.claude/docs/technical-preferences.md` — read naming conventions and performance budgets
5. **Engine preferences**: `naming.*` and `performance.*` from `project.yaml` (for any key absent or empty, fall back to `.claude/docs/technical-preferences.md`)
6. **Test file path**: `[path from story's Test Evidence section]` — this file must be created as part of implementation
7. **Test requirement** (Logic and Integration stories only): The test file MUST be created at `[path from the story's Test Evidence section]`. Write the test alongside the implementation — do not defer it. The story cannot be closed via `/story-done` without this file present. Each acceptance criterion must have at least one test function covering it. Test file naming: `[system]_[feature]_test.[ext]`. Function naming: `test_[scenario]_[expected_outcome]`. No random seeds, no time-dependent assertions, no external I/O.
7. **Test requirement** (Logic and Integration stories only; **omit this entire item at `qa.level: minimal`** — tests are not required there. When you omit it, tell the agent so explicitly: *"Do not write a test file for this story — test evidence is waived at `qa.level: minimal`."* An omitted item and a forgotten one are indistinguishable to the agent, and a programmer briefed with no test instruction may write tests anyway, or may silently assume they were meant to): The test file MUST be created at `[path from the story's Test Evidence section]`. Write the test alongside the implementation — do not defer it. At `qa.level: standard`/`full` the story cannot be closed via `/story-done` without this file present. Each acceptance criterion must have at least one test function covering it. Test file naming: `[system]_[feature]_test.[ext]`. Function naming: `test_[scenario]_[expected_outcome]`. No random seeds, no time-dependent assertions, no external I/O.
8. **Explicit instruction**: implement this story following the ADR guidelines, respect the manifest rules, stay within the story's Out of Scope boundaries. Write clean, doc-commented public APIs.
The agent should:
- Create or modify files in `src/` following the ADR guidelines
- Create or modify files under the **resolved code root** following the ADR guidelines. Resolve it per `.claude/docs/code-root-resolution.md` — `src/` is the Godot row, `Assets/Scripts/<System>/` is Unity's, `Source/<Module>/<System>/` is Unreal's. **If the code root cannot be resolved, do not write: report it and stop.** Selecting the engine specialist above is NOT the same as resolving the code root
- Respect all Required and Forbidden patterns from the control manifest
- Stay within the story's Out of Scope boundaries (do not touch unrelated files)
- Write clean, doc-commented public APIs
@@ -202,9 +370,12 @@ changed from/to.
### Visual/Feel stories
Spawn `gameplay-programmer` to implement the code/animation calls. Note that
Visual/Feel acceptance criteria cannot be auto-verified — the "does it feel right?"
check happens in `/story-done` via manual confirmation.
Spawn `gameplay-programmer` to implement the code/animation calls. The *look*
half of the acceptance criteria — layout, clipping, presence, colour — is
verified in Phase 6 step 4 by launching the build and retaining a screenshot;
it is not deferred. The *feel* half — timing, weight, responsiveness — is not
something a still can show: say which half the run covered, and leave feel to
`/team-qa`.
---
@@ -212,24 +383,117 @@ check happens in `/story-done` via manual confirmation.
The test requirement was included in the Phase 4 programmer agent brief (item 7). This phase summarizes what evidence each story type requires — used when collecting the Phase 6 summary.
| Story Type | Required Evidence | Notes |
|---|---|---|
| **Logic** | Automated unit test at path from story's Test Evidence section | BLOCKING — included in Phase 4 agent brief |
| **Integration** | Integration test OR documented playtest record | BLOCKING — included in Phase 4 agent brief |
| **Visual/Feel** | Evidence doc at `production/qa/evidence/[slug]-evidence.md` | ADVISORY — note in Phase 6 summary |
| **UI** | Manual walkthrough doc or interaction test | ADVISORY — note in Phase 6 summary |
| **Config/Data** | None — smoke check serves as evidence | N/A |
**Skip this phase at `qa.level: minimal`** (resolved earlier) — no test evidence
is required, so there is nothing to gate; do not flag the story unverifiable for a
missing test.
For Visual/Feel and UI stories, include in the Phase 6 summary: "Manual evidence required at `production/qa/evidence/[slug]-evidence.md` before this story can be fully closed."
> **Say so in the Phase 6 summary.** A skipped phase must announce itself in the
> output, not only in this file (`.claude/rules/skill-authoring.md`, obligation
> 3). Emit the line:
>
> > *Test evidence: **waived** at `qa.level: minimal` — no test was required or
> > written for this story.*
>
> Without it, a minimal-tier summary that simply lacks a tests row is
> indistinguishable from a `standard`-tier run where the programmer forgot to
> write them — and the permissive reading is the one that gets believed.
Otherwise:
**Resolve the gate level for this story's type** from `testing.strict` in
`project.yaml`. BLOCKING means a missing test marks the story unverifiable;
ADVISORY means a missing test is noted but does not block:
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 the **the resolved-config block at the top of this skill**, not from
`project.yaml` directly. If its value is `true` (case-insensitive) →
BLOCKING; if `false` → ADVISORY; `unset` → fall through.
> `testing.strict.*` is locally overridable (`/settings --local
> testing.strict.logic=false`). Reading `project.yaml` on its own ignores
> `project.local.yaml` entirely, so the override is accepted and then does
> nothing. `resolve_config` merges the two.
2. Else read `testing.strict` as a plain boolean (legacy single-value form) — if
its value is `true` or `false`, it applies to every type.
3. Else use the **Default Gate Level** column below.
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 at path from story's Test Evidence section | BLOCKING |
| **Integration** | Integration test OR documented playtest record | BLOCKING |
| **Visual/Feel** | Retained screenshot + evidence doc at `production/qa/evidence/[slug]-evidence.md` | BLOCKING |
| **UI** | Retained screenshot of each screen touched, in `production/qa/evidence/` | BLOCKING |
| **Config/Data** | None — smoke check serves as evidence | ADVISORY |
The test is written alongside the implementation (Phase 4, item 7) regardless of
the gate level — strictness controls only how a *missing* test is reported in the
Phase 6 summary. At a BLOCKING level, a missing test is flagged "story
unverifiable — test required before `/story-done`". At an ADVISORY level it is
noted as a recommendation. The **Default Gate Level** column applies when
`testing.strict` is unset.
Visual/Feel and UI default to **BLOCKING**: for a game the rendered result is the
product, and an advisory visual gate gets deferred in favour of whatever does
block. A project that genuinely does not need it sets `testing.strict.visual` or
`testing.strict.ui` to `false`.
For Visual/Feel and UI stories, include in the Phase 6 summary: "Retained screenshot required at `production/qa/evidence/[slug]-evidence.md` before this story can be closed — at the default BLOCKING level a story with no screenshot on disk is unverifiable."
---
## Phase 6: Collect and Summarise
After the programmer agent(s) complete, collect:
### First: did the agent actually finish?
**Do not assume completion.** A programmer agent can stop at its turn limit
mid-edit, and the work it leaves behind can be syntactically broken — a helper
called but never defined, an import half-moved. Its partial report reads like
progress, and this phase's summary would print "Implementation Complete" over
code that does not load.
Before collecting anything:
1. **Check the agent's own terminal state.** If it reported stopping early, hit a
turn/step limit, or its report ends mid-task, treat the story as **INCOMPLETE**.
2. **Verify the output parses.** Run the cheapest check the engine offers —
`commands.test` or `commands.smoke` from `project.yaml`, or for Godot
`godot --headless --path . --import`, which surfaces parse errors without
running the game. Report what you ran and what it said.
3. If the engine binary is unavailable, write **`parse NOT VERIFIED — engine
binary not available`**. Do not infer that the code is fine because it reads
correctly; that inference is exactly what this step exists to replace.
4. **Run it and look.** A parse check is not a run. For every story that
changes something a player can see — every Visual/Feel and UI story, and any
Logic, Integration or Config/Data story with a surface — launch the build
via `commands.run`, straight into the scene or map the story touched, and
retain a screenshot under `production/qa/evidence/[story-slug]/`. Then
`Read` the image and compare it to the acceptance criteria: clipped text,
an overflowing panel, a missing element are defects, and this is the only
step that finds them. Procedure per engine, including how to capture
unattended in Godot, Unity and Unreal: `.claude/docs/run-and-observe.md`.
Report exactly one line — `Run result: OBSERVED — <what was on screen>`
with the retained path, `Run result: NOT VERIFIED — <reason>`, or
`Run result: N/A — <reason>` for a story with genuinely nothing observable.
**`NOT VERIFIED` is a blocker at the default gate level for Visual/Feel and
UI, not a note** — `/story-done` reads this line. This step is **not waived
at `qa.level: minimal`**; tests are, the look is not.
**If INCOMPLETE:** say so as the headline, list what exists so far, name the
specific breakage, and offer to resume the agent. Do **not** emit
"Implementation Complete", and do not advance the story's status.
### Then collect:
- Files created or modified (with paths)
- Test file created (path and number of test functions written)
- **Verification result** — what was run, and its outcome (or why it could not run)
- Test file created (path and number of test functions written) — **or**, at
`qa.level: minimal`, the waiver line from Phase 5
- Any deviations from the story's Out of Scope boundary (flag these)
- Any questions or blockers the agent surfaced
- Any engine-specific risks the specialist flagged
@@ -240,19 +504,24 @@ Present a concise implementation summary:
## Implementation Complete: [Story Title]
**Files changed**:
- `src/[path]` — created / modified ([brief description])
- `tests/[path]` — test file ([N] test functions)
- `<code root>/[path]` — created / modified ([brief description])
- `tests/[path]` — test file ([N] test functions) — *omit this line at
`qa.level: minimal` and print the Phase 5 waiver line instead*
**Verification**: [what was run] — [result, or `NOT VERIFIED — <reason>`]
**Run result**: [`OBSERVED — <what was on screen>` + retained path | `NOT VERIFIED — <reason>` | `N/A — <reason>`] — see `.claude/docs/run-and-observe.md`
**Acceptance criteria covered**:
- [x] [criterion] — implemented in [file:function]
- [x] [criterion] — covered by test [test_name]
- [ ] [criterion] — DEFERRED: requires playtest (Visual/Feel)
- [x] [criterion] — OBSERVED in `production/qa/evidence/[slug]/01-[what].png` (Visual/UI look)
- [ ] [criterion] — DEFERRED: requires playtest (Visual/Feel *feel* — timing, weight; a still cannot show it)
**Deviations from scope**: [None] or [list files touched outside story boundary]
**Engine risks flagged**: [None] or [specialist finding]
**Blockers**: [None] or [describe]
**Before running `/story-done`:** run your test suite locally and confirm the tests you wrote pass. `/story-done` will re-run them automatically, but a failing test discovered there means returning to implementation context.
**Before running `/story-done`:** run your test suite locally and confirm the tests you wrote pass. *(At `qa.level: minimal` no tests were written — print the Phase 5 waiver line here instead of this paragraph. Telling a user to confirm the passing of tests that do not exist is worse than saying nothing.)* **`/story-done` does NOT re-run them** — its Phase 3 checks that the test FILE exists, with `Glob`, and nothing executes it. A test that exists and fails satisfies that gate. Nothing downstream makes the local run safe to skip. Pass/fail is established by `/gate-check` and `/smoke-check`, both of which execute a suite — and both come later than story closure.
Ready for: `/code-review [file1] [file2]` then `/story-done [story-path]`
```
@@ -278,26 +547,32 @@ Create `active.md` if it does not exist. Confirm: "Session state updated."
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
- ADR status is Proposed → do not implement; run `/architecture-decision` first
- A *referenced* ADR's status is Proposed → do not implement; run `/architecture-decision` first (at `standard`/`minimal` a story that references no ADR is not blocked on this — see Phase 2)
- Scope too large → split into two stories via `/create-stories`
- Conflicting instructions between ADR and story → surface the conflict, do not guess
- Manifest version mismatch → show diff to user, ask whether to proceed with old rules or update story first
## Collaborative Protocol
- **File writes are delegated** — all source code, test files, and evidence docs are written by sub-agents spawned via Task. Each sub-agent enforces the "May I write to [path]?" protocol individually. This orchestrator does not write files directly.
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
- **File writes are delegated** — all source code, test files, and evidence docs are written by sub-agents spawned via `Agent`. Each sub-agent enforces the "May I write to [path]?" protocol individually. This orchestrator does not write files directly.
- **Load before implementing** — do not start coding until all context is loaded
(story, TR-ID, ADR, manifest, engine prefs). Incomplete context produces code
that drifts from design.
@@ -308,8 +583,9 @@ Common blockers:
the story requires touching an out-of-scope file, stop and surface it:
"Implementing [criterion] requires modifying [file], which is out of scope.
Shall I proceed or create a separate story?"
- **Test is not optional for Logic/Integration** — do not mark implementation
complete without the test file existing
- **Test is not optional for Logic/Integration** (at `qa.level: standard`/`full`) —
do not mark implementation complete without the test file existing. At
`qa.level: minimal` tests are not required and this does not apply.
- **Visual/Feel criteria are deferred, not skipped** — mark them as DEFERRED
in the summary; they will be manually verified in `/story-done`
- **Ask before large structural decisions** — if the story requires an
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: estimate
description: "Estimates task effort by analyzing complexity, dependencies, historical velocity, and risk factors. Produces a structured estimate with confidence levels."
description: "Estimate task effort from complexity, dependencies, velocity, risk. Structured estimate with confidence levels."
argument-hint: "[task-description]"
user-invocable: true
allowed-tools: Read, Glob, Grep
+81
View File
@@ -0,0 +1,81 @@
# /gate-check — Handoff Contract
## Role in Pipeline
Validates whether the project is ready to advance from one development phase to the next by auditing required artifacts and quality checks, producing a PASS / NOT ASSESSED / CONCERNS / FAIL verdict (NOT ASSESSED outranks PASS — a gate that could not check part of its scope has not established readiness; see SKILL.md's verdict section for the precedence order), and — on PASS with user confirmation — writing the new stage name to `project.stage` in `project.yaml` (and legacy `production/stage.txt` for backward compatibility).
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `project.yaml` (`project.stage`, fallback `production/stage.txt`) | Stage name (used when no argument provided, to auto-detect current stage) | Yes |
| `project.yaml` (`modes.workflow`, default `standard`; `workflow_overrides.system_overrides.*`, `workflow_overrides.art_bible_strict`) | Workflow tier — selects the per-gate artifact checklist (Section 2b); per-system overrides resolved when validating MVP GDDs | Yes |
| `docs/engine-reference/[engine]/VERSION.md` | Engine version, post-cutoff risk levels (read during engine validation checks) | Yes |
| `.claude/docs/technical-preferences.md` | Legacy fallback for `engine.*`, `naming.*` and `performance.*` when those keys are absent or empty in `project.yaml`; sole source for forbidden patterns (never migrated). Referenced in quality checks | Yes — required only for keys absent from `project.yaml` |
| `docs/consistency-failures.md` | Domain-tagged entries surfaced as increased-scrutiny context (read if exists; skip if absent) | Yes |
### Phase-specific inputs (subset read depending on target gate)
| Target Gate | Key Files Checked |
|-------------|------------------|
| Concept → Systems Design | `design/gdd/game-concept.md`; pillars either inside it **or** in an optional `design/gdd/game-pillars.md` |
| Systems Design → Technical Setup | `design/gdd/systems-index.md`, all MVP GDDs in `design/gdd/`, cross-GDD review report |
| Technical Setup → Pre-Production | `docs/architecture/` ADRs (≥3), `docs/engine-reference/[engine]/deprecated-apis.md`, `docs/architecture/architecture.md`, `docs/architecture/requirements-traceability.md`, `design/accessibility-requirements.md`, `design/ux/interaction-patterns.md` |
| Pre-Production → Production | `prototypes/` (≥1 concept REPORT.md), `production/sprints/` (first sprint plan), `docs/architecture/control-manifest.md`, `production/epics/` (Foundation + Core layer epics), `production/qa/playtests/` (≥3 sessions), `design/ux/hud.md`, `design/ux/` key screen specs |
| Production → Polish | code-root subsystems (resolve per `.claude/docs/code-root-resolution.md`), `tests/unit/` + `tests/integration/` (all Logic stories covered), `production/qa/smoke-*.md` (PASS verdict), `production/qa/playtests/` (≥3 sessions) |
| Polish → Release | Full story test evidence for all Must Have stories, QA sign-off report, localization check, `production/qa/` QA plan, release checklist output, changelog |
### Preconditions
- The target phase argument must be one of: `systems-design`, `technical-setup`, `pre-production`, `production`, `polish`, `release`; if omitted, auto-detects from `project.stage` in `project.yaml` (fallback `production/stage.txt`) and validates the next transition
- The skill does not require any prior skill to have run in the same session, but it will surface missing prerequisites (e.g., missing ADRs, missing playtest reports) as blockers in the verdict
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `production/gate-checks/gate-[phase]-[date].md` (or path chosen by user) | Full checklist with per-item status, Blockers list, Recommendations, Verdict, Chain-of-Verification note | written only after user approves ("May I write this gate check report to production/gate-checks/?") |
| `project.yaml` (`project.stage`) + legacy `production/stage.txt` | New stage name (dual-write for backward compat) | written ONLY when verdict is PASS AND user explicitly confirms; never written on CONCERNS or FAIL |
### Output Guarantees
- The gate report always contains: artifact checklist (with file sizes or "MISSING"), quality check results, list of blockers (empty if PASS), recommendations, and the Chain-of-Verification note
- `project.stage` (and legacy `production/stage.txt`) is updated to the new stage name only on a confirmed PASS — never speculatively
- Any item that cannot be automatically verified is marked `MANUAL CHECK NEEDED` and the user is asked before the verdict is finalized
## Immutability Rules
- READS but does NOT modify: all GDDs in `design/gdd/`, all ADRs in `docs/architecture/`, `docs/architecture/control-manifest.md`, `docs/architecture/tr-registry.yaml`, `.claude/docs/technical-preferences.md` (legacy fallback), `docs/engine-reference/[engine]/VERSION.md`, `docs/engine-reference/[engine]/deprecated-apis.md`, all story files in `production/epics/`, all sprint files in `production/sprints/`, all playtest files in `production/qa/playtests/`, source files in the code root (Grep only), test files in `tests/` (run via Bash)
- MODIFIES: `project.yaml` (`project.stage` only) + legacy `production/stage.txt` (both on PASS + user confirmation only), `production/gate-checks/[report].md` (new file, with user approval)
- Does NOT modify story files, ADRs, GDDs, or any source/test code
## Hard Constraints (Never Violate)
- Never writes stage (either `project.yaml` `project.stage` or legacy `production/stage.txt`) unless the verdict is PASS and the user has explicitly confirmed advancement
- Never writes stage on a CONCERNS or FAIL verdict under any circumstances
- Never auto-advances stage — even a PASS verdict requires explicit user confirmation before the file is written
- Never assumes PASS for items that cannot be automatically verified — always marks them `MANUAL CHECK NEEDED` and asks the user
- Never blocks the user from advancing — the verdict is advisory; if the user overrides, document the risks explicitly in the gate report
- Always runs Chain-of-Verification (5 challenge questions) after drafting the verdict before finalizing it
- If any Vertical Slice Validation item is NO at the Pre-Production → Production gate, the verdict is automatically FAIL regardless of all other checks — and regardless of workflow tier (tier reductions relax what must *exist*, never make a broken built artifact passable)
- Workflow-tier reductions (Section 2b) only ever *relax* a requirement (Required → CONCERNS-if-absent, or drop); they never add one. The sole exception that adds is `workflow_overrides`: a system pinned via `system_overrides` to a higher tier than the project blocks the gate until that one system's GDD meets the higher section count, and `art_bible_strict: true` forces the complete art bible regardless of tier
- gate-check honors `modes.workflow` but is exempt from `modes.automation` — the collaborative prompting protocol (Section 8) always applies; a phase gate is never auto-run
## Downstream Skill Expects
**Next skill (on PASS):** varies by gate
| Gate Passed | Enabled downstream skill |
|-------------|-------------------------|
| Concept → Systems Design | `/map-systems` |
| Systems Design → Technical Setup | `/architecture-decision`, `/setup-engine` |
| Technical Setup → Pre-Production | `/create-epics`, `/create-stories`, prototyping skills |
| Pre-Production → Production | `/dev-story`, `/sprint-plan`, `/story-readiness` |
| Production → Polish | `/perf-profile`, `/playtest-report`, `/smoke-check` |
| Polish → Release | `/launch-checklist`, `/release-checklist` |
- Downstream skills read `project.stage` from `project.yaml` (fallback `production/stage.txt`) to confirm their phase is active before proceeding
- `/dev-story` specifically checks that the project is in Production stage before implementing stories; if the resolved stage is still `Pre-Production`, stories may be blocked
- `/create-epics` requires `docs/architecture/control-manifest.md` to exist (enforced by the Technical Setup → Pre-Production gate)
## Known Fragile Points
- `project.stage` in `project.yaml` (with legacy `production/stage.txt` as fallback) is the authoritative stage indicator — if either is manually edited to a wrong value outside of `/gate-check`, auto-detection in future sessions will be incorrect; never edit them outside of a PASS gate
- The Production → Polish gate runs the test suite via Bash. If the test runner command is not configured or fails to start (e.g. the `godot --headless --script` path is wrong), the test check now yields `NOT ASSESSED`, which outranks PASS — so the gate cannot advance a stage on the strength of a suite that never ran. Without the `NOT ASSESSED` branch this masks silent test regressions: Section 3 runs the suite "if a test runner is configured", and with no else an unconfigured runner simply contributes nothing to the verdict
- The Pre-Production → Production gate has a hard Vertical Slice validation block; any subjective checklist item (e.g., "core mechanic feels good") requires a user response via `AskUserQuestion` — if the user answers without playing the build, a false PASS is possible
- Gate report files in `production/gate-checks/` are not validated for completeness by any downstream skill; a partial report written due to a session interruption will look identical to a complete one
- `docs/consistency-failures.md` is optional context that adjusts scrutiny but does not change the formal checklist; if this file exists but is stale, the increased-scrutiny signals may point at resolved issues
+456 -219
View File
@@ -1,12 +1,18 @@
---
name: gate-check
description: "Validate readiness to advance between development phases. Produces a PASS/CONCERNS/FAIL verdict with specific blockers and required artifacts. Use when user says 'are we ready to move to X', 'can we advance to production', 'check if we can start the next phase', 'pass the gate'."
description: "Ready to advance between development phases? PASS/CONCERNS/NOT ASSESSED/FAIL with blockers and required artifacts. 'Can we move to production?'"
argument-hint: "[target-phase: systems-design | technical-setup | pre-production | production | polish | release] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, Agent, AskUserQuestion
model: opus
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,workflow,qa.level,testing.strict,performance.enforce,team.size,project.stage,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Phase Gate Validation
This skill validates whether the project is ready to advance to the next development
@@ -27,8 +33,7 @@ The project progresses through these stages:
6. **Polish** — Performance, playtesting, bug fixing
7. **Release** — Launch prep, certification
**When a gate passes**, write the new stage name to `production/stage.txt`
(single line, e.g. `Production`). This updates the status line immediately.
**When a gate passes**, update the stage in both `project.yaml` (set `project.stage: <new-stage>`) AND write the new stage name to `production/stage.txt` (single line, e.g. `Production`). Dual-write keeps backward compatibility with hooks that haven't migrated yet. This updates the status line immediately.
---
@@ -36,13 +41,40 @@ The project progresses through these stages:
**Target phase:** `$ARGUMENTS[0]` (blank = auto-detect current stage, then validate next transition)
Also resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
Note: in `solo` mode, director spawns (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE) are skipped — gate-check becomes artifact-existence checks only. In `lean` mode, all four directors still run (phase gates are the purpose of lean mode).
**`workflow`** (per `.claude/docs/workflow-modes.md`):
`gate-check` runs project-wide, so it uses the project-level `workflow` for the
gate's overall artifact checklist (the loaded gate file), AND consults
`workflow_overrides.system_overrides.<system>` per-system when validating MVP
GDDs — a system pinned to a higher tier must meet that tier's section count
before the gate passes, regardless of the project-level workflow (see Section 2b,
"Per-system overrides").
> **gate-check honors `workflow` but is exempt from `automation`.** The artifact
> checklist changes per tier; the collaborative prompting protocol (Section 8)
> always applies — a phase gate is a deliberate human checkpoint, never auto-run.
**`qa.level`**: controls test enforcement at phase gates, where `workflow`
controls which artifacts are required. `modes.rigor` sets both together; set
`qa.level` explicitly to vary enforcement alone. At `minimal`, no test gates apply — the
test-evidence / unit-test / smoke artifact items become non-required and the
Section 3 `testing.strict` check is a no-op. At `standard`, Logic + Integration
tests must pass. At `full`, a full coverage check + regression suite are required
(coverage minimum from `qa.coverage_minimum` if set).
**`team.size`**: does not change how many directors spawn at a phase gate — panel
width is `workflow`'s axis (Section 4b). This value affects only the
**specialist depth within each director's review**.
`individual` uses the core specialist set; `small` the standard set; `studio`
adds engine sub-specialists. It never skips a director — skipping directors is
`review_mode`'s job. Both `review_mode` and `team.size` are now fronted by
`modes.rigor` — one rigor choice sets both — and each still overrides that axis
when set explicitly (a full-rigor project gets the `studio` set; lighter tiers
get `individual`).
- **With argument**: `/gate-check production` — validate readiness for that specific phase
- **No argument**: Auto-detect current stage using the same heuristics as
`/project-stage-detect`, then **confirm with the user before running**:
@@ -59,198 +91,129 @@ Note: in `solo` mode, director spawns (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GA
## 2. Phase Gate Definitions
### Gate: Concept → Systems Design
Each gate's checklist — required artifacts, quality checks, and its workflow-tier
reductions — lives in its own file. **Read only the row for the target phase
transition; never load the others.**
**Required Artifacts:**
- [ ] `design/gdd/game-concept.md` exists and has content
- [ ] Game pillars defined (in concept doc or `design/gdd/game-pillars.md`)
- [ ] Visual Identity Anchor section exists in `design/gdd/game-concept.md` (from brainstorm Phase 4 art-director output)
| Gate | Definition file |
|------|-----------------|
| Concept → Systems Design | `.claude/skills/gate-check/references/gate-systems-design.md` |
| Systems Design → Technical Setup | `.claude/skills/gate-check/references/gate-technical-setup.md` |
| Technical Setup → Pre-Production | `.claude/skills/gate-check/references/gate-pre-production.md` |
| Pre-Production → Production | `.claude/skills/gate-check/references/gate-production.md` |
| Production → Polish | `.claude/skills/gate-check/references/gate-polish.md` |
| Polish → Release | `.claude/skills/gate-check/references/gate-release.md` |
**Recommended (not blocking):**
- [ ] Concept prototype exists in `prototypes/` with a REPORT.md showing PROCEED verdict
(`/prototype [core-mechanic]`) — skipping this means GDDs may be written for an
idea that hasn't been played. Acceptable if the concept is proven by other means.
Each file states the `full` baseline first, then the `standard` and `minimal`
reductions for that gate. Apply the tier resolved in Section 1.
**Quality Checks:**
- [ ] Game concept has been reviewed (`/design-review` verdict not MAJOR REVISION NEEDED)
- [ ] Core loop is described and understood
- [ ] Target audience is identified
- [ ] Visual Identity Anchor contains a one-line visual rule and at least 2 supporting visual principles
## 2b. Workflow Tier Adjustment
---
Each gate file carries its own tier reductions (see Section 2). Two rules apply
across all of them:
### Gate: Systems Design → Technical Setup
> **How to apply:** run the loaded gate's checklist, then apply that file's tier
> reduction for the tier resolved in Section 1. **drop** = not checked at this
> tier; **→ recommended** = absent surfaces as CONCERNS, never a Blocker; items
> not named keep their baseline status. Reductions only ever *relax* a
> requirement — the only thing that adds one is `workflow_overrides` (below).
>
> **`qa.level` (Section 1) further relaxes the test items independently of the
> tier:** at `qa.level: minimal` the test-evidence / unit-test items become
> non-required at every workflow tier (so even `workflow: full` does not require
> them); the Section 3 `testing.strict` check is then a no-op.
>
> **The smoke check is excluded from that relaxation, and is the floor.**
> `qa.level` relaxes *per-story test evidence*; a smoke check is **build health**,
> not story evidence, and the two are already held apart on exactly this basis in
> `.claude/docs/coding-standards.md` ("`/smoke-check` is a build-health gate, not
> a per-story evidence gate ... This divergence is intentional"). So a gate file
> that requires a smoke report keeps requiring it at every `qa.level`.
>
> Without that exclusion the Production → Polish gate had **zero required
> artifacts at `rigor: minimal`** and could not fail on artifacts by
> construction: `minimal` reduced the gate to the smoke check alone, `qa.level`
> then dropped the smoke check too, and one `modes.rigor` setting fires both. Two
> agents found it independently on the same fixture.
**Required Artifacts:**
- [ ] Systems index exists at `design/gdd/systems-index.md` with at least MVP systems enumerated
- [ ] All MVP-tier GDDs exist in `design/gdd/` and individually pass `/design-review`
- [ ] A cross-GDD review report exists in `design/gdd/` (from `/review-all-gdds`)
> **A gate with no required artifacts left must say so, and may not return
> PASS.** After applying the tier reduction and the `qa.level` relaxation, count
> what remains required. If the count is zero, report
> **NOT ASSESSED** naming both reducers and the gate — *"Production → Polish at
> `workflow: minimal` + `qa.level: minimal` leaves no required artifact; this
> gate verified nothing"* — rather than a PASS earned by having nothing to check.
> Per `.claude/rules/skill-authoring.md` obligation 1, a run that could not
> assess its scope has not established that the scope is good, and obligation 3
> requires the emptiness to be visible in the output rather than inferable from
> a silent green.
>
> **`performance.enforce` is likewise independent of the tier, and a tier
> reduction never suppresses it.** The performance check in Section 3 runs at
> every workflow tier, and `block` makes a breach a Blocker at every workflow
> tier. Do **not** read a gate file's *"everything else drops"* as dropping it:
> `off` is the only thing that makes budgets informational, and it is a
> deliberate choice the user makes on the same key.
>
> Without this, `performance.enforce: block` is **inert on every `rigor: minimal`
> project** — `minimal` used to reduce the Polish gate to the smoke check alone, and
> "Performance is within budget" sits in the dropped remainder. Two independent
> agents run against a project breaching three of four budgets both spotted the
> contradiction, both overrode the literal reading to reach FAIL, and both
> flagged it as the call most likely to be wrong. A setting that only works
> because agents disregard a rule is not wired.
**Quality Checks:**
- [ ] All MVP GDDs pass individual design review (8 required sections, no MAJOR REVISION NEEDED verdict)
- [ ] `/review-all-gdds` verdict is not FAIL (cross-GDD consistency and design theory checks pass)
- [ ] All cross-GDD consistency issues flagged by `/review-all-gdds` are resolved or explicitly accepted
- [ ] System dependencies are mapped in the systems index and are bidirectionally consistent
- [ ] MVP priority tier is defined
- [ ] No stale GDD references flagged (older GDDs updated to reflect decisions made in later GDDs)
### Per-system overrides (`workflow_overrides.system_overrides`)
---
Independent of the project-level tier above, and applied **only** on the gates
that validate MVP GDDs (Systems Design → Technical Setup, and the GDD-completeness
checks at Pre-Production → Production). For each system, resolve its effective
tier:
### Gate: Technical Setup → Pre-Production
1. If the block's `system_overrides` lists `<system>` → that tier
2. Else the project-level `workflow`
**Required Artifacts:**
- [ ] Engine chosen (CLAUDE.md Technology Stack is not `[CHOOSE]`)
- [ ] Technical preferences configured (`.claude/docs/technical-preferences.md` populated)
- [ ] Art bible exists at `design/art/art-bible.md` with at least Sections 1–4 (Visual Identity Foundation)
- [ ] At least 3 Architecture Decision Records in `docs/architecture/` covering
Foundation-layer systems (scene management, event architecture, save/load)
- [ ] Engine reference docs exist in `docs/engine-reference/[engine]/`
- [ ] Test framework initialized: `tests/unit/` and `tests/integration/` directories exist
- [ ] CI/CD test workflow exists at `.github/workflows/tests.yml` (or equivalent)
- [ ] At least one example test file exists to confirm the framework is functional
- [ ] Master architecture document exists at `docs/architecture/architecture.md`
- [ ] Architecture traceability index exists at `docs/architecture/requirements-traceability.md`
- [ ] `/architecture-review` has been run (a review report file exists in `docs/architecture/`)
- [ ] `design/accessibility-requirements.md` exists with accessibility tier committed
- [ ] `design/ux/interaction-patterns.md` exists (pattern library initialized, even if minimal)
**Before applying any of them, check the block the other way round: does every
KEY match a system?** `<system>` is the GDD filename stem
(`.claude/docs/workflow-modes.md`), so for each key in `system_overrides`, look
for `design/gdd/<key>.md`. Any key with no matching stem is reported, naming the
key and listing the stems that do exist:
**Quality Checks:**
- [ ] Architecture decisions cover core systems (rendering, input, state management)
- [ ] Technical preferences have naming conventions and performance budgets set
- [ ] Accessibility tier is defined and documented (even "Basic" is acceptable — undefined is not)
- [ ] At least one screen's UX spec started (often the main menu or core HUD is designed during Technical Setup)
- [ ] All ADRs have an **Engine Compatibility section** with engine version stamped
- [ ] All ADRs have a **GDD Requirements Addressed section** with explicit GDD linkage
- [ ] No ADR references APIs listed in `docs/engine-reference/[engine]/deprecated-apis.md`
- [ ] All HIGH RISK engine domains (per VERSION.md) have been explicitly addressed
in the architecture document or flagged as open questions
- [ ] Architecture traceability matrix has **zero Foundation layer gaps**
(all Foundation requirements must have ADR coverage before Pre-Production)
> `system_overrides key 'no-such-system' matches no GDD in design/gdd/. Available stems: combat, inventory, hammer-heat-system. This override is doing nothing.`
**ADR Circular Dependency Check**: For all ADRs in `docs/architecture/`, read each ADR's
"ADR Dependencies" / "Depends On" section. Build a dependency graph (ADR-A → ADR-B means
A depends on B). If any cycle is detected (e.g. A→B→A, or A→B→C→A):
- Flag as **FAIL**: "Circular ADR dependency: [ADR-X] → [ADR-Y] → [ADR-X].
Neither can reach Accepted while the cycle exists. Remove one 'Depends On' edge to
break the cycle."
Surface it as a **CONCERNS**-level finding, not a Blocker — the project is still
gateable, but an override the user believes is in force and is not is exactly how
a documented escape hatch silently stops working.
**Engine Validation** (read `docs/engine-reference/[engine]/VERSION.md` first):
- [ ] ADRs that touch post-cutoff engine APIs are flagged with Knowledge Risk: HIGH/MEDIUM
- [ ] `/architecture-review` engine audit shows no deprecated API usage
- [ ] All ADRs agree on the same engine version (no stale version references)
> **This is the one site that performs the check.** `workflow-modes.md:72` says
> *"a key that matches no system is an error, not a no-op"*, and this is the only
> skill that implements it — the three story skills resolve only in the
> system → override direction, so an orphan key is never looked up and
> never noticed. `/gate-check` is the right home: it already resolves the whole
> block, and it is the project-wide audit rather than a per-story one.
---
Validate each GDD against its own effective tier's section count:
### Gate: Pre-Production → Production
- A system pinned **higher** than the project (e.g. `system_overrides.combat:
full` on a `standard` project) **blocks the gate** until that system's GDD
meets the higher bar (combat → all 8 sections). This is the one case where a
per-system setting makes the gate *stricter* than the project tier.
- A system pinned **lower** (e.g. `inventory: minimal`) relaxes only that system
— its GDD is checked at the lower tier; every other system stays at the project
level. A system pinned **`minimal` imposes no GDD section requirement at all**
(`minimal` = "game brief replaces GDDs" — `.claude/docs/workflow-modes.md`): it
never blocks the gate on a missing or incomplete GDD. Do not invent an
"acceptance-criteria-only" floor for it — there is none.
**Required Artifacts:**
- [ ] Vertical slice exists in `prototypes/` with a REPORT.md (run `/vertical-slice`) — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] First sprint plan exists in `production/sprints/`
- [ ] Art bible is complete (all 9 sections) and AD-ART-BIBLE sign-off verdict is recorded in `design/art/art-bible.md`
- [ ] Entity inventory exists at `design/assets/entity-inventory.md` (recommended — run `/asset-spec` with no arguments to generate collaboratively from GDDs + art bible)
- [ ] All MVP-tier GDDs from systems index are complete
- [ ] Master architecture document exists at `docs/architecture/architecture.md`
- [ ] At least 3 ADRs covering Foundation-layer decisions exist in `docs/architecture/`
- [ ] All Foundation and Core layer ADRs have status `Accepted` (not `Proposed`) — stories cannot be unblocked until their governing ADR is accepted
- [ ] Control manifest exists at `docs/architecture/control-manifest.md`
(generated by `/create-control-manifest` from Accepted ADRs)
- [ ] Epics defined in `production/epics/` with at least Foundation and Core
layer epics present (use `/create-epics layer: foundation` and
`/create-epics layer: core` to create them, then `/create-stories [epic-slug]`
for each epic)
- [ ] Vertical Slice build exists and is playable (not just scope-defined) — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] Vertical Slice has been playtested with at least 1 documented session — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] Vertical Slice playtest report exists at `production/playtests/` or equivalent — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] UX specs exist for key screens: main menu, core gameplay HUD (at `design/ux/`), pause menu
- [ ] HUD design document exists at `design/ux/hud.md` (if game has in-game HUD)
- [ ] All key screen UX specs have passed `/ux-review` (verdict APPROVED or NEEDS REVISION accepted)
**Quality Checks:**
- [ ] **Core loop fun is validated** — playtest data confirms the central mechanic is enjoyable, not just functional. Explicitly check the Vertical Slice playtest report.
- [ ] UX specs cover all UI Requirements sections from MVP-tier GDDs
- [ ] Interaction pattern library documents patterns used in key screens
- [ ] Accessibility tier from `design/accessibility-requirements.md` is addressed in all key screen UX specs
- [ ] Sprint plan references real story file paths from `production/epics/`
(not just GDDs — stories must embed GDD req ID + ADR reference)
- [ ] **Vertical Slice is COMPLETE**, not just scoped — the build demonstrates the full core loop end-to-end. At least one complete [start → challenge → resolution] cycle works.
- [ ] Architecture document has no unresolved open questions in Foundation or Core layers
- [ ] All ADRs have Engine Compatibility sections stamped with the engine version
- [ ] All ADRs have ADR Dependencies sections (even if all fields are "None")
- [ ] Manual validation confirms GDDs + architecture + epics are coherent
(run `/review-all-gdds` and `/architecture-review` if not done recently)
- [ ] **Core fantasy is delivered** — at least one playtester independently described an experience that matches the Player Fantasy section of the core system GDDs (without being prompted).
**Vertical Slice Validation** (only run these checks if a Vertical Slice was built):
- [ ] A human has played through the core loop without developer guidance
- [ ] The game communicates what to do within the first 2 minutes of play
- [ ] No critical "fun blocker" bugs exist in the Vertical Slice build
- [ ] The core mechanic feels good to interact with (this is a subjective check — ask the user)
> **Verdict rules for Vertical Slice:**
> - **Slice was built AND any validation item is NO** → verdict is automatically FAIL. A broken
> or unfun vertical slice should not advance to Production.
> - **Slice was not built (skipped)** → downgrade to CONCERNS only, not FAIL. Surface the risk
> clearly: "Advancing without a validated Vertical Slice increases the risk of late-stage design
> pivots. Recommended before committing full production scope." The user decides.
> - Skipping is a valid solo dev or time-constrained call. Shipping a broken one is not.
---
### Gate: Production → Polish
**Required Artifacts:**
- [ ] `src/` has active code organized into subsystems
- [ ] All core mechanics from GDD are implemented (cross-reference `design/gdd/` with `src/`)
- [ ] Main gameplay path is playable end-to-end
- [ ] Test files exist in `tests/unit/` and `tests/integration/` covering Logic and Integration stories
- [ ] All Logic stories from this sprint have corresponding unit test files in `tests/unit/`
- [ ] Smoke check has been run with a PASS or PASS WITH WARNINGS verdict — report exists in `production/qa/`
- [ ] QA plan exists in `production/qa/` (generated by `/qa-plan`) covering this sprint or final production sprint
- [ ] At least one QA plan exists in `production/qa/` covering this production phase — run `/qa-plan` if missing (CONCERNS — advisory, not blocking)
- [ ] QA sign-off report exists in `production/qa/` (generated by `/team-qa`) with verdict APPROVED or APPROVED WITH CONDITIONS
- [ ] At least 3 distinct playtest sessions documented in `production/playtests/`
- [ ] Playtest reports cover: new player experience, mid-game systems, and difficulty curve
- [ ] Fun hypothesis from Game Concept has been explicitly validated or revised
**Quality Checks:**
- [ ] Tests are passing (run test suite via Bash)
- [ ] No critical/blocker bugs in any bug tracker or known issues
- [ ] Core loop plays as designed (compare to GDD acceptance criteria)
- [ ] Performance is within budget (check technical-preferences.md targets)
- [ ] Playtest findings have been reviewed and critical fun issues addressed (not just documented)
- [ ] No "confusion loops" identified — no point in the game where >50% of playtesters got stuck without knowing why
- [ ] Difficulty curve matches the Difficulty Curve design doc (if one exists at `design/difficulty-curve.md`)
- [ ] All implemented screens have corresponding UX specs (no "designed in-code" screens)
- [ ] Interaction pattern library is up-to-date with all patterns used in implementation
- [ ] Accessibility compliance verified against committed tier in `design/accessibility-requirements.md`
---
### Gate: Polish → Release
**Required Artifacts:**
- [ ] All features from milestone plan are implemented
- [ ] Content is complete (all levels, assets, dialogue referenced in design docs exist)
- [ ] Localization strings are externalized (no hardcoded player-facing text in `src/`)
- [ ] QA test plan exists (`/qa-plan` output in `production/qa/`)
- [ ] QA sign-off report exists (`/team-qa` output — APPROVED or APPROVED WITH CONDITIONS)
- [ ] All Must Have story test evidence is present (Logic/Integration: test files pass; Visual/Feel/UI: sign-off docs in `production/qa/evidence/`)
- [ ] Smoke check passes cleanly (PASS verdict) on the release candidate build
- [ ] No test regressions from previous sprint (test suite passes fully)
- [ ] Balance data has been reviewed (`/balance-check` run)
- [ ] Release checklist completed (`/release-checklist` or `/launch-checklist` run)
- [ ] Store metadata prepared (if applicable)
- [ ] Changelog / patch notes drafted
**Quality Checks:**
- [ ] Full QA pass signed off by `qa-lead`
- [ ] All tests passing
- [ ] Performance targets met across all target platforms
- [ ] No known critical, high, or medium-severity bugs
- [ ] Accessibility basics covered (remapping, text scaling if applicable)
- [ ] Localization verified for all target languages
- [ ] Legal requirements met (EULA, privacy policy, age ratings if applicable)
- [ ] Build compiles and packages cleanly
> **Additive overrides (the only things that make the gate stricter).**
> - `workflow_overrides.art_bible_strict: true` forces the complete (9-section)
> art bible at the Technical Setup → Pre-Production and Pre-Production →
> Production gates regardless of tier or whether visual-asset stories exist.
> - `workflow_overrides.edge_cases: true` and `workflow_overrides.tuning_knobs:
> true` force those GDD sections required when validating GDD completeness,
> additive on top of the resolved tier (e.g. at `standard`, `tuning_knobs: true`
> makes the otherwise-optional Tuning Knobs section blocking). These never
> relax — a `false` value is the default/no-op, never a way to drop a section
> the tier already requires.
---
@@ -266,27 +229,132 @@ increased scrutiny on those specific checks.
For each item in the target gate:
### Artifact Checks
- Use `Glob` and `Read` to verify files exist and have meaningful content
- Don't just check existence — verify the file has real content (not just a template header)
- For code checks, verify directory structure and file counts
**Resolve existence and counts deterministically — do not open files to find out
what exists:**
```
Bash: bash .claude/scripts/artifact-check.sh --phase [source-phase]
```
Pass the phase being advanced *from* (its steps are the work that must be
complete): `systems-design` for the Systems Design → Technical Setup gate,
`pre-production` for Pre-Production → Production, and so on.
It reads `workflow-catalog.yaml` — which already encodes each step's `glob`,
`pattern`, `min_count` and `any_of` — and reports per step:
| status | Meaning |
|---|---|
| `PRESENT` | glob matched, `min_count` met, `pattern` found where specified |
| `ABSENT` | nothing matched |
| `SHORT` | matched but fewer than `min_count` (`count=` and `min=` given) |
| `PATTERN_MISS` | files exist but none contains the required marker |
| `NO_CHECK` | the step declares no artifact — **not detectable from disk** |
It emits observations, never a verdict: **you** apply the workflow tier and the
required/optional split from Section 2. An `ABSENT` required artifact is a
blocker at `full` and frequently not one at `minimal`; the script does not know
that and does not decide it.
**`NO_CHECK` is not `PRESENT`.** The header prints a `NO_CHECK:` count before any
row precisely so this cannot be skimmed past. Those steps were *scanned*, not
*satisfied* — carry each into Section 4 (Collaborative Assessment) and ask, or
mark MANUAL CHECK NEEDED. A gate that reports PASS because most of its checklist
was undetectable is the failure mode this count exists to prevent.
**Existence is not adequacy.** The script cannot tell a real document from a
template skeleton. So: for any artifact the verdict actually turns on, spot-read
it and confirm it has real content — the same escalation rule the
`gdd-structure-check.sh` step below uses. Do not spot-read artifacts the verdict
does not turn on.
> **A smoke report is always an artifact the verdict turns on — spot-reading it
> is mandatory, not discretionary.** At `minimal` it is frequently the *only*
> required artifact, so the whole gate rests on one file that nothing generated
> and nothing verifies. Check its claims against the repo, and raise any that the
> tree contradicts:
>
> - It reports a passing automated suite → `tests/` must actually contain test
> files and the project must have a runner. "24 passed, 0 failed" in a repo
> with no `tests/unit/`, no `tests/integration/` and no runner is a finding,
> not evidence.
> - It marks a critical path PASS → the code for that path must exist in the code
> root. A PASS on "banking ends the run" with no banking code is a finding.
> - It carries no date, or predates the newest commit touching the code root →
> say so; a stale smoke report describes a build that no longer exists.
>
> Report a contradiction at the same level the artifact was required at: a
> Blocker where the smoke check is required, CONCERNS where it is recommended.
> This was found by handing a gate a one-page fabricated smoke report on a
> two-file repo; it cleared on existence plus a verdict-line grep.
For code checks, verify directory structure and file counts.
**Systems Design → Technical Setup gate — cross-GDD review check**:
Use `Glob('design/gdd/gdd-cross-review-*.md')` to find the `/review-all-gdds` report.
If no file matches, mark the "cross-GDD review report exists" artifact as **FAIL** and
surface it prominently: "No `/review-all-gdds` report found in `design/gdd/`. Run
`/review-all-gdds` before advancing to Technical Setup."
If a file is found, read it and check the verdict line: a FAIL verdict means the
cross-GDD consistency check failed and must be resolved before advancing.
If no file matches: at `full` mark the "cross-GDD review report exists" artifact as
**FAIL** and surface it prominently ("No `/review-all-gdds` report found in
`design/gdd/`. Run `/review-all-gdds` before advancing to Technical Setup."); at
`standard` the report is recommended, so mark it **CONCERNS**, not a blocker; at
`minimal` this gate is not applicable (see the gate file). If a file is found, read it and
check the verdict line: a FAIL verdict means the cross-GDD consistency check failed
and must be resolved before advancing.
### Quality Checks
- For test checks: Run the test suite via `Bash` if a test runner is configured
- For design review checks: `Read` the GDD and check for the 8 required sections
- For performance checks: `Read` technical-preferences.md and compare against any
profiling data in `tests/performance/` or recent `/perf-profile` output
- For localization checks: `Grep` for hardcoded strings in `src/`
- For test checks: Run the test suite via `Bash` if a test runner is configured.
**If no runner is configured, that is `NOT ASSESSED`, not a silent skip** — see
the trigger in the verdict section. A gate that ran no tests found no test
failures, which is not the same as passing.
A test failure's effect on the verdict depends on the `testing.strict` block
**resolved in Phase 1** (`resolve_config` merges `project.local.yaml` over
`project.yaml`; reading the file directly would drop a local override), per
test type:
- **Logic** — failures in `tests/unit/`, gated by `testing.strict.logic`.
- **Integration** — failures in `tests/integration/`, gated by `testing.strict.integration`.
- For each type: take `testing.strict.<type>` from that block; use it only
if its value is `true` or `false` (case-insensitive). If the key is absent,
empty, or holds any other value, read `testing.strict` as a plain boolean
(legacy single-value form); if that too is absent or invalid, default to
`true` (Logic and Integration are both strict by default — behavior unchanged
from before this setting existed). Surface any unrecognized value to the user.
- At a strict (`true`) gate level, failures of that type are **Blockers**
(verdict FAIL). At an advisory (`false`) level, they are **Concerns**
(verdict minimum CONCERNS, not FAIL) — list them under Recommendations, not
Blockers.
- For design review checks, gather section presence **deterministically** — do not
read the GDDs to count headings:
```
Bash: bash .claude/scripts/gdd-structure-check.sh
```
It prints a `PRESENT:` / `ABSENT:` pair per GDD and already accepts
`## Detailed Design` as satisfying the `Detailed Rules` requirement. It reports
presence only and makes no REQUIRED/ADVISORY judgment.
Then apply each GDD's **effective tier** (per-system resolution below) to those
lists — all 8 sections at `full`, the 5 standard sections (+ conditional
Formulas) at `standard`. A missing *required* section blocks; a missing section
that is optional at the effective tier is advisory. A section reported PRESENT
can still fail review if it is an empty heading — spot-read any section the
verdict actually turns on.
- For performance checks: read the budgets (`performance.target_framerate`,
`frame_budget_ms`, `draw_call_limit`, `memory_ceiling_mb`) from `project.yaml`
(else technical-preferences.md) and compare against any profiling data in
`tests/performance/` or recent `/perf-profile` output. What a breach *means*
is set by `performance.enforce`, taken from the Phase 1 resolved block (it is
locally overridable, so do not read the file for this one):
- `warn` (default) — breaches are **CONCERNS**, never Blockers.
- `block` — breaches are **Blockers** from the Polish gate onward.
- `off` — budgets are informational; do not surface breaches in the verdict.
Only these three values are recognized. Surface anything else to the user and
fall back to `warn` rather than guessing.
- For localization checks: `Grep` for hardcoded 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.**
### Cross-Reference Checks
- Compare `design/gdd/` documents against `src/` implementations
- Compare `design/gdd/` documents against implementations in the **code root**
- Check that every system referenced in architecture docs has corresponding code
- Verify sprint plans reference real work items
@@ -306,24 +374,54 @@ For items that can't be automatically verified, **ask the user**:
## 4b. Director Panel Assessment
**Apply review mode before spawning any director:**
- `solo` → skip all four directors. Note in output: "Director Panel skipped — Solo mode. Gate verdict based on artifact and quality checks only." Proceed to Phase 5.
- `lean` → spawn all four directors (phase gates always run in lean mode — this is their purpose).
- `full` → spawn all four directors as normal.
The panel is set by **two independent axes**, both resolved in Phase 1: `review_mode`
decides *whether* the panel runs, `workflow` decides *how wide* it is.
(Review mode was resolved in Phase 1. Use that stored value here.)
**Axis 1 — `review_mode` decides whether any director spawns:**
- `solo` → skip the panel entirely. Note in output: "Director Panel skipped — Solo mode. Gate verdict based on artifact and quality checks only." Proceed to Phase 5.
- `lean` → run the panel (phase gates always run in lean mode — this is their purpose).
- `full` → run the panel.
Before generating the final verdict, spawn all four directors as **parallel subagents** via Task using the parallel gate protocol from `.claude/docs/director-gates.md`. Issue all four Task calls simultaneously — do not wait for one before starting the next.
**Axis 2 — `workflow` decides the panel width.** Directors are Opus-tier, so a
fixed four-director panel costs a two-system jam exactly what it costs a
thirty-system commercial project. The gate still runs at every tier; only its
breadth scales:
**Spawn in parallel:**
| `workflow` | Panel | Directors |
|---|---|---|
| `minimal` | 1 | `producer` |
| `standard` | 2 | `technical-director`, `producer` |
| `full` | 4 | `creative-director`, `technical-director`, `producer`, `art-director` |
1. **`creative-director`** — gate **CD-PHASE-GATE** (`.claude/docs/director-gates.md`)
2. **`technical-director`** — gate **TD-PHASE-GATE** (`.claude/docs/director-gates.md`)
3. **`producer`** — gate **PR-PHASE-GATE** (`.claude/docs/director-gates.md`)
4. **`art-director`** — gate **AD-PHASE-GATE** (`.claude/docs/director-gates.md`)
`producer` is in every panel — scope and schedule readiness is the one judgment
no tier makes optional. `technical-director` joins at `standard` because that is
the first tier requiring architecture artifacts. `creative-director` and
`art-director` join at `full`, the only tier requiring the full art bible and
UX spec set for them to assess.
> **Width is not the same as strictness.** A narrower panel does not soften the
> verdict: the escalation rule in `.claude/docs/director-gates.md` is unchanged —
> the strictest verdict returned by *whoever ran* still wins. Do not infer PASS
> from a perspective that was never consulted.
Before generating the final verdict, spawn the directors for the resolved tier as **parallel subagents** via `Agent` using the parallel gate protocol from `.claude/docs/director-gates.md`. Issue all the `Agent` calls simultaneously — do not wait for one before starting the next.
**Gate IDs:**
1. **`creative-director`** — gate **CD-PHASE-GATE** (`.claude/docs/director-gates/cd-phase-gate.md`)
2. **`technical-director`** — gate **TD-PHASE-GATE** (`.claude/docs/director-gates/td-phase-gate.md`)
3. **`producer`** — gate **PR-PHASE-GATE** (`.claude/docs/director-gates/pr-phase-gate.md`)
4. **`art-director`** — gate **AD-PHASE-GATE** (`.claude/docs/director-gates/ad-phase-gate.md`)
Pass to each: target phase name, list of artifacts present, and the context fields listed in that gate's definition.
**Name the omissions in the output.** Below the Director Panel summary, when the
panel ran narrower than four, state which perspectives did not run and how to get
them — e.g. "Panel: 2 of 4 (`workflow: standard`). Creative and Art perspectives
not consulted. Run `/gate-check --review full` or set `modes.workflow: full` for
the complete panel." A silently narrow panel reads as a clean bill of health from
reviewers who never looked.
**Collect all four responses, then present the Director Panel summary:**
```
@@ -376,12 +474,82 @@ Art Director: [READY / CONCERNS / NOT READY]
- [Priority actions to resolve blockers]
- [Optional improvements that aren't blocking]
### Verdict: [PASS / CONCERNS / FAIL]
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
- **PASS**: All required artifacts present, all quality checks passing
- **CONCERNS**: Minor gaps exist but can be addressed during the next phase
- **FAIL**: Critical blockers must be resolved before advancing
- **NOT ASSESSED**: One or more required checks could not be run at all — name
which, and why, in the Blockers section
```
**`NOT ASSESSED` — when the gate could not look.** Rank: it **outranks PASS**
(a gate that could not check part of its scope has not established the phase is
ready) and **ranks below CONCERNS and FAIL** (a known blocker is more actionable
than an unknown, and demoting it behind an access problem buries it). It is not a
softer FAIL: "I checked and found a blocker" and "I could not check" need
different fixes — one needs work done, the other needs the input produced or made
readable.
**Verdict precedence — first matching rule wins**, evaluated in this order:
**FAIL**, then **CONCERNS**, then **NOT ASSESSED**, then **PASS**. A gate with
both a real blocker and an unassessable check is FAIL: the blocker is the
actionable finding. Stating the order mechanically removes the inference — the
rank sentence above says what outranks what, but only an ordered list says what
to do when two conditions hold at once.
Emit it when any of:
- A **required artifact exists but cannot be assessed** — empty, unreadable, or
still entirely `[TO BE CONFIGURED]` / template placeholders. Present-but-empty
is the case that most looks like present.
- A **quality check's input carries no measured data**. Section 3 compares the
performance budgets against "profiling data in `tests/performance/` or recent
`/perf-profile` output" — and `/perf-profile`'s report template pre-fills
`[16.67ms]` as the budget, so it can render ">99% headroom" from zero profiler
data. Placeholder numbers are not measurements: a budget nobody set is not a
budget that was met. Absent data already prompts (Section 4 offers to run
`/perf-profile`); this covers data that is *present and hollow*, which is the
case that looks like a measurement.
- A **test check the tier requires could not be executed** — no test runner is
configured, or the runner is configured but failed to start. Section 3 runs the
suite "if a test runner is configured", and an unconfigured runner produced no
failures, so the test check contributed nothing to the verdict and the gate
could still reach PASS. Meanwhile `testing.strict.logic` and
`.integration` both default to `true`, so the project's own configuration
called those gates BLOCKING. A blocking gate that never ran is the unknown this
verdict exists to name. Remediation is already listed under Common Gaps
(`/test-setup`); this is what the verdict does with it.
> **Scope this to tiers that require tests.** At `qa.level: minimal` no test
> gates apply at all (see the config block above), so a missing runner there is
> the configured posture, not a hole — firing the trigger would make every
> `minimal` gate permanently NOT ASSESSED and stop stage advancement, the same
> over-broad reading the director trigger below warns against. Fires only where
> the resolved tier actually asked for the test check.
- A **`MANUAL CHECK NEEDED` item the user never resolved**. Section 4 already
refuses to assume PASS for unverifiable items and marks them this way — but
until now the verdict vocabulary had nowhere to put one, so an unresolved
manual check had to land inside PASS, CONCERNS or FAIL anyway. This is where it
goes.
- A director the **resolved tier was supposed to spawn** did not return — it
errored, produced no verdict, or was interrupted.
> **Scope this narrowly, and do not read it as "fewer than four directors ran".**
> Section 4b narrows the panel *by design* — 1 director at `minimal`, 2 at
> `standard`, 4 at `full`, and none in `solo` — and that narrowing is a
> deliberate, announced reduction, not a failure to assess. The broad reading
> makes every `minimal`, `standard` and `solo` gate permanently NOT ASSESSED,
> which means the verdict can never be PASS and Section 6 can never advance
> `project.stage`. **That would break stage advancement for most projects,**
> since those are the common tiers. The trigger fires only when a director the
> tier *did* call for fails to come back — a hole in the panel you expected,
> never the panel you deliberately chose.
- A referenced upstream verdict is itself `NOT ASSESSED` — it propagates upward
rather than resolving to a pass.
Never resolve an unknown by assuming the permissive reading. If the check could
not run, that fact is the finding.
---
## 5a. Chain-of-Verification
@@ -418,7 +586,14 @@ Do NOT reference the draft verdict text — re-check specific files or ask the u
**Step 3 — Revise if needed:**
- If any answer reveals a missed blocker → upgrade verdict (PASS→CONCERNS or CONCERNS→FAIL)
- If any answer reveals a check that **could not be run** rather than one that
ran and passed → PASS→NOT ASSESSED. The first two PASS-draft questions above
("verified by actually reading a file, vs. inferring", "MANUAL CHECK NEEDED
items I marked PASS") exist to find exactly this, and until now a yes to either
had no verdict to move to
- If any answer reveals an over-stated blocker → downgrade only if citing specific evidence
- Never revise NOT ASSESSED down to PASS by re-reasoning about the missing input.
Only obtaining the input clears it
- If answers are consistent → confirm verdict unchanged
**Step 4 — Note the verification** in the final report output:
@@ -428,23 +603,77 @@ Do NOT reference the draft verdict text — re-check specific files or ask the u
## 6. Update Stage on PASS
When the verdict is **PASS** and the user confirms they want to advance:
When the verdict is **PASS** and the user confirms they want to advance, write the
new stage to BOTH `project.yaml` and the legacy `production/stage.txt`.
1. Write the new stage name to `production/stage.txt` (single line, no trailing newline)
2. This immediately updates the status line for all future sessions
### 6.1 Primary write — `project.yaml`
Example: if passing the "Pre-Production → Production" gate:
Set `project.stage` to the new stage name in `project.yaml` at the repo root.
- **If a `project:` block already exists**: Read `project.yaml` first (the Edit
tool requires the file to have been read in this session), then use the Edit
tool to change its `stage:` value.
- **If `project.yaml` exists but has no `project:` block**: Read `project.yaml`
first, then use the Edit tool to insert the block immediately after the
`framework:` block (before `modes:`). Insert exactly (replace `<new-stage>`):
```yaml
project:
stage: <new-stage>
```
- **If `project.yaml` does not exist at all**: create it with the Write tool using
this v1.1 minimal template (replace `<new-stage>` and the date):
```yaml
# CCGS project configuration — single source of truth for project settings.
# Schema: grep the `## <key>` section of .claude/docs/effects-map.md —
# it is ~31k tokens whole, ~900 per section. Do not open it entire.
schema_version: 1
framework:
version: 1.1.0
last_upgraded: <YYYY-MM-DD>
project:
stage: <new-stage>
```
Do not seed `modes.review_mode` here. It is a rigor-fronted knob — `modes.rigor`
supplies its value, so an explicit value would shadow the rigor expansion and pin
the review mode regardless of the project's rigor. Test Y.6 locks this in.
### 6.2 Legacy fallback write — `production/stage.txt`
Also write the single-line stage name (no trailing newline) so hooks that have not
migrated still work. Ensure the `production/` directory exists first:
```bash
echo -n "Production" > production/stage.txt
mkdir -p production && printf '%s' "Production" > production/stage.txt
```
**Always ask before writing**: "Gate passed. May I update `production/stage.txt` to 'Production'?"
### 6.3 Verify both writes
After both writes, Read `project.yaml` and `production/stage.txt` and confirm both
show the new stage. If they diverge, report the discrepancy to the user and stop —
a split stage indicator corrupts future auto-detection.
**Always ask before writing**: "Gate passed. May I update `project.stage` in `project.yaml` to 'Production' (and the legacy `production/stage.txt`)?"
### 6.4 Rigor-fit check (advisory — never affects the verdict)
After the stage advance is confirmed, apply the raise trigger in
`.claude/docs/settings-guidance.md § 4`: if the new stage is **Production** (or
later) while the resolved `modes.workflow` is `minimal` (the `rigor: minimal`
posture, from the config block above), add one line:
> "You're entering [stage] on `rigor: minimal` — most projects this size run
> `standard`. Revisit with `/settings modes.rigor=standard`?"
Offer it **once**, here at the gate. Route to `/settings` — never change the
setting yourself.
---
## 7. Closing Next-Step Widget
After the verdict is presented and any stage.txt update is complete, close with a structured next-step prompt using `AskUserQuestion`.
After the verdict is presented and any stage update is complete (project.yaml + stage.txt), close with a structured next-step prompt using `AskUserQuestion`.
**Tailor the options to the gate that just ran:**
@@ -515,8 +744,16 @@ Based on the verdict, suggest specific next steps:
- **Tests failing?** → delegate to `lead-programmer` or `qa-tester`
- **No playtest data?** → `/playtest-report`
- **No playtest sessions beyond the minimum?** → Additional sessions give more reliable signal. 3+ total is recommended before committing the full team. Use `/playtest-report` to structure findings.
- **No Difficulty Curve doc?** → Create `design/difficulty-curve.md` from the template at `.claude/docs/templates/difficulty-curve.md` — or use `/quick-design "difficulty curve"` for a guided session.
- **No player journey map?** → Create `design/player-journey.md` from the template at `.claude/docs/templates/player-journey.md` — or author it collaboratively using `/ux-design` Phase 2b.
- **No Difficulty Curve doc?** → Author `design/difficulty-curve.md` by hand from the template at `.claude/docs/templates/difficulty-curve.md`. (`/quick-design` is a related session but writes to `design/quick-specs/`, not to this path — use it to think the curve through, then copy the outcome here.)
- **No player journey map?** → Author `design/player-journey.md` by hand from the template at `.claude/docs/templates/player-journey.md`.
> **Neither of these has a skill that writes it — the remediations must not imply
> otherwise.** Naming "`/ux-design` Phase 2b" would point at the step that *reads*
> `design/player-journey.md`, landing the user back at the check that just
> failed. Naming `/quick-design` would point at a skill that writes
> `design/quick-specs/[name]-[date].md` and would leave this gate still failing.
> Both docs are hand-authored from their templates; say so plainly rather than
> naming a skill that cannot produce them.
- **Need a quick sprint check?** → `/sprint-status` for current sprint progress snapshot
- **Performance unknown?** → `/perf-profile`
- **Not localized?** → `/localize`
@@ -0,0 +1,48 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Production → Polish
**Required Artifacts:**
- [ ] The code root has active code organized into subsystems
- [ ] All core mechanics from GDD are implemented (cross-reference `design/gdd/` with the code root)
- [ ] Main gameplay path is playable end-to-end
- [ ] Test files exist in `tests/unit/` and `tests/integration/` covering Logic and Integration stories
- [ ] All Logic stories from this sprint have corresponding unit test files in `tests/unit/`
- [ ] Smoke check has been run with a PASS or PASS WITH WARNINGS verdict — report exists in `production/qa/`
- [ ] At least one QA plan exists in `production/qa/` (generated by `/qa-plan`) covering this sprint, the final production sprint, or this production phase — run `/qa-plan` if missing (CONCERNS — advisory, not blocking)
- [ ] QA sign-off report exists in `production/qa/` (generated by `/team-qa`) with verdict APPROVED or APPROVED WITH CONDITIONS
- [ ] At least 3 distinct playtest sessions documented in `production/qa/playtests/`
- [ ] Playtest reports cover: new player experience, mid-game systems, and difficulty curve
- [ ] Fun hypothesis from Game Concept has been explicitly validated or revised
**Quality Checks:**
- [ ] Tests are passing (run test suite via Bash)
- [ ] No critical/blocker bugs in any bug tracker or known issues
- [ ] Core loop plays as designed (compare to GDD acceptance criteria)
- [ ] Performance is within budget (check `performance.*` in `project.yaml`, else technical-preferences.md targets)
- [ ] Playtest findings have been reviewed and critical fun issues addressed (not just documented)
- [ ] No "confusion loops" identified — no point in the game where >50% of playtesters got stuck without knowing why
- [ ] Difficulty curve matches the Difficulty Curve design doc (if one exists at `design/difficulty-curve.md`)
- [ ] All implemented screens have corresponding UX specs (no "designed in-code" screens)
- [ ] Interaction pattern library is up-to-date with all patterns used in implementation
- [ ] Accessibility compliance verified against committed tier in `design/accessibility-requirements.md`
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — core mechanics + Logic/Integration tests + smoke check (PASS) + QA sign-off + 3+ playtests all required
- **`standard`** — QA sign-off + per-story test coverage → recommended;
**core mechanics + smoke check + playable end-to-end + 1+ documented
playtest + no critical/blocker bugs** required
- **`minimal`** — **smoke check + playable end-to-end + no critical/blocker
bugs** required; the core-mechanics cross-check → recommended; everything
else **drops**. Reductions relax what must *exist*, never what must *work* —
a gate that closes production on "it boots" alone has not asked whether the
game plays.
@@ -0,0 +1,67 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Technical Setup → Pre-Production
**Required Artifacts:**
- [ ] Engine chosen (CLAUDE.md Technology Stack is not `[CHOOSE]`)
- [ ] Project config populated (`project.yaml` has engine/naming/performance set, or legacy `.claude/docs/technical-preferences.md` populated)
- [ ] Art bible exists at `design/art/art-bible.md` with at least Sections 1–4 (Visual Identity Foundation)
- [ ] At least 3 Architecture Decision Records in `docs/architecture/` covering
Foundation-layer systems (scene management, event architecture, save/load)
- [ ] Engine reference docs exist in `docs/engine-reference/[engine]/`
- [ ] Test framework initialized: `tests/unit/` and `tests/integration/` directories exist
- [ ] CI/CD test workflow exists at `.github/workflows/tests.yml` (or equivalent)
- [ ] At least one example test file exists to confirm the framework is functional
- [ ] Master architecture document exists at `docs/architecture/architecture.md`
- [ ] Architecture traceability index exists at `docs/architecture/requirements-traceability.md`
- [ ] `/architecture-review` has been run (a review report file exists in `docs/architecture/`)
- [ ] `design/accessibility-requirements.md` exists with accessibility tier committed
- [ ] `design/ux/interaction-patterns.md` exists (pattern library initialized, even if minimal)
**Quality Checks:**
- [ ] Architecture decisions cover core systems (rendering, input, state management)
- [ ] Technical preferences have naming conventions and performance budgets set
- [ ] Accessibility tier is defined and documented (even "Basic" is acceptable — undefined is not)
- [ ] At least one screen's UX spec started (often the main menu or core HUD is designed during Technical Setup)
- [ ] All ADRs have an **Engine Compatibility section** with engine version stamped
- [ ] All ADRs have a **GDD Requirements Addressed section** with explicit GDD linkage
- [ ] No ADR references APIs listed in `docs/engine-reference/[engine]/deprecated-apis.md`
- [ ] All HIGH RISK engine domains (per VERSION.md) have been explicitly addressed
in the architecture document or flagged as open questions
- [ ] Architecture traceability matrix has **zero Foundation layer gaps**
(all Foundation requirements must have ADR coverage before Pre-Production)
**ADR Circular Dependency Check**: run the deterministic graph builder rather than
reading every ADR to trace the graph by hand — a manual trace across a dozen ADRs
eventually misses an edge; the script cannot:
```
Bash: bash .claude/scripts/adr-dep-graph.sh
```
It prints `ADRS`, `EDGES` (one `adr-A -> adr-B` per Depends-On reference),
`NO_DEPS_SECTION` (ADRs with no Depends On), and a `CYCLE:` line per node in any
dependency cycle.
- **Any `CYCLE:` lines → FAIL**: "Circular ADR dependency: [the nodes on the
`CYCLE:` lines]. Neither can reach Accepted while the cycle exists. Remove one
'Depends On' edge to break the cycle."
- No `CYCLE:` lines → this check passes. But the acyclic result is only as
trustworthy as the dependency sections are complete: if `NO_DEPS_SECTION` lists
many ADRs, surface that as a CONCERNS note rather than a clean pass.
**Engine Validation** (read `docs/engine-reference/[engine]/VERSION.md` first):
- [ ] ADRs that touch post-cutoff engine APIs are flagged with Knowledge Risk: HIGH/MEDIUM
- [ ] `/architecture-review` engine audit shows no deprecated API usage
- [ ] All ADRs agree on the same engine version (no stale version references)
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — engine + art bible §1–4+ + 3+ ADRs + architecture + UX specs started + accessibility doc + traceability index all required
- **`standard`** — art bible required **only if visual-asset stories exist**; ADRs reduced to **critical (Foundation-layer) only**; UX-specs-started, accessibility doc, interaction-patterns, traceability index → recommended
- **`minimal`** — only **engine configured** required (the minimal floor); everything else **drops**
@@ -0,0 +1,78 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Pre-Production → Production
**Required Artifacts:**
- [ ] Vertical slice exists in `prototypes/` with a REPORT.md (run `/vertical-slice`) — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] First sprint plan exists in `production/sprints/`
- [ ] Art bible is complete (all 9 sections) and AD-ART-BIBLE sign-off verdict is recorded in `design/art/art-bible.md`
- [ ] Entity inventory exists at `design/assets/entity-inventory.md` (recommended — run `/asset-spec` with no arguments to generate collaboratively from GDDs + art bible)
- [ ] All MVP-tier GDDs from systems index are complete
- [ ] Master architecture document exists at `docs/architecture/architecture.md`
- [ ] At least 3 ADRs covering Foundation-layer decisions exist in `docs/architecture/`
- [ ] All Foundation and Core layer ADRs have status `Accepted` (not `Proposed`) — stories cannot be unblocked until their governing ADR is accepted
- [ ] Control manifest exists at `docs/architecture/control-manifest.md`
(generated by `/create-control-manifest` from Accepted ADRs)
- [ ] Epics defined in `production/epics/` with at least Foundation and Core
layer epics present (use `/create-epics layer: foundation` and
`/create-epics layer: core` to create them, then `/create-stories [epic-slug]`
for each epic)
- [ ] Vertical Slice build exists and is playable (not just scope-defined) — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] Vertical Slice has been playtested with at least 1 documented session — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] Vertical Slice playtest report exists at `production/qa/playtests/` or equivalent — **recommended, not blocking**; if absent, surface as CONCERNS
- [ ] UX specs exist for key screens: main menu, core gameplay HUD (at `design/ux/`), pause menu
- [ ] HUD design document exists at `design/ux/hud.md` (if game has in-game HUD)
- [ ] All key screen UX specs have passed `/ux-review` (verdict APPROVED or NEEDS REVISION accepted)
**Quality Checks:**
- [ ] **Core loop fun is validated** — playtest data confirms the central mechanic is enjoyable, not just functional. Explicitly check the Vertical Slice playtest report.
- [ ] UX specs cover all UI Requirements sections from MVP-tier GDDs
- [ ] Interaction pattern library documents patterns used in key screens
- [ ] Accessibility tier from `design/accessibility-requirements.md` is addressed in all key screen UX specs
- [ ] Sprint plan references real story file paths from `production/epics/`
(not just GDDs — stories must embed GDD req ID + ADR reference)
- [ ] **Vertical Slice is COMPLETE**, not just scoped — the build demonstrates the full core loop end-to-end. At least one complete [start → challenge → resolution] cycle works.
- [ ] Architecture document has no unresolved open questions in Foundation or Core layers
- [ ] All ADRs have Engine Compatibility sections stamped with the engine version
- [ ] All ADRs have ADR Dependencies sections (even if all fields are "None")
- [ ] Manual validation confirms GDDs + architecture + epics are coherent
(run `/review-all-gdds` and `/architecture-review` if not done recently)
- [ ] **Core fantasy is delivered** — at least one playtester independently described an experience that matches the Player Fantasy section of the core system GDDs (without being prompted).
**Vertical Slice Validation** (only run these checks if a Vertical Slice was built):
- [ ] A human has played through the core loop without developer guidance
- [ ] The game communicates what to do within the first 2 minutes of play
- [ ] No critical "fun blocker" bugs exist in the Vertical Slice build
- [ ] The core mechanic feels good to interact with (this is a subjective check — ask the user)
> **Verdict rules for Vertical Slice:**
> - **Slice was built AND any validation item is NO** → verdict is automatically FAIL. A broken
> or unfun vertical slice should not advance to Production.
> - **Slice was not built (skipped)** → downgrade to CONCERNS only, not FAIL. Surface the risk
> clearly: "Advancing without a validated Vertical Slice increases the risk of late-stage design
> pivots. Recommended before committing full production scope." The user decides.
> - Skipping is a valid solo dev or time-constrained call. Shipping a broken one is not.
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — sprint plan + complete (9-section) art bible + epics + 3+ playtests + UX specs + control manifest all required; **Vertical Slice keeps its Section 2 status** (see note)
- **`standard`** — **1+ playtest** required (not 3); epics + sprint plan required; art bible complete + UX specs + control manifest → recommended
- **`minimal`** — only **sprint plan** required (the minimal floor); epics, playtests, art bible, UX, control manifest all **drop**
> **The Vertical Slice keeps its Section 2 status at every tier.** The
> Pre-Production → Production "prototype/Vertical Slice" floor is NOT upgraded to
> blocking by the tier table — the Vertical Slice artifacts stay *recommended,
> not blocking* (absent → CONCERNS, not FAIL) exactly as Section 2 defines, at
> `full`, `standard`, and `minimal` alike. The genuinely-required floor item at
> this gate is the **sprint plan**. The one hard rule that binds at every tier:
> if a Vertical Slice *was built* and any of its validation items is NO, the
> verdict is FAIL regardless of tier — tier reductions relax what must *exist*,
> never what must *work*.
@@ -0,0 +1,41 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Polish → Release
**Required Artifacts:**
- [ ] All features from milestone plan are implemented
- [ ] Content is complete (all levels, assets, dialogue referenced in design docs exist)
- [ ] Localization strings are externalized (no hardcoded player-facing text in the code root)
- [ ] QA test plan exists (`/qa-plan` output in `production/qa/`)
- [ ] QA sign-off report exists (`/team-qa` output — APPROVED or APPROVED WITH CONDITIONS)
- [ ] All Must Have story test evidence is present (Logic/Integration: test files pass; Visual/Feel/UI: sign-off docs in `production/qa/evidence/`)
- [ ] Smoke check passes cleanly (PASS verdict) on the release candidate build
- [ ] No test regressions from previous sprint (test suite passes fully)
- [ ] Balance data has been reviewed (`/balance-check` run)
- [ ] Release checklist completed (`/release-checklist` or `/launch-checklist` run)
- [ ] Store metadata prepared (if applicable)
- [ ] Changelog / patch notes drafted
**Quality Checks:**
- [ ] Full QA pass signed off by `qa-lead`
- [ ] All tests passing
- [ ] Performance targets met across all target platforms
- [ ] No known critical, high, or medium-severity bugs
- [ ] Accessibility basics covered (remapping, text scaling if applicable)
- [ ] Localization verified for all target languages
- [ ] Legal requirements met (EULA, privacy policy, age ratings if applicable)
- [ ] Build compiles and packages cleanly
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — all features + content complete + localization + QA sign-off + smoke (PASS) + no critical bugs all required
- **`standard`** — content-complete audit + QA sign-off + localization → recommended; **all features + smoke + no critical bugs** required
- **`minimal`** — only **smoke + no critical bugs** required; everything else **drops**
@@ -0,0 +1,33 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Concept → Systems Design
**Required Artifacts:**
- [ ] `design/gdd/game-concept.md` exists and has content
- [ ] Game pillars defined (in concept doc or `design/gdd/game-pillars.md`)
- [ ] Visual Identity Anchor section exists in `design/gdd/game-concept.md` (from brainstorm Phase 4 art-director output)
**Recommended (not blocking):**
- [ ] Concept prototype exists in `prototypes/` with a REPORT.md showing PROCEED verdict
(`/prototype [core-mechanic]`) — skipping this means GDDs may be written for an
idea that hasn't been played. Acceptable if the concept is proven by other means.
**Quality Checks:**
- [ ] Game concept has been reviewed (`/design-review` verdict not MAJOR REVISION NEEDED)
- [ ] Core loop is described and understood
- [ ] Target audience is identified
- [ ] Visual Identity Anchor contains a one-line visual rule and at least 2 supporting visual principles
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — game-concept.md + pillars + Visual Identity Anchor all required
- **`standard`** — pillars + Visual Identity Anchor → recommended; `game-concept.md` stays required
- **`minimal`** — gate target is **`design/game-brief.md`** (not `game-concept.md`); the GDD / pillars / Visual Identity Anchor checks **drop** (a brief with content = PASS). `/brainstorm` writes `design/game-brief.md` at this tier (Option A); `game-concept.md` remains the `standard`/`full` concept doc.
@@ -0,0 +1,36 @@
> Gate definition, loaded by `/gate-check` for the TARGET PHASE ONLY.
> Never load the other five — one gate applies per invocation.
# Gate: Systems Design → Technical Setup
**Required Artifacts:**
- [ ] Systems index exists at `design/gdd/systems-index.md` with at least MVP systems enumerated
- [ ] All MVP-tier GDDs exist in `design/gdd/` and individually pass `/design-review`
- [ ] A cross-GDD review report exists in `design/gdd/` (from `/review-all-gdds`)
**Quality Checks:**
- [ ] All MVP GDDs pass individual design review (8 required sections, no MAJOR REVISION NEEDED verdict)
- [ ] `/review-all-gdds` verdict is not FAIL (cross-GDD consistency and design theory checks pass)
- [ ] All cross-GDD consistency issues flagged by `/review-all-gdds` are resolved or explicitly accepted
- [ ] System dependencies are mapped in the systems index and are bidirectionally consistent
- [ ] MVP priority tier is defined
- [ ] No stale GDD references flagged (older GDDs updated to reflect decisions made in later GDDs)
## Workflow tier reductions
The checklist above is the **`full` baseline**. At lower tiers apply the
reduction for the resolved tier; items not named keep their status above.
Reductions only ever *relax* a requirement — `workflow_overrides` is the
only thing that adds one.
- **`full`** — systems-index + all MVP GDDs at 8 sections + cross-GDD review report all required
- **`standard`** — MVP GDDs validated at the **5 standard sections** (+ conditional Formulas); cross-GDD review report → recommended
- **`minimal`** — **gate not applicable** — no gate between brief and code; auto-PASS with a note (see below)
> **`minimal` "not applicable" gate.** The Systems Design → Technical Setup gate
> has no meaning at `minimal` (no GDDs exist by design). Return a PASS verdict
> with the note: *"No design gate at minimal workflow — minimal skips the
> Systems Design phase; advancing brief → code."* The Section 6 stage write still
> applies on user confirmation. Do NOT flag absent GDDs as blockers.
+67 -23
View File
@@ -1,11 +1,9 @@
---
name: help
description: "Analyzes what is done and the users query and offers advice on what to do next. Use if user says what should I do next or what do I do now or I'm stuck or I don't know what to do"
description: "What should I do next? Use when stuck or you don't know what to do."
argument-hint: "[optional: what you just finished, e.g. 'finished design-review' or 'stuck on ADRs']"
user-invocable: true
allowed-tools: Read, Glob, Grep
context: |
!echo "=== Live Project State ===" && echo "Stage: $(cat production/stage.txt 2>/dev/null | tr -d '[:space:]' || echo 'not set')" && echo "Latest sprint: $(ls -t production/sprints/*.md 2>/dev/null | head -1 || echo 'none')" && echo "Session state: $(head -5 production/session-state/active.md 2>/dev/null || echo 'none')"
allowed-tools: Read, Glob, Grep, Bash
model: haiku
---
@@ -17,6 +15,21 @@ This skill figures out exactly where you are in the game development pipeline an
tells you what comes next. It is **lightweight** — not a full audit. For a full
gap analysis, use `/project-stage-detect`.
## Live Project State
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys project.stage,workflow`
!`echo "Latest sprint: $(ls -t production/sprints/*.md 2>/dev/null | head -1 || echo 'none')"; echo "Session state: $(head -5 production/session-state/active.md 2>/dev/null || echo 'none')"`
Both blocks are resolved before this skill runs. Use them as-is:
- **`project.stage`** from the config block is the authoritative phase for Step 2
— it already applies the `project.yaml` → `production/stage.txt` fallback, and
preserves values containing spaces (`Systems Design`).
- **`workflow`** from the config block is the tier for Step 5 — do not re-read it.
- If no config block rendered, shell preprocessing is disabled; fall back to the
defaults in `.claude/docs/config-resolution.md`.
---
## Step 1: Read the Catalog
@@ -54,8 +67,7 @@ skills in production/polish, etc.).
Check in this order:
1. **Read `production/stage.txt`** — if it exists and has content, this is the
authoritative phase name. Map it to a catalog phase key:
1. **Take `project.stage` from the config block above** — it is already resolved. Map its value to a catalog phase key:
- "Concept" → `concept`
- "Systems Design" → `systems-design`
- "Technical Setup" → `technical-setup`
@@ -64,19 +76,23 @@ Check in this order:
- "Polish" → `polish`
- "Release" → `release`
2. **If stage.txt is missing**, infer phase from artifacts (most-advanced match wins):
- `src/` has 10+ source files → `production`
- `production/stories/*.md` exists → `pre-production`
2. **If neither is set**, infer phase from artifacts (most-advanced match wins):
- code root has 10+ source files → `production`
- `production/epics/**/story-*.md` exists → `pre-production`
- `docs/architecture/adr-*.md` exists → `technical-setup`
- `design/gdd/systems-index.md` exists → `systems-design`
- `design/gdd/game-concept.md` exists → `concept`
- `design/gdd/game-concept.md` (or `design/game-brief.md`) exists → `concept`
- Nothing → `concept` (fresh project)
3. **Take `workflow` from the config block above** (per
`.claude/docs/workflow-modes.md`). It controls whether optional docs are
surfaced as next steps (Step 5).
---
## Step 3: Read Session Context
Read `production/session-state/active.md` if it exists. Extract:
Read `production/session-state/active.md` if it exists — it is append-only and grows unbounded, and only the latest block is relevant, so read just the tail rather than the whole file: grep the last heading (`Grep pattern="^## (Session Extract|STATUS)" path="production/session-state/active.md" output_mode="content" -n`, take the highest line number) and `Read(offset=that line)`. Extract:
- What was most recently worked on
- Any in-progress tasks or open questions
- Current epic/feature/task from STATUS block (if present)
@@ -92,18 +108,33 @@ For each step in the current phase (from the catalog):
### Artifact-based checks
If the step has `artifact.glob`:
- Use Glob to check if files matching the pattern exist
- If `min_count` is specified, verify at least that many files match
- If `artifact.pattern` is specified, use Grep to verify the pattern exists in the matched file
- **Complete** = artifact condition is met
- **Incomplete** = artifact is missing or pattern not found
**Resolve these deterministically — one call, not a glob per step:**
If the step has `artifact.note` (no glob):
- Mark as **MANUAL** — cannot auto-detect, will ask user
```
Bash: bash .claude/scripts/artifact-check.sh --phase [current-phase]
```
If the step has no `artifact` field:
- Mark as **UNKNOWN** — completion not trackable (e.g. repeatable implementation work)
It evaluates every `glob`, `pattern`, `min_count` and `any_of` in the catalog
against the working tree and reports one line per step. Map its statuses:
| status | Report as |
|---|---|
| `PRESENT` | **Complete** |
| `ABSENT` | **Incomplete** |
| `SHORT` | **Incomplete** — say how far short (`count=`/`min=` are given) |
| `PATTERN_MISS` | **Incomplete** — the file exists but lacks its marker; say so, since "missing" would send the user to recreate a file they already have |
| `NO_CHECK` | **MANUAL** if the step carries a `note=`, else **UNKNOWN** — completion is not trackable (e.g. repeatable implementation work) |
Do not re-derive any of this with Glob/Grep. `any_of` in particular is a list of
**alternatives** — one match is enough — and hand-evaluating it has already
produced a false "incomplete" once: `engine-setup` is satisfied by `engine.name`
in `project.yaml` **or** by the legacy `Engine:` line in
`.claude/docs/technical-preferences.md`, and the script reports which alternative
matched (`alt=`/`match=`).
**`NO_CHECK` never means done.** The script prints a `NO_CHECK:` total before the
rows; if most of a phase is NO_CHECK, say that plainly rather than implying the
phase is nearly complete.
### Special case: production phase — read `sprint-status.yaml`
@@ -134,7 +165,11 @@ From the completion data, determine:
2. **Current blocker** — the first incomplete *required* step (this is what the
user must do next)
3. **Optional opportunities** — incomplete *optional* steps that can be done
before or alongside the blocker
before or alongside the blocker. **Surface these per the workflow tier**: at
`full`, list all of them; at `standard`, list an optional doc only if it is
required for the current system/phase (do not flag genuinely-optional docs as
gaps); at `minimal`, do not surface optional docs at all — once the brief,
engine, and a sprint plan exist, the next step is code
4. **Upcoming required steps** — required steps after the current blocker
(show as "coming up" so user can plan ahead)
@@ -211,10 +246,19 @@ Need more detail?
- `/project-stage-detect` — full gap analysis with all missing artifacts listed
- `/gate-check` — formal readiness check for your next phase
- `/start` — re-orient from scratch
- `/settings` — if the process feels mismatched to your project, adjust
`modes.rigor`. Apply the change-triggers in
`.claude/docs/settings-guidance.md § 4`: a **lower** tier when the user sounds
overwhelmed by process (and rigor isn't already `minimal`), or a **higher** tier
when the project has outgrown it (many systems, or in Production on
`workflow: minimal`)
```
Only show this if the user's input suggested confusion (e.g. "I don't know", "stuck",
"lost", "not sure"). Don't show it for simple "what's next?" queries.
"lost", "not sure"). Don't show it for simple "what's next?" queries. Show the
`/settings` rigor line only when a `settings-guidance.md § 4` trigger actually
fires — the user sounds overwhelmed (and rigor isn't already `minimal`), or the
project has outgrown its tier — not on every confused query.
---
+49 -8
View File
@@ -1,9 +1,10 @@
---
name: hotfix
description: "Emergency fix workflow that bypasses normal sprint processes with a full audit trail. Creates hotfix branch, tracks approvals, and ensures the fix is backported correctly."
description: "Emergency fix bypassing normal sprint process — hotfix branch, approvals tracked, backport verified, full audit trail."
argument-hint: "[bug-id or description]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
---
@@ -85,11 +86,17 @@ Only run `git checkout -b hotfix/[short-name] [base-ref]` if user selects [A]. I
---
## Phase 4: Investigate and Implement
## Phase 4: Investigate and Propose
Focus on the minimal change that resolves the issue. Do NOT refactor, clean up, or add features alongside the hotfix.
Find the root cause. Draft the minimal fix: which files change, what the change does, and what it deliberately leaves alone. Do NOT refactor, clean up, or add features alongside the hotfix.
Validate the fix by running targeted tests for the affected system. Check for regressions in adjacent systems.
Present the root cause and proposed fix, then ask: "May I implement this fix?" Do not modify any code before this approval — an emergency flow earns its audit trail by approving the change *before* it exists, not after.
---
## Phase 4b: Implement (only after approval)
Implement the approved minimal change. Validate the fix by running targeted tests for the affected system. Check for regressions in adjacent systems.
Update the hotfix record with root cause, fix details, and test results.
@@ -97,7 +104,7 @@ Update the hotfix record with root cause, fix details, and test results.
## Phase 5: Collect Approvals
Use the Task tool to request sign-off in parallel:
Use the `Agent` tool to request sign-off in parallel:
- `subagent_type: lead-programmer` — Review the fix for correctness and side effects
- `subagent_type: qa-tester` — Run targeted regression tests on the affected system
@@ -109,7 +116,7 @@ All three must return APPROVE before proceeding. If any returns CONCERNS or REJE
## Phase 5b: QA Re-Entry Gate
After approvals, determine the QA scope required before deploying the hotfix. Spawn `qa-lead` via Task with:
After approvals, determine the QA scope required before deploying the hotfix. Spawn `qa-lead` via `Agent` with:
- The hotfix description and affected system
- The regression test results from Phase 5
- A list of all systems that touch the changed files (use Grep to find callers)
@@ -121,12 +128,43 @@ Apply the verdict:
- **Targeted QA pass required** — run `/team-qa [affected-system]` scoped to the changed system only. If QA returns APPROVED or APPROVED WITH CONDITIONS, proceed to Phase 6.
- **Full QA required** — S1 fixes that touch core systems may require a full `/team-qa sprint`. This delays deployment but prevents a bad patch.
**If the QA step returns `NOT ASSESSED`, the gate did not run — treat it as unmet,
not as met.** `/smoke-check` returns it when the suite never executed and
`/team-qa` when a cycle produced no executed evidence. **A NOT ASSESSED result is
not a pass** — from either skill — and under time pressure the permissive reading
is the one that will feel reasonable,
which is exactly why it is written down here. Either obtain the missing result —
the verdict names what would make it runnable — or take the decision to the
producer explicitly, as a decision to deploy an unverified hotfix rather than as a
gate that quietly cleared.
Do not skip this gate. A hotfix that breaks something else is worse than the original bug.
---
## Phase 6: Update Bug Status and Deploy
> **STOP — deployment requires explicit approval, unconditionally.** Merging a
> hotfix to a release branch is the one irreversible act in this skill, so it is
> gated even though branch creation (reversible) already is. Before any merge,
> tag, or deploy, use `AskUserQuestion`:
>
> - Prompt: "Hotfix validated and approved. Merge to the release branch and
> deploy?"
> - Options: `[A] Yes — merge and deploy` / `[B] Merge to development only — hold
> the release` / `[C] Stop here`
>
> This holds regardless of `modes.automation`, including `autonomous`. An
> emergency process is exactly where an unreviewed irreversible step is most
> likely and least recoverable.
> **Backport is not verified unless you verify it.** The frontmatter advertises
> "backport verified", and until this note the word `backport` appeared **once in
> this file — in that claim**. After merging, confirm the fix is present on BOTH
> the release branch and the development branch, and state the result. An
> unbackported hotfix means the bug returns in the next release from development,
> which is the single most common hotfix regression.
Update the original bug file if one exists:
```markdown
@@ -146,8 +184,11 @@ Output a deployment summary:
**Severity**: [S1/S2]
**Root cause**: [one line]
**Fix**: [one line]
**QA gate**: [Smoke check PASS / Team-QA APPROVED]
**QA gate**: [Smoke check PASS / Team-QA APPROVED / NOT ASSESSED — [why, and whose
explicit decision it was to deploy anyway]]
**Approvals**: lead-programmer ✓ / qa-tester ✓ / producer ✓
**Backport**: [verified present on release AND development — or NOT VERIFIED, with
what was not checked]
**Rollback plan**: [from Phase 2 record]
Merge to: release branch AND development branch
+111 -5
View File
@@ -1,11 +1,60 @@
---
name: launch-checklist
description: "Complete launch readiness validation covering every department: code, content, store, marketing, community, infrastructure, legal, and go/no-go sign-offs."
description: "Launch readiness across every department: code, content, store, marketing, community, infrastructure, legal, go/no-go sign-offs."
argument-hint: "[launch-date or 'dry-run']"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys rigor,project.stage,cert_tier,automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Resolved above — use as-is. No block → defaults in `.claude/docs/config-resolution.md`.
**Scope this checklist to the project.** Emitting every item for every platform
trains the reader to skip the list, which defeats the gate:
- **`project.stage`** — items for phases this project has not reached are out of
scope; say so rather than listing them unchecked.
- **`modes.rigor`** — at `minimal`, drop items whose only justification is process
weight this project has opted out of.
- **`platform.cert_tier`** — emit certification items **only** for the tier the
project targets. If it is **unset**, **ask which platforms are in scope**
rather than emitting all of them — an unset value is a question, not a licence
to emit every certification track. If it cannot be determined, mark the section
**`NOT ASSESSED — cert tier unknown`**. **Unset is not `none`:** `none` is a
decision, unset is a missing one, and they must not produce the same output.
Branch on the **four values this key takes** — `none | itch | steam | console` —
and not on platform names; `.claude/docs/effects-map.md` holds the full
requirement table and is the source, so read it rather than restating it.
- `none` — **emit no certification section at all.** Internal release, alpha or
jam game. Say the section was omitted and why; do not leave it blank.
- `itch` — itch.io upload requirements only: build size, page setup, age tags.
**No console and no Steamworks items.**
- `steam` — Steamworks: store page, depot build, achievements, system
requirements, common content rules. **No console certification items.**
- `console` — full platform certification (TRC / XR / Lotcheck), save-data
rules, controller-mapping rules, age-rating boards. The heaviest tier.
> **Branch on the `cert_tier` values above, not on platform names.** "Emit
> console/mobile certification items only for the platforms the project targets"
> is the wrong test: it treats an `itch` project and a `steam` project
> identically, conflates `none` with unset, and keys on `mobile`, which is not a
> `cert_tier` value at all. Use the vocabulary the config defines.
If an item cannot be scoped because the config is absent, mark it
**`NOT ASSESSED — platform/stage unknown`**. Do not silently include it: a
`rigor: standard`, single-platform project would otherwise receive a ~150-item
checklist demanding PC **and** console **and** mobile certification plus age
ratings, of which ~140 are unassessable.
---
> **Explicit invocation only**: This skill should only run when the user explicitly requests it with `/launch-checklist`. Do not auto-invoke based on context matching.
@@ -26,11 +75,34 @@ Read the argument for the launch date or `dry-run` mode. Dry-run mode generates
## Phase 3: Scan Codebase Health
> **Every scan in this phase is a search for something bad, so a zero-hit result
> is ambiguous by construction: it means either "searched and found none" or
> "there was nothing to search". On a launch gate those are opposite findings,
> and a green checkbox renders them identically.**
>
> **Establish the denominator before every scan below, and report it.** Each line
> reads either `scanned [N] files, [M] hits` or
> `NOT ASSESSED — [no src/ | no assets/ | directory empty]`. Never a bare tick.
>
> This is written once, over the whole phase, rather than under **one** of the
> four bullets. All four search `src/` the same way — for placeholder assets,
> TODOs, debug output and hardcoded test values — so if only one carries the
> warning, an empty or absent `src/` returns zero
> hits three times and read as three clean results. The original
> instance shipped: with no `assets/` directory the scan returned zero hits and
> "All placeholder art replaced" was ticked green.
- Count `TODO`, `FIXME`, `HACK` comments and their locations
- Check for any `console.log`, `print()`, or debug output left in production code
- Check for placeholder assets (search for `placeholder`, `temp_`, `WIP_`)
- Check for hardcoded test/dev values (localhost, test credentials, debug flags)
**Carry the distinction into the checklist itself.** An item whose scan returned
`NOT ASSESSED` is written `- [?]`, not `- [ ]`. An unticked box says *work
remains*; a `[?]` says *nobody could check*, and only one of those is closed by
doing the work. Include the legend wherever a `[?]` appears:
`[?] = not assessed — the input to this check was absent`.
---
## Phase 4: Generate the Launch Checklist
@@ -114,12 +186,46 @@ Generated: [Date]
- [ ] Edge cases tested (full storage, no network, suspend/resume)
### Platform Certification
- [ ] PC: Steam/Epic/GOG SDK requirements met
- [ ] Console: TRC/TCR/Lotcheck submission prepared
- [ ] Mobile: App Store/Play Store guidelines compliant
- [ ] Accessibility: minimum standards met (remapping, text scaling, colorblind)
**Emit ONLY the block matching `platform.cert_tier`** (resolved in the resolved-config block at the top of this skill — see
the `platform.cert_tier` rule above). Do not emit this section's other blocks, and
do not fall back to emitting all of them.
**At `none`** — omit the section and say so in one line:
`Platform Certification: omitted — cert_tier is 'none' (internal/jam release).`
**At `itch`:**
- [ ] Build size within itch.io upload limits
- [ ] itch.io page complete (cover art, screenshots, description, tags)
- [ ] Age/content tags set honestly
- [ ] Downloadable vs browser build decided and tested
**At `steam`:**
- [ ] Steamworks SDK integrated and tested
- [ ] Store page complete (capsule art, trailer, description, system requirements)
- [ ] Depot build uploaded and installs cleanly from a fresh account
- [ ] Achievements functional
- [ ] Steam common content rules reviewed
**At `console`:**
- [ ] TRC/TCR/Lotcheck submission prepared
- [ ] Save-data rules compliant (corruption, full storage, user switching)
- [ ] Controller-mapping rules met, platform-correct button prompts
- [ ] Suspend/resume verified
- [ ] Age ratings obtained (ESRB, PEGI, regional)
**Every tier**, because these are not certification-gated:
- [ ] Accessibility: minimum standards met (remapping, text scaling, colorblind)
> **Keep this template gated by tier.** An ungated list — PC *and* Console *and*
> Mobile rows emitted at every tier — contradicts the `cert_tier` rule at the top
> of this skill, which says an `itch` project gets no console and no Steamworks
> items. When a rule and a template disagree, the template wins in practice,
> because a template is what gets copied.
>
> Changing the branching vocabulary is only half the job: the rows that branching
> governs have to move with it, or the rule describes behaviour nothing reaches.
### Performance
- [ ] Target FPS met on minimum spec hardware
- [ ] Load times within budget on all platforms
+27 -12
View File
@@ -1,13 +1,16 @@
---
name: localize
description: "Full localization pipeline: scan for hardcoded strings, extract and manage string tables, validate translations, generate translator briefings, run cultural/sensitivity review, manage VO localization, test RTL/platform requirements, enforce string freeze, and report coverage."
description: "Localization pipeline — find hardcoded strings, extract string tables, cultural review, VO, RTL, enforce string freeze."
argument-hint: "[scan|extract|validate|status|brief|cultural-review|vo-pipeline|rtl-check|freeze|qa]"
user-invocable: true
agent: localization-lead
allowed-tools: Read, Glob, Grep, Write, Bash, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Bash, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
# Localization Pipeline
Localization is not just translation — it is the full process of making a game
@@ -32,9 +35,13 @@ If no subcommand is provided, output usage and stop. Verdict: **FAIL** — missi
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Phase 2A: Scan Mode
Search `src/` for hardcoded user-facing strings:
Search the **code root** (resolve per `.claude/docs/code-root-resolution.md`) for hardcoded user-facing strings. **If the code root is unresolved, report `NOT ASSESSED — code root unresolved` rather than zero hits.** Zero hits from an unresolved root reads as "nothing to localize", which is the failure this guards:
- String literals in UI code not wrapped in a localization function (`tr()`, `Tr()`, `NSLocalizedString`, `GetText`, etc.)
- Concatenated strings that should be parameterized
@@ -83,7 +90,7 @@ Read all string table files in `assets/data/strings/`. For each locale, check:
- **Placeholder mismatches** — source has `{name}` but translation omits it or adds extras
- **String length violations** — translation exceeds the character limit recorded in the source `context` field
- **Plural form count** — locale requires N plural forms; translation provides fewer
- **Orphaned keys** — translation exists but nothing in `src/` references the key
- **Orphaned keys** — translation exists but nothing in the code root references the key
- **Stale translations** — source string changed after translation was written (flag for re-translation)
- **Encoding** — non-ASCII characters present and font atlas supports them (flag if uncertain)
@@ -104,7 +111,15 @@ String freeze: [Active / Not yet called / Lifted]
| Locale | Total | Translated | Missing | Stale | Coverage |
|--------|-------|-----------|---------|-------|----------|
| en (source) | [N] | [N] | 0 | 0 | 100% |
| en (source) | [N] | [N] | [N] | [N] | [N]% |
> **Every cell above is a count you must take from the string table — including
> the source row.** Do not pre-fill the source locale as `100%`: that asserts a
> result before counting, and on a project with no `assets/data/strings/` it
> produces a coverage report for a table that does not exist. If the string table
> is absent, the whole status output is
> **`NOT ASSESSED — no string table found`**, not a matrix of zeros with a
> confident source row.
| [locale] | [N] | [N] | [N] | [N] | [X]% |
### Issues
@@ -180,7 +195,7 @@ Ask: "May I write this translator brief to `production/localization/translator-b
## Phase 2F: Cultural Review Mode
Spawn `localization-lead` via Task. Ask them to audit the following for cultural sensitivity across the target locales (read from `assets/data/strings/` and `assets/`):
Spawn `localization-lead` via `Agent`. Ask them to audit the following for cultural sensitivity across the target locales (read from `assets/data/strings/` and `assets/`):
### Content Areas to Review
@@ -268,7 +283,7 @@ Glob `assets/audio/vo/[locale]/` for all `.wav`/`.ogg` files. Cross-reference ag
### VO Pipeline: Integrate
Grep `src/` for VO audio references. Verify each referenced path exists in `assets/audio/vo/[locale]/`. Report broken references.
Grep the code root for VO audio references. Verify each referenced path exists in `assets/audio/vo/[locale]/`. Report broken references.
---
@@ -277,7 +292,7 @@ Grep `src/` for VO audio references. Verify each referenced path exists in `asse
Right-to-left languages (Arabic, Hebrew, Persian, Urdu) require layout mirroring beyond
just translating text. This mode validates the implementation.
Read `.claude/docs/technical-preferences.md` to determine the engine. Then check:
Determine the engine: read `engine.name` from `project.yaml`; if that key is absent or empty (including when `project.yaml` has no `engine:` block), fall back to `.claude/docs/technical-preferences.md`. Then check:
**Layout mirroring**
- Is RTL layout enabled in the engine? (Godot: `Control.layout_direction`, Unity: `RTL Support` package, Unreal: text direction flags)
@@ -364,10 +379,10 @@ When `extract` mode finds new or modified strings and `freeze-status.md` shows S
## Phase 2J: QA Mode
Localization QA is a dedicated pass that runs after translations are delivered but
before any locale ships. This is not the same as `/validate` (which checks completeness)
— this is a structured playthrough-based quality check.
before any locale ships. This is not the same as `/localize validate` (which checks
completeness) — this is a structured playthrough-based quality check.
Spawn `localization-lead` via Task with:
Spawn `localization-lead` via `Agent` with:
- The target locale(s) to QA
- The list of all screens/flows in the game (from `design/gdd/` or `/content-audit` output)
- The current `/localize validate` report
+108 -22
View File
@@ -1,12 +1,18 @@
---
name: map-systems
description: "Decompose a game concept into individual systems, map dependencies, prioritize design order, and create the systems index."
description: "Decompose a concept into individual systems, map dependencies, prioritize design order, create the systems index."
argument-hint: "[next | system-name] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, TodoWrite, Task
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate, Agent
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,docs.density`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
When this skill is invoked:
## Parse Arguments
@@ -18,12 +24,46 @@ Two modes:
- **`next`**: `/map-systems next` — Pick the highest-priority undesigned system
from the index and hand off to `/design-system` (Phase 6).
Also resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which sections exist. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = one-line system descriptions;
`balanced` = a brief paragraph per system + dependency notes (default);
`thorough` = full system-by-system rationale + relationship analysis. Apply it to
every section you author.
> **Where the per-system prose goes.** `templates/systems-index.md`'s Systems
> Enumeration is a fixed-column table with no description column, so at
> `balanced` and `thorough` the prose belongs in `## Overview` — one short
> paragraph per system at `balanced`, plus relationship analysis at `thorough` —
> and in the `## Dependency Map` layer notes. **Do not add a column to the
> enumeration table** — it is a fixed contract in
> `.claude/docs/templates/systems-index.md`, and its consumers
> (`/design-system` §6 and §7, `/create-epics`) are written against the columns it
> defines. Widening it is a schema change, not a formatting choice.
>
> **How the consumers actually read it.** Nothing parses this table
> positionally. The two scripts that mention `systems-index.md`
> (`gdd-structure-check.sh:51`, `review-scope.sh:40`) match it **by filename** in a
> `case` statement and parse no columns at all; the two skills key on the
> **`Category` column by name** (`design-system:229`, `:780`). So `Category` is
> the column that must never be renamed or dropped, and the table stays a fixed
> contract because every consumer is written against the set of columns the
> template defines.
> At `terse`, the table plus a one-paragraph `## Overview` is the whole output.
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` / `standard` — required before `/design-system` (systems must be mapped
before per-system GDDs are authored).
- `minimal` — not required (the game brief replaces the systems index). Can
still be run voluntarily.
---
@@ -33,9 +73,10 @@ Read the game concept and any existing design work. This provides the raw materi
for systems decomposition.
**Required:**
- Read `design/gdd/game-concept.md` — **fail with a clear message if missing**:
> "No game concept found at `design/gdd/game-concept.md`. Run `/brainstorm` first
> to create one, then come back to decompose it into systems."
- Read `design/gdd/game-concept.md` (at `minimal`, read `design/game-brief.md`
instead) — **fail with a clear message if neither is found**:
> "No game concept found. Run `/brainstorm` first to create one, then come back
> to decompose it into systems."
**Optional (read if they exist):**
- Read `design/gdd/game-pillars.md` — pillars constrain priority and scope
@@ -102,7 +143,16 @@ Then use `AskUserQuestion` to capture feedback:
- "Should any of these be combined or split?"
- "Are there systems listed that this game does NOT need?"
Iterate until the user approves the enumeration.
**At `collaborative`** — iterate until the user approves the enumeration.
**At `guided`** — ask once, apply the answer, and proceed; do not loop.
**At `autonomous`** — do not ask. Record the enumeration and its inferred systems
via `log_decision` and proceed.
> **The loop needed an exit that does not depend on being asked.**
> `automation-modes.md:56` defines `autonomous` as *"No `AskUserQuestion`"*, so a
> loop terminating on "the user approves" has no termination path there at all.
> Same class as Step 5b, one level up: that was an unconditional *write* gate,
> this is an unconditional *control-flow loop* around the question.
---
@@ -150,7 +200,7 @@ dependencies I'm missing or that should be removed?"
- `lean` → skip (not a PHASE-GATE). Note: "TD-SYSTEM-BOUNDARY skipped — Lean mode." Proceed to priority assignment.
- `full` → spawn as normal.
**After dependency mapping is approved, spawn `technical-director` via Task using gate TD-SYSTEM-BOUNDARY (`.claude/docs/director-gates.md`) before proceeding to priority assignment.**
**After dependency mapping is approved, spawn `technical-director` via `Agent` using gate TD-SYSTEM-BOUNDARY (`.claude/docs/director-gates/td-system-boundary.md`) before proceeding to priority assignment.**
Pass: the dependency map summary, layer assignments, bottleneck systems list, any circular dependency resolutions.
@@ -182,19 +232,37 @@ Which systems should be higher or lower priority?"
Explain reasoning in conversation: "I placed [system] in MVP because the core loop
requires it — without [system], the 30-second loop can't function."
**"Why" column guidance**: When explaining why each system was placed in a priority tier, mix technical necessity with player-experience reasoning. Do not use purely technical justifications like "Combat needs damage math" — connect to player experience where relevant. Examples of good "Why" entries:
- "Required for the core loop — without it, placement decisions have no consequence (Pillar 2: Placement is the Puzzle)"
- "Ballista's punch-through identity is established here — this stat definition is what makes it feel different from Archer"
- "Foundation for all economy decisions — players must understand upgrade costs to make meaningful placement choices"
**How to phrase the reasoning** — this governs what you *say*, not a column you
write. Neither table has a `Why` column: Systems Enumeration is
`# / Name / Category / Priority / Status / Design Doc / Depends On`, and
Recommended Design Order is `Order / System / Priority / Layer / Agent(s) /
Est. Effort`. The rationale lives in the conversation above and, for anything
the user should still see after the session, in the index's `## Overview`
paragraph. Do not invent a column for it.
Pure technical necessity ("X depends on Y") is insufficient alone when the system directly shapes player experience.
Mix technical necessity with player-experience reasoning. A purely technical
justification — "the damage system needs damage math" — is insufficient on its
own when the system directly shapes what the player feels. Good reasoning names
both, and cites the pillar it serves:
- "Required for the core loop — without it the player's main choice has no
consequence (Pillar [N]: [pillar name])"
- "This is where [system]'s identity is established — the stat definitions here
are what make it feel different from [the sibling system]"
- "Foundation for every later economy decision — the player must understand
costs before any of the choices built on top of it mean anything"
> **Fill the brackets from *this* project.** The bracketed slots are not
> decoration. Worked examples from another genre (a tower-defense "Ballista's
> punch-through identity… what makes it feel different from Archer", "Pillar 2:
> Placement is the Puzzle") get reproduced verbatim by a run against a different
> game, which then carries that game's vocabulary instead of its own.
**Review mode check** — apply before spawning PR-SCOPE:
- `solo` → skip. Note: "PR-SCOPE skipped — Solo mode." Proceed to writing the systems index.
- `lean` → skip (not a PHASE-GATE). Note: "PR-SCOPE skipped — Lean mode." Proceed to writing the systems index.
- `full` → spawn as normal.
**After priorities are approved, spawn `producer` via Task using gate PR-SCOPE (`.claude/docs/director-gates.md`) before writing the index.**
**After priorities are approved, spawn `producer` via `Agent` using gate PR-SCOPE (`.claude/docs/director-gates/pr-scope.md`) before writing the index.**
Pass: total system count per milestone tier, estimated implementation volume per tier (system count × average complexity), team size, stated project timeline.
@@ -233,20 +301,34 @@ Present a summary of the document:
- First 3 systems in the design order
- Any high-risk items
Ask: "May I write the systems index to `design/gdd/systems-index.md`?"
**At `automation: collaborative`** — ask: "May I write the systems index to
`design/gdd/systems-index.md`?" Wait for approval. Write the file only after
"yes."
Wait for approval. Write the file only after "yes."
**At `automation: guided`** — present the summary above, name the destination
(`design/gdd/systems-index.md`), and write it without waiting for an explicit
"yes", per `.claude/docs/automation-modes.md`. Say what you wrote afterwards.
> **Keep this line scoped to its mode.** `automation-modes.md` says `guided`
> *"proceeds after a short summary, does not wait for explicit yes"*, and this
> skill's own Collaborative Protocol section is scoped to `collaborative`. An
> unconditional "wait for approval" here collides with both.
**Review mode check** — apply before spawning CD-SYSTEMS:
- `solo` → skip. Note: "CD-SYSTEMS skipped — Solo mode." Proceed to Phase 7 next steps.
- `lean` → skip (not a PHASE-GATE). Note: "CD-SYSTEMS skipped — Lean mode." Proceed to Phase 7 next steps.
- `full` → spawn as normal.
**After the systems index is written, spawn `creative-director` via Task using gate CD-SYSTEMS (`.claude/docs/director-gates.md`).**
**After the systems index is written, spawn `creative-director` via `Agent` using gate CD-SYSTEMS (`.claude/docs/director-gates/cd-systems.md`).**
Pass: systems index path, game pillars and core fantasy (from `design/gdd/game-concept.md`), MVP priority tier system list.
Present the assessment. If REJECT, revise the system set with the user before GDD authoring begins. If CONCERNS, record them in the systems index as a `> **Creative Director Note**` at the top of the relevant tier section.
Present the assessment. If REJECT, revise the system set with the user before GDD authoring begins. If CONCERNS, record them in the systems index as a `> **Creative Director Note**`
placed **directly beneath the `## Priority Tiers` table**, naming the tier each
concern applies to — e.g. `> **Creative Director Note** (MVP): …`.
`templates/systems-index.md` has a Priority Tiers *definition table*, not a
section per tier, so there is no "top of the tier section" to write to — do not
direct the writer to one.
### Step 5c: Update Session State
@@ -326,6 +408,10 @@ After any individual GDD is completed:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
This skill follows the collaborative design principle at every phase:
1. **Question -> Options -> Decision -> Draft -> Approval** at every step
+79 -12
View File
@@ -1,35 +1,102 @@
---
name: milestone-review
description: "Generates a comprehensive milestone progress review including feature completeness, quality metrics, risk assessment, and go/no-go recommendation. Use at milestone checkpoints or when evaluating readiness for a milestone deadline."
description: "Milestone progress review — completeness, quality metrics, risk, go/no-go recommendation. At checkpoints or before a deadline."
argument-hint: "[milestone-name|current] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation`
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 0: Parse Arguments
Extract the milestone name (`current` or a specific name) and resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
Extract the milestone name (`current` or a specific name).
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
---
## Phase 1: Load Milestone Data
Read the milestone definition from `production/milestones/`. If the argument is `current`, use the most recently modified milestone file.
Read the milestone definition from `production/milestones/` if it exists. If the
argument is `current`, use the most recently modified milestone file.
Read all sprint reports for sprints within this milestone from `production/sprints/`.
> **No skill writes `production/milestones/`** — definitions are authored by hand
> from `.claude/docs/templates/milestone-definition.md`, so most projects have
> none. When the directory is absent or empty, say so and review against the
> sprint reports alone; do not fabricate a definition. Take care with `current`:
> this skill writes its own output as `[milestone-name]-review.md`, so a
> most-recently-modified match can be a previous *review* rather than a
> definition. Skip files ending `-review.md` when selecting.
Gather the sprint reports for sprints within this milestone from
`production/sprints/`. Establish the denominator (glob them, count **N**), then
scan the sections a milestone review actually aggregates rather than reading each
report whole:
```
Grep pattern="^## (Sprint Goal|Capacity|Tasks|Carryover|Risks|Progress|Burndown Assessment|Emerging Risks|Definition of Done)" glob="production/sprints/sprint-*.md" output_mode="content" -A 12
```
> **These alternates are copied from `/sprint-plan`'s emitted headings — keep
> them in sync with it, not with what a milestone review wishes existed.** The
> previous pattern asked for `Summary|Goal|Velocity|Completed|Blockers|
> Retrospective`, none of which `/sprint-plan` writes (it emits `## Sprint
> Goal`, not `## Goal`). Only `Carryover` matched — and that was the trap: a
> non-zero match count meant the zero-match escape hatch below could never
> fire, so every milestone review silently aggregated carryover tables and
> nothing else while reporting full coverage.
Full-read a single sprint report when its scanned sections point outside
themselves, or when it matched nothing — a zero-match report predates the
template and must be read, never silently dropped from the milestone's history.
Report any sprint that contributed nothing: a milestone summary that quietly
omits a sprint understates the work and the slippage both.
---
## Phase 2: Scan Codebase Health
- Scan for `TODO`, `FIXME`, `HACK` markers that indicate incomplete work
- Check the risk register at `production/risk-register/`
- Check the risk register at `production/risk-register/` if it exists (hand-authored from `.claude/docs/templates/risk-register-entry.md`; no skill writes it, so absence is normal — note it rather than skipping risk assessment silently)
---
@@ -92,7 +159,7 @@ Read all sprint reports for sprints within this milestone from `production/sprin
## Go/No-Go Assessment
**Recommendation**: [GO / CONDITIONAL GO / NO-GO]
**Recommendation**: [NOT ASSESSED / GO / CONDITIONAL GO / NO-GO]
**Conditions** (if conditional):
- [Condition 1 that must be met]
@@ -114,7 +181,7 @@ Read all sprint reports for sprints within this milestone from `production/sprin
- `lean` → skip (not a PHASE-GATE). Note: "PR-MILESTONE skipped — Lean mode." Present the Go/No-Go section without a producer verdict.
- `full` → spawn as normal.
Before generating the Go/No-Go recommendation, spawn `producer` via Task using gate **PR-MILESTONE** (`.claude/docs/director-gates.md`).
Before generating the Go/No-Go recommendation, spawn `producer` via `Agent` using gate **PR-MILESTONE** (`.claude/docs/director-gates/pr-milestone.md`).
Pass: milestone name and target date, current completion percentage, blocked story count, velocity data from sprint reports (if available), list of cut candidates.
+40 -2
View File
@@ -1,12 +1,50 @@
---
name: onboard
description: "Generates a contextual onboarding document for a new contributor or agent joining the project. Summarizes project state, architecture, conventions, and current priorities relevant to the specified role or area."
description: "Onboarding doc for a new contributor or agent — project state, conventions, priorities relevant to the specified role."
argument-hint: "[role|area]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: haiku
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1: Load Project Context
Read CLAUDE.md for project overview and standards.
@@ -17,7 +55,7 @@ Read the relevant agent definition from `.claude/agents/` if a specific role is
## Phase 2: Scan Relevant Area
- For programmers: scan `src/` for architecture, patterns, key files
- For programmers: scan the code root (resolve per `.claude/docs/code-root-resolution.md`) for architecture, patterns, key files
- For designers: scan `design/` for existing design documents
- For narrative: scan `design/narrative/` for world-building and story docs
- For QA: scan `tests/` for existing test coverage
+58 -3
View File
@@ -1,11 +1,66 @@
---
name: patch-notes
description: "Generate player-facing patch notes from git history, sprint data, and internal changelogs. Translates developer language into clear, engaging player communication."
description: "Player-facing patch notes from git history and changelogs. Translates developer language into player communication."
argument-hint: "[version] [--style brief|detailed|full]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash
model: haiku
agent: community-manager
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Provenance check — before reading any history
**Confirm the history you are about to read belongs to THIS game.** Run this
before Phase 2 and stop if it fails.
1. Sample the recent log: `git log --oneline -20`.
2. **Classify every commit in the range, one at a time**, into exactly one of:
- **Game** — changes the game the player plays: mechanics, content, balance,
art, audio, UI, a bug in any of those.
- **Framework / maintenance** — changes CCGS itself or the project's tooling:
subjects naming skills, hooks, agents, the test plan, CI, the framework's
own docs. **Excluded from player-facing notes, but not a reason to stop.**
- **Unclear** — treat as framework. A commit you cannot confidently place is
not one to write player copy from.
3. Then decide from the counts:
- **At least one Game commit** → proceed, using **only** those. Say how many
of how many you used, so the reader can see the filter ran.
- **Zero Game commits** → stop, using the message below.
> **Filter per commit; do not stop on a repo that merely contains maintenance
> work.** Every project built on this framework accumulates commits touching
> hooks, CI and skills — the game repo *is* the framework repo. An earlier
> version of this check listed "subjects naming the framework, its skills, hooks,
> agents or test plan" as a hard STOP, which fires on virtually every real
> project and contradicted its own step 2 whenever a history was mostly the
> game's. The danger was never that such commits *exist*; it is that they get
> **rendered as player-facing copy**. Excluding them addresses that exactly, and
> a repo-level stop does not.
Corroborate before you proceed, cheaply: the Game commits should name systems
that appear in `design/` and `src/`. If they name a product those directories
never mention, that is the real wrong-history signal — stop.
If **no** commit in the range is this game's, say so and stop:
> "The git history in this repo does not appear to belong to [game]. The recent
> commits describe [what they actually describe]. I cannot generate release notes
> from it — point me at the right history, or supply the change list directly."
**Why this is a hard stop, not a warning.** This exact failure is real, not
hypothetical: a batch of framework-internal commits produced player-facing copy
reading *"Fixed an issue where progress from your last session could be lost on launch"*
— a session-hook timeout rendered as a gameplay fix for a game with **no save
system**. It was fluent, plausible, and entirely false. A reader cannot tell the
difference; only this check can.
---
## Phase 1: Parse Arguments
+105 -3
View File
@@ -1,13 +1,71 @@
---
name: perf-profile
description: "Structured performance profiling workflow. Identifies bottlenecks, measures against budgets, and generates optimization recommendations with priority rankings."
description: "Performance profiling — find bottlenecks, measure against budgets, produce ranked optimization recommendations."
argument-hint: "[system-name or 'full']"
user-invocable: true
agent: performance-analyst
allowed-tools: Read, Glob, Grep, Bash
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys performance.enforce,automation`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 0: Resolve Budget Enforcement
`performance.enforce` decides what a budget violation *means* in this run. It
does not change which budgets are measured — `performance.target_framerate`,
`frame_budget_ms`, `draw_call_limit` and `memory_ceiling_mb` are profiled the
same way at every level:
| Value | Effect on this profile's findings |
|-------|-----------------------------------|
| `warn` (default) | Violations are reported as findings. They do not block; CI logs them without failing. |
| `block` | Violations are **blockers**. Say so explicitly in the report — a `block` project treats an over-budget system as release-stopping, and `/gate-check` will FAIL the Polish gate on it. |
| `off` | Budgets are informational only. Still report measured values, but do not raise violations as findings or recommendations to fix. |
Only `warn`, `block` and `off` are recognized. Surface any other value to the
user and fall back to `warn` rather than guessing.
> The value is locally overridable (`/settings --local performance.enforce=block`),
> so use the resolved block above rather than reading `project.yaml` — a
> teammate's stricter local setting is meant to bite on their machine only.
## Phase 1: Determine Scope
Read the argument:
@@ -19,7 +77,30 @@ Read the argument:
## Phase 2: Load Performance Budgets
Check for existing performance targets in design docs or CLAUDE.md:
**Read the committed budgets from config first** — they are the project's
record of what it agreed to, and design docs are the fallback, not the source:
```bash
source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null
get_effective_yaml_key performance.target_framerate
get_effective_yaml_key performance.frame_budget_ms
get_effective_yaml_key performance.draw_call_limit
get_effective_yaml_key performance.memory_ceiling_mb
```
> Written as four literal keys rather than a loop over leaf names, deliberately.
> The dead-settings audit matches the **full dotted key**, so a loop building
> `performance.$k` leaves three of the four spelled nowhere and the audit
> reports them DEAD while this skill reads them. Spell each key out in full.
> **Resolve these budgets from `project.yaml`, not from prose.** Phase 0 above
> states these four budgets "are profiled the same way at every level". Sending
> the reader to *"design docs or CLAUDE.md"* instead means a user who set
> `performance.target_framerate: 60` in `project.yaml` has it ignored by the one
> skill that profiles against budgets. The keys resolve correctly — this phase
> has to actually ask for them.
Then fall back to design docs or CLAUDE.md for anything config does not carry:
- Target FPS (e.g., 60fps = 16.67ms frame budget)
- Memory budget (total and per-system)
@@ -27,6 +108,11 @@ Check for existing performance targets in design docs or CLAUDE.md:
- Draw call budgets
- Network bandwidth limits (if multiplayer)
**A metric with no committed budget is `NOT ASSESSED`, not a pass.** Do not
measure against the template's `[16.67ms]` placeholder — an unset budget is not
a budget that was met, and reporting headroom against a number nobody chose is
the exact fabrication this skill's own header warns about.
---
## Phase 3: Analyze Codebase
@@ -62,6 +148,22 @@ Check for existing performance targets in design docs or CLAUDE.md:
## Phase 4: Generate Profiling Report
**Write the report to `production/polish/[scope]-report-[date].md`**, asking first
per the Collaboration Protocol: *"May I write this profiling report to
`production/polish/[scope]-report-[date].md`?"* Create the directory if absent.
> **Name the destination — do not just render the template into the
> conversation.** A profile that lives only in the transcript is gone the moment
> the session ends, and no two runs can be compared. `production/polish/`
> is the same location `/team-polish` writes, deliberately: a profile taken by
> either route belongs in one place, or the comparison this skill exists to enable
> cannot be made.
>
> If a `NOT ASSESSED` section survives into the report, keep it in the written
> file. A profile whose gaps are edited out on the way to disk reads, later, as a
> complete measurement.
```markdown
## Performance Profile: [System or Full]
Generated: [Date]
+20 -9
View File
@@ -1,20 +1,25 @@
---
name: playtest-report
description: "Generates a structured playtest report template or analyzes existing playtest notes into a structured format. Use this to standardize playtest feedback collection and analysis."
description: "Structured playtest report template, or turn existing playtest notes into structured feedback."
argument-hint: "[new|analyze path-to-notes] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation`
## Phase 1: Parse Arguments
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Determine the mode:
@@ -122,9 +127,15 @@ Present the categorized list, then route:
- `lean` → skip (not a PHASE-GATE). Note: "CD-PLAYTEST skipped — Lean mode." Proceed to Phase 4 (save the report).
- `full` → spawn as normal.
After categorising findings, spawn `creative-director` via Task using gate **CD-PLAYTEST** (`.claude/docs/director-gates.md`).
After categorising findings, spawn `creative-director` via `Agent` using gate **CD-PLAYTEST** (`.claude/docs/director-gates/cd-playtest.md`).
Pass: the structured report content, game pillars and core fantasy (from `design/gdd/game-concept.md`), the specific hypothesis being tested.
Pass: the structured report content, game pillars and core fantasy (from
`design/gdd/game-concept.md`), the specific hypothesis being tested. **If
`game-concept.md` does not exist** — expected at `minimal`, where
`design/game-brief.md` replaces it — pass the brief's pillars instead, and if
neither exists say so in the prompt: *"No pillars available — assess against
the hypothesis alone."* A director gate handed silence about pillars will
invent them.
Present the creative director's assessment before saving the report. If CONCERNS or REJECT, add a `## Creative Director Assessment` section to the report capturing the verdict and feedback. If APPROVE, note the approval in the report.
+80 -11
View File
@@ -1,6 +1,6 @@
---
name: project-stage-detect
description: "Automatically analyze project state, detect stage, identify gaps, and recommend next steps based on existing artifacts. Use when user asks 'where are we in development', 'what stage are we in', 'full project audit'."
description: "Analyze project state, detect stage, identify gaps, recommend next steps. 'Where are we in development?'"
argument-hint: "[optional: role filter like 'programmer' or 'designer']"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write
@@ -21,19 +21,62 @@ of artifacts, and gaps that need attention. It's especially useful when:
## Workflow
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys workflow,automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
> **Resolve the tier — do not assume it.** Saying "surface gaps per the **resolved** workflow
> tier" without resolving it — no bootstrap, no helper call — leaves
> the tier as whatever the model assumed. The tier decides what counts as a gap
> at all: at `full` every missing doc is one; at `minimal` none of them are,
> because a brief plus an engine is the normal state and code is the expected
> next step. Guessing high tells a jam project it is missing GDDs, an art bible
> and ADRs — the exact "process feels mismatched to my project" experience
> `modes.rigor` exists to prevent. A missing bootstrap is invisible to a static
> read — the config block simply does not render — so verify it by running.
**`workflow`** (per `.claude/docs/workflow-modes.md`). The tier governs
which absent documents count as gaps (step 3) — below `full`, optional docs are
not flagged.
### 1. Scan Key Directories
Analyze project structure and content:
**Start with the deterministic pass — it answers "what exists" for every
catalogued artifact in one call:**
```
Bash: bash .claude/scripts/artifact-check.sh
```
With no `--phase` it reports every phase, so a single call covers the whole
project: per step, `PRESENT` / `ABSENT` / `SHORT` (with `count=` and `min=`) /
`PATTERN_MISS` / `NO_CHECK`. Use it instead of hand-globbing each artifact
below, and treat its `NO_CHECK` total as the honest bound on what existence
checks can tell you.
It reports observations only — this skill still decides what stage those
observations imply, and the tier still governs which absences are gaps at all
(see the workflow-tier note below).
Then analyze what the script cannot: content quality, counts it does not
track, and the judgement calls.
**Design Documentation** (`design/`):
- Count GDD files in `design/gdd/*.md`
- Check for game-concept.md, game-pillars.md, systems-index.md
- Check for game-concept.md (or `design/game-brief.md` at `minimal`), game-pillars.md, systems-index.md
- If systems-index.md exists, count total systems vs. designed systems
- Analyze completeness (Overview, Detailed Design, Edge Cases, etc.)
- Count narrative docs in `design/narrative/`
- Count level designs in `design/levels/`
**Source Code** (`src/`):
**Source Code** (the code root — `src/` Godot, `Assets/` Unity, `Source/` Unreal; resolve per `.claude/docs/code-root-resolution.md`):
- Count source files (language-agnostic)
- Identify major systems (directories with 5+ files)
- Check for core/, gameplay/, ai/, networking/, ui/ directories
@@ -59,23 +102,46 @@ Analyze project structure and content:
### 2. Classify Project Stage
Based on scanned artifacts, determine stage. Check `production/stage.txt` first —
if it exists, use its value (explicit override from `/gate-check`). Otherwise,
auto-detect using these heuristics (check from most-advanced backward):
Based on scanned artifacts, determine stage. Check `project.stage` in `project.yaml` first (if present); else `production/stage.txt` (legacy fallback) — either is an explicit override from `/gate-check`. Otherwise, auto-detect using these heuristics (check from most-advanced backward):
> **Always run the heuristics, even when a stage is configured — then COMPARE.**
> The configured value is authoritative for what the stage *is*; it is not
> evidence that the artifacts support it. Report both, and when they disagree say
> so explicitly:
>
> > "Configured stage: **Release**. Observed artifacts indicate
> > **Pre-Production** (2 source files, 0 ADRs, no architecture doc, no epics).
> > These disagree — the configured stage may be stale, or work exists outside
> > this repo."
>
> Reading config and reporting it back is not detection. This skill's own
> description promises "analyze project state, detect stage", and a stage
> detector that cannot contradict its input is the one thing it must never be.
> Observed live: it reported `Release` for a project whose artifacts matched its
> own Pre-Production row, four stages below, and said nothing.
| Stage | Indicators |
|-------|-----------|
| **Concept** | No game concept doc, brainstorming phase |
| **Systems Design** | Game concept exists, systems index missing or incomplete |
| **Technical Setup** | Systems index exists, engine not configured |
| **Pre-Production** | Engine configured, `src/` has <10 source files |
| **Production** | `src/` has 10+ source files, active development |
| **Pre-Production** | Engine configured, code root has <10 source files |
| **Production** | code root has 10+ source files, active development |
| **Polish** | Explicit only (set by `/gate-check` Production → Polish gate) |
| **Release** | Explicit only (set by `/gate-check` Polish → Release gate) |
### 3. Collaborative Gap Identification
**DO NOT** just list missing files. Instead, **ask clarifying questions**:
**Surface gaps per the resolved workflow tier:**
- **`full`** — flag every missing doc type (GDDs, art bible, UX specs, ADRs) as a gap.
- **`standard`** — flag only required docs: missing GDDs for built systems and
missing critical (Foundation-layer) ADRs. Do NOT flag an absent art bible unless
visual-asset stories exist, and do NOT flag non-core UX specs.
- **`minimal`** — a `design/game-brief.md` + engine present is the normal state. Do NOT flag
absent GDDs, art bible, UX specs, or ADRs as gaps; the expected next step is code.
**DO NOT** just list missing files. Instead, **ask clarifying questions** (only
for gaps the tier above says to surface):
- "I see combat code (`src/gameplay/combat/`) but no `design/gdd/combat-system.md`. Was this prototyped first, or should we reverse-document?"
- "You have 15 ADRs but no architecture overview. Should I create one to help new contributors?"
@@ -171,7 +237,10 @@ Wait for user approval before creating the file.
## Follow-Up Actions
After generating the report, suggest relevant next steps:
After generating the report, suggest relevant next steps — **only for gaps the
resolved workflow tier surfaces** (step 3). At `standard`/`minimal`, do not
suggest authoring optional docs (e.g. don't suggest `/reverse-document` for an
absent GDD at `minimal`, where code is the expected next step):
- **Concept exists but no systems index?** → `/map-systems` to decompose into systems
- **Missing design docs?** → `/reverse-document design src/[system]`
+116 -24
View File
@@ -1,13 +1,16 @@
---
name: propagate-design-change
description: "When a GDD is revised, scans all ADRs and the traceability index to identify which architectural decisions are now potentially stale. Produces a change impact report and guides the user through resolution."
description: "A GDD changed — scan ADRs and the traceability index for now-stale architectural decisions. Impact report, guides resolution."
argument-hint: "[path/to/changed-gdd.md]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash, Task
allowed-tools: Read, Glob, Grep, Write, Bash, Agent, AskUserQuestion
model: sonnet
agent: technical-director
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,system_overrides`
# Propagate Design Change
When a GDD changes, architectural decisions written against it may no longer be
@@ -18,6 +21,20 @@ what the GDD now says, and guides the user through resolution.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt — ADR/schema impacts here fall
under `schema_changes` and `architecture_decisions`).
**Workflow tier**: resolve for the **changed GDD's system** (per
`.claude/docs/workflow-modes.md`): use the
`system_overrides` row for that system if the block lists one, else the
project value. (A system pinned `minimal` has no ADRs even on a `standard`
project — so its change is N/A.) It scopes the cascade: `full` cascades across all
ADRs; `standard` checks only critical (Foundation-layer) ADRs plus any ADR
referencing the changed GDD; `minimal` is **not applicable** — no ADRs to cascade.
See Step 4.
## 1. Validate Argument
A GDD path argument is **required**. If missing, fail with:
@@ -29,29 +46,46 @@ Verify the file exists. If not, fail with:
---
## 2. Read the Changed GDD
## 2. Diff the GDD Against Its Previous Version
Read the current GDD in full.
---
## 3. Read the Previous Version
Run git to get the previous committed version:
**Ask git what changed — do not read two whole documents and compare them by
eye.** The previous form of this step read the current GDD in full *and*
`git show`-ed the full committed version, then diffed them mentally: two entire
documents in context to find what is usually a handful of lines, and a model
comparing 400-line documents will eventually miss an edit. Git cannot.
```bash
git show HEAD:design/gdd/[filename].md
git diff HEAD -- design/gdd/[filename].md
```
If that is empty, the change may already be committed — widen to the commit that
last touched it:
```bash
git diff HEAD~1 HEAD -- design/gdd/[filename].md
```
If the file has no git history (new file), report:
> "No previous version in git — this appears to be a new GDD, not a revision.
> Nothing to propagate."
If git returns the previous version, do a conceptual diff:
If the diff is empty **and** the file has history, report that plainly — "no
uncommitted or last-commit changes to `[file]`" — and ask which revision to
propagate. An empty diff is not "no impact"; it means nothing changed *here*.
From the diff hunks:
- Identify sections that changed (new rules, removed rules, modified formulas,
changed acceptance criteria, changed tuning knobs)
- Identify sections that are unchanged
- Produce a change summary:
changed acceptance criteria, changed tuning knobs). The `@@` hunk headers name
the enclosing section, so the changed-section list falls out of the diff itself.
- Read the surrounding section from the current GDD **only** where a hunk is too
small to interpret on its own (a changed number whose meaning depends on the
rule above it). That is a targeted read of one section, not the document.
- Sections with no hunk are unchanged — by construction, not by inspection.
---
## 3. Produce the Change Summary
From the hunks resolved in step 2:
```
## Change Summary: [GDD filename]
@@ -68,23 +102,77 @@ Key changes affecting architecture:
- [Change 2]
```
**Downstream GDD impact via the registry.** If `design/registry/entities.yaml`
exists, it already records which other GDDs depend on this system's facts —
compute the affected set from it rather than re-reading every GDD:
```
Grep pattern="source: design/gdd/[filename]" path="design/registry/entities.yaml" output_mode="content" -A 6
```
For each entity/constant/formula this GDD **owns** whose value the diff changed,
its `referenced_by:` list is the set of downstream GDDs that may now be
inconsistent — report them under "Downstream GDDs to re-check". **If
`design/registry/entities.yaml` does not exist or has no entries** (it ships as
an empty stub until `/design-system` populates it), skip this — the ADR cascade
below still runs.
---
## 4. Load Architecture Inputs
Read all ADRs in `docs/architecture/`:
- For each ADR, read the full file
- Extract the "GDD Requirements Addressed" table
- Note which GDD documents and requirement IDs each ADR references
Read ADRs in `docs/architecture/` **per the resolved tier**:
- **`full`** — read **all** ADRs.
- **`standard`** — read only **critical (Foundation-layer) ADRs** plus any ADR
that references the changed GDD.
- **`minimal`** — **not applicable**: there are no ADRs to cascade. Report "No ADR
cascade at minimal workflow — design change recorded; no architecture impact
analysis." and stop here.
Read `docs/architecture/architecture-traceability.md` if it exists.
**Establish the denominator first.** Glob the in-scope ADRs (per the tier above).
Call the count **N**. If N is 0: "No ADRs found in `docs/architecture/` — nothing
to cascade." Stop.
Report: "Loaded [N] ADRs. [M] reference [gdd filename]."
**Scan the requirement tables — do not full-read the ADRs at this step:**
```
Grep pattern="## GDD Requirements Addressed" glob="docs/architecture/adr-*.md" output_mode="content" -A 15
```
**Recall net — an ADR may cite the changed GDD in prose without tabling it:**
```
Grep pattern="[changed-gdd-basename]" glob="docs/architecture/adr-*.md" output_mode="files_with_matches"
```
Take the **union** of the two results as the affected set **M**. This turns
N × ~200 lines into N × ~15 lines; §5 full-reads only the M.
Interpret the result — a zero-match scan is **never** "no impact" by default:
| Result | Meaning | Action |
|---|---|---|
| **M ≥ 1** | Normal. | Proceed. The N − M non-matching ADRs are *out of scope for this cascade* — do not describe them as verified unaffected. |
| **Both scans 0, N > 0** | Ambiguous — either no ADR references this GDD, or the ADRs lack requirement tables. | Run `Grep pattern="## GDD Requirements Addressed" glob="docs/architecture/adr-*.md" output_mode="files_with_matches"`. If that is **also** empty: "[N] ADRs found, none contains a 'GDD Requirements Addressed' section — traceability cannot be computed (a `gate-pre-production` blocker). Run `/architecture-decision [adr] retrofit`." If it is **non-empty**: the tables exist and genuinely none reference this GDD — "No ADR references [gdd] — no architecture impact." |
Read `docs/architecture/requirements-traceability.md` if it exists.
Report: "Loaded [N] ADRs by scan. [M] reference [gdd filename] ([X] via
requirements table, [Y] via prose reference only)."
---
## 5. Impact Analysis
Now read each ADR in the affected set **M** for its reasoning, not just its
table — judging whether a decision is still valid needs the ADR's `## Context`
and `## Decision` (and `## Consequences` where present), not scan output. **Do
not attempt the judgement below from scan output.**
This read is unbounded only up to a point — check size first
(`Bash: wc -c "docs/architecture/[adr-file].md"`):
- **Under ~50KB** — one full `Read` is fine and cheapest at this size.
- **~50KB or larger** — map headings first
(`Grep pattern="^## " path="docs/architecture/[adr-file].md" output_mode="content" -n`),
then bounded-`Read` only `## Context`, `## Decision`, and `## Consequences`.
An unbounded `Read` on a large ADR hits the 25k-token cap and, unrecovered,
the only path forward is paging through the entire remainder — measured at
103k tokens on a 34k-token ADR, most of it content this analysis never uses.
For each ADR that references the changed GDD:
Compare the ADR's "GDD Requirements Addressed" entries against the changed sections
@@ -153,7 +241,7 @@ ADRs referencing this GDD: [M]
- `lean` → skip. Note: "TD-CHANGE-IMPACT skipped — Lean mode." Proceed to Phase 7.
- `full` → spawn as normal.
Spawn `technical-director` via Task using gate **TD-CHANGE-IMPACT** (`.claude/docs/director-gates.md`).
Spawn `technical-director` via `Agent` using gate **TD-CHANGE-IMPACT** (`.claude/docs/director-gates/td-change-impact.md`).
Pass: the full Design Change Impact Report from Phase 6 (change summary, all affected ADRs with their Still Valid / Needs Review / Likely Superseded classifications, and recommended actions).
@@ -189,7 +277,7 @@ For ADRs marked **Superseded**:
## 8. Update Traceability Index
If `docs/architecture/architecture-traceability.md` exists:
If `docs/architecture/requirements-traceability.md` exists:
- Add the changed GDD requirements to the "Superseded Requirements" table:
```markdown
@@ -232,6 +320,10 @@ Based on the resolution decisions, suggest:
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Read silently** — compute the full impact before presenting anything
2. **Show the full report first** — let the user see the scope before asking for action
3. **Ask per-ADR** — don't batch decisions; each affected ADR may need different treatment
+16 -10
View File
@@ -1,14 +1,17 @@
---
name: prototype
description: "Concept prototype — validate the core idea is worth designing before writing GDDs. Run right after /brainstorm and /setup-engine. Routes to HTML, Engine, or Paper path based on game type. Produces a throwaway build and a PROCEED/PIVOT/KILL verdict."
description: "Concept prototype before GDDs — throwaway HTML, Engine or Paper build, PROCEED/PIVOT/KILL. After /brainstorm and /setup-engine."
argument-hint: "[concept-description] [--path html|engine|paper] [--review full|lean|solo] [--spike]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
agent: prototyper
isolation: worktree
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation`
## Purpose
This is the **concept prototype** — a fast, throwaway build that answers one question:
@@ -29,10 +32,10 @@ before committing to Production, run `/vertical-slice` instead.
## Phase 1: Define the Question
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Check for spike mode:** If `--spike` was passed, skip to the **Spike Mode** section
at the bottom of this skill.
@@ -94,8 +97,11 @@ Read `design/gdd/game-concept.md` if it exists. Extract:
- Core fantasy (what the player is supposed to feel)
- Core loop (the moment-to-moment action being tested)
Read `CLAUDE.md` and `.claude/docs/technical-preferences.md` for the engine and
language in use.
Determine the engine and language in use: read `engine.name` and
`engine.language` from `project.yaml`. For each field, if its key is absent or
empty (including when `project.yaml` has no `engine:` block), fall back to
`CLAUDE.md` and `.claude/docs/technical-preferences.md`. Treat a
`[TO BE CONFIGURED]` value as not set.
---
@@ -415,7 +421,7 @@ is the project's complete history of what was tried and what was learned.
**Review mode check:**
- `solo` → skip. Note: "CD-PLAYTEST skipped — Solo mode."
- `lean` → skip. Note: "CD-PLAYTEST skipped — Lean mode."
- `full` → spawn `creative-director` via Task using gate **CD-PLAYTEST** if
- `full` → spawn `creative-director` via `Agent` using gate **CD-PLAYTEST** if
`design/gdd/game-concept.md` exists with game pillars defined. If pillars are
not yet defined, note: "CD-PLAYTEST skipped — game pillars not yet defined at
concept prototype stage."
+94 -24
View File
@@ -1,13 +1,18 @@
---
name: qa-plan
description: "Generate a QA test plan for a sprint or feature. Reads GDDs and story files, classifies stories by test type (Logic/Integration/Visual/UI), and produces a structured test plan covering automated tests required, manual test cases, smoke test scope, and playtest sign-off requirements. Run before sprint begins or when starting a major feature."
description: "QA test plan for a sprint — classifies stories by Logic/Integration/Visual/UI, covers automated tests, manual cases, smoke scope."
argument-hint: "[sprint | feature: system-name | story: path]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion
model: sonnet
agent: qa-lead
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,qa.level,system_overrides`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
# QA Plan
This skill generates a structured QA plan for a sprint, feature, or individual
@@ -24,6 +29,20 @@ plan.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Workflow tier**: resolve per the GDD's system as each is read (per
`.claude/docs/workflow-modes.md`): `workflow_overrides.system_overrides.<system>`
if the block lists one, else the project value. It sets how many GDD sections
the test plan is mined from — see Phase 2.
**`qa.level`**: at `minimal`, produce only a minimal smoke
plan — drop the automated-test-required rows and the test-file DoD; at `standard`,
a full plan per story type; at `full`, also add per-system coverage targets.
Distinct axis from `workflow` (which sets how many GDD sections are mined).
## Phase 1: Parse Scope
**Argument:** `$ARGUMENTS` (blank = ask user via AskUserQuestion)
@@ -49,32 +68,73 @@ If a story file path is referenced but the file does not exist, note it as
MISSING and continue with the remaining stories. Do not fail the entire plan
for one missing file.
> **If the resolved scope contains ZERO stories, stop — do not build a plan.**
> Report `NOT ASSESSED — no stories in scope`, naming which scope was searched
> and which path was empty, and route:
> - no file in `production/sprints/` → "No sprint plan found. Run `/sprint-plan new`."
> - a sprint plan exists but references no stories → "Sprint plan `[path]` lists no
> stories. Run `/create-stories [epic-slug]`."
> - `feature:`/`story:` scope matched nothing → name the glob that came back empty.
>
> **The N=0 guard is mandatory.** Without it an empty scope reports "Building QA
> plan for 0 stories" and continues into Phase 4, producing a plan document with
> empty tables — and **a QA plan for zero stories looks exactly like a completed
> QA plan.** This skill gates the hand-off to manual QA, so a false-clean here
> sends a build to QA on the strength of a plan that tested nothing.
>
> Note the shape, because this skill already had the harder half of the rule.
> Phase 2 states **"Never treat an absent section as an absent story"** — the
> sophisticated inner case, correctly handled. The outer boundary, no stories at
> all, had nothing. The same shape appears in `/story-readiness`, where `NOT ASSESSED`
> existed for per-story failures and the empty scope could not reach it.
>
> The rule at the top of this block still stands: one missing file among several
> is MISSING-and-continue. This is the different case where there is no *several*.
---
## Phase 2: Load Inputs
For each in-scope story file, read the full file and extract:
Establish the denominator first — glob the in-scope story files and count **N** —
then collect the fields below with **targeted section greps, not a full read of
each story**. A QA plan needs each story's type and acceptance criteria; it does
not need its implementation notes, out-of-scope boundaries or ADR rationale, and
reading N stories whole to reach two sections is where this phase's cost lives:
- **Story title** and story ID (from filename or header)
- **Story Type** field (if present in the file header — e.g., `Type: Logic`)
- **Acceptance criteria** — the complete numbered/bulleted list
- **Implementation files** — listed under "Files to Create / Modify" or similar
- **Engine notes** — any engine API warnings or version-specific notes
- **GDD reference** — the GDD path(s) cited
- **ADR reference** — the ADR(s) cited
- **Estimate** — hours or story points if present
- **Dependencies** — other stories this one depends on
```
Grep pattern="^## Acceptance Criteria" glob="production/epics/**/story-*.md" output_mode="content" -A 15
Grep pattern="^> \*\*(Type|Status|Estimate)\*\*" glob="production/epics/**/story-*.md" output_mode="content"
Grep pattern="^## (Context|Dependencies)" glob="production/epics/**/story-*.md" output_mode="content" -A 8
```
(Scope the globs to the sprint plan's story paths in `sprint` mode.) From those:
- **Story title** and story ID — from the file name and path; no read at all
- **Story Type** field — from the header grep (e.g., `Type: Logic`)
- **Acceptance criteria** — the complete numbered/bulleted list, from the first grep
- **GDD / ADR reference** and **Dependencies** — from the `## Context` grep
- **Estimate** — from the header grep if present
- **Implementation files** and **Engine notes** — only needed for stories whose
test plan actually turns on them; full-read those individual stories
**Never treat an absent section as an absent story.** If a story matched no
`## Acceptance Criteria`, full-read that one and say so — a story with no
testable criteria is a QA finding in its own right, not a story to skip.
After reading stories, load supporting context once (not per story):
- `design/gdd/systems-index.md` — to understand system priorities and which
GDDs are approved
- For each unique GDD referenced across all stories: read the
**Acceptance Criteria**, **Formulas**, and **Edge Cases** sections. Do not load
the full GDD text. These three sections contain the testable requirements, the math
to verify, and the boundary conditions that tests must cover. If an Edge Cases
section is absent from the GDD, note it per GDD: "No Edge Cases section found — edge
case coverage will be inferred from acceptance criteria only."
- For each unique GDD referenced across all stories: mine test material per that
system's workflow tier (resolved above) — at `full`, mine all 8 sections; at
`standard`, mine the test-relevant subset of the required sections
(**Acceptance Criteria** and **Edge Cases** always, plus **Formulas** for any
system that defines numeric rules); at `minimal`, **Acceptance
Criteria only**. Do not load the full GDD
text. These sections contain the testable requirements, the math to verify, and
the boundary conditions tests must cover. If an Edge Cases section is absent (or
not expected at minimal), note per GDD: "No Edge Cases section found — edge case
coverage will be inferred from acceptance criteria only."
- `docs/architecture/control-manifest.md` — scan for forbidden patterns that
automated tests should guard against (if the file exists)
@@ -118,7 +178,7 @@ Assemble the full QA plan document. Use this structure:
**Date**: [date]
**Generated by**: /qa-plan
**Scope**: [N stories across [N systems]]
**Engine**: [engine name from .claude/docs/technical-preferences.md, or "Not configured"]
**Engine**: [engine name — `engine.name` from project.yaml if present and non-empty, else the Engine field from .claude/docs/technical-preferences.md, else "Not configured"]
**Sprint File**: [path to sprint plan if applicable]
---
@@ -137,6 +197,10 @@ Assemble the full QA plan document. Use this structure:
## Automated Tests Required
*(At `qa.level: minimal`, omit this entire section and blank the Test Summary's
"Automated Test Required" column — automated tests are not required there; list
manual/smoke verification only.)*
### [Story Title] — [Type]
**Test file path**: `tests/[unit|integration]/[system]/[story-slug]_test.[ext]`
**What to test**:
@@ -210,13 +274,15 @@ this sprint.*
## Definition of Done — This Sprint
A story is DONE when ALL of the following are true:
A story is DONE when ALL of the following are true (at `qa.level: minimal`, drop
the test-file / evidence-document / smoke rows below — only acceptance-criteria
verification is required):
- [ ] All acceptance criteria verified — via automated test result OR documented
manual evidence (screenshot, video, or playtest notes with sign-off)
- [ ] Test file exists at the specified path for all Logic and Integration stories
- [ ] Manual evidence document exists for all Visual/Feel and UI stories
- [ ] Smoke check passes (run `/smoke-check sprint` before QA hand-off)
- [ ] Test file exists at the specified path for all Logic and Integration stories *(qa.level standard/full)*
- [ ] Manual evidence document exists for all Visual/Feel and UI stories *(qa.level standard/full)*
- [ ] Smoke check passes (run `/smoke-check sprint` before QA hand-off) *(qa.level standard/full)*
- [ ] No regressions introduced
- [ ] Code reviewed (via `/code-review` or documented peer review)
- [ ] Story file updated to `Status: Complete` (via `/story-done`)
@@ -265,6 +331,10 @@ Silently append to `production/session-state/active.md` (create the file if it d
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
- **Never write the plan without asking** — Phase 5 requires explicit approval.
- **Classify conservatively**: when a story is ambiguous between Logic and
Integration, classify it as Integration — it requires both unit and
+9 -1
View File
@@ -1,12 +1,16 @@
---
name: quick-design
description: "Lightweight design spec for small changes — tuning adjustments, minor mechanics, balance tweaks. Skips full GDD authoring when a system GDD already exists or the change is too small to warrant one. Produces a Quick Design Spec that embeds directly into story files."
description: "Lightweight spec for small changes — tuning adjustments, minor mechanics. Embeds directly into stories; skips full GDD."
argument-hint: "[brief description of the change]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
# Quick Design
This is the **lightweight design path** for changes that don't need a full GDD.
@@ -22,6 +26,10 @@ meaningful to implement without a written rationale.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## 1. Classify the Change
First, read the argument and determine which category this change falls into:
+69 -4
View File
@@ -1,12 +1,18 @@
---
name: regression-suite
description: "Map test coverage to GDD critical paths, identify fixed bugs without regression tests, flag coverage drift from new features, and maintain tests/regression-suite.md. Run after implementing a bug fix or before a release gate."
description: "Map test coverage to GDD critical paths, find fixed bugs lacking regression tests, flag drift from new features."
argument-hint: "[update | audit | report]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,qa.level,system_overrides`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
# Regression Suite
This skill ensures that every bug fix is backed by a test that would have
@@ -27,8 +33,30 @@ and known failure points. This skill maintains that list.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Workflow tier**: `modes.workflow` as resolved above — supplied by `modes.rigor`
unless set explicitly — per `.claude/docs/workflow-modes.md`; in `audit` mode consider
`workflow_overrides.system_overrides.<system>` per system as each GDD is read. It
sets whether GDD critical paths are mapped or coverage is smoke-only — see Step 2c.
**`qa.level`**: controls whether the suite is generated at
all. At `minimal`, the regression suite is **not generated** (report that and
stop); at `standard`, generate it at Polish-stage entry; at `full`, at
Production-stage entry. Distinct axis from `workflow`.
## 1. Parse Arguments
**Early `qa.level` guard (resolved above):** if `qa.level: minimal`, the
regression suite is **not generated** — report "Regression suite not generated at
qa.level minimal" and **STOP here, before any scan**, in every mode
(`update` / `audit` / `report`). This is the `qa.level` axis; it is distinct from
the `workflow`-tier `minimal` branch in Step 2c (which only changes the
critical-path *source*, not *whether* the suite runs). Do not enter Step 2c's
`minimal` branch on account of `qa.level`.
**Modes:**
- `/regression-suite update` — scan new bug fixes this sprint and check
for regression test presence; add new tests to the suite manifest
@@ -70,8 +98,21 @@ Do not read test file contents unless needed for name-to-test mapping.
### Step 2c — Load GDD critical paths
For `audit` mode: read `design/gdd/systems-index.md` to get all systems.
For each MVP-tier system, read its GDD and extract:
For `audit` mode: read `design/gdd/systems-index.md` to get all systems, then
scope the scan by each system's workflow tier (resolved above):
- **`full`** — read the GDD and map critical paths from all sections.
- **`standard`** — same, from the required sections (Acceptance Criteria, Edge
Cases, and Formulas where the system defines numeric rules).
A system pinned higher via `system_overrides` is mapped at its higher tier.
- **`minimal`** — **skip the GDD critical-path scan**. Instead read the latest
smoke-check report in `production/qa/smoke-*.md` and take the critical paths it
exercises as the regression scope (Step 3 maps coverage against those, not GDD
acceptance criteria). If no smoke report exists, report that and stop — there is
no critical-path source at minimal without one.
(Tier affects `audit` mode only; `update` and `report` modes are tier-independent.)
For each in-scope MVP-tier system's GDD, extract:
- Acceptance Criteria (these define the critical paths)
- Formulas section (formulas must have regression tests)
- Edge Cases section (known edge cases should have regression tests)
@@ -90,7 +131,9 @@ or `Status: Fixed` field. Note:
## 3. Map Coverage — Critical Paths
For `audit` mode only:
For `audit` mode only. (At `minimal` the critical paths come from the smoke-check
report identified in Step 2c, not from GDD acceptance criteria — map coverage
against those smoke paths and skip the GDD-criterion loop below.)
For each GDD acceptance criterion, determine whether a test exists:
@@ -179,6 +222,24 @@ Check for drift indicators:
### Suite manifest format (`tests/regression-suite.md`)
> **Before computing coverage, check the denominator.** If the GDD
> glob returns **zero critical paths**, or the test globs return **zero test
> files**, do not emit a percentage — report
> `Coverage: NOT ASSESSED — [no GDDs found | no test files found]` and name which
> side was empty and the skill that produces it (`/map-systems` and
> `/design-system` for GDDs, `/test-setup` for the test scaffold).
>
> A percentage computed from an empty denominator is not a low score; it is not a
> number. `0%` reads as "measured and terrible" and `100%` as "measured and
> perfect" — both are claims about a comparison that never happened. This is the
> same defect `/scope-check` carries a Phase 4 guard against, in the same words:
> *"a percentage computed from no baseline items is not a small number; it is not
> a number."*
>
> **A hand-written list of skills required to carry `NOT ASSESSED` pins what was
> known when it was written**, so a skill added later inherits no obligation and
> nothing notices. Derive that set rather than enumerating it.
The manifest is a curated index — not the tests themselves, but a registry
of which tests should always pass before a release:
@@ -245,6 +306,10 @@ Verdict: **COMPLETE** — regression suite updated. (If user declined write: Ver
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
- **Never remove existing regression tests from the manifest** without
explicit user approval — removing a test that was deliberately written is a
regression risk itself
+143 -10
View File
@@ -1,11 +1,60 @@
---
name: release-checklist
description: "Generates a comprehensive pre-release validation checklist covering build verification, certification requirements, store metadata, and launch readiness."
description: "Pre-release checklist — build verification, certification requirements, store metadata, launch readiness."
argument-hint: "[platform: pc|console|mobile|all]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys rigor,project.stage,cert_tier,automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Resolved above — use as-is. No block → defaults in `.claude/docs/config-resolution.md`.
**Scope this checklist to the project.** Emitting every item for every platform
trains the reader to skip the list, which defeats the gate:
- **`project.stage`** — items for phases this project has not reached are out of
scope; say so rather than listing them unchecked.
- **`modes.rigor`** — at `minimal`, drop items whose only justification is process
weight this project has opted out of.
- **`platform.cert_tier`** — emit certification items **only** for the tier the
project targets. If it is **unset**, **ask which platforms are in scope**
rather than emitting all of them — an unset value is a question, not a licence
to emit every certification track. If it cannot be determined, mark the section
**`NOT ASSESSED — cert tier unknown`**. **Unset is not `none`:** `none` is a
decision, unset is a missing one, and they must not produce the same output.
Branch on the **four values this key takes** — `none | itch | steam | console` —
and not on platform names; `.claude/docs/effects-map.md` holds the full
requirement table and is the source, so read it rather than restating it.
- `none` — **emit no certification section at all.** Internal release, alpha or
jam game. Say the section was omitted and why; do not leave it blank.
- `itch` — itch.io upload requirements only: build size, page setup, age tags.
**No console and no Steamworks items.**
- `steam` — Steamworks: store page, depot build, achievements, system
requirements, common content rules. **No console certification items.**
- `console` — full platform certification (TRC / XR / Lotcheck), save-data
rules, controller-mapping rules, age-rating boards. The heaviest tier.
> **Branch on the `cert_tier` values above, not on platform names.** "Emit
> console/mobile certification items only for the platforms the project targets"
> is the wrong test: it treats an `itch` project and a `steam` project
> identically, conflates `none` with unset, and keys on `mobile`, which is not a
> `cert_tier` value at all. Use the vocabulary the config defines.
If an item cannot be scoped because the config is absent, mark it
**`NOT ASSESSED — platform/stage unknown`**. Do not silently include it: a
`rigor: standard`, single-platform project would otherwise receive a ~150-item
checklist demanding PC **and** console **and** mobile certification plus age
ratings, of which ~140 are unassessable.
---
> **Explicit invocation only**: This skill should only run when the user explicitly requests it with `/release-checklist`. Do not auto-invoke based on context matching.
@@ -13,6 +62,16 @@ model: sonnet
Read the argument for the target platform (`pc`, `console`, `mobile`, or `all`). If no platform is specified, default to `all`.
**The argument selects DEVICE requirements. It never selects the certification
track.** Certification is decided by `platform.cert_tier`, resolved in the resolved-config block at the top of this skill —
see the `platform.cert_tier` rule above. The two axes are different lists that
happen to share one word: `pc`/`console`/`mobile` are hardware shapes, while
`none|itch|steam|console` are certification regimes. They agree on `console` and
nowhere else — `itch` and `none` have no device block at all, and `mobile` is not
a `cert_tier` value. So emitting a device block says nothing about which
certification block to emit, and `all` is **not** a licence to emit every
certification track.
---
## Phase 2: Load Project Context
@@ -24,6 +83,17 @@ Read the argument for the target platform (`pc`, `console`, `mobile`, or `all`).
## Phase 3: Scan Codebase
> **State the denominator with every count.** These scans look for something bad,
> so `0` means either "searched and found none" or "there was nothing to search",
> and on a release gate those are opposite findings. Report
> `scanned [N] source files: [M] TODO, [M] FIXME, [M] HACK` — or, when `src/` is
> absent or holds no source files,
> **`NOT ASSESSED — no source files found to scan`**. A bare `0` is not a result.
>
> `/launch-checklist` scans the same way and is most often run beside this one.
> Keep the two consistent: changing the rule in one and not the other leaves a
> route to the same misleading `0`.
Scan for outstanding issues:
- Count `TODO` comments
@@ -32,6 +102,9 @@ Scan for outstanding issues:
- Note their locations and severity
Check for test results in any test output directories or CI logs if available.
**If none are found, say so** — `Test results: NOT ASSESSED — no test output or
CI logs found` — rather than omitting the line. An absent test result and a
passing one must not produce the same release checklist.
---
@@ -75,7 +148,10 @@ Generated: [Date]
- [ ] Credits complete and accurate
```
Add platform-specific sections based on the argument:
Add **device** sections based on the argument. These carry no certification or
storefront-SDK items — those are gated on `platform.cert_tier` in the next
subsection, and duplicating them here is what let an `itch` project receive
Steamworks rows.
**For `pc`:**
```markdown
@@ -86,24 +162,16 @@ Add platform-specific sections based on the argument:
- [ ] Resolution scaling tested (1080p, 1440p, 4K, ultrawide)
- [ ] Windowed, borderless, and fullscreen modes working
- [ ] Graphics settings save and load correctly
- [ ] Steam/Epic/GOG SDK integrated and tested
- [ ] Achievements functional
- [ ] Cloud saves functional
- [ ] Steam Deck compatibility verified (if targeting)
```
**For `console`:**
```markdown
### Platform Requirements: Console
- [ ] TRC/TCR/Lotcheck requirements checklist complete
- [ ] Platform-specific controller prompts display correctly
- [ ] Suspend/resume works correctly
- [ ] User switching handled properly
- [ ] Network connectivity loss handled gracefully
- [ ] Storage full scenario handled
- [ ] Parental controls respected
- [ ] Platform-specific achievement/trophy integration tested
- [ ] First-party certification submission prepared
```
**For `mobile`:**
@@ -121,6 +189,71 @@ Add platform-specific sections based on the argument:
- [ ] App size within store limits
```
> **Mobile storefront rows stay here on purpose.** `platform.cert_tier` models
> `none|itch|steam|console` and has no mobile regime, so App Store / Play Store
> compliance cannot be gated on it. Leaving these in the device block is a
> deliberate choice, not an oversight — do not "fix" it by inventing a `mobile`
> tier, which is the exact wrong vocabulary the `cert_tier` rule warns against.
**Certification — emit ONLY the block matching `platform.cert_tier`** (resolved in
the resolved-config block at the top of this skill). Do not emit this subsection's other blocks, and do not fall back to
emitting all of them because the platform argument was `all`.
**At `none`** — emit no certification block at all. Emit exactly this one line in
its place, so the omission is visible rather than looking like a missing section:
```markdown
Certification: omitted — cert_tier is 'none' (internal build, alpha or jam release).
```
**At `itch`:**
```markdown
### Certification: itch.io
- [ ] Build size within itch.io upload limits
- [ ] itch.io page complete (cover art, screenshots, description)
- [ ] Age/content tags set honestly
- [ ] Downloadable vs browser build decided and tested
- [ ] Butler channel names correct for each platform uploaded
```
**At `steam`:**
```markdown
### Certification: Steamworks
- [ ] Steamworks SDK integrated and tested
- [ ] Depot build uploaded and installs cleanly from a fresh account
- [ ] Achievements functional
- [ ] Cloud saves functional
- [ ] Steam Deck compatibility verified (if targeting)
- [ ] Steam common content rules reviewed
```
**At `console`:**
```markdown
### Certification: Console
- [ ] TRC/TCR/Lotcheck requirements checklist complete
- [ ] First-party certification submission prepared
- [ ] Platform-specific achievement/trophy integration tested
- [ ] Parental controls respected
- [ ] Save-data rules compliant (corruption, full storage, user switching)
- [ ] Age ratings obtained (ESRB, PEGI, regional)
```
If `cert_tier` is **unset**, ask which platforms are in scope rather than
emitting every track; if it cannot be determined, emit
`### Certification: NOT ASSESSED — cert tier unknown` and say why. **Unset is not
`none`** — `none` is a decision and unset is a missing one.
> **Certification rows belong here, in one `cert_tier`-gated subsection.** Do not
> spread them back through the PC, Console and Mobile device blocks: those are
> selected by the command argument and default to `all`, so an `itch` project
> running `/release-checklist` with no argument would be handed the Steamworks SDK
> rows *and* the Lotcheck rows — exactly what the `cert_tier` rule at the top of
> this skill forbids.
>
> **`console` means two different things in this file.** It is a device-block
> argument value *and* a `cert_tier` value, colliding on one word out of four. A
> `**For \`console\`:**` heading is argument-gating, not tier-gating — do not read
> it as evidence that certification is already scoped by tier.
**Store and launch sections (all platforms):**
```markdown
### Store / Distribution
+39 -1
View File
@@ -1,12 +1,50 @@
---
name: retrospective
description: "Generates a sprint or milestone retrospective by analyzing completed work, velocity, blockers, and patterns. Produces actionable insights for the next iteration."
description: "Sprint or milestone retrospective from completed work, velocity, blockers. Actionable insights for the next iteration."
argument-hint: "[sprint-N|milestone-name]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Insufficient input — check this before producing any report
**If the inputs this skill needs do not exist, the answer is "could not run" —
not a filled-in report.** Check first, and stop if the check fails.
1. List the inputs this skill reads (data files, prior reports, profiler output,
test results, registries, source code).
2. For each, record `FOUND` or `ABSENT` — not "assumed present".
3. If any input required for a section is ABSENT, that section is
**`NOT ASSESSED — NO DATA`**. Do not estimate it, do not infer it from an
adjacent artifact, and do not leave a mandated cell to be filled by whoever
reads the template next.
4. If **every** required input is ABSENT, stop and report
**`NOT ASSESSED — NO DATA`** as the whole verdict, naming what was missing and
which skill produces it.
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
"what does the data say?" when there is no data. The failure mode this prevents is
specific and has been observed in practice: report templates whose verdict
enum had no "could not run" state produced **false clean passes** — an asset audit
returning COMPLIANT on a project with no assets and no standards, and a
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
profiler data and no budget ever set.
**Absence of evidence is never evidence of absence.** A scan that finds no
matches because there are no files to scan has not verified anything. Say which of
the two happened — a reader cannot tell from a green result.
---
## Phase 1: Parse Arguments
Determine whether this is a sprint retrospective (`sprint-N`) or a milestone retrospective (`milestone-name`).
+131 -7
View File
@@ -1,6 +1,6 @@
---
name: reverse-document
description: "Generate design or architecture documents from existing implementation. Works backwards from code/prototypes to create missing planning docs."
description: "Generate missing design or architecture docs from existing implementation — works backwards from code and prototypes."
argument-hint: "<type> <path> (e.g., 'design src/gameplay/combat' or 'architecture src/core')"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash
@@ -35,6 +35,30 @@ appropriate design or architecture documentation. Use this when:
- `src/core/event-system.cpp` → Specific file
- `prototypes/stealth-mech/` → Prototype directory
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys workflow,system_overrides,automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
**Resolve the workflow tier** for the target system: map `<path>` to a system
name, then use the `system_overrides` row for that system if the block above
lists one, else the project `workflow` value. It sets how much document is
generated — see Phase 5. Semantics of each tier are in
`.claude/docs/workflow-modes.md`.
> **Resolve the tier — do not assume it.** "Resolve the tier per
> `workflow-modes.md`" with no bootstrap names a resolution it gives no way to
> perform: that document defines what each tier *means*, but it cannot say what
> *this project* is set to. The consequence is large here — at `full` this skill
> writes an 8-section GDD and at `minimal` a one-page brief, so a wrong tier
> produces the wrong artifact entirely.
**Examples**:
```bash
/reverse-document design src/gameplay/magic-system
@@ -90,6 +114,35 @@ appropriate design or architecture documentation. Use this when:
- "The prototype emphasizes stealth over combat. Is that the intended pillar?"
- "Players seem to exploit the grappling hook for speed. Feature or bug?"
## Phase 3b: Sufficiency Check — is there enough here to document?
**Run this before Phase 4, and stop here if it fails.** This skill infers a
design from an implementation, so when the implementation is thin there is
nothing to infer *from* — and the template below will happily accept invented
content, because every section of it is mandatory.
Count what Phase 2 actually found:
| Signal | What counts |
|---|---|
| Mechanics | A named behaviour with observable rules — not a stub, not an empty class |
| Formulas | An expression computing a gameplay value from inputs |
| Values | A tuning constant with a use site |
**If all three counts are zero, or the target path holds fewer than ~20 lines of
non-boilerplate code, stop and say so:**
> "`[path]` does not contain enough implementation to reverse-document.
> Found: [N] mechanics, [N] formulas, [N] tuning values.
> Reverse-documentation infers design from behaviour; with no behaviour to read,
> anything I produce would be invention wearing the format of a design document.
> If the design exists only in your head, `/design-system [name]` is the skill
> that captures it — it asks rather than infers."
**Do not proceed on a partial count by filling the rest.** A path with two
mechanics and no formulas gets a document with two mechanics and an explicit
`FORMULAS DISCOVERED: none found in the source` — see Phase 4.
## Phase 4: Present Findings
Before drafting, show what you discovered:
@@ -115,8 +168,28 @@ UNCLEAR INTENT AREAS:
Before I draft the design doc, could you clarify these points?
```
> **Every section above may be empty, and an empty one must say so.** Write
> `none found in the source` under the heading — never omit the heading (which
> reads as "not looked for") and never populate it from what a system like this
> usually has. The bracketed rows are *shapes*, not quotas: a source with one
> mechanic yields one row, not four.
>
> This matters more here than in a report, because the output of this skill is not
> a report — it is a **design document**, and `/design-review`, `/create-epics` and
> `/create-stories` will read it as a statement of authored intent. A fabricated
> formula in a GDD does not stay a documentation error; it becomes a requirement,
> and then a story, and then code written to satisfy it.
Wait for user to clarify intent before drafting.
**If the user does not answer the `UNCLEAR INTENT AREAS` questions, do not draft
the resolved version anyway.** Those questions exist because **code cannot tell
you why** — it records what was built, never what was intended, and the gap
between them is the entire content of a design document. Unanswered items are
carried into the draft verbatim as open questions, in the document, marked
`INTENT UNKNOWN — inferred from implementation, not confirmed`. An inferred
intent presented as a settled one is the failure mode of this whole skill.
## Phase 5: Draft Document Using Template
Based on type, use appropriate template:
@@ -127,12 +200,51 @@ Based on type, use appropriate template:
| `architecture` | `templates/architecture-doc-from-code.md` | `docs/architecture/[decision-name].md` |
| `concept` | `templates/concept-doc-from-prototype.md` | `prototypes/[name]/CONCEPT.md` or `design/concepts/[name].md` |
**The `design` output scales with the workflow tier** (resolved in Phase 1):
- **`full`** — generate a full 8-section GDD.
- **`standard`** — generate a 5-section GDD (Overview, Detailed Design, Edge Cases,
Dependencies, Acceptance Criteria; + Formulas when the recovered system defines
numeric rules). Skip Player Fantasy and Tuning Knobs.
- **`minimal`** — generate a **game brief** in the one-page format
(`.claude/docs/templates/game-brief.md`), not a GDD. For the whole game write
`design/game-brief.md`; for a single reverse-engineered system write
`design/[system-name]-brief.md`.
(`architecture` and `concept` outputs are tier-independent.)
**Draft structure**:
- Capture **what exists** (mechanics, patterns, implementation)
- Document **why it exists** (intent clarified with user)
- Identify **what's missing** (edge cases not handled, gaps in design)
- Flag **follow-up work** (balance tuning, missing features)
### Stamp the provenance — required, at the top of every document this skill writes
A document produced here lands at the same path, in the same format, as one a
designer wrote by hand, and **every downstream consumer treats the two
identically**. `/design-review` checks it for completeness, `/create-epics`
derives epics from it, `/create-stories` turns its lines into acceptance
criteria. Nothing anywhere asks where it came from.
The difference is not cosmetic: an authored GDD states **intent**, and this one
states **observed behaviour plus inference**. When they disagree, the code is
what needs changing in the first case and the document in the second — and a
reader cannot tell which they are holding unless the document says.
Emit this immediately under the title:
```markdown
> **Reverse-documented from implementation** — generated by `/reverse-document`
> from `[path]` on `[date]`, at commit `[short-sha]`.
> This records what the code **does**; intent marked `INTENT UNKNOWN` below was
> inferred, not confirmed by the author. Where this document and the code
> disagree, do not assume the document is the requirement.
```
Keep the banner on revision. If a human later confirms the intent and adopts the
document as authored design, removing it is their explicit act — not a
side effect of the next edit.
## Phase 6: Show Draft and Request Approval
**Collaborative protocol**:
@@ -150,10 +262,22 @@ SECTIONS MARKED AS INCOMPLETE:
- "[System] interaction with [other-system]" (not fully implemented yet)
- "[Variant or feature]" (only [subset] implemented so far)
May I write this to design/gdd/[system-name].md?
May I write this to [output path]?
```
Wait for approval. User may request changes before writing.
Use the tier-correct output path in the prompt: `design/gdd/[system-name].md` for
a `full`/`standard` GDD, or `design/[system-name]-brief.md` for a `minimal` brief.
**At `collaborative`** — wait for approval; the user may request changes before
writing. **At `guided`** — this is a *new* file, so `automation-modes.md:81`
still has it asked ("May I write?" is asked for new files only); if the target
already exists, present the diff and proceed without waiting for an explicit
"yes". **At `autonomous`** — write and log the decision.
> **Keep this line scoped to its mode.** The skill header defers every file
> write to `automation-modes.md`, so an unconditional "wait for approval" here
> collides with it at both `guided` and `autonomous`. Same class as
> `/map-systems` Step 5b.
## Phase 7: Write Document with Metadata
@@ -200,11 +324,11 @@ Would you like me to tackle any of these now?
| If analyzing... | Use template... | Because... |
|----------------|-----------------|------------|
| `src/gameplay/*` | design-doc-from-implementation.md | Gameplay mechanics → GDD |
| `src/core/*`, `src/ai/*` | architecture-doc-from-code.md | Core systems → ADR |
| `<code root>/gameplay/*` | design-doc-from-implementation.md | Gameplay mechanics → GDD |
| `<code root>/core/*`, `<code root>/ai/*` | architecture-doc-from-code.md | Core systems → ADR |
| `prototypes/*` | concept-doc-from-prototype.md | Experiments → concept doc |
| `src/networking/*` | architecture-doc-from-code.md | Technical systems → ADR |
| `src/ui/*` | design-doc-from-implementation.md | UI/UX → design spec |
| `<code root>/networking/*` | architecture-doc-from-code.md | Technical systems → ADR |
| `<code root>/ui/*` | design-doc-from-implementation.md | UI/UX → design spec |
---
+156 -27
View File
@@ -1,12 +1,16 @@
---
name: review-all-gdds
description: "Holistic cross-GDD consistency and game design review. Reads all system GDDs simultaneously and checks for contradictions between them, stale references, ownership conflicts, formula incompatibilities, and game design theory violations (dominant strategies, economic imbalance, cognitive overload, pillar drift). Run after all MVP GDDs are written, before architecture begins."
description: "Holistic cross-GDD review — contradictions between systems, dominant strategies, economic imbalance, cognitive overload, pillar drift."
argument-hint: "[focus: full | consistency | design-theory | since-last-review]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion, Task
allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion, Agent
model: opus
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,system_overrides`
# Review All GDDs
This skill reads every system GDD simultaneously and performs two complementary
@@ -27,6 +31,10 @@ completeness. This skill reviews the *relationships* between all GDDs.
- Before `/create-architecture` begins (architecture built on inconsistent GDDs
inherits those inconsistencies)
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Argument modes:**
**Focus:** `$ARGUMENTS[0]` (blank = `full`)
@@ -38,6 +46,13 @@ completeness. This skill reviews the *relationships* between all GDDs.
---
**`workflow`** per GDD (per `.claude/docs/workflow-modes.md`): each GDD validates
against its effective tier — the project value, overridden per system by the
`system_overrides` row for that system when the block lists one. At `full`, validate all 8
sections across all GDDs. At `standard`, validate the 5 required sections;
optional sections (Player Fantasy, Tuning Knobs, conditional Formulas) are
surfaced as advisory only. At `minimal`, this skill is not applicable (no GDDs).
## Phase 1: Load Everything
### Phase 1a — L0: Summary Scan (fast, low tokens)
@@ -49,6 +64,14 @@ from all GDD files:
Grep pattern="## Summary" glob="design/gdd/*.md" output_mode="content" -A 5
```
**Fail open on a missing Summary.** Establish the denominator: glob
`design/gdd/*.md` and count **N**. A scan matching fewer than N means those GDDs
predate `## Summary` — never treat an absent Summary as a system out of scope.
A zero-match scan means "no GDD carries a Summary yet", not "nothing to review".
This review is holistic and loads its in-scope GDDs regardless (see Phase 1c);
the Summary scan only builds the manifest and narrows `since-last-review`, it
never shrinks the review set.
Display a manifest to the user:
```
Found [N] GDDs. Summaries:
@@ -57,10 +80,22 @@ Found [N] GDDs. Summaries:
...
```
For `since-last-review` mode: run `git log --name-only` to identify GDDs
modified since the last review report file was written. Show the user which
GDDs are in scope based on summaries before doing any full reads. Only
proceed to L1 for those GDDs plus any GDDs listed in their "Key deps".
For `since-last-review` mode, compute the scope deterministically instead of
reasoning through git history:
```
Bash: bash .claude/scripts/review-scope.sh
```
It prints `PRIOR_REVIEW:`, a `CHANGED:` list, and a `DEPS ...:` list of each
changed GDD's declared dependencies. Use those lists as the scope — the
dependency lines are already the "Key deps" expansion, so no second pass is
needed. If `PRIOR_REVIEW: NONE`, a full review is required; fall back to `full`
mode.
Show the user which GDDs are in scope based on summaries before doing any full
reads. Only proceed to L1 for the `CHANGED` set plus the GDDs named on the
`DEPS` lines.
### Phase 1b — Registry Pre-Load (fast baseline)
@@ -80,15 +115,38 @@ If the registry is empty or absent: proceed without it. Note in the report:
"Entity registry is empty — consistency checks rely on full GDD reads only.
Run `/consistency-check` after this review to populate the registry."
### Phase 1c — L1/L2: Full Document Load
### Phase 1c — L1/L2: Section Load
Full-read the in-scope documents:
Read whole (small, and every part is used):
1. `design/gdd/game-concept.md` — game vision, core loop, MVP definition
2. `design/gdd/game-pillars.md` if it exists — design pillars and anti-pillars
3. `design/gdd/systems-index.md` — authoritative system list, layers, dependencies, status
4. **Every in-scope system GDD in `design/gdd/`** — read completely (skip
game-concept.md and systems-index.md — those are read above)
Then, for **every in-scope system GDD**, load the sections this review actually
consumes — **not the whole file**:
```
Grep pattern="^## (Dependencies|Detailed Rules|Detailed Design|Formulas|Tuning Knobs|Acceptance Criteria|Player Fantasy)" glob="design/gdd/*.md" output_mode="content" -A 40
```
That list is not a guess — it is exactly the union the Parallel Execution
contract below already enumerates: Phase 2 needs Dependencies, Detailed
Design/Rules, Formulas, Tuning Knobs and Acceptance Criteria; Phase 3 needs
Player Fantasy and progression/reward structure. Overview is narrative restated
by the Summary this skill already scanned in Phase 1a, and Edge Cases feeds no
checklist item here (`/design-review` owns per-GDD completeness). Loading them
put content in three context windows — this one and both sub-agents' — that no
checklist item ever read.
Accept **either** `## Detailed Rules` or `## Detailed Design`; the design standard
and the GDD template disagree on the name and they denote the same section.
**Escalate to a full read of one GDD** when a scanned section cross-references
material outside itself, or when a GDD matched **zero** sections — that GDD
predates the template, and a zero-match there means "unstructured", not "empty".
Never let a zero-match silently drop a system: the scan narrows the *read*, it
never shrinks the *review set*.
Report: "Loaded [N] system GDDs covering [M] systems. Pillars: [list]. Anti-pillars: [list]."
@@ -101,17 +159,26 @@ If fewer than 2 system GDDs exist, stop:
### Parallel Execution
Phase 2 (Consistency) and Phase 3 (Design Theory) are independent — they read
the same GDD inputs but produce separate reports. Spawn both as parallel Task
the same GDD inputs but produce separate reports. Spawn both as parallel `Agent`
agents simultaneously rather than waiting for Phase 2 to complete before
starting Phase 3. Collect both results before writing the combined report.
**When spawning parallel Task agents for Phase 2 and Phase 3, always pass:**
- The complete list of GDD file paths loaded in Phase 1 (explicit paths, not just counts)
Spawn both as `game-designer` sub-agents (`subagent_type: game-designer`) — GDD
consistency and design-theory review is its domain.
**When spawning the Phase 2 and Phase 3 agents, always pass:**
- The loaded GDD **content** each phase needs — **not file paths**. Paste the
sections; the sub-agent has its own context and cannot re-read Phase 1's
results, so a path forces a full re-read (and contradicts the "do not re-read"
rule below). Pass only the phase's slice: Phase 2 (consistency) needs each GDD's
Dependencies, Detailed Design/Rules, Formulas, Tuning Knobs and Acceptance
Criteria; Phase 3 (design theory) needs Player Fantasy, progression/reward
structure and the game pillars.
- The full TR registry contents if loaded in Phase 1b (paste the registry text, not just a file path)
- The specific checklist items assigned to that agent's phase (Phase 2 gets 2a–2f; Phase 3 gets 3a–3g)
- The engine name and version from `.claude/docs/technical-preferences.md` and `docs/engine-reference/[engine]/VERSION.md`
- The engine name and version — `engine.name` and `engine.version` from `project.yaml`, resolving each field independently (if its key is absent or empty, use `.claude/docs/technical-preferences.md`) — plus `docs/engine-reference/[engine]/VERSION.md`
Do not rely on the subagent to re-read these files — it has its own context window and cannot access Phase 1 results unless they are explicitly passed in the Task prompt.
Do not rely on the subagent to re-read these files — it has its own context window and cannot access Phase 1 results unless they are explicitly passed in the `Agent` prompt.
---
@@ -158,6 +225,21 @@ Categories to scan:
### 2c: Stale References
**Start from the `## Cross-References` table where a GDD has one.** That table is
the document's own declaration of what it depends on — `templates/game-design-document.md`
tells authors it is machine-checked here, and `/design-system` requires it
whenever Dependencies names another GDD. For each row, confirm the `Target GDD`
exists and the `Specific Element Referenced` is still present in it under that
name, with the declared `Nature` still accurate.
A table that is absent, or still holding the template's bracketed examples, is
itself reportable: say the GDD declares no cross-references and that the prose
scan below was the only check applied. Do not treat an absent table as "no
dependencies" — it far more often means the section was never authored.
**Then scan the prose regardless**, table or no table: a declared table catches
what the author remembered, and the scan below catches what they did not.
For every cross-document reference (GDD-A mentions a mechanic, value, or
system name from GDD-B), verify the referenced element still exists in GDD-B
with the same name and behaviour:
@@ -538,16 +620,42 @@ Scenarios walked: [N]
---
### Verdict: [PASS / CONCERNS / FAIL]
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
PASS: No blocking issues. Warnings present but don't prevent architecture.
NOT ASSESSED: One or more review phases could not run — named below.
CONCERNS: Warnings present that should be resolved but are not blocking.
FAIL: One or more blocking issues must be resolved before architecture begins.
### If NOT ASSESSED — what could not be reviewed, and why:
[Name each phase that did not run and the input it needed]
### If FAIL — required actions before re-running:
[Specific list of what must change in which GDD]
```
**`NOT ASSESSED` — a cross-review is only as wide as what it could read.** Rank:
**above PASS**, **below CONCERNS and FAIL**. This skill's whole value is
comparing systems *against each other*, so it is unusually easy for it to look
thorough while covering a fraction of the surface. Emit it when any of:
- **Fewer than two GDDs were readable.** Contradiction-hunting across one document
is not a cross-review; a clean result there means only that nothing was
compared. This is the single most important trigger in this skill.
- **A whole review phase did not run** — consistency, design theory, economy,
pillar drift. A parallel phase that returned nothing has to be distinguished
from one that returned no findings; if a spawned agent produced no report, that
phase is NOT ASSESSED, not clean — an agent can return a fluent sentence,
write nothing, and consume a phase.
- **The design pillars are undefined**, so pillar-drift has no reference to drift
from — the same shape as an accessibility gate with no committed tier.
- **A GDD is present but empty** (headings only, or all placeholders). Present is
not the same as reviewable, and a stub contradicts nothing.
Report the covered set explicitly either way: `GDDs reviewed: [N] of [M] present`.
A cross-review that silently skipped half the systems is indistinguishable from
one that found them consistent.
---
## Phase 6: Write Report and Flag GDDs
@@ -556,6 +664,16 @@ Use `AskUserQuestion` for write permission:
- Prompt: "May I write this review to `design/gdd/gdd-cross-review-[date].md`?"
- Options: `[A] Yes — write the report` / `[B] No — skip`
> **`[date]` here means ISO 8601 — `YYYY-MM-DD`, e.g.
> `gdd-cross-review-2026-08-19.md`. This is not a style preference.**
> `.claude/scripts/review-scope.sh` picks the prior review with
> `sort | tail -1`, so lexical order IS chronological order only for ISO dates.
> Written as `aug-19-2026` or `19-08-2026`, the wrong file is chosen as the
> baseline, the changed-set is computed from it, and GDDs modified since the
> real last review silently escape the next one. That is the same
> quiet-escape failure the three fixes documented at the top of that script
> exist to prevent.
If any GDDs are flagged for revision, use a second `AskUserQuestion`:
- Prompt: "Should I update the systems index to mark these GDDs as needing revision? ([list of flagged GDDs])"
- Options: `[A] Yes — update systems index` / `[B] No — leave as-is`
@@ -569,8 +687,9 @@ After writing the report (and updating systems index if approved), silently
append to `production/session-state/active.md`:
## Session Extract — /review-all-gdds [date]
- Verdict: [PASS / CONCERNS / FAIL]
- GDDs reviewed: [N]
- Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
- GDDs reviewed: [N of M present]
- Phases not run: [names, or "None"]
- Flagged for revision: [comma-separated list, or "None"]
- Blocking issues: [N — brief one-line descriptions, or "None"]
- Recommended next: [the Phase 7 handoff action, condensed to one line]
@@ -606,26 +725,36 @@ Build the option list dynamically — only include options that apply:
Assign letters A, B, C… only to included options. Mark the most pipeline-advancing option as `(recommended)`.
Never end the skill with plain text. Always close with this widget.
In collaborative and guided modes, never end the skill with plain text — always
close with this widget. In autonomous mode, print the verdict and recommended
next step, then record via `log_decision` (no widget).
---
## Error Recovery Protocol
If any spawned agent returns BLOCKED, errors, or fails to complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "fails to complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" before continuing
2. **Assess dependencies**: If the blocked agent's output is required by a later phase, do not proceed past that phase without user input
3. **Offer options** via AskUserQuestion with three choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope (fewer GDDs, single-system focus)
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed so work is not lost
If any spawned agent returns BLOCKED, errors, or fails to complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report** (retry scope here = fewer GDDs / single-system). Full procedure:
`.claude/docs/error-recovery-protocol.md`.
---
## Collaborative Protocol
**In `collaborative` mode (the default).** For `guided` and `autonomous` modes,
see `.claude/docs/automation-modes.md`. In `autonomous` mode the
PASS/CONCERNS/FAIL verdict is still printed and logged — only the closing
handoff widget is skipped.
1. **Read silently** — load all GDDs before presenting anything
2. **Show everything** — present the full consistency and design theory analysis
before asking for any action
+32 -2
View File
@@ -1,6 +1,6 @@
---
name: scope-check
description: "Analyze a feature or sprint for scope creep by comparing current scope against the original plan. Flags additions, quantifies bloat, and recommends cuts. Use when user says 'any scope creep', 'scope review', 'are we staying in scope'."
description: "Scope creep check — current scope versus the original plan. Flags additions, quantifies bloat, recommends cuts. 'Any scope creep?'"
argument-hint: "[feature-name or sprint-N]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash
@@ -56,6 +56,13 @@ Generated: [Date]
### Current Scope
[List of items currently implemented or in progress]
> **If Phase 4 will return NOT ASSESSED, do not render the numeric block below.**
> Replace the counts and the Bloat Score with
> `Baseline unusable — see verdict` and give the reason. A rendered
> `Original items: 0 / Net scope change: 0%` one section above a NOT ASSESSED
> verdict re-creates the exact "0% reads as on track" hazard Phase 4 exists to
> kill, one phase earlier — and readers trust a number over a caveat.
### Scope Additions (not in original plan)
| Addition | Source | When | Justified? | Effort |
|----------|--------|------|------------|--------|
@@ -98,11 +105,30 @@ Assign a canonical verdict based on net scope change:
| 25–50% | **FAIL** | Significant Creep — must cut or formally extend timeline |
| >50% | **FAIL** | Out of Control — stop, re-plan, escalate to producer |
**Before applying that table, check that the percentage means something.** Emit
**NOT ASSESSED** instead — never a computed percentage — when any of:
- The **baseline document exists but enumerates no scope items** (all headings,
placeholders, or `[TO BE CONFIGURED]`). Phase 1 stops when the file is *absent*;
this is the case where it is present and empty, and it is the more dangerous
one, because zero items yields a 0% net change that renders as **PASS — On
Track**. Nothing was compared. Nothing was on track.
- The **current state cannot be determined** — no related source files, no commits
in the window, nothing in progress to read. Comparing a real baseline against an
unreadable present is not a 0% change.
- The denominator would be zero for any other reason. A percentage computed from
no baseline items is not a small number; it is not a number.
`NOT ASSESSED` **outranks PASS** (a comparison that never happened has not shown
scope is on track) and **ranks below CONCERNS and FAIL** (measured creep is more
actionable than an unmeasurable baseline).
Output the verdict prominently:
```
**Scope Verdict: [PASS / CONCERNS / FAIL]**
**Scope Verdict: [PASS / CONCERNS / NOT ASSESSED / FAIL]**
Net change: [+X%] — [On Track / Minor Creep / Significant Creep / Out of Control]
[or: NOT ASSESSED — [which side could not be read, and why]]
```
---
@@ -112,6 +138,10 @@ Net change: [+X%] — [On Track / Minor Creep / Significant Creep / Out of Contr
After presenting the report, offer concrete follow-up:
- **PASS** → no action required. Suggest re-running before next milestone.
- **NOT ASSESSED** → say which side was unreadable and what would fix it (populate
the baseline document, or point the skill at where the work actually lives).
Do not offer a re-run against the same inputs — it will produce the same
non-answer.
- **CONCERNS** → offer to identify the 2–3 additions with best cut ratio. Reference `/sprint-plan update` to formally re-scope.
- **FAIL** → recommend escalating to producer. Reference `/sprint-plan update` for re-planning or `/estimate` to re-baseline timeline.
+117 -14
View File
@@ -1,13 +1,20 @@
---
name: security-audit
description: "Audit the game for security vulnerabilities: save tampering, cheat vectors, network exploits, data exposure, and input validation gaps. Produces a prioritised security report with remediation guidance. Run before any public release or multiplayer launch."
description: "Security audit — save tampering, cheat vectors, network exploits, data exposure, input validation. Before public or multiplayer release."
argument-hint: "[full | network | save | input | quick]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write, Task
allowed-tools: Read, Glob, Grep, Bash, Write, Agent
model: sonnet
agent: security-engineer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Security Audit
Security is not optional for any shipped game. Even single-player games have
@@ -36,19 +43,46 @@ remediation plan.
- `quick` — high-severity checks only (fastest, for iterative use)
- No argument — run `full`
Read `.claude/docs/technical-preferences.md` to determine:
- Engine and language (affects which patterns to search for)
- Target platforms (affects which attack surfaces apply)
- Whether multiplayer/networking is in scope
Read `project.yaml` to determine the following, falling back to `.claude/docs/technical-preferences.md` for engine/language/platforms when a key is absent or empty:
- `engine.name` and `engine.language` — **load-bearing: they select the Phase 3
pattern set, and an engine with no sourced set for a category forces
`NOT ASSESSED` for it.** If `engine.name` is absent or empty, say so in the
report and treat every grep category as `NOT ASSESSED`; do not fall back to
the Godot lists because they are the ones written out in full
- `platform.targets` (affects which attack surfaces apply)
- `platform.multiplayer` and `platform.online` — whether multiplayer/networking is
in scope. `technical-preferences.md` has no equivalent fields, so the legacy
fallback cannot supply them.
> **ABSENT DOES NOT MEAN `false`.** These keys have a reader —
> this skill — and **no writer anywhere in the framework**: neither
> `/setup-engine` nor `/start` nor any other skill emits a `platform:` block,
> so on essentially every CCGS project both keys are absent. The previous rule
> here defaulted them to `false`, which meant **Category 2 (Network and
> Multiplayer Security) was skipped on every project including genuinely
> multiplayer ones** — a security category failing open on a value nothing
> sets.
>
> When either key is absent or empty: **do not assume single-player, and do not
> skip Category 2.** Ask the user whether the game has multiplayer or online
> features. If you cannot ask, run Category 2 anyway and mark it
> `NOT ASSESSED — multiplayer scope unconfirmed (platform.multiplayer unset,
> and no skill sets it)`, which makes `CLEAR TO SHIP` unreachable per Phase 5.
> Over-scanning a single-player game costs a few minutes; under-scanning a
> multiplayer one ships the category unrun.
>
> Set them explicitly with `/settings platform.multiplayer=true` (they are
> project-wide, so `--local` is refused). Recording it in `project.yaml` is the
> fix; this rule is the guard for until someone does.
---
## Phase 2: Spawn Security Engineer
Spawn `security-engineer` via Task. Pass:
Spawn `security-engineer` via `Agent`. Pass:
- The audit scope/mode
- Engine and language from technical preferences
- A manifest of all source directories: `src/`, `assets/data/`, any config files
- Engine and language (from `project.yaml`, else technical preferences)
- A manifest of all source directories: the resolved **code root** (per `.claude/docs/code-root-resolution.md`), `assets/data/`, any config files
The security-engineer runs the audit across 6 categories (see Phase 3). Collect their full findings before proceeding.
@@ -58,6 +92,39 @@ The security-engineer runs the audit across 6 categories (see Phase 3). Collect
The security-engineer evaluates each of the following. Skip categories not applicable to the project scope.
### Engine pattern sets — read this before any Category below
**Every pattern list in Categories 1–3 was written for Godot.** On a Unity or
Unreal project they match nothing, and this skill already states what a zero-hit
scan means: it renders the report clean, "the most dangerous possible failure for
a security audit". That warning was earned along the **version** axis
(`File.open` vs `FileAccess`) and the identical hole along the **engine** axis
shipped anyway. Use the table for `engine.name` resolved in Phase 1.
| Category | Godot | Unity | Unreal |
|---|---|---|---|
| 1 — Save / serialization | the Godot list below | **NOT SOURCEABLE** | **NOT SOURCEABLE** |
| 2 — Network / multiplayer | the Godot list below | `ServerRpc`, `ClientRpc`, `NetworkVariable`, `NetworkObject`, `NetworkManager`, `NetworkBehaviour`, `IsServer`, `IsOwner` | `UFUNCTION`, `Server`, `Client`, `NetMulticast`, `Replicated`, `DOREPLIFETIME`, `GetLifetimeReplicatedProps`, `HasAuthority` |
| 3 — Input | the Godot list below | `InputSystem`, `PlayerInput`, `ReadValue`, `InputValue` | `EnhancedInput`, `UInputAction`, `InputMappingContext`, `BindAction`, `FInputActionValue` |
| 4 — Data exposure | engine-agnostic — the list below applies to all three | | |
| 5, 6 | judgement and manifests, not greps — no engine set needed | | |
The Unity and Unreal names above are **sourced from this repo's pinned
references** (`docs/engine-reference/unity/modules/{networking,input}.md`,
`docs/engine-reference/unreal/modules/{networking,input}.md`), not from recall.
Verify them against the pin before use and add what the reference documents that
this table omits — it is a floor, not a complete set.
> **`NOT SOURCEABLE` is a verdict, not a gap to fill from memory.** Neither
> reference tree carries a serialization/save module, so the save-API names for
> Unity and Unreal cannot be confirmed here. **Do not write them from training
> data.** A confidently wrong pattern list is worse in this skill than in any
> other: it produces a scan that looks thorough, finds nothing, and reads as a
> pass. Where the table says NOT SOURCEABLE, that category is **`NOT ASSESSED`**
> for this engine — see Phase 5. To close it properly, add the module to
> `docs/engine-reference/<engine>/` first; then this table can cite it.
### Category 1: Save File and Serialization Security
- Are save files validated before loading? (no blind deserialization)
- Are save file paths constructed from user input? (path traversal risk)
@@ -65,7 +132,22 @@ The security-engineer evaluates each of the following. Skip categories not appli
- Does the game trust numeric values from save files without bounds checking?
- Are there any eval() or dynamic code execution calls near save loading?
Grep patterns: `File.open`, `load`, `deserialize`, `JSON.parse`, `from_json`, `read_file` — check each for validation.
Grep patterns — **check the pinned engine reference before trusting this list**
(see the API-name warning below): `FileAccess`, `File.open`, `open(`, `load`,
`deserialize`, `parse`, `parse_string`, `from_json`, `read_file`, `get_var`,
`bytes_to_var` — check each for validation.
> **API names are version-specific and this list is a starting point, not a
> complete set.** `File.open` is **Godot 3.x**; Godot 4 renamed the class to
> `FileAccess` (`docs/engine-reference/godot/breaking-changes.md`). Before relying
> on these patterns, read `docs/engine-reference/<engine>/` for the version this
> project pins and add the names it documents. A grep for a class that no longer
> exists returns zero hits, and **zero hits in this category renders the report
> clean** — which is the most dangerous possible failure for a security audit.
> Searching only `File.open` against a Godot 4 project finds nothing and reports
> CLEAR TO SHIP on a codebase nobody checked. If you cannot confirm the correct
> names for the pinned version, say so in the report rather than presenting a
> zero-hit scan as a pass.
### Category 2: Network and Multiplayer Security (skip if single-player only)
- Is game state authoritative on the server, or does the client dictate outcomes?
@@ -75,7 +157,14 @@ Grep patterns: `File.open`, `load`, `deserialize`, `JSON.parse`, `from_json`, `r
- Are authentication tokens handled correctly (never sent in plaintext)?
- Does the game expose any debug endpoints in release builds?
Grep for: `recv`, `receive`, `PacketPeer`, `socket`, `NetworkedMultiplayerPeer`, `rpc`, `rpc_id` — check each call site for validation.
Grep for: `recv`, `receive`, `PacketPeer`, `socket`, `MultiplayerPeer`,
`ENetMultiplayerPeer`, `NetworkedMultiplayerPeer`, `rpc`, `rpc_id`,
`@rpc` — check each call site for validation.
> Same version caveat as Category 1. `NetworkedMultiplayerPeer` is **Godot 3.x**;
> Godot 4 uses `ENetMultiplayerPeer`
> (`docs/engine-reference/godot/modules/networking.md`). The bare substring
> `MultiplayerPeer` matches both and is the safer probe.
### Category 3: Input Validation
- Are any player-supplied strings used in file paths? (path traversal)
@@ -86,7 +175,7 @@ Grep for: `recv`, `receive`, `PacketPeer`, `socket`, `NetworkedMultiplayerPeer`,
Grep for: `get_input`, `Input.get_`, `input_map`, user-facing text fields — check validation.
### Category 4: Data Exposure
- Are any API keys, credentials, or secrets hardcoded in `src/` or `assets/`?
- Are any API keys, credentials, or secrets hardcoded in the code root or `assets/`?
- Are debug symbols or verbose error messages included in release builds?
- Does the game log sensitive player data to disk or console?
- Are any internal file paths or system information exposed to players?
@@ -148,7 +237,21 @@ For each finding, assign:
| MEDIUM | [N] | Recommended |
| LOW | [N] | Optional |
**Release recommendation**: [CLEAR TO SHIP / FIX CRITICALS FIRST / DO NOT SHIP]
**Release recommendation**: [NOT ASSESSED — INSUFFICIENT IMPLEMENTATION / CLEAR TO SHIP / FIX CRITICALS FIRST / DO NOT SHIP]
> **`NOT ASSESSED` is required when there was not enough implemented surface to
> audit**, or when the API names for the pinned engine version could not be
> confirmed. A zero-finding scan over two files of source is not a clean bill of
> health, and `CLEAR TO SHIP` must never be reachable by having nothing to look
> at. Name what was missing and which skill produces it.
>
> **The engine axis is part of that rule, not a separate one.** If
> the Phase 3 table marks a category `NOT SOURCEABLE` for this project's
> `engine.name`, that category is `NOT ASSESSED` — state it by name in the
> Executive Summary, and **`CLEAR TO SHIP` is unreachable for the run**. Report
> `NOT ASSESSED — <category> has no sourced pattern set for <engine>` instead.
> A scan that could not look is not a scan that found nothing, and only the
> report can tell the reader which of the two happened.
---
+459
View File
@@ -0,0 +1,459 @@
---
name: settings
description: "View or change project config — effective merged values, or set locally in project.local.yaml."
argument-hint: "[key | key=value | --local key=value]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion
model: sonnet
---
# /settings — view or change project config
Manages `project.yaml` (team-wide config, committed) and `project.local.yaml`
(per-developer overrides, gitignored). Use this skill to inspect current
settings or change them without manually editing YAML.
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). The approval gates in Phase 4 and
Phase 5 follow the pattern in `.claude/docs/automation-modes.md`. **Note**:
writing to `project.yaml` is a `schema_changes` decision (a default
`automation_always_ask` category), so `/settings` confirms config writes even
in `autonomous` mode unless the user has removed `schema_changes` from their
always-ask list.
## Phase 0: Parse Arguments
Determine which of the four forms the user invoked:
| Form | Mode |
|------|------|
| `/settings` (no args) | **View-all** (Phase 2) |
| `/settings <key>` (single arg, no `=`) | **View-one** (Phase 3) |
| `/settings <key>=<value>` (single arg with `=`) | **Set-yaml** (Phase 4) |
| `/settings --local <key>=<value>` (`--local` prefix) | **Set-local** (Phase 5) |
For Set-yaml and Set-local, `<key>` is a dotted YAML path (e.g.
`modes.review_mode`, `testing.strict.logic`) and `<value>` is the new value.
**Empty-operand validation:** After splitting the `key=value` operand on
`=`, if either `<key>` or `<value>` is empty, this is malformed — route to
Phase 6 (usage) rather than attempting the write. The rule applies in both
Set-yaml and Set-local routing: for `--local`, strip the `--local` token
first, then check the remaining operand the same way (so `/settings --local =foo`
and `/settings --local key=` both go to Phase 6).
Anything else that doesn't match the four forms above → Phase 6 (usage).
## Phase 1: Load Helper
All four subcommands need `yaml-helper.sh`. Source it once via Bash:
```bash
source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh"
```
If `.claude/hooks/yaml-helper.sh` is missing, this is not a CCGS project.
Report the error and exit.
## Phase 1b: Reserved-setting detection
Some settings are fully documented, enum-validated and settable, and **no skill
or hook reads them** — setting one changes nothing. **This skill must say so.**
Returning an ordinary success lets a user reasonably believe the behaviour the
setting describes is now enforced — an accessibility tier being the case that
motivates this. (The key is not named here on purpose; see the note below.)
The banner exists only in
`.claude/docs/effects-map.md`, which someone
configuring their project will never open. A setting that does nothing must never look
exactly like one that works — `.claude/rules/skill-authoring.md` obligation 3.
Derive the set; do not hardcode it (obligation 5):
```bash
grep -B14 '^> ### RESERVED' .claude/docs/effects-map.md | grep -E '^## '
```
**Match the banner HEADING (`> ### RESERVED`), never the bare word "RESERVED".**
`platform.cert_tier`'s section *mentions* the banner in prose, to record that it
carried one and later became a live setting. A looser match re-reports a working
setting as dead — the direction that understates what the framework does, and
why the dead-settings gate asserts both directions.
A heading may name **two keys joined by " and "** — split on that separator so
both are captured, or the second one silently escapes the set. Let
`RESERVED_SET` be the result.
> Deliberately phrased without naming those keys. The dead-settings gate asserts
> that a setting on the allowlist has **no** readers, and it counts any skill
> file that spells the key. Naming them here to illustrate the split would make
> `/settings` register as a reader of two settings nothing reads, and the gate
> would fail — correctly. Spelling a dead path out while explaining why not to
> use it trips the same wire. Reword instead of adding an exemption: the
> strictness is the point, so do not re-introduce the literal names to make an
> example clearer.
Never refuse a write to a reserved key. Storing the value a user intends is
legitimate; storing it *silently* is the defect.
## Phase 2: View-all Mode
(when no arguments)
1. Confirm `project.yaml` exists. If missing, report:
> "No `project.yaml` found — run `/start` to create one."
And exit.
2. Check if `project.local.yaml` exists.
3. Run `validate_yaml_enum project.yaml` and capture any errors.
If `project.local.yaml` exists, also run `validate_yaml_enum project.local.yaml`.
Tag each error with its source file so the user can tell them apart.
4. **Enumerate leaves.** Use the `Read` tool to read both YAML files as
text. Walk through each file's structure and collect every leaf key
into a deduplicated list of dotted paths. A leaf is a `key: value`
line whose value is non-empty (a scalar or inline-array) — NOT a
parent block that introduces a nested map. Maintain insertion order
per file; merge by appending leaves from `project.local.yaml` that
aren't already present from `project.yaml`. The resulting list is
the set of leaves to display.
**Then append the rigor family** — `modes.rigor`, `modes.workflow`,
`docs.density`, `qa.level`, `modes.story_granularity`, `modes.review_mode`,
`team.size` — for any of the seven the merged list does not already
contain. These are normally leaves of neither file: `modes.rigor` has a
terminal default and the other six are supplied by the rigor expansion
(`modes.review_mode` and `team.size` may also appear as file leaves when set
locally, but must still be appended so their *derived* value shows). Enumerating
only file leaves would hide exactly the settings a user just chose, in the one
view meant to show them.
5. **For each leaf**, perform three reads and one check:
- `resolve_setting <path>` → `<value>`, TAB, `<source>`. This walks the
whole chain (`project.local.yaml` → `project.yaml` → legacy file →
`rigor` expansion → default), so it is the only read that can report
a derived value or name what supplied it.
- `get_yaml_key project.yaml <path>` → yaml-only value (needed only to
show what a local override is shadowing)
- `is_locally_overridable <path>` → 0 (overridable) or 1 (locked)
Compute the **source annotation** from `<source>`:
| `<source>` | Annotation |
|---|---|
| `project.local.yaml`, yaml-only value non-empty | `(LOCAL OVERRIDE — yaml has: <yamlvalue>)` |
| `project.local.yaml`, yaml-only value empty | `(project.local.yaml)` |
| `project.yaml` | `(project.yaml)` |
| a legacy file path (e.g. `production/review-mode.txt`) | `(<path>, legacy)` |
| `rigor:<level>` | `(derived from rigor: <level>)` |
| `default` | `(default)` |
| `unset` | skip the leaf (don't print unset keys) |
Append `, locked` to the annotation when `is_locally_overridable`
returned 1.
**Append `, reserved` when the leaf is in `RESERVED_SET` (Phase 1b)**, and
print this line with the legend below the block:
```
reserved = stored and validated, but nothing reads it. Setting it changes
no behaviour today.
```
> **All four phases must carry the reserved marking — view-one, view-all,
> and both write paths.** Marking view-one and the writes while leaving
> view-all — **the most-used form of this skill** — unmarked means a user who
> set a reserved key sees it listed beside working settings with an ordinary
> `(project.yaml)` annotation, in the view most people actually run. Guard
> all four: view-one and view-all are twins in exactly the way the two write
> paths are.
6. **Print**, grouped by top-level section (`framework`, `modes`,
`engine`, etc.) in the order leaves first appeared. The grouping is
determined by the dotted path, not by which file the leaf came from
— e.g. `modes.automation` groups under `modes:` even if only
`project.local.yaml` defines it. Within each section, indent leaves
by 2 spaces; nest further for sub-blocks (e.g. `testing.strict.*`).
Example output:
```
project.yaml: present
project.local.yaml: present
Schema validation: ok
Effective config:
framework:
version: 1.1.0 (project.yaml, locked)
modes:
review_mode: lean (project.yaml)
automation: autonomous (LOCAL OVERRIDE — yaml has: collaborative)
rigor: full (project.yaml, locked)
workflow: full (derived from rigor: full, locked)
story_granularity: fine (derived from rigor: full, locked)
docs:
density: terse (project.yaml, locked)
qa:
level: full (derived from rigor: full, locked)
engine:
name: Godot (project.yaml, locked)
version: 4.6 (project.yaml, locked)
testing:
strict:
logic: false (LOCAL OVERRIDE — yaml has: true)
integration: true (project.yaml)
locked = cannot be overridden in project.local.yaml (project-wide setting).
It does NOT mean fixed: a derived value can still be set explicitly with
/settings <key>=<value>, and an explicit value wins over rigor.
```
Print that two-line legend after the config block whenever any rendered
line carries `locked`. Without it users read `locked` as "immutable" and
conclude a rigor-derived knob cannot be changed — the opposite of what
Phase 3's view-one tells them for the same knob ("an explicit value wins
over rigor"). The two views must not leave contradictory impressions of
the same knob's mutability.
The `docs.density` line above is the precedence rule made visible: an
explicit `project.yaml` value keeps winning over the level `rigor` would
otherwise derive, so "comprehensive but compact" stays expressible.
If schema errors exist, print them in this form before the effective
config block:
```
Schema validation: ERRORS
[project.yaml] modes.review_mode: 'chaotic' is not a valid value (expected: full|lean|solo)
[project.local.yaml] engine.name: 'Pygame' is not a valid value (expected: Godot|Unity|Unreal)
```
## Phase 3: View-one Mode
(when single arg, no `=`)
**If `<key>` is in `RESERVED_SET`, print this BEFORE the value block** — above,
not below. A caveat under a value reads as a footnote on a working setting:
> **`<key>` is RESERVED — nothing reads it.** The value below is stored and
> validated; it changes no behaviour today.
Let `<key>` be the argument. Perform four reads:
1. `resolve_setting <key>` → `<value>`, TAB, `<source>` (effective value + provenance)
2. `get_yaml_key project.yaml <key>` → yaml-only value
3. `get_yaml_key project.local.yaml <key>` → local-only value (skip if file absent)
4. `is_locally_overridable <key>` → 0 (overridable) or 1 (locked)
Determine the **source** from `<source>` (same table as Phase 2 step 5)
and the **Locally overridden** status:
- `yes` if the local-only value is non-empty
- `no` otherwise
Print:
```
<key>
Effective value: <effective-value or "(not set)" if <source> is unset>
Source: <project.yaml | project.local.yaml | project.local.yaml (overrides project.yaml) | derived from rigor: <level> | default>
Locally overridden: <yes | no>
Whitelist: <"can be locally overridden" if is_locally_overridable returned 0, else "locked — project-wide">
```
When both files set the key (the LOCAL OVERRIDE case), add two more
lines under Source:
```
project.yaml value: <yamlvalue>
project.local.yaml value: <localvalue>
```
When `<source>` is `rigor:<level>`, add one line under Source so the user
knows the value is settable and how:
```
Set explicitly with: /settings <key>=<value> (an explicit value wins over rigor)
```
When the effective value is empty (key not set anywhere), print just:
```
<key>
Effective value: (not set)
Locally overridden: no
Whitelist: <"can be locally overridden" | "locked — project-wide">
```
## Phase 4: Set-yaml Mode
(when `<key>=<value>`, no `--local`)
1. **Schema validation**: call `validate_enum_value <key> <value>`. If
it returns 1, the stderr line is shown to the user verbatim
(`Invalid value '<value>' for '<key>'. Allowed: ...`) and the skill
exits without writing. If it returns 0, the value is either valid
or the key has no enum constraint — proceed.
2. **Reserved warning**: if `<key>` is in `RESERVED_SET` (Phase 1b), print
BEFORE the approval prompt:
> "Note: `<key>` is RESERVED — no skill or hook reads it, so setting it will
> not change any behaviour. Your value is stored either way."
Then continue to the approval gate as normal. Phase 5 carries the identical
warning. Warning on one write path and not the other leaves a silent route
to the same outcome, which is the whole failure this guards against.
3. **Shadow warning**: read `get_yaml_key project.local.yaml <key>`. If
it returns a non-empty value, print BEFORE the approval prompt:
> "Note: this setting is currently locally overridden in `project.local.yaml` (value: `<localvalue>`). Writing to `project.yaml` will not change your effective value."
4. **Approval gate**: use `AskUserQuestion`:
- Prompt: ``Set `<key>=<value>` in `project.yaml`?``
- Options: `[A] Yes, write` / `[B] No, cancel`
5. **Write** using the `Edit` tool. The edit strategy depends on what
already exists in `project.yaml`:
**Case A — key exists**: Read `project.yaml`. Locate the line
`<lastsegment>: <oldvalue>` and the line immediately above it that
introduces its parent block (e.g. `modes:` for `modes.review_mode`).
Construct the `Edit` with `old_string` that includes the parent
block line PLUS the leaf line, so the match is unique even if
`<lastsegment>: <oldvalue>` appears elsewhere. Example for
`modes.review_mode=full`:
```
old_string:
modes:
review_mode: lean
new_string:
modes:
review_mode: full
```
**Case B — parent block exists, leaf doesn't**: Find the last line
of the parent block. Use `Edit` to append the new leaf line at the
correct indentation, using the last existing leaf as the `old_string`
anchor.
**Case C — parent block doesn't exist**: Append a new top-level
block at end-of-file (deterministic — always end-of-file, never
between blocks). Use `Edit` with the last non-empty line of the
file as `old_string` and append the new block after it.
**Case D — file structure is unusual** (commented-out keys with the
same name, ambiguous nesting, malformed YAML): STOP and ask via
`AskUserQuestion`:
> "Couldn't find a clean insertion point for `<key>` in `project.yaml`. Show me what to do."
6. Confirm: ``Set `<key>=<value>` in `project.yaml`.``
**When `<key>` is `modes.rigor`**, the write also moves six other
knobs, so print what they resolve to now — re-read each with
`resolve_setting` rather than reciting the expansion table, since any
of them may carry an explicit value that still wins:
```
Set modes.rigor=full in project.yaml. It now supplies:
modes.workflow: full (derived from rigor: full)
docs.density: terse (project.yaml — explicit, unchanged)
qa.level: full (derived from rigor: full)
modes.story_granularity: fine (derived from rigor: full)
modes.review_mode: full (derived from rigor: full)
team.size: studio (derived from rigor: full)
```
## Phase 5: Set-local Mode
(when `--local <key>=<value>`)
1. **Whitelist check**: call `is_locally_overridable <key>`.
- If it returns 1 (locked), print one line:
> ``<key> cannot be locally overridden — it's a project-wide setting. Use `/settings <key>=<value>` (no `--local`) to change it for the whole team.``
- Exit without writing.
2. **Schema validation**: call `validate_enum_value <key> <value>`. If
it returns 1, show the stderr message verbatim and exit without
writing.
2b. **Reserved warning**: if `<key>` is in `RESERVED_SET` (Phase 1b), print
BEFORE the approval prompt:
> "Note: `<key>` is RESERVED — no skill or hook reads it, so setting it will
> not change any behaviour. Your value is stored either way."
Identical to Phase 4 step 2, and deliberately so. Both write paths reach the
same file-of-record for a user's intent; warning on one only would leave
`--local` as the silent route.
3. **Base check**: if `project.yaml` doesn't exist:
> "Cannot create `project.local.yaml` — `project.yaml` is missing. Run `/start` to create one first."
Exit. (Local overrides require a base, per spec.)
4. **Approval gate**: use `AskUserQuestion`:
- Prompt: ``Set `<key>=<value>` in `project.local.yaml` (your personal override, gitignored)?``
- Options: `[A] Yes, write` / `[B] No, cancel`
5. **Write**:
- If `project.local.yaml` doesn't exist, use `Write` to create it
with the new setting wrapped in its parent block(s). Minimal
example for `--local modes.automation=autonomous`:
```yaml
# project.local.yaml — per-developer overrides (gitignored)
modes:
automation: autonomous
```
- If it exists, use `Edit` with the same Case A/B/C strategy from
Phase 4 step 4.
6. Confirm: ``Set `<key>=<value>` in `project.local.yaml` (your override).``
## Phase 6: Usage
When the argument doesn't match any of the four valid forms (or has
empty operands), print:
```
Usage:
/settings — view all effective config
/settings <key> — view a single setting
/settings <key>=<value> — change a setting (project.yaml)
/settings --local <key>=<value> — change a setting locally
(project.local.yaml, gitignored)
Examples:
/settings modes.review_mode
/settings modes.review_mode=full
/settings --local modes.automation=autonomous
```
## Notes
- All YAML writes go through `Edit` (existing keys/blocks) or `Write`
(new files). The skill does not depend on `yq` or any external YAML library.
- The whitelist is enforced in `yaml-helper.sh`
(`is_locally_overridable` function). To extend it, edit the
`_yaml_helper_locally_overridable` constant — do not duplicate the list here.
- **Derived values are not stored anywhere.** `modes.workflow`, `docs.density`,
`qa.level`, `modes.story_granularity`, `modes.review_mode` and `team.size` have no
terminal default; when no file sets them their value comes from the `modes.rigor`
expansion in `yaml-helper.sh`
(`_yaml_helper_rigor_expansion`). Report them via `resolve_setting` — a
`get_yaml_key` read returns empty and would render them "(not set)" while every
skill is in fact acting on a real value.
- The schema-validation enum constants are in `yaml-helper.sh`
(`_yaml_helper_enums`). `validate_enum_value` is the single-key
validator for pending writes; `validate_yaml_enum` validates whole
files (used by `session-start.sh`).
- `project.local.yaml` is gitignored. These
overrides never propagate to teammates.
- For **which value to choose** for a given game type or situation — and when to
suggest changing one — see `.claude/docs/settings-guidance.md` (advisory presets
+ change triggers). `effects-map.md` says what each setting does; that doc says
which to pick.
+693 -155
View File
@@ -1,14 +1,27 @@
---
name: setup-engine
description: "Configure the project's game engine and version. Pins the engine in CLAUDE.md, detects knowledge gaps, and populates engine reference docs via WebSearch when the version is beyond the LLM's training data."
description: "Configure engine and version. Pins it in CLAUDE.md; WebSearch fills reference docs when the version is beyond LLM training data."
argument-hint: "[engine] | [engine version] | refresh | upgrade [old-version] [new-version] | no args for guided selection"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, WebSearch, WebFetch, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, WebSearch, WebFetch, Agent, AskUserQuestion
model: sonnet
---
When this skill is invoked:
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys workflow`
**Tier awareness.** The `workflow` tier resolved above governs which design
artifact this skill expects and the finish path it recommends in §12:
- **`minimal`** — the design artifact is the one-page `design/game-brief.md`
(no GDDs, systems decomposition, or per-system design at this tier).
`/setup-engine` runs *first* in the minimal path, so a missing brief here is
normal, not a gap. The finish path is the 4-step floor.
- **`standard` / `full`** — the design artifact is `design/gdd/game-concept.md`
and the finish path is the full pipeline.
If the block did not render (shell preprocessing disabled), assume `standard`.
## 1. Parse Arguments
Four modes:
@@ -26,13 +39,22 @@ Four modes:
If no engine is specified, run an interactive engine selection process:
### Check for existing game concept
- Read `design/gdd/game-concept.md` if it exists — extract genre, scope, platform
targets, art style, team size, and any engine recommendation from `/brainstorm`
- If no concept exists, inform the user:
Read the design artifact for the resolved tier (see **Tier awareness** above):
- **`standard` / `full`**: read `design/gdd/game-concept.md` if it exists —
extract genre, scope, platform targets, art style, team size, and any engine
recommendation from `/brainstorm`.
- **`minimal`**: read `design/game-brief.md` if it exists — extract genre,
scope, platform, and art direction from its fields. Its absence is **expected**
at `minimal` (the brief is authored *after* engine setup in the minimal path), so
do not treat a missing brief as a gap — proceed straight to guided selection.
- If no concept **or** brief exists, inform the user:
> "No game concept found. Consider running `/brainstorm` first to discover what
> you want to build — it will also recommend an engine. Or tell me about your
> game and I can help you pick."
(At `minimal` this is optional, not a prerequisite — you can pick an engine now
and write the brief next.)
### If the user wants to pick without a concept, ask in this order:
**Question 1 — Prior experience** (ask this first, always, via `AskUserQuestion`):
@@ -123,6 +145,33 @@ Once the engine is chosen:
- Search: `"[engine] latest stable version [current year]"`
- Confirm with the user: "The latest stable [engine] is [version]. Use this?"
### Check the chosen version against what is actually installed
A version found by web search is what exists, not what the developer has. Pinning
one they cannot run means every later instruction — build, test, smoke, the
engine reference docs — targets an engine that is not on the machine.
Probe for the binary (Bash), and treat failure as unknown, never as absent:
| Engine | Probe |
|--------|-------|
| Godot | `godot --version`, else look for `godot`/`Godot_v*` on PATH or in the platform's usual install location |
| Unity | `Unity -version`, else the Hub's editor directory |
| Unreal | `UnrealEditor-Cmd -version`, else the launcher's install directory |
Then:
- **Match** — say so in one line and continue.
- **Mismatch** — state both versions and ask, offering three options: pin the
installed version, pin the newer one and upgrade later, or pin the newer one
deliberately. Record the answer; do not pick silently.
- **Not found / probe failed** — report `installed version NOT DETERMINED` and
continue with the chosen version. Do **not** report this as "no engine
installed": a probe that could not run has not established absence.
Whatever the outcome, write it into Section 7's `VERSION.md` as an
`Installed at pin time` row, so a later reader can tell a deliberate
version-ahead pin from an accident.
---
## 4. Update CLAUDE.md Technology Stack
@@ -150,7 +199,7 @@ Wait for confirmation before making any edits.
Update the Technology Stack section, replacing the `[CHOOSE]` placeholders with the actual values:
**For Godot** — use the template matching the language chosen above. See **Appendix A** at the bottom of this skill for all three variants (GDScript, C#, Both).
**For Godot** — use the template matching the language chosen above. See `.claude/skills/setup-engine/references/godot-language-config.md` (**A1**) for all three variants (GDScript, C#, Both).
**For Unity:**
```markdown
@@ -168,6 +217,21 @@ Update the Technology Stack section, replacing the `[CHOOSE]` placeholders with
- **Asset Pipeline**: Unreal Content Pipeline
```
### Engine reference import
In the same CLAUDE.md write, set the **Engine Version Reference** import to the
chosen engine. Find the line marked `ENGINE-REFERENCE-IMPORT` (an
`@docs/engine-reference/<engine>/VERSION.md` line under its comment) and Edit it
to point at the configured engine:
- Godot → `@docs/engine-reference/godot/VERSION.md`
- Unity → `@docs/engine-reference/unity/VERSION.md`
- Unreal → `@docs/engine-reference/unreal/VERSION.md`
This is why a fresh Unity or Unreal project no longer loads the Godot reference in
every session. It is idempotent — re-running `/setup-engine` for a different
engine rewrites the same line. (The target `docs/engine-reference/<engine>/`
directory is created in Section 8 below if it does not yet exist.)
---
## 5. Populate Technical Preferences
@@ -180,7 +244,7 @@ engine-appropriate defaults. Read the existing template first, then fill in:
### Naming Conventions (engine defaults)
**For Godot** — see **Appendix A** for GDScript, C#, and Both variants.
**For Godot** — see `.claude/skills/setup-engine/references/godot-language-config.md` (**A2**) for GDScript, C#, and Both variants.
**For Unity (C#):**
- Classes: PascalCase (e.g., `PlayerController`)
@@ -217,6 +281,22 @@ For **Primary Input**, use the dominant input for the game genre:
- Mobile game → Touch
- Cross-platform → ask the user
> **Genre may not exist yet — check before deriving from it.** At `minimal` the
> design artifact is `design/game-brief.md`, and it is authored *after* this
> skill runs (Section 2 says so explicitly). There is no genre to map. The same
> is true at any tier when `/setup-engine` is run before the concept exists.
>
> When genre is unavailable, **ask** — do not infer one from the platform, and do
> not leave the field silently blank:
> - Prompt: "Primary input for a [2D/3D] [platform] game? Genre isn't established
> yet — the brief comes next — so this can't be derived."
> - Options: the plausible inputs for that platform, plus
> `Leave as [TO BE CONFIGURED]` — a legitimate answer here, revisited via
> `/settings` once the brief exists.
>
> Gamepad Support and Touch Support still come from the platform table above;
> only Primary Input depends on genre.
Present the derived values and ask the user to confirm or adjust before writing.
Example filled section:
@@ -235,7 +315,13 @@ Example filled section:
- Prompt: "Should I set default performance budgets now, or leave them for later?"
- Options: `[A] Set defaults now (60fps, 16.6ms frame budget, engine-appropriate draw call limit)` / `[B] Leave as [TO BE CONFIGURED] — I'll set these when I know my target hardware`
- If [A]: populate with the suggested defaults. If [B]: leave as placeholder.
- **Testing**: Suggest engine-appropriate framework (GUT for Godot, NUnit for Unity, etc.) — ask before adding.
- **Testing**: Suggest the engine-appropriate framework — **gdUnit4** for Godot,
NUnit for Unity, Automation Spec for Unreal — and ask before adding.
> **Must match `commands.test` in Section 5.5.1, which writes
> `godot --headless --script tests/gdunit4_runner.gd`, and
> `.claude/docs/coding-standards.md`, which names the same runner.** Naming GUT
> here would have the skill recommend one framework and configure another in the
> same run.
- **Forbidden Patterns**: Leave as placeholder — do NOT pre-populate.
- **Allowed Libraries**: Leave as placeholder — do NOT pre-populate dependencies the project does not currently need. Only add a library here when it is actively being integrated, not speculatively.
@@ -245,7 +331,7 @@ Example filled section:
Also populate the `## Engine Specialists` section in `technical-preferences.md` with the correct routing for the chosen engine:
**For Godot** — see **Appendix A** for the routing table matching the language chosen.
**For Godot** — see `.claude/skills/setup-engine/references/godot-language-config.md` (**A3**) for the routing table matching the language chosen.
**For Unity:**
```markdown
@@ -294,7 +380,7 @@ Also populate the `## Engine Specialists` section in `technical-preferences.md`
### Collaborative Step
Present the filled-in preferences to the user. For Godot, include the chosen language and note where the full naming conventions and routing tables live:
> "Here are the default technical preferences for [engine] ([language if Godot]). The naming conventions and specialist routing are in Appendix A of this skill — I'll apply the [GDScript/C#/Both] variant. Want to customize any of these, or shall I save the defaults?"
> "Here are the default technical preferences for [engine] ([language if Godot]). The naming conventions and specialist routing are in this skill's references directory — I'll apply the [GDScript/C#/Both] variant. Want to customize any of these, or shall I save the defaults?"
For all other engines, present the defaults directly without referencing the appendix.
@@ -302,15 +388,398 @@ Wait for approval before writing the file.
---
## 5.5 Populate `project.yaml` (Primary Config Store)
> **v1.1:** `project.yaml` at the repo root is the **primary** store for project
> configuration. The `.claude/docs/technical-preferences.md` file written in
> Section 5 is kept as a **legacy mirror** for backward compatibility. This step
> is a **dual-write** — the same engine facts go into both files, and
> `project.yaml` wins when a skill reads a key present in both.
After `technical-preferences.md` is written and approved, dual-write the
structured config into `project.yaml`. Four blocks are written: `engine`,
`specialists`, `naming`, and `commands`.
### 5.5.1 Build the four blocks
Derive every value from the engine and language already chosen in Sections 3–4.
Do NOT re-ask for the **engine, version or language** — reuse those decisions.
> **That is not a blanket "never ask".** `rendering` and `physics` below depend on
> two further inputs — target platform and 2D-vs-3D — which **Section 2 collects on
> only one of the four entry paths**. When they were never collected, ask; the
> unavailable-branch under the project-shape table says how.
**`engine` block:**
```yaml
engine:
name: "<Godot|Unity|Unreal>"
version: "<version from Section 3>"
language: "<GDScript|C#|C++|Blueprint>"
rendering: "<engine default — see table>"
physics: "<engine default — see table>"
```
**On Godot these two values depend on the answers Section 2 already collected —
the target platform and 2D-vs-3D — so do not pick them from the engine name
alone.** On Unity and Unreal the table has a single `any` row and the engine name
*is* sufficient; take those rows directly.
| Engine | Project shape | `rendering` default | `physics` default |
|--------|---------------|---------------------|-------------------|
| Godot 4.x | 2D · web target | Compatibility | Godot Physics 2D |
| Godot 4.x | 2D · non-web | Forward+ | Godot Physics 2D |
| Godot 4.x | 3D · web target | Compatibility | Jolt |
| Godot 4.x | 3D · non-web | Forward+ | Jolt |
| Unity | any | URP | PhysX |
| Unreal | any | Lumen + Nanite (deferred) | Chaos |
> **Why this table has a shape column and the others do not.** Both Godot
> defaults were wrong for a 2D browser game, and both were wrong from data this
> skill had already collected and then discarded.
> - **Jolt is Godot's default *3D* engine.** `docs/engine-reference/godot/modules/physics.md`:
> "Jolt Physics is the DEFAULT 3D engine" and "2D physics UNCHANGED (still
> Godot Physics 2D)". Writing `Jolt` on a 2D project sends the implementer to
> tune a backend their game does not use.
> - **Forward+ is desktop-focused.** `docs/engine-reference/godot/modules/rendering.md`:
> Forward+ is "Full featured, desktop-focused"; Compatibility is
> "OpenGL 3.3 / WebGL 2, broadest hardware support" — the browser path.
>
> If Section 2's platform answer was `Multiple platforms` **including** web, use
> the web row: the renderer must work everywhere the game ships.
> **Godot only — Unity and Unreal have one row each, keyed `any`.** Shape cannot
> change `rendering` or `physics` for those two, so do **not** run the resolution
> below for them: asking an operator a question whose answer you will discard is
> exactly what §5.5.1 opens by forbidding. On Unity write `URP`/`PhysX` and on
> Unreal write `Lumen + Nanite (deferred)`/`Chaos` straight from the table.
>
> **Section 2 did not necessarily run — check before reading its answers.**
> Target platform and 2D-vs-3D are collected under *Questions 2–6, only if no
> prior engine experience*. **Three of the four entry paths never reach them:**
> `/setup-engine <engine> <version>` and `/setup-engine <engine>` skip Section 2
> outright, and guided mode skips the matrix as soon as the user names an engine
> they have worked in before. Only guided mode answered `None` or `Multiple`
> collects both.
>
> Resolve each input in this order and stop at the first that answers:
> 1. **Section 2's answers**, if that path ran.
> 2. **The design artifact** — `design/gdd/game-concept.md` at `standard`/`full`,
> `design/game-brief.md` at `minimal`. Section 2 already extracts platform
> targets from these; extract 2D-vs-3D the same way when it is stated.
> 3. **Ask.** Do not infer the shape from the engine name, and do not write a row
> you could not justify:
> - Prompt: "`rendering` and `physics` depend on the project's shape, which
> hasn't been established yet. Is this 2D or 3D, and does it ship to web?"
> - Options: `2D · non-web` / `2D · web` / `3D · non-web` / `3D · web`, plus
> `Leave as [TO BE CONFIGURED]` — a legitimate answer here, revisited via
> `/settings` once the concept exists.
>
> `[TO BE CONFIGURED]` is a valid value for both keys. A wrong `Jolt` on a 2D
> project is worse than an unset one, because nothing downstream questions it.
- `rendering` and `physics` are engine-typical defaults — tell the user they can
be changed later via `/settings` if the project uses a different setup.
- For Godot **Both**, write `language: "GDScript"` (the primary gameplay
language); the C# usage is recorded in `technical-preferences.md`.
- For Unreal, write `language: "C++"` — or `"Blueprint"` only if the project is
Blueprint-primary. Blueprint as a secondary tool does not change this value.
**`specialists` block** — copy directly from the routing table chosen in
Section 5 (**A3** in `.claude/skills/setup-engine/references/godot-language-config.md` for Godot):
| Engine / language | `code` | `shader` | `ui` | `additional` |
|-------------------|--------|----------|------|--------------|
| Godot — GDScript | godot-gdscript-specialist | godot-shader-specialist | godot-specialist | [godot-gdextension-specialist] |
| Godot — C# | godot-csharp-specialist | godot-shader-specialist | godot-specialist | [godot-gdextension-specialist] |
| Godot — Both | godot-gdscript-specialist | godot-shader-specialist | godot-specialist | [godot-csharp-specialist, godot-gdextension-specialist] |
| Unity | unity-specialist | unity-shader-specialist | unity-ui-specialist | [unity-dots-specialist, unity-addressables-specialist] |
| Unreal | unreal-specialist | unreal-specialist | ue-umg-specialist | [ue-gas-specialist, ue-blueprint-specialist, ue-replication-specialist] |
```yaml
specialists:
code: "<code specialist>"
shader: "<shader specialist>"
ui: "<ui specialist>"
additional: ["<...>"]
```
**`naming` block** — enum values (NOT the prose form used in
`technical-preferences.md`). Use the column matching the engine and, for Godot,
the language:
| Field | Godot GDScript | Godot C# | Unity | Unreal |
|-------|----------------|----------|-------|--------|
| `classes` | PascalCase | PascalCase | PascalCase | PascalCase |
| `variables` | snake_case | camelCase | camelCase | **PascalCase** |
| `constants` | SCREAMING_SNAKE | PascalCase | SCREAMING_SNAKE | SCREAMING_SNAKE |
| `signals` | past_tense | on_event_name | **PascalCase `On<Event>`** | **PascalCase `On<Event>`** |
| `files` | snake_case | PascalCase | PascalCase | PascalCase |
| `scenes` | snake_case | PascalCase | PascalCase | PascalCase |
> **The Unreal column is sourced, not inherited from the table's generic shape.**
> `variables: camelCase` and `signals: on_event_name` are the two rows that shape
> would produce, and both are wrong for Unreal. Checked against this repo's
> pinned reference: `docs/engine-reference/unreal/` contains **zero** camelCase
> variable declarations and uses PascalCase throughout (`int32 Health;`,
> `FVector ServerPosition;`), and the word "signal" **never appears in it at all** —
> it is Godot vocabulary. Unreal has delegates and events, and the reference's
> handlers are PascalCase `On<Event>`.
>
> Two caveats kept rather than smoothed over. (1) `classes: PascalCase` is
> **incomplete** for Unreal, not wrong: UE requires a mandatory type prefix
> (`U`/`A`/`F`/`E`/`I`/`T`) that this enum cannot express, so an Unreal project's
> coding standards must state it separately. (2) `scenes` is a **category
> mismatch** — Unreal has Levels and Maps under World Partition, not scenes — left
> in place because the key is shared across engines and renaming it is a schema
> change, not a value fix.
>
> The blast radius is limited: `naming.*` is currently a
> **documented-but-unread** setting, so wrong values misinform a human reading
> `project.yaml` rather than driving any automated check — today. That is a
> reason to get them right now, while it is cheap.
> **Three further rules for this table.**
>
> **The Unity `build` row must not hardcode `-buildTarget StandaloneLinux64`.**
> A hardcoded target gives every Unity project a **Linux** build command, whatever
> platform it actually ships on. The row reads `<TARGET>`: **ask the operator for
> the build target and write the value they give.** The correct `-buildTarget` identifiers
> are not sourceable from `docs/engine-reference/unity/`, so this skill must not
> emit one from recall — the same call made for `/security-audit`'s save
> patterns and for Unity's release dates. A wrong-but-plausible default is worse
> than an explicit question: it produces a `commands.build` that runs, succeeds,
> and builds the wrong artifact.
>
> **The Godot `build` row must not hardcode `'Linux/X11'` either — same defect,
> same remedy.** A Godot export preset name is **project-defined**: it is whatever
> string the operator typed into `export_presets.cfg`, and the shipped defaults are
> per-platform (`Windows Desktop`, `macOS`, `Web`, `Linux/X11`). Writing
> `'Linux/X11'` gives a Windows-targeting project a build command that fails with
> `Unknown export preset`, and gives a project that *does* have a Linux preset a
> command that silently builds the wrong platform. The row reads `<PRESET>`:
> **ask the operator which export preset to build and write the value they give**,
> exactly as the Unity row does. If no presets exist yet — common, since
> `/setup-engine` usually runs before the Godot project has any — write
> `[TO BE CONFIGURED]` and say so, rather than guessing a name that does not exist.
>
> **The `constants` row must not contradict this skill's own prose.** The table says
> `SCREAMING_SNAKE` for Unity; the Unity section of this same file says
> "Constants: PascalCase or UPPER_SNAKE_CASE". Both cannot be authoritative, and
> an agent following one produces config the other rejects. The row is **left
> unchanged pending sourcing** rather than picked by preference — neither
> `docs/engine-reference/unity/` nor `unreal/` contains a SCREAMING_SNAKE constant
> to confirm or refute it, and the Unreal run flagged the same row as wrong for
> Unreal on the same grounds. Resolve by adding a naming section to the engine
> references, then correct table and prose together. Until then, treat
> `naming.constants` as unverified for Unity and Unreal.
>
> **Write that caveat into `project.yaml`, do not leave it here.** On Unity and
> Unreal, emit the `constants` line with a trailing comment:
> ```yaml
> naming:
> constants: SCREAMING_SNAKE # UNVERIFIED — not sourceable from
> # docs/engine-reference/<engine>/; confirm before relying on it
> ```
> Without it, a value the skill *knows* is unsourced is recorded as flatly as
> `classes: PascalCase`, which is sourced, and the reader of the primary config
> store cannot tell them apart. The `commands` block nine lines below already does
> exactly this with its `# TODO: confirm these` line — this is the same pattern,
> applied to the value that needs it just as much.
For Godot **Both**, use the GDScript column — `.gd` files dominate gameplay
scripting; `.cs` files follow C# conventions per-file (see **A2** in `.claude/skills/setup-engine/references/godot-language-config.md`).
```yaml
naming:
classes: <value>
variables: <value>
constants: <value>
signals: <value>
files: <value>
scenes: <value>
```
**`commands` block** — engine-default shell commands, simple-string form:
| Engine | `build` | `test` | `run` | `smoke` |
|--------|---------|--------|-------|---------|
| Godot | `godot --headless --export-debug '<PRESET>'` **(ASK — do not default)** | `godot --headless --script tests/gdunit4_runner.gd` | `godot --path . --windowed --resolution 1280x720` | `godot --headless --quit-after 5` |
| Unity | `Unity -batchmode -quit -projectPath . -buildTarget <TARGET>` **(ASK — do not default)** | `Unity -runTests -projectPath . -testPlatform PlayMode` | `Builds/<Target>/<Game>.exe -screen-width 1280 -screen-height 720 -screen-fullscreen 0` | `Unity -batchmode -quit -projectPath . -executeMethod SmokeCheck.Run` |
> **`commands.run` is the one the run-and-observe step depends on.** It must
> launch the **game**, windowed, at a fixed resolution — never the editor, and
> never with a headless / batch / null-RHI flag, which exist to skip rendering.
> `/dev-story` Phase 6 step 4 appends the per-engine capture flags to it
> (`.claude/docs/run-and-observe.md`). `test` and `smoke` feed the parse check
> and `/smoke-check`; `build` is the one row you must ask for.
> **YAML quoting rule — applies to EVERY command value.** `yaml-helper.sh` — the
> parser every config read in this framework goes through — decodes **no**
> escape sequences: neither `\"` inside a double-quoted scalar nor `''` inside a
> single-quoted scalar. It takes the first matching quote character as the end of
> the value and discards the rest, so `"he said \"hi\" now"` parses as
> `he said \`. Verified against the parser, not inferred. The rule is
> preventative here — it applies the moment anything does read `commands.*`, and
> to every other quoted value in `project.yaml` today.
> Pick the quote style that needs **no escaping**:
> - value contains a single quote `'` (e.g. the Godot `build` above) → wrap it in
> a **double-quoted** YAML scalar: `"... 'Linux/X11' ..."`
> - value contains a double quote `"` (e.g. the Unreal `test`/`smoke` below) →
> wrap it in a **single-quoted** YAML scalar: `'... "Quit" ...'`
> - value contains neither → use a double-quoted scalar for consistency.
> Never use a quote style that forces an escape (`\"` or `''`) — the parser
> truncates the value at the escape. A value containing BOTH quote types cannot
> be represented for this parser; rewrite the command to drop one.
**Godot / Unity** — write the table values directly, substituting the operator's
answer for `<PRESET>` / `<TARGET>`. Godot's `build` contains a single quote, so it
takes a double-quoted scalar (`Windows Desktop` below is the *example* answer, not
a default — write what the operator said):
```yaml
commands:
build: "godot --headless --export-debug 'Windows Desktop'"
test: "godot --headless --script tests/gdunit4_runner.gd"
run: "godot --path . --windowed --resolution 1280x720"
smoke: "godot --headless --quit-after 5"
```
> **Also write `engine.path` if the editor is not on `PATH`.** These commands name
> the executable bare, which assumes it resolves — and on Windows none of the three
> engines installs onto `PATH` by default. Ask for or probe the install location and
> record it:
>
> ```yaml
> engine:
> path: "C:/Program Files/Epic Games/UE_5.7" # omit if the editor is on PATH
> ```
>
> **This is not cosmetic.** Without it, an agent reports *"no editor on this
> machine"* and ships C++ it never compiled — on a machine where that engine WAS
> installed. Nothing in the project told it where to look, so absence of a path read
> as absence of an engine.
For **Unreal**, UE build/test commands vary by version and project setup. Write
best-effort values and add a `# TODO` comment so the user knows to confirm them.
The `test`/`smoke` commands embed double quotes, so they take single-quoted
scalars:
```yaml
commands:
# TODO: confirm these for your UE version and project — adjust via /settings
build: 'RunUAT.bat BuildCookRun -project=<project>.uproject -platform=Win64 -build -cook'
test: 'UnrealEditor-Cmd.exe <project>.uproject -ExecCmds="Automation RunTests <project>; Quit" -unattended -nullrhi'
run: 'UnrealEditor.exe <project>.uproject -game -windowed -ResX=1280 -ResY=720'
smoke: 'UnrealEditor-Cmd.exe <project>.uproject -game -nullrhi -unattended -ExecCmds="Quit"'
```
**Two details are load-bearing.** `smoke` needs `-game`: without it
`UnrealEditor-Cmd` boots the *editor*, where a bare `Quit` console command only
ends a play-in-editor session — the process stays resident and the command
never returns; with `-game` the same line boots headless and exits in seconds.
`test` needs the `; Quit` inside the `Automation` string: the automation
runner handles that trailing `Quit` itself and exits the editor once the tests
finish, and without it the run also never returns.
### 5.5.2 Write the blocks to `project.yaml`
Show the user the full set of four blocks and ask:
> "May I write the `engine`, `specialists`, `naming`, and `commands` blocks to `project.yaml`?"
Wait for confirmation, then apply based on the file's current state:
- **`project.yaml` does not exist** — create it with the Write tool using this
v1.1 template (the four blocks appended after `framework`; replace `<...>` and
the date):
```yaml
# CCGS project configuration — single source of truth for project settings.
# Schema: grep the `## <key>` section of .claude/docs/effects-map.md —
# it is ~31k tokens whole, ~900 per section. Do not open it entire.
schema_version: 1
framework:
version: 1.1.0
last_upgraded: <today's date>
engine:
name: "<...>"
version: "<...>"
language: "<...>"
rendering: "<...>"
physics: "<...>"
specialists:
code: "<...>"
shader: "<...>"
ui: "<...>"
additional: ["<...>"]
naming:
classes: <...>
variables: <...>
constants: <...>
signals: <...>
files: <...>
scenes: <...>
commands:
build: "<...>"
test: "<...>"
run: "<...>"
smoke: "<...>"
```
Do not seed `modes.review_mode` here. It is a rigor-fronted knob — `modes.rigor`
supplies its value, so an explicit value would shadow the rigor expansion and pin
the review mode regardless of the project's rigor. Test Y.6 locks this in.
- **`project.yaml` exists** — Read it first (the Edit tool requires the file to
have been read this session), then, processing the blocks in the order
`engine` → `specialists` → `naming` → `commands`, for each block:
- **Block absent** — insert the whole block, appended after the last existing
top-level block.
- **Block already present** (a re-run of `/setup-engine`) — Edit the existing
keys in place, and add any keys the block is missing (a partial block must
end up with its full key set). Do NOT add a second copy of the block.
Preserve all other content in `project.yaml` (`schema_version`, `framework`,
`modes`, `project`, etc.) — only the four blocks are touched.
### 5.5.3 Verify the dual-write
Read `project.yaml` back and confirm the four blocks are present and that
`engine.name`, `engine.language`, and the naming values match what was written
to `technical-preferences.md`. If they diverge, report the discrepancy to the
user and stop — a split config corrupts skill and hook reads.
---
## 6. Determine Knowledge Gap
Check whether the engine version is likely beyond the LLM's training data.
**Known approximate coverage** (update this as models change):
- LLM knowledge cutoff: **May 2025**
- Godot: training data likely covers up to ~4.3
- Unity: training data likely covers up to ~2023.x / early 6000.x
- Unreal: training data likely covers up to ~5.3 / early 5.4
**Known approximate coverage** — *last re-checked 2026-08-28*:
- LLM knowledge cutoff: **May 2026**
- Godot: training data likely covers up to ~4.6
- Unity: training data likely covers up to ~6000.x
- Unreal: training data likely covers up to ~5.5
> **This table goes stale silently, and a stale table fails in the dangerous
> direction only if it is too *new*.** A cutoff left unchanged for a year after
> it stopped being true over-classifies risk — safe, but every project then pays
> for full reference docs it may not have needed.
> The opposite error is the harmful one: a cutoff claimed *later* than the model's
> actual one marks post-cutoff versions LOW RISK and suppresses the reference
> docs that exist to stop invented APIs.
>
> **If the date above is more than six months old, do not trust it.** Say so, and
> treat the engine version as `HIGH RISK` regardless of the comparison — an
> unverifiable cutoff is not a cutoff that was met.
Compare the user's chosen version against these baselines:
@@ -324,6 +793,53 @@ Inform the user which category they're in and why.
## 7. Populate Engine Reference Docs
### First: does a reference set already exist for this engine?
**Check before doing anything else.** The template ships
`docs/engine-reference/godot/`, `unity/` and `unreal/` **already populated**, so
"the directory exists and pins a version" is the state of *every* fresh project,
not an edge case. Both branches below say "create", and following either one
literally on a pre-populated directory either overwrites curated content or
leaves `project.yaml` and the CLAUDE.md-imported reference disagreeing.
Read `docs/engine-reference/<engine>/VERSION.md` and compare its
**Engine Version** to the version chosen in Section 3:
- **No directory, or no `VERSION.md`** → create, using the risk branch below.
- **Same version** → nothing to do. Refresh `Last Docs Verified` only if you
actually re-verified against the docs this run. Do not restamp a date you did
not check.
- **Directory pins an OLDER version than the one chosen** → **update, do not
replace.** This is the common case.
1. Edit `VERSION.md` in place: new **Engine Version**, new **Project Pinned**
and **Last Docs Verified**, the `Installed at pin time` row from Section 3,
and a new row in the post-cutoff timeline for each version added.
2. **Append** to `breaking-changes.md`, `deprecated-apis.md` and
`current-best-practices.md` under a heading naming the version span
(`## 4.6 → 4.7`). Never truncate the older spans — a project migrating
across two versions still needs the earlier one.
3. Re-grade the older timeline rows if the cutoff moved past them.
- **Directory pins a NEWER version than the one chosen** → stop and ask. Someone
pinned forward deliberately, or the version choice is wrong. Do not silently
downgrade a curated reference.
### Sourcing rule for everything written in this section
**Never fill a gap from training data. Write the gap down instead.**
The whole purpose of these files is to be the thing agents consult *instead of*
their training data. A confidently wrong entry here is worse than no entry: it
produces work that looks verified and is not.
- Every claim must come from a page you fetched this run. Record the URL.
- If the official docs do not state something the template asks for — a release
date, a subsystem's behaviour, web-export specifics — write
**`NOT SOURCEABLE — <what>, not stated at <url>`** and move on.
- A `NOT SOURCEABLE` line is a successful outcome, not a failure to finish.
- Do not infer one fact from an adjacent one. "The migration guide lists no
physics change" is not "the physics default is unchanged"; if you record the
inference, label it as an inference and name what it rests on.
### If WITHIN training data (LOW RISK):
Create a minimal `docs/engine-reference/<engine>/VERSION.md`:
@@ -387,21 +903,140 @@ Wait for confirmation before writing any files.
---
## 8. Update CLAUDE.md Import
## 7.5 Scaffold the Engine Project
Ask: "May I update the `@` import in `CLAUDE.md` to point to the new engine reference?"
**Without this step the framework produces source files no engine can open.**
`/dev-story` writes `.gd`/`.cs`/`.cpp` under the resolved code root, and the `minimal` path
advertises "four steps to running code" — but nothing anywhere created a project
for the engine to load. Verified by grep across every skill: no `project.godot`,
no Unity project, no `.uproject` was ever written. The files were real and
orphaned.
Wait for confirmation, then update the `@` import under "Engine Version Reference" to point to the
correct engine:
### Godot — write `project.godot` if one is absent
**Never overwrite an existing `project.godot`.** If the file is already there,
say so and skip to Section 8 — the developer has a project and its settings are
theirs.
Show the proposed file, then ask: *"May I create `project.godot` at the repo
root?"* On approval, write:
```ini
config_version=5
[application]
config/name="<project name>"
config/features=PackedStringArray("<major.minor>", "<renderer feature>")
[rendering]
renderer/rendering_method="<rendering method>"
```
Fill it from decisions already made — do not ask again:
| Field | Source |
|-------|--------|
| `config/name` | the brief's working title, else the repo directory name |
| `<major.minor>` | `engine.version` from Section 3, major and minor only (`4.7.2` → `4.7`) |
| `<renderer feature>` / `<rendering method>` | the `rendering` value chosen in Section 5.5.1 — Compatibility → `"GL Compatibility"` / `gl_compatibility`; Forward+ → `"Forward Plus"` / `forward_plus`; Mobile → `"Mobile"` / `mobile` |
**Leave `run/main_scene` unset.** There is no scene yet at engine-setup time.
Add a comment saying `/dev-story` or the developer sets it once a scene exists;
an empty project with no main scene opens fine in the editor.
**Then verify, and report what the verification actually was.** If the engine
binary was found in Section 3, run its headless import
(`godot --headless --path . --import`) and report the result. If the binary was
not found, or its version differs from the pinned one, write
**`project.godot NOT VERIFIED — <reason>`**. The `config_version` and feature
strings are stable across Godot 4.x, but "stable in the versions I know" is not
the same as "checked against the version you pinned", and only the run
establishes the latter.
### Unity and Unreal — instruct, do not fabricate
A Unity project and an `.uproject` are editor-generated and span many files,
several of them binary or machine-specific. This repo cannot source their
correct contents, and a hand-written scaffold would be the exact failure
Section 7's sourcing rule forbids — something that looks finished and is quietly
wrong.
Tell the user, in one short block, that CCGS does not create the project for
these engines and they should create it first:
- **Unity** — create the project in Unity Hub at the repo root, choosing the
template matching the 2D/3D answer from Section 2, then re-run `/setup-engine`.
- **Unreal** — create the project in the Epic launcher or via `UnrealEditor`,
then re-run.
Report the outcome in the Section 12 summary either way — created, already
present, or "not created, engine requires the editor" — so the user leaves this
skill knowing whether a runnable project exists.
> **Deliberately not a `project.yaml` key.** An `engine.project_scaffolded` flag
> would be written here and read by nothing, which is a dead setting — the same
> writer-without-reader defect the config gates exist to catch. The filesystem is
> the source of truth: any skill that needs to know globs for `project.godot`,
> `*.uproject`, or `ProjectSettings/ProjectVersion.txt`.
---
## 8. Verify the CLAUDE.md Import
**This import was already written in Section 4 — do not edit it again and do not
ask again.** Section 4 sets it as part of the same CLAUDE.md write, anchored to
the `ENGINE-REFERENCE-IMPORT` marker. This step only confirms the result.
Read `CLAUDE.md` and confirm the line under the marker reads:
```markdown
## Engine Version Reference
@docs/engine-reference/<engine>/VERSION.md
```
If the previous import pointed to a different engine (e.g., switching from
Godot to Unity), update it.
with `<engine>` the engine just configured. If it still points at a different
engine, Section 4 did not complete — go back and finish it rather than patching
the line here.
> **Why this is a check and not a second write.** Repeating the edit here with
> its own approval prompt would ask the user twice for one change, and the second
> ask would be for work already done. Locate the line by its marker, never by the
> `## Engine Version Reference` heading — the marker exists precisely so the line
> can still be found when the heading moves or is reworded.
---
## 8.5 Read Back What You Just Wrote
This section exists because prose did not hold. Section 5.5.1's rendering/physics
table already carries an emphatic, source-cited warning naming the two mistakes
most often made here -- and it is still entirely possible to make **both** of
them anyway, writing `Forward+` and `Jolt` for a 2D browser game. Section 3's
`Installed at pin time` row is just as easy to drop silently, because a missing
row leaves no trace.
Neither is fixed by adding more instructions. They are fixed by verifying the
files after writing them:
```bash
bash .claude/scripts/project-coherence.sh
```
It compares `project.yaml` against `docs/engine-reference/<engine>/VERSION.md`,
against `project.godot`, and against the engine binary actually on PATH, and it
checks that the files `commands.build` and `commands.test` name exist.
**Report every `[DIFFERS]` line to the user and resolve it before finishing.**
Each one means two files this skill just wrote disagree, or describe something
that is not there.
**`[NOT CHECKED]` is not a pass.** Each such line names why a comparison could
not be made -- an absent binary, a missing `project.godot`. Say which ones
applied. A comparison that could not run has not established agreement.
The script emits observations and never a verdict, per the convention in
CLAUDE.md. The judgement is yours and the user's.
---
@@ -463,7 +1098,7 @@ any "must migrate" items.
### Step 3 — Pre-Upgrade Audit
Scan `src/` for code that uses APIs known to be deprecated or changed in the
Scan the **code root** (resolve per `.claude/docs/code-root-resolution.md`) for code that uses APIs known to be deprecated or changed in the
target version:
- Use Grep to search for deprecated API names extracted from the migration
@@ -492,8 +1127,8 @@ Recommended migration order (dependency-sorted):
...
```
If no deprecated APIs are found in `src/`, report: "No deprecated API usage
found in src/ — upgrade may be low-risk."
If no deprecated APIs are found in the code root, report: "No deprecated API usage
found in the code root — upgrade may be low-risk."
### Step 4 — Confirm Before Updating
@@ -523,6 +1158,10 @@ After confirmation:
2. If `breaking-changes.md` or `deprecated-apis.md` exist in the engine
reference directory, append the new version's changes to those files.
3. If `project.yaml` exists at the repo root and has an `engine` block, Read it
first, then update `engine.version` to `[new-version]` so the primary config
store stays in sync with VERSION.md.
### Step 6 — Post-Upgrade Reminder
After updating VERSION.md, output:
@@ -555,10 +1194,26 @@ Knowledge Risk: [LOW/MEDIUM/HIGH]
Reference Docs: [created/skipped]
CLAUDE.md: [updated]
Tech Prefs: [created/updated]
project.yaml: [created/updated]
Agent Config: [verified]
Next Steps:
1. Review docs/engine-reference/<engine>/VERSION.md
```
Then print **one** Next-Steps list, matching the resolved `workflow` tier:
**`minimal` — the lean 4-step floor (you are on step 1):**
```
2. Run /brainstorm to produce your one-page design/game-brief.md (the lean-tier design artifact)
3. Run /create-stories to turn the brief's MVP list into stories
4. Run /dev-story — first line of game code
```
(No `/map-systems`, `/design-system`, `/prototype`, or `/sprint-plan` at
`minimal` — the brief replaces the GDDs and its build order is the plan.)
**`standard` / `full` — the full pipeline:**
```
2. [If from /brainstorm] Run /map-systems to decompose your concept into individual systems
3. [If from /brainstorm] Run /design-system to author per-system GDDs (guided, section-by-section)
4. [If from /brainstorm] Run /prototype [core-mechanic] to validate the core idea before writing GDDs
@@ -573,144 +1228,27 @@ Verdict: **COMPLETE** — engine configured and reference docs populated.
## Guardrails
- NEVER guess an engine version — always verify via WebSearch or user confirmation
- `project.yaml` is the primary config store (v1.1). Always dual-write engine
config to BOTH `project.yaml` (primary) and `technical-preferences.md` (legacy
mirror). If the two ever diverge, `project.yaml` is authoritative.
- NEVER overwrite existing reference docs without asking — append or update
- If reference docs already exist for a different engine, ask before replacing
- Always show the user what you're about to change before making CLAUDE.md edits
- If WebSearch returns ambiguous results, show the user and let them decide
- When the user chose **GDScript**: copy the GDScript CLAUDE.md template from Appendix A1 exactly. NEVER add "C++ via GDExtension" to the Language field. GDScript projects may use GDExtension, but it is not a primary project language. The `godot-gdextension-specialist` in the routing table is available for when native extensions are needed — it does not make C++ a project language.
- When the user chose **GDScript**: copy the GDScript CLAUDE.md template from **A1** in `.claude/skills/setup-engine/references/godot-language-config.md` exactly. NEVER add "C++ via GDExtension" to the Language field. GDScript projects may use GDExtension, but it is not a primary project language. The `godot-gdextension-specialist` in the routing table is available for when native extensions are needed — it does not make C++ a project language.
---
## Appendix A — Godot Language Configuration
All Godot-specific variants for language-dependent configuration. Referenced from Sections 4 and 5 — only relevant when Godot is the chosen engine. Use the subsection matching the language chosen in Section 4.
Moved out of this file so it costs nothing on non-Godot runs.
---
**When the chosen engine is Godot, read**
`.claude/skills/setup-engine/references/godot-language-config.md`
and use the subsection for the chosen language:
### A1. CLAUDE.md Technology Stack Templates
- **A1** — CLAUDE.md Technology Stack templates (GDScript / C# / Both)
- **A2** — naming conventions
- **A3** — engine specialist routing and file-extension tables
**GDScript:**
```markdown
- **Engine**: Godot [version]
- **Language**: GDScript
- **Build System**: SCons (engine), Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
> **Guardrail**: When using this GDScript template, write the Language field as exactly "`GDScript`" — no additions. Do NOT append "C++ via GDExtension" or any other language. The C# template below includes GDExtension because C# projects commonly wrap native code; GDScript projects do not.
**C#:**
```markdown
- **Engine**: Godot [version]
- **Language**: C# (.NET 8+, primary), C++ via GDExtension (native plugins only)
- **Build System**: .NET SDK + Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
**Both — GDScript + C#:**
```markdown
- **Engine**: Godot [version]
- **Language**: GDScript (gameplay/UI scripting), C# (performance-critical systems), C++ via GDExtension (native only)
- **Build System**: .NET SDK + Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
---
### A2. Naming Conventions
**GDScript:**
- Classes: PascalCase (e.g., `PlayerController`)
- Variables/functions: snake_case (e.g., `move_speed`)
- Signals: snake_case past tense (e.g., `health_changed`)
- Files: snake_case matching class (e.g., `player_controller.gd`)
- Scenes: PascalCase matching root node (e.g., `PlayerController.tscn`)
- Constants: UPPER_SNAKE_CASE (e.g., `MAX_HEALTH`)
**C#:**
- Classes: PascalCase (`PlayerController`) — must also be `partial`
- Public properties/fields: PascalCase (`MoveSpeed`, `JumpVelocity`)
- Private fields: `_camelCase` (`_currentHealth`, `_isGrounded`)
- Methods: PascalCase (`TakeDamage()`, `GetCurrentHealth()`)
- Signal delegates: PascalCase + `EventHandler` suffix (`HealthChangedEventHandler`)
- Files: PascalCase matching class (`PlayerController.cs`)
- Scenes: PascalCase matching root node (`PlayerController.tscn`)
- Constants: PascalCase (`MaxHealth`, `DefaultMoveSpeed`)
**Both — GDScript + C#:**
Use GDScript conventions for `.gd` files and C# conventions for `.cs` files. Mixed-language files do not exist — the boundary is per-file. When in doubt about which language a new system should use, ask the user and record the decision in `technical-preferences.md`.
---
### A3. Engine Specialists Routing
**GDScript:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **Language/Code Specialist**: godot-gdscript-specialist (all .gd files)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for architecture decisions, ADR validation, and cross-cutting code review. Invoke GDScript specialist for code quality, signal architecture, static typing enforcement, and GDScript idioms. Invoke shader specialist for material design and shader code. Invoke GDExtension specialist only when native extensions are involved.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.gd files) | godot-gdscript-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
**C#:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **Language/Code Specialist**: godot-csharp-specialist (all .cs files)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for architecture decisions, ADR validation, and cross-cutting code review. Invoke C# specialist for code quality, [Signal] delegate patterns, [Export] attributes, .csproj management, and C#-specific Godot idioms. Invoke shader specialist for material design and shader code. Invoke GDExtension specialist only when native C++ plugins are involved.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.cs files) | godot-csharp-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Project config (.csproj, NuGet) | godot-csharp-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
**Both — GDScript + C#:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **GDScript Specialist**: godot-gdscript-specialist (.gd files — gameplay/UI scripts)
- **C# Specialist**: godot-csharp-specialist (.cs files — performance-critical systems)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for cross-language architecture decisions and which systems belong in which language. Invoke GDScript specialist for .gd files. Invoke C# specialist for .cs files and .csproj management. Prefer signals over direct cross-language method calls at the boundary.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.gd files) | godot-gdscript-specialist |
| Game code (.cs files) | godot-csharp-specialist |
| Cross-language boundary decisions | godot-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Project config (.csproj, NuGet) | godot-csharp-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
**Load discipline.** On any engine other than Godot, **never load it** — nothing in Sections 4, 5 or 5.5 needs it, and reading it anyway spends the tokens the split exists to save. On Godot, read it once when you first reach Section 4 and keep using it for Sections 5 and 5.5; do not re-read it at each reference.
@@ -0,0 +1,147 @@
# Godot Language Configuration — setup-engine reference
Lookup tables for `/setup-engine`, split out of the skill body so they cost
nothing on invocations that are not Godot. Read this file only when the
chosen engine is Godot, and then only the subsection for the chosen language.
Referenced from Sections 4, 5 and 5.5 of
`.claude/skills/setup-engine/SKILL.md` by the names A1, A2 and A3.
---
### A1. CLAUDE.md Technology Stack Templates
**GDScript:**
```markdown
- **Engine**: Godot [version]
- **Language**: GDScript
- **Build System**: SCons (engine), Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
> **Guardrail**: When using this GDScript template, write the Language field as exactly "`GDScript`" — no additions. Do NOT append "C++ via GDExtension" or any other language. The C# template below includes GDExtension because C# projects commonly wrap native code; GDScript projects do not.
**C#:**
```markdown
- **Engine**: Godot [version]
- **Language**: C# (.NET 8+, primary), C++ via GDExtension (native plugins only)
- **Build System**: .NET SDK + Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
**Both — GDScript + C#:**
```markdown
- **Engine**: Godot [version]
- **Language**: GDScript (gameplay/UI scripting), C# (performance-critical systems), C++ via GDExtension (native only)
- **Build System**: .NET SDK + Godot Export Templates
- **Asset Pipeline**: Godot Import System + custom resource pipeline
```
---
### A2. Naming Conventions
**GDScript:**
- Classes: PascalCase (e.g., `PlayerController`)
- Variables/functions: snake_case (e.g., `move_speed`)
- Signals: snake_case past tense (e.g., `health_changed`)
- Files: snake_case matching class (e.g., `player_controller.gd`)
- Scenes: snake_case matching the file (e.g., `player_controller.tscn`)
- Constants: UPPER_SNAKE_CASE (e.g., `MAX_HEALTH`)
> **This list and the `naming` enum table in Section 5.5.1 of the skill must
> agree, value for value.** They are written into two different files —
> `technical-preferences.md` from here, `project.yaml` from there — and Section
> 5.5.3 compares them and **stops the skill** on any mismatch. They disagreed on
> `scenes` (this list said PascalCase, the enum table said snake_case) for the
> GDScript column only, which halted `/setup-engine` on the most common Godot
> configuration there is. Changing a value in one place without the other
> reintroduces that halt.
**C#:**
- Classes: PascalCase (`PlayerController`) — must also be `partial`
- Public properties/fields: PascalCase (`MoveSpeed`, `JumpVelocity`)
- Private fields: `_camelCase` (`_currentHealth`, `_isGrounded`)
- Methods: PascalCase (`TakeDamage()`, `GetCurrentHealth()`)
- Signal delegates: PascalCase + `EventHandler` suffix (`HealthChangedEventHandler`)
- Files: PascalCase matching class (`PlayerController.cs`)
- Scenes: PascalCase matching root node (`PlayerController.tscn`)
- Constants: PascalCase (`MaxHealth`, `DefaultMoveSpeed`)
**Both — GDScript + C#:**
Use GDScript conventions for `.gd` files and C# conventions for `.cs` files. Mixed-language files do not exist — the boundary is per-file. When in doubt about which language a new system should use, ask the user and record the decision in `technical-preferences.md`.
---
### A3. Engine Specialists Routing
**GDScript:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **Language/Code Specialist**: godot-gdscript-specialist (all .gd files)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for architecture decisions, ADR validation, and cross-cutting code review. Invoke GDScript specialist for code quality, signal architecture, static typing enforcement, and GDScript idioms. Invoke shader specialist for material design and shader code. Invoke GDExtension specialist only when native extensions are involved.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.gd files) | godot-gdscript-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
**C#:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **Language/Code Specialist**: godot-csharp-specialist (all .cs files)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for architecture decisions, ADR validation, and cross-cutting code review. Invoke C# specialist for code quality, [Signal] delegate patterns, [Export] attributes, .csproj management, and C#-specific Godot idioms. Invoke shader specialist for material design and shader code. Invoke GDExtension specialist only when native C++ plugins are involved.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.cs files) | godot-csharp-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Project config (.csproj, NuGet) | godot-csharp-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
**Both — GDScript + C#:**
```markdown
## Engine Specialists
- **Primary**: godot-specialist
- **GDScript Specialist**: godot-gdscript-specialist (.gd files — gameplay/UI scripts)
- **C# Specialist**: godot-csharp-specialist (.cs files — performance-critical systems)
- **Shader Specialist**: godot-shader-specialist (.gdshader files, VisualShader resources)
- **UI Specialist**: godot-specialist (no dedicated UI specialist — primary covers all UI)
- **Additional Specialists**: godot-gdextension-specialist (GDExtension / native C++ bindings only)
- **Routing Notes**: Invoke primary for cross-language architecture decisions and which systems belong in which language. Invoke GDScript specialist for .gd files. Invoke C# specialist for .cs files and .csproj management. Prefer signals over direct cross-language method calls at the boundary.
### File Extension Routing
| File Extension / Type | Specialist to Spawn |
|-----------------------|---------------------|
| Game code (.gd files) | godot-gdscript-specialist |
| Game code (.cs files) | godot-csharp-specialist |
| Cross-language boundary decisions | godot-specialist |
| Shader / material files (.gdshader, VisualShader) | godot-shader-specialist |
| UI / screen files (Control nodes, CanvasLayer) | godot-specialist |
| Scene / prefab / level files (.tscn, .tres) | godot-specialist |
| Project config (.csproj, NuGet) | godot-csharp-specialist |
| Native extension / plugin files (.gdextension, C++) | godot-gdextension-specialist |
| General architecture review | godot-specialist |
```
+9 -1
View File
@@ -1,12 +1,20 @@
---
name: skill-improve
description: "Improve a skill using a test-fix-retest loop. Runs static checks, proposes targeted fixes, rewrites the skill, re-tests, and keeps or reverts based on score change."
description: "Improve a skill via a test-fix-retest loop — static checks, targeted fixes, keep or revert on score change."
argument-hint: "[skill-name]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Bash
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Skill Improve
Runs an improvement loop on a single skill:
+54 -9
View File
@@ -1,12 +1,20 @@
---
name: skill-test
description: "Validate skill files for structural compliance and behavioral correctness. Three modes: static (linter), spec (behavioral), audit (coverage report)."
description: "Validate skill files for structural compliance and behavioral correctness. Four modes: static linter, spec, category rubric, audit."
argument-hint: "static [skill-name | all] | spec [skill-name] | category [skill-name | all] | audit"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Skill Test
Validates `.claude/skills/*/SKILL.md` files for structural compliance and
@@ -62,10 +70,29 @@ The skill must have ≥2 numbered phase headings. Look for patterns like:
**FAIL** if fewer than 2 phase-like headings are found.
### Check 3 — Verdict Keywords
The skill must contain at least one of: `PASS`, `FAIL`, `CONCERNS`, `APPROVED`,
`BLOCKED`, `COMPLETE`, `READY`, `COMPLIANT`, `NON-COMPLIANT`
**FAIL** if none are present.
The skill must communicate a clear outcome. Accept any of:
- **Gate / review verdicts** — `PASS`, `FAIL`, `CONCERNS`, `APPROVED`,
`BLOCKED`, `COMPLETE`, `READY`, `COMPLIANT`, `NON-COMPLIANT`
- **Go / no-go verdicts** — `PROCEED`, `PIVOT`, `KILL`, `GO`, `NO-GO`
- **Severity scales** — `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`. Audit skills rank
findings by severity instead of issuing one verdict for the whole run.
**FAIL** if none are present **and** the skill produces an assessment — its
description or body promises a review, audit, check, gate, or readiness
judgement.
**WARN** (never FAIL) if none are present and the skill's output is an artifact
or a value rather than a judgement. `/settings` is the reference case: it prints
and writes configuration and has no verdict to give. Do not invent one to
satisfy this check.
> The narrow earlier list (gate verdicts only, hard FAIL) failed 5 of 74 skills
> for reasons that were not their fault — `/prototype` and `/vertical-slice`
> advertise `PROCEED`/`PIVOT`/`KILL` in their own descriptions, `/adopt` and
> `/security-audit` rank by severity, and `/settings` has no verdict by design.
> A linter that cries wolf on 7% of the corpus stops being read.
### Check 4 — Collaborative Protocol Language
The skill must contain ask-before-write language. Look for:
@@ -120,7 +147,7 @@ Recommended: Add a "Follow-Up Actions" section at the end of the skill.
For `static all`, produce a summary table then list any non-compliant skills:
```
=== Skill Static Check: All 52 Skills ===
=== Skill Static Check: All 74 Skills ===
Skill | Result | Issues
-----------------------|--------------|-------
@@ -129,10 +156,20 @@ design-review | COMPLIANT |
story-readiness | WARNINGS | Check 5: no handoff
...
Summary: 48 COMPLIANT, 3 WARNINGS, 1 NON-COMPLIANT
Aggregate Verdict: N WARNINGS / N FAILURES
Summary: 48 COMPLIANT, 3 WARNINGS, 1 NON-COMPLIANT, 1 NOT ASSESSED
Aggregate Verdict: N WARNINGS / N FAILURES / N NOT ASSESSED
```
**`NOT ASSESSED` is a per-skill result here, not only an aggregate line.** A skill
whose file could not be read or parsed, or whose checks could not run, is reported
as `NOT ASSESSED` with the reason — never omitted from the table and never counted
as COMPLIANT. Ranked **above COMPLIANT**, **below WARNINGS and NON-COMPLIANT**.
**And state the denominator.** `All 74 Skills` in the header must be the number
actually examined, not the number that exist: report `[N] of [M] skills checked`
whenever they differ. A summary whose counts silently sum to less than its own
title is the failure this skill is supposed to catch in others.
---
## Phase 2B: Spec Mode — Behavioral Verifier
@@ -169,6 +206,14 @@ Mark each assertion:
- **PASS** — skill instructions clearly satisfy this assertion
- **PARTIAL** — skill instructions partially address it, but with ambiguity
- **FAIL** — skill instructions would NOT satisfy this assertion given the fixture
- **NOT ASSESSED** — the assertion could not be evaluated at all: it names a
fixture state the spec never defines, depends on runtime behavior no static
read can settle, or references a file or section that does not exist. Rank it
**above PASS** (an assertion nobody could evaluate has not been satisfied) and
**below PARTIAL and FAIL** (an ambiguity somebody identified is more actionable
than one nobody could reach). Do not resolve an unevaluable assertion to PASS
because the skill "probably" handles it — that judgement is what the spec exists
to replace.
For **Protocol Compliance** assertions (always present):
- Check whether the skill requires "May I write" before file writes
@@ -308,8 +353,8 @@ For each agent in catalog's `agents:` section:
=== Skill Test Coverage Audit ===
Date: [date]
SKILLS (72 total)
Specs written: 72 (100%) | Never static tested: 72 | Never category tested: 72
SKILLS (74 total)
Specs written: 72 (97%) | Never static tested: 74 | Never category tested: 74
Skill | Cat | Has Spec | Last Static | S.Result | Last Cat | C.Result | Priority
-----------------------|----------|----------|-------------|----------|----------|----------|----------
+187 -28
View File
@@ -1,12 +1,16 @@
---
name: smoke-check
description: "Run the critical path smoke test gate before QA hand-off. Executes the automated test suite, verifies core functionality, and produces a PASS/FAIL report. Run after a sprint's stories are implemented and before manual QA begins. A failed smoke check means the build is not ready for QA."
description: "Critical-path smoke gate before QA hand-off — runs the automated suite. A failed check means the build is not QA-ready."
argument-hint: "[sprint | quick | --platform pc|console|mobile|all]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,qa.level,testing.strict`
# Smoke Check
This skill is the gate between "implementation done" and "ready for QA
@@ -21,6 +25,16 @@ Handing a broken build to QA wastes their time and demoralises the team.
---
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`qa.level`**: at `minimal`, smoke-check is **optional** — if
run, a FAIL is advisory and never blocks hand-off; at `standard`, it is required
before a phase transition; at `full`, before every commit. This sits in front of
the Phase 6 `testing.strict.config` resolution (which only matters once a smoke run
gates). Distinct axis from `workflow`.
## Parse Arguments
Arguments can be combined: `/smoke-check sprint --platform console`
@@ -46,17 +60,50 @@ Phase 5 outputs a per-platform verdict table in addition to the overall verdict.
Before running anything, understand the environment:
1. **Test framework check**: verify `tests/` directory exists.
If it does not: "No test directory found at `tests/`. Run `/test-setup`
to scaffold the testing infrastructure, or create the directory manually
if tests live elsewhere." Then stop.
0. **Config coherence**: run `bash .claude/scripts/project-coherence.sh`.
It compares what `project.yaml` declares against the real project file, the
installed engine binary, and the files `commands.*` name. This runs first
because two of its checks are about *this skill's own inputs*: a
`commands.test` naming a runner that does not exist, or a `commands.build`
naming an export preset with no `export_presets.cfg`, will fail here and read
as a broken build rather than as broken config.
Report any `[DIFFERS]` lines in the report's Environment section. They do not
by themselves decide the verdict -- but a smoke check run against a project
whose declared engine is not the installed one is worth saying out loud.
1. **Test framework check**: verify that **game** test files exist — not merely
that `tests/` does. Check `tests/unit/`, `tests/integration/` and
`tests/smoke/` for actual test files.
If none are found, **deliver a NOT ASSESSED verdict — do not merely stop.**
"Smoke check: **NOT ASSESSED — no game tests found** under
`tests/unit|integration|smoke`. Run `/test-setup` to scaffold the testing
infrastructure, or point me at where tests live." Then stop.
> A bare halt is the wrong shape here.
> This is the state with the **least** information about build health, so it is
> the last one that should exit without a verdict: the caller gets no
> machine-readable outcome, and "the skill said nothing" is easy to read as
> "nothing was wrong". Replacing a *wrong* verdict with *no* verdict is not an
> improvement either — the honest result is the one that names what could not
> be established.
> **Do not gate on `tests/` existing.** `/test-setup` creates `tests/unit/`
> and `tests/integration/` with placeholder files, so the directory tree is
> present on any project that ran setup — whether or not a single game test
> was ever written. Count actual test files instead. That is not
> hypothetical: a fixture with no build and zero game tests passed this step
> and went on to score **PASS WITH WARNINGS**.
2. **CI check**: check whether `.github/workflows/` contains a workflow file
referencing tests. Note in the report whether CI is configured.
3. **Engine detection**: read `.claude/docs/technical-preferences.md` and
extract the `Engine:` value. Store this for test command selection in
Phase 2.
3. **Engine detection**: read `engine.name` from `project.yaml`; if that key
is absent or empty (including when `project.yaml` has no `engine:` block),
fall back to the `Engine:` value in `.claude/docs/technical-preferences.md`
(a `[TO BE CONFIGURED]` value means not configured). Store this for test
command selection in Phase 2.
4. **Smoke test list**: check whether `production/qa/smoke-tests.md` or
`tests/smoke/` exists. If a smoke test list is found, load it for use in
@@ -90,16 +137,26 @@ If neither path exists, note: "GDUnit4 runner not found — confirm the runner
path for your test framework."
**Unity:**
Unity tests require the editor and cannot be run headlessly via shell in most
environments. Check for recent test result artifacts:
Unity **can** run tests headlessly via shell. Do not skip to reading artifacts.
First confirm the Unity Test Framework is installed. A project without it does
not fail cleanly — it **hangs** until something kills it, which is the
observation the old "Unity cannot test headlessly" advice was generalised from:
```bash
# List most recent test results (bash) — on Windows PowerShell use the fallback below
ls -t test-results/ 2>/dev/null | head -5 \
|| powershell -Command "Get-ChildItem test-results/ -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 5 -ExpandProperty Name"
grep -q 'com.unity.test-framework' Packages/manifest.json && echo present || echo ABSENT
```
If test result files exist (XML or JSON), read the most recent one and parse
PASS/FAIL counts. If no artifacts exist: "Unity tests must be run from the
editor or CI pipeline. Please confirm test status manually before proceeding."
If ABSENT, report `NOT ASSESSED — Unity Test Framework not installed` and
give the one-line fix (add `com.unity.test-framework` to `Packages/manifest.json`).
**Do not fall through to reading stale artifacts** — an unknown-age XML
reported as a pass is worse than no gate.
If present, run the suite with an explicit timeout:
```bash
timeout 900 "<Unity.exe>" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/results.xml
```
Parse `test-results/results.xml` for the `passed` and `failed` counts on the
`<test-run>` element. **A timeout (exit 124) is a gate FAILURE, never a pass** —
the run never completed and nothing was verified.
**Unreal Engine:**
```bash
@@ -111,19 +168,23 @@ If no matching log found: "UE automation tests must be run via the Session
Frontend or CI pipeline. Please confirm test status manually."
**Unknown engine / not configured:**
"Engine not configured in `.claude/docs/technical-preferences.md`. Run
`/setup-engine` to specify the engine, then re-run `/smoke-check`."
"Engine not configured in `project.yaml` or
`.claude/docs/technical-preferences.md`. Run `/setup-engine` to specify the
engine, then re-run `/smoke-check`."
**If the test runner is not available in this environment** (engine binary not
on PATH, runner script not found, etc.), report clearly:
"Automated tests could not be executed — engine binary not found on PATH.
Status will be recorded as NOT RUN. Confirm test results from your local IDE
or CI pipeline. Unconfirmed NOT RUN is treated as PASS WITH WARNINGS, not
FAIL — the developer must manually confirm results."
or CI pipeline. Until you do, the verdict is NOT ASSESSED — not FAIL, and not
a pass either: nothing has been observed about this build yet."
Do not treat NOT RUN as an automatic FAIL. Record it as a warning. The
developer's manual confirmation in Phase 4 can resolve it.
Do not treat NOT RUN as an automatic FAIL. Record it, and let the developer's
manual confirmation in Phase 4 resolve it. Until that confirmation arrives the
verdict is **NOT ASSESSED** (see the verdict rules in Phase 5), which ranks
above both pass values and below FAIL. An unrun suite is not a healthy build; it
is an unknown one, and the two need different follow-ups.
Parse runner output and extract:
- Total tests run
@@ -178,6 +239,15 @@ Draw the smoke test checklist from, in priority order:
3. `tests/smoke/` directory contents (if it exists)
4. The standard fallback list below (used only when none of the above exist)
**Name the source you used in the report**, on its own line — *"Checklist source:
`production/qa/smoke-tests.md`"*, or *"Checklist source: standard fallback list —
no QA plan scope, no `production/qa/smoke-tests.md`, no `tests/smoke/`."* The
fallback is a real fallback, so nothing is silently skipped here; what was
missing is that a report drawn from the generic list and one drawn from this
project's own smoke definitions were indistinguishable. `/gate-check` now
validates a smoke report's claims against the repo, and it cannot weigh them
without knowing what the checklist was drawn from.
Tailor batches 2 and 3 to the actual systems identified from the sprint or QA
plan. Replace bracketed placeholders with real mechanic names from the current
sprint's stories.
@@ -301,7 +371,7 @@ will determine whether the automated test row contributes to a FAIL verdict."
| Story | Type | Test File | Coverage Status |
|-------|------|-----------|----------------|
| [title] | Logic | `tests/unit/[system]/[slug]_test.[ext]` | COVERED |
| [title] | Visual/Feel | `tests/evidence/[slug]-screenshots.md` | MANUAL |
| [title] | Visual/Feel | `production/qa/evidence/[slug]-screenshots.md` | MANUAL |
| [title] | Logic | — | MISSING ⚠ |
| [title] | Config/Data | — | EXPECTED |
@@ -346,7 +416,7 @@ Any platform with one or more FAIL checks contributes to the overall FAIL verdic
---
### Verdict: [PASS | PASS WITH WARNINGS | FAIL]
### Verdict: [PASS | PASS WITH WARNINGS | NOT ASSESSED | FAIL]
[Verdict rules — first matching rule wins:]
@@ -355,8 +425,21 @@ Any platform with one or more FAIL checks contributes to the overall FAIL verdic
- Any Batch 1 (core stability) check returned FAIL
- Any Batch 2 (primary sprint mechanic or regression check) returned FAIL
**NOT ASSESSED** if ANY of:
- The automated suite is **unconfirmed NOT RUN** — nobody has reported a result
- A Batch 1 or Batch 2 check could not be executed (no build, engine not
configured, platform unavailable) as opposed to executing and failing
- **Any story's coverage row is `UNKNOWN`** (Phase 3: story file missing or
unreadable). A story nobody could read is not a story with no gaps — without
this line, a run where *every* row is UNKNOWN and the suite passes matches
**PASS**, because PASS only requires "no MISSING entries"
- **Batch 3 was offered and skipped** ("Performance not checked this session").
It is not a FAIL, not an execution failure, and not "PASS or N/A", so without
this line it matches no rule at all and renders as `[-]` beside a PASS
**PASS WITH WARNINGS** if ALL of:
- Automated tests PASS or NOT RUN (developer has not yet confirmed)
- Automated tests PASS, or NOT RUN **and the developer has confirmed the result
from their local IDE or CI**
- All Batch 1 and Batch 2 smoke checks PASS
- One or more Logic/Integration stories have MISSING test evidence
@@ -366,6 +449,19 @@ Any platform with one or more FAIL checks contributes to the overall FAIL verdic
- No MISSING test evidence entries
````
**`NOT ASSESSED` — the build nobody could check.** Rank: it **outranks PASS and
PASS WITH WARNINGS** and **ranks below FAIL**. A suite that never ran has not
shown the build is healthy; a suite that ran and failed is the more actionable
finding and must not be demoted behind one that did not run.
This is a change in where unconfirmed `NOT RUN` lands, and it is deliberate. The
rule below — **never treat NOT RUN as an automatic FAIL** — is unchanged and
still correct: NOT ASSESSED is not a FAIL, and it ranks below one. What changes
is that an unrun suite no longer resolves to a *pass* verdict while waiting for a
confirmation that may never come. Confirmed NOT RUN (the developer reports the
result from their own IDE or CI) still lands at PASS WITH WARNINGS, because
somebody did look.
---
## Phase 6: Write and Gate
@@ -376,9 +472,36 @@ Present the full report in conversation, then ask:
Write only after approval.
**First apply `qa.level` (resolved earlier).** At `qa.level: minimal`, a FAIL is
**advisory** regardless of `testing.strict.config` — skip the resolution below and
deliver the advisory-FAIL outcome (smoke-check is optional at minimal and never
blocks hand-off). Otherwise:
**Resolve the gate enforcement level.** A FAIL verdict either *blocks* QA
hand-off or is *flagged while hand-off proceeds*, governed by the
`testing.strict` block **resolved in the resolved-config block at the top of this skill** (which merges
`project.local.yaml` over `project.yaml` — read that block, not the file, or a
developer's local override is silently ignored):
1. Take `testing.strict.config` 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` or `false`, it applies.
3. Else default to **blocking** — an unset `testing.strict.config` keeps
smoke-check's FAIL gate blocking (behavior unchanged from before this setting
existed). Smoke check is a build-health gate, so its unset default is strict
even though the `config` test type defaults to advisory elsewhere. The
reciprocal carve-out is recorded in `.claude/skills/story-done/SKILL.md` and
`.claude/docs/coding-standards.md`, which own the per-story evidence table.
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.
After writing, deliver the gate verdict:
**If verdict is FAIL:**
**If verdict is FAIL and the gate is blocking:**
"The smoke check failed. Do not hand off to QA until these failures are
resolved:
@@ -387,6 +510,37 @@ resolved:
Fix the failures and run `/smoke-check` again to re-gate before QA hand-off."
**If verdict is FAIL and the gate is advisory** (`testing.strict.config: false`):
"The smoke check failed, but `testing.strict.config` is set to advisory — QA
hand-off is not blocked. Resolve these before release:
[List each failing automated test or smoke check with a one-line description]
QA hand-off: share `production/qa/qa-plan-[sprint].md` with the qa-tester
agent to begin manual verification. Re-run `/smoke-check` once the failures
are fixed."
**If verdict is NOT ASSESSED:**
"The smoke check could not establish build health — it did not fail, it did not
run. Do not hand off to QA on this result:
[Name each check that could not execute, and why: suite unconfirmed NOT RUN,
engine binary absent, no build, platform unavailable]
[For each, the one thing that would make it runnable — e.g. 'confirm the suite
result from your IDE or CI', 'run `/setup-engine`', 'produce a build'.]
Re-run `/smoke-check` once any of those is resolved."
This outcome is **not governed by `testing.strict.config`**. That setting decides
whether a *failure* blocks hand-off; it has nothing to say about a check that
never produced a result, and reading an unrun check as advisory-therefore-fine is
the exact substitution this verdict exists to prevent. Say what could not be
checked and let the user decide — do not resolve it to either pass or FAIL on
their behalf.
**If verdict is PASS WITH WARNINGS:**
"Smoke check passed with warnings. The build is ready for manual QA.
@@ -408,9 +562,14 @@ agent to begin manual verification."
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
- **Never treat NOT RUN as automatic FAIL** — record it as NOT RUN and let
the developer confirm status manually. Unconfirmed NOT RUN contributes to
PASS WITH WARNINGS, not FAIL.
the developer confirm status manually. Unconfirmed NOT RUN yields **NOT
ASSESSED**, not FAIL — and not a pass verdict either, which is what it used to
yield.
- **Never auto-fix failures** — report them and state what must be resolved.
Do not attempt to edit source code or test files.
- **PASS WITH WARNINGS does not block QA hand-off** — it records advisory
+58 -14
View File
@@ -1,12 +1,20 @@
---
name: soak-test
description: "Generate a soak test protocol for extended play sessions. Defines what to observe, measure, and log during long play sessions to surface slow leaks, fatigue effects, and edge cases that only appear after sustained play. Primarily used in Polish and Release phases."
description: "Soak test protocol for extended play — what to observe and log for slow leaks, fatigue, late-appearing edge cases."
argument-hint: "[duration: 30m | 1h | 2h | 4h] [focus: memory | stability | balance | all]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Soak Test
A soak test (also called an endurance test) is an extended play session run
@@ -53,16 +61,18 @@ human does the actual playing.**
## 2. Load Context
Read:
- `.claude/docs/technical-preferences.md` — engine (for engine-specific memory
monitoring guidance), performance budgets (memory ceiling, target FPS)
- `project.yaml` — `engine.name` (for engine-specific memory monitoring
guidance) and `performance.*` budgets (memory ceiling, target FPS); for any
key absent or empty (including when `project.yaml` has no `performance` or
`engine` block), fall back to `.claude/docs/technical-preferences.md`
- `design/gdd/game-concept.md` — intended session length (for comparison against
soak duration), core loop description
- Most recent file in `production/playtests/` — prior playtest findings
- Most recent file in `production/qa/playtests/` — prior playtest findings
(to avoid re-documenting known issues)
- Most recent file in `production/qa/qa-plan-*.md` — current sprint test coverage
(to understand what has been formally tested vs. what the soak covers)
Note any performance budget targets from technical-preferences.md:
Note any performance budget targets (`performance.*` from `project.yaml`, else `.claude/docs/technical-preferences.md`):
- Memory ceiling: [N MB, or "not set"]
- Target FPS: [N, or "not set"]
- Frame budget: [N ms, or "not set"]
@@ -87,26 +97,46 @@ Phase 4.
### Memory / Stability observation items (if focus = memory or all)
Engine-specific monitoring guidance:
Engine-specific monitoring guidance.
> **Record the unit the tool shows; never convert, and never assume one.**
> A soak test looks for **growth**, so every threshold below is a *ratio or a
> delta against this session's own T+0 baseline* — which is unit-agnostic and
> stays correct however the editor reports the number. Write the unit down at
> T+0 exactly as displayed and use it consistently for the rest of the run.
>
> This replaces a note asserting the return units of
> `Performance.get_monitor` — **NOT SOURCEABLE from `docs/engine-reference/`**,
> the identifier appears nowhere in it — a claim that sat one line under a row asking
> the tester to record "Static Memory (**KB**)". A wrong units claim in a leak
> detector is off by 1024× in the one measurement the protocol exists to take,
> and it would read as a plausible instruction throughout. Deltas need no such
> claim, so the safest fix was to stop needing it.
**Godot 4:**
- Open Debugger → Monitors tab; track `Memory → Static Memory` and
`Object Count → Objects` across checkpoints
- Record: Static Memory (KB), Object Count, Orphan Nodes count
- Record: Static Memory (**unit as displayed**), Object Count, Orphan Nodes count
- Alert threshold: Memory growth > 20% from T+0 after the first 15 minutes
(some growth on load is expected; sustained growth indicates a leak)
- Note: `Performance.get_monitor(Performance.MEMORY_STATIC)` returns bytes
in Godot 4.6
- **Orphan Nodes is the one absolute number worth watching**: it should return to
its T+0 value after a scene unload. A ratio hides that; a non-zero floor that
keeps rising is a leak regardless of units
**Unity:**
- Open Memory Profiler (Window → Analysis → Memory Profiler)
- Record: Total Reserved Memory (MB), GC Allocated (MB), Object Count at each checkpoint
- Alert threshold: GC Allocated growing monotonically across 3+ checkpoints
- Record: Total Reserved Memory, GC Allocated, Object Count at each checkpoint
(**units as displayed**)
- Alert threshold: GC Allocated growing monotonically across 3+ checkpoints —
a monotonicity check, deliberately unit-free
**Unreal Engine:**
- Use `stat memory` console command at each checkpoint
- Record: Physical Memory Used (MB), Physical Memory Available
- Alert threshold: Physical Memory Used growth > 50MB over the full soak
- Record: Physical Memory Used, Physical Memory Available (**units as displayed**)
- Alert threshold: Physical Memory Used growth **> 20% over the full soak**,
measured against this run's T+0. The previous threshold was an absolute
"> 50MB", which silently assumes both the unit *and* a project scale — 50MB is
a rounding error for one game and a catastrophe for another
### Stability observation items (if focus = stability or all)
@@ -235,12 +265,26 @@ Difficulty arc: [appropriate / too easy throughout / difficulty spike at T+N]
---
## Verdict: PASS / PASS WITH CONCERNS / FAIL
## Verdict: PASS / PASS WITH CONCERNS / NOT ASSESSED / FAIL
**PASS**: No leaks detected, stability maintained, fun factor consistent
**PASS WITH CONCERNS**: Minor drift or fatigue noted; addressable in Polish
**NOT ASSESSED**: The soak did not run to a length that could show what it looks
for — say how far it got and which checkpoints were never reached
**FAIL**: Memory leak confirmed, stability breach, or severe fun fatigue
> **A short soak cannot return PASS.** Everything this protocol exists to detect
> — slow leaks, fatigue, late-appearing edge cases — is by definition invisible
> early, so a session that ended before the checkpoints it was built around has
> not shown stability; it has shown nothing yet. Record `NOT ASSESSED — reached
> T+[N] of [duration]; checkpoints [list] not reached`. Ranks **above both pass
> values** and **below FAIL**: a crash observed at T+20 is a real finding no
> matter how short the run, and must not be demoted behind the run's length.
> The same applies when the build crashed for reasons unrelated to the soak, when
> no memory instrumentation was available (nothing was measured, so "no leaks
> detected" means "no leaks could have been detected"), or when the protocol was
> written but never executed — a protocol document is not a result.
---
## Sign-Off
+88 -25
View File
@@ -1,47 +1,110 @@
---
name: sprint-plan
description: "Generates a new sprint plan or updates an existing one based on the current milestone, completed work, and available capacity. Pulls context from production documents and design backlogs."
description: "New or updated sprint plan from the current milestone, completed work, and available capacity."
argument-hint: "[new|update|status] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion
model: sonnet
context: |
!ls production/sprints/ 2>/dev/null
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,story_granularity,workflow`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
## Existing Sprints
!`ls production/sprints/ 2>/dev/null || echo "(no production/sprints/ directory yet)"`
Resolved before this skill runs — use it to identify the previous sprint in
Phase 1 rather than re-globbing.
---
## Phase 0: Parse Arguments
Extract the mode argument (`new`, `update`, or `status`) and resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
Extract the mode argument (`new`, `update`, or `status`).
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**`story_granularity`** — it sets how
many stories to allocate per sprint, scaled by velocity: **2–4** at `coarse`,
**6–10** at `balanced` (default), **15–25** at `fine`.
**Review mode check** (before gates run):
- Read `production/review-mode.txt` if it exists. Use that mode.
- If the file doesn't exist and this is a `new` sprint: use `AskUserQuestion`:
- The review mode was already resolved in steps 1–4 above — do not re-resolve it.
- **Special case:** if steps 1–3 all found nothing configured (no `--review`
flag, no `modes.review_mode` in `project.yaml`, no `production/review-mode.txt`)
**and** this is a `new` sprint, do not silently take the step-4 `lean` default
— instead use `AskUserQuestion`:
- Prompt: "No review mode is set. Which review depth would you like for this sprint?"
- Options:
- `[A] full — spawn all director and lead gates`
- `[B] lean — skip non-phase-gate director reviews (recommended for most sprints)`
- `[C] solo — skip all gate spawning`
- After selection: write `production/review-mode.txt` with the chosen mode. Say: "Review mode set to [mode] and saved to production/review-mode.txt."
- If the file doesn't exist and this is NOT a `new` sprint (e.g., updating an existing sprint): default to `lean` silently.
- After selection: dual-write the chosen mode — set `modes.review_mode` in `project.yaml` (primary; add the `modes:` block if absent) AND write `production/review-mode.txt` (legacy fallback). Say: "Review mode set to [mode] and saved to project.yaml (and production/review-mode.txt)."
- In every other case the value resolved in steps 1–4 stands (for a non-`new`
sprint with nothing configured, that is the `lean` default).
> **Do not write until Phase 1 confirms the sprint can be planned.** This write
> lands in Phase 0, before the Phase 1 backlog check that aborts the run —
> observed live: the run correctly BLOCKED on "No stories found under
> `production/epics/`" and `project.yaml` had *already* gained
> `review_mode: lean`. A skill that decides it cannot run must not have edited
> config on the way to deciding. Hold the selection in memory, complete Phase 1,
> and write only if planning proceeds.
> **Confirm the destination before writing.** The question above asks for review
> depth "for this sprint"; the write is permanent project config on a
> rigor-fronted knob. Ask explicitly: "Set `modes.review_mode: [mode]` in
> `project.yaml` (persists beyond this sprint), or use it for this sprint only?"
---
## Phase 1: Gather Context
1. **Read the current milestone** from `production/milestones/`.
1. **Read the current milestone** from `production/milestones/` **if it exists**.
No skill writes this directory — it is authored by hand from
`.claude/docs/templates/milestone-definition.md`. On the majority of projects
it is absent, which is the normal state, not a gap: note "no milestone
defined — planning against the story backlog alone" and continue. Never block
sprint planning on it, and never infer a milestone from the sprint files.
2. **Read the previous sprint** (if any) from `production/sprints/` to
understand velocity and carryover.
3. **Scan design documents** in `design/gdd/` for features tagged as ready
for implementation.
3. **Find the stories to plan** — this is the actual backlog, and it is the one
input this phase cannot do without:
```
Glob production/epics/**/story-*.md
Grep pattern="^> \*\*Status\*\*" glob="production/epics/**/story-*.md" output_mode="content"
```
Stories live at `production/epics/[epic-slug]/story-NNN-[slug].md` — that is
where `/create-stories` writes them and where `/dev-story` looks for them. Plan
from the ones marked `Ready`. Use the grep rather than reading each story: at
this stage you need status and title, not the body.
4. **Check the risk register** at `production/risk-register/`.
If the glob returns nothing: "No stories found under `production/epics/`. Run
`/create-stories` first (at `standard`/`full`, `/create-epics` before it)."
Do not proceed to invent work items — a sprint plan that references stories
which do not exist cannot be implemented.
4. **Scan design documents** in `design/gdd/` for additional context on the
features those stories implement. At `workflow: minimal` there are no
per-system GDDs — use `design/game-brief.md` instead, and do not treat the
absent GDDs as missing work. (Note: `/sprint-plan` is **optional** at
`minimal` — the brief's Build order already is the plan.)
5. **Check the risk register** at `production/risk-register/` **if it exists**.
Like the milestone above, no skill writes it — entries are authored by hand
from `.claude/docs/templates/risk-register-entry.md`. If the directory is
absent, say so once ("no risk register — risks assessed from the sprint
contents only") rather than skipping risk assessment silently.
---
@@ -49,7 +112,7 @@ See `.claude/docs/director-gates.md` for the full check pattern.
For `new`:
**Generate a sprint plan** following this format and present it to the user. Do NOT ask to write yet — the producer feasibility gate (Phase 4) runs first and may require revisions before the file is written.
**Generate a sprint plan** following this format and present it to the user. Do NOT ask to write yet — the gate phases run first and may require revisions before the file is written: the producer feasibility gate (Phase 4, spawned only in `full` review mode — skipped in `lean`/`solo`) and the QA plan check (Phase 5, all modes).
```markdown
# Sprint [N] — [Start Date] to [End Date]
@@ -153,7 +216,7 @@ After generating a new sprint plan, also prepare the `production/sprint-status.y
This is the machine-readable source of truth for story status — read by
`/sprint-status`, `/story-done`, and `/help` without markdown parsing.
**Do not write the yaml yet** — hold it in context. The producer feasibility gate (Phase 4) may revise the story list. Both files will be written together after Phase 4 in a single write approval.
**Do not write the yaml yet** — hold it in context. The producer feasibility gate (Phase 4, `full` review mode only) may revise the story list; the QA plan check (Phase 5) runs in every mode. Both files are written together after Phase 5 in a single write approval.
Format:
@@ -179,7 +242,7 @@ updated: "[YYYY-MM-DD]"
stories:
- id: "[epic-story, e.g. 1-1]"
name: "[story name]"
file: "[production/stories/path.md]"
file: "[production/epics/[epic-slug]/story-NNN-[slug].md]" # the real path, verbatim from the Glob above
priority: must-have # must-have | should-have | nice-to-have
status: ready-for-dev # backlog | ready-for-dev | in-progress | review | done | blocked
owner: ""
@@ -205,7 +268,7 @@ stories that haven't changed, add new stories, remove dropped ones.
- `lean` → skip (not a PHASE-GATE). Note: "PR-SPRINT skipped — Lean mode." Proceed to Phase 5 (QA plan gate).
- `full` → spawn as normal.
Before finalising the sprint plan, spawn `producer` via Task using gate **PR-SPRINT** (`.claude/docs/director-gates.md`).
Before finalising the sprint plan, spawn `producer` via `Agent` using gate **PR-SPRINT** (`.claude/docs/director-gates/pr-sprint.md`).
Pass: proposed story list (titles, estimates, dependencies), total team capacity in hours/days, any carryover from the previous sprint, milestone constraints and deadline.
@@ -273,9 +336,9 @@ After the sprint plan is written and QA plan status is resolved:
- `/sprint-status` — check progress mid-sprint
- `/scope-check [epic]` — verify no scope creep before implementation begins
**Review mode configuration:** All director gates (producer feasibility, QA review, code review) respect the project review mode. The review mode is set in Phase 0 when the file does not exist (for `new` sprints), or can be overridden per-run with `--review full|lean|solo` as an argument. The file `production/review-mode.txt` contains one of:
- `lean` — skip automated director gates (default if file is absent — fastest for solo dev)
**Review mode configuration:** All director gates (producer feasibility, QA review, code review) respect the project review mode, resolved by the Phase 0 chain (`--review` flag → `modes.review_mode` in `project.yaml` → `production/review-mode.txt` → the `modes.rigor` expansion, which yields `lean` at standard rigor and `solo` at minimal). For a `new` sprint with nothing configured, Phase 0 prompts for it and dual-writes the choice. The mode is one of:
- `lean` — skip non-phase-gate director gates (default — fastest for solo dev)
- `full` — run all director gates as spawned sub-agents
- `solo` — skip all gates unconditionally (single-developer, no review)
- `solo` — skip all gate spawning unconditionally (single developer, no review)
This file is read by `/sprint-plan`, `/story-readiness`, `/story-done`, and other skills at startup.
`modes.review_mode` in `project.yaml` is the primary source; `production/review-mode.txt` is the legacy fallback. Both are read by `/sprint-plan`, `/story-readiness`, `/story-done`, and other gate-using skills at startup.
+26 -6
View File
@@ -1,12 +1,16 @@
---
name: sprint-status
description: "Fast sprint status check. Reads the current sprint plan, scans story files for status, and produces a concise progress snapshot with burndown assessment and emerging risks. Run at any time during a sprint for quick situational awareness. Use when user asks 'how is the sprint going', 'sprint update', 'show sprint progress'."
description: "Fast, concise sprint snapshot — burndown and emerging risks for situational awareness. 'How is the sprint going?'"
argument-hint: "[sprint-number or blank for current]"
user-invocable: true
allowed-tools: Read, Glob, Grep
model: haiku
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys story_granularity`
# Sprint Status
This is a fast situational awareness check, not a sprint review. It reads the
@@ -17,6 +21,10 @@ concise snapshot in under 30 lines. For detailed sprint management, use
**This skill is read-only.** It never proposes changes, never asks to write
files, and makes at most one concrete recommendation.
**`story_granularity`** — it sets the
grain of the burn-down read: **feature-sized** chunks at `coarse`, **task-sized**
at `balanced` (default), **AC-sized** at `fine`.
---
## 1. Find the Sprint
@@ -74,7 +82,7 @@ fall back to markdown scanning:
When using the fallback, add a note at the bottom of the output:
"⚠ No `sprint-status.yaml` found — status inferred from markdown. Run `/sprint-plan update` to generate one."
Optionally (fast check only — do not do a deep scan): grep `src/` for a
Optionally (fast check only — do not do a deep scan): grep the code root for a
directory or file name that matches the story's system slug to check for
implementation evidence. This is a hint only, not a definitive status.
@@ -82,10 +90,22 @@ implementation evidence. This is a hint only, not a definitive status.
After collecting status for all stories, check each IN PROGRESS story for staleness:
- For each story that has a referenced file, read the file and look for a
`Last Updated:` field in the frontmatter or header (e.g., `Last Updated: 2026-04-01`
or `updated: 2026-04-01`). Accept any reasonable date field name: `Last Updated`,
`Updated`, `last-updated`, `updated_at`.
- Resolve the dates with **one grep across the story set, not a read per story**
— a date is a single line, and opening every in-progress story to find it is
the whole cost of this check:
```
Grep pattern="\*{0,2}(Last Updated|Updated|last-updated|updated_at)\*{0,2}[[:space:]]*:" glob="production/epics/**/story-*.md" output_mode="content"
```
That one pattern accepts every field-name variant. A story with no match has
**no date**, which is not the same as being stale — report it as "never
stamped" and do not compute an age for it.
> **The `\*{0,2}` wrappers are why this works at all.** `/create-stories` emits
> `> **Last Updated**: …`, so a pattern requiring `:` immediately after the word
> matched no story ever written. Combined with the "no match = never stamped"
> rule directly above — which is correct in itself — the failure was completely
> silent: every in-progress story reported as never stamped, and stale-story
> detection never once fired. A bare `Updated:` anchor will regress it.
- Calculate days since that date using today's date.
- If the date is more than 4 days ago, flag the story as **STALE**. (4-day threshold accounts for weekends — a story last touched on Friday won't appear stale until Wednesday.)
- If no date field is found in the story file, note "no timestamp — cannot check staleness."
+226 -99
View File
@@ -1,28 +1,53 @@
---
name: start
description: "First-time onboarding — asks where you are, then guides you to the right workflow. No assumptions."
description: "First-time onboarding — asks where you are, then guides you to the right workflow."
argument-hint: "[no arguments]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion
model: sonnet
---
# Guided Onboarding
This skill writes one file: `production/review-mode.txt` (review mode config set in Phase 3b).
This skill writes `project.yaml` — the `project.stage`, `modes.rigor` and
`modes.automation` settings — plus one legacy mirror, `production/stage.txt`,
for backward compatibility with hooks that have not migrated. `modes.rigor` and
`modes.automation` have no legacy mirror; they are written to `project.yaml`
only.
> **`/start` never writes `modes.review_mode`, in either location.** It is a
> rigor-fronted knob: writing it explicitly pins it and shadows the `modes.rigor`
> expansion, so the Phase 3d question would stop changing director-review depth
> (see Phase 3d, and the same rule in `project.yaml`'s header comment). It must
> **not** write `production/review-mode.txt` either — the legacy step sits
> **above** the rigor expansion in the resolution chain, deliberately, so a genuine
> v1.0 project's explicit choice survives migration. On a new project that
> ordering works against you: a mirror file written here would outrank the
> expansion permanently. Verified: `rigor: minimal` plus a `review-mode.txt`
> containing `lean` resolves to `lean`, not the expected `solo`.
This skill is the entry point for new users. It does NOT assume you have a game idea, an engine preference, or any prior experience. It asks first, then routes you to the right workflow.
---
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). **Note**: on a fresh project no
`modes.automation` is set yet, so `/start` runs collaboratively — it is
creating the config. Its core onboarding questions (starting point, rigor,
automation) are project-shaping and always prompt regardless
of mode. Engine choice is **not** among them — it is deferred to
`/setup-engine`, which Phase 4 hands off to.
If `/start` is re-run on an already-configured project, the resolved mode
applies per `.claude/docs/automation-modes.md`.
## Phase 1: Detect Project State
Before asking anything, silently gather context so you can tailor your guidance. Do NOT show these results unprompted — they inform your recommendations, not the conversation opener.
Check:
- **Engine configured?** Read `.claude/docs/technical-preferences.md`. If the Engine field contains `[TO BE CONFIGURED]`, the engine is not set.
- **Game concept exists?** Check for `design/gdd/game-concept.md`.
- **Source code exists?** Glob for source files in `src/` (`*.gd`, `*.cs`, `*.cpp`, `*.h`, `*.rs`, `*.py`, `*.js`, `*.ts`).
- **Engine configured?** Read `engine.name` from `project.yaml`; if that key is absent or empty (including when `project.yaml` has no `engine:` block), fall back to `.claude/docs/technical-preferences.md` (an Engine field of `[TO BE CONFIGURED]`, or no file, means not set). The engine is configured if either source yields a real engine name.
- **Game concept exists?** Check for `design/gdd/game-concept.md` (or `design/game-brief.md` at the `minimal` tier).
- **Source code exists?** Resolve the code root from the `engine.name` read above (`src/` Godot, `Assets/` Unity, `Source/` Unreal; full order in `.claude/docs/code-root-resolution.md`), then Glob it for source files (`*.gd`, `*.cs`, `*.cpp`, `*.h`, `*.rs`, `*.py`, `*.js`, `*.ts`). **If the code root is unresolved, say so rather than concluding there is no code** — a Unity or Unreal project scanned as `src/` returns zero files and reads as greenfield.
- **Prototypes exist?** Check for subdirectories in `prototypes/`.
- **Design docs exist?** Count markdown files in `design/gdd/`.
- **Production artifacts?** Check for files in `production/sprints/` or `production/milestones/`.
@@ -53,60 +78,32 @@ Wait for the user's selection. Do not proceed until they respond.
The user needs creative exploration before anything else.
1. Acknowledge that starting from zero is completely fine
2. Briefly explain what `/brainstorm` does (guided ideation using professional frameworks — MDA, player psychology, verb-first design). Mention that it has two modes: `/brainstorm open` for fully open exploration, or `/brainstorm [hint]` if they have even a vague theme (e.g., "space", "cozy", "horror").
2. Briefly explain what `/brainstorm` does: it turns "no idea" into a written design your next step can build from. Mention that it has two modes: `/brainstorm open` for fully open exploration, or `/brainstorm [hint]` if they have even a vague theme (e.g., "space", "cozy", "horror").
> **Describe it tier-neutrally here.** Phase 3d has not run, so you do not yet
> know how much process this project wants — and `/brainstorm` changes shape
> completely on that answer. At `minimal` it runs a short Lean Brief flow and
> stops, producing a one-page `design/game-brief.md`; at `standard`/`full` it
> runs the full ideation walk (MDA, player psychology, verb-first design) and
> produces the concept document. Naming the full walk here, then having Phase 4
> describe the same skill as "produce the one-page brief", gives the user two
> contradicting accounts of one skill inside a single `/start` run. Phase 4 is
> where the tier-specific description belongs.
3. Recommend running `/brainstorm open` as the next step, but invite them to use a hint if something comes to mind
4. Show the recommended path:
**Concept phase:**
- `/brainstorm open` — discover your game concept
- `/setup-engine` — configure the engine (brainstorm will recommend one)
- `/prototype` — throwaway concept build: validate the core idea is fun before designing (1–3 days)
- `/art-bible` — define visual identity (uses the Visual Identity Anchor brainstorm produces)
- `/map-systems` — decompose the concept into systems
- `/design-system` — author a GDD for each MVP system
- `/review-all-gdds` — cross-system consistency check
- `/gate-check` — validate readiness before architecture work
**Architecture phase:**
- `/create-architecture` — produce the master architecture blueprint and Required ADR list
- `/architecture-decision (×N)` — record key technical decisions, following the Required ADR list
- `/create-control-manifest` — compile decisions into an actionable rules sheet
- `/architecture-review` — validate architecture coverage
**Pre-Production phase:**
- `/ux-design` — author UX specs for key screens (main menu, HUD, core interactions)
- `/vertical-slice` — production-quality end-to-end build to validate the full game loop
- `/playtest-report (×1+)` — document each vertical slice playtest session
- `/create-epics` — map systems to epics
- `/create-stories` — break epics into implementable stories
- `/sprint-plan` — plan the first sprint
**Production phase:** → pick up stories with `/dev-story`
4. Name the **immediate next step only** — `/brainstorm open`. Do not list the
full pipeline here. Phase 3d has not yet asked how much process the user
wants, and that answer changes the path substantially. Say: "I'll lay out the
full path once I know how much process you want — two quick questions away."
#### If B: Vague idea
1. Ask them to share their vague idea — even a few words is enough
2. Validate the idea as a starting point (don't judge or redirect)
3. Recommend running `/brainstorm [their hint]` to develop it
4. Show the recommended path:
**Concept phase:**
- `/brainstorm [hint]` — develop the idea into a full concept
- `/setup-engine` — configure the engine
- `/prototype` — throwaway concept build: validate the core idea is fun before designing (1–3 days)
- `/art-bible` — define visual identity (uses the Visual Identity Anchor brainstorm produces)
- `/map-systems` — decompose the concept into systems
- `/design-system` — author a GDD for each MVP system
- `/review-all-gdds` — cross-system consistency check
- `/gate-check` — validate readiness before architecture work
**Architecture phase:**
- `/create-architecture` — produce the master architecture blueprint and Required ADR list
- `/architecture-decision (×N)` — record key technical decisions, following the Required ADR list
- `/create-control-manifest` — compile decisions into an actionable rules sheet
- `/architecture-review` — validate architecture coverage
**Pre-Production phase:**
- `/ux-design` — author UX specs for key screens (main menu, HUD, core interactions)
- `/vertical-slice` — production-quality end-to-end build to validate the full game loop
- `/playtest-report (×1+)` — document each vertical slice playtest session
- `/create-epics` — map systems to epics
- `/create-stories` — break epics into implementable stories
- `/sprint-plan` — plan the first sprint
**Production phase:** → pick up stories with `/dev-story`
4. Name the **immediate next step only** — `/brainstorm [their hint]`. Do not
list the full pipeline here; Phase 3d has not yet asked how much process the
user wants, and that answer changes the path. Say: "I'll lay out the full
path once I know how much process you want — two quick questions away."
#### If C: Clear concept
@@ -116,29 +113,10 @@ The user needs creative exploration before anything else.
- **Options**:
- `Formalize it first` — Run `/brainstorm [concept]` to structure it into a proper game concept document
- `Jump straight in` — Go to `/setup-engine` now and write the GDD manually afterward
3. Show the recommended path:
**Concept phase:**
- `/brainstorm` or `/setup-engine` — (their pick from step 2)
- `/prototype` — throwaway concept build: validate the core idea is fun before designing (1–3 days)
- `/art-bible` — define visual identity (after brainstorm if run, or after concept doc exists)
- `/design-review` — validate the concept doc
- `/map-systems` — decompose the concept into individual systems
- `/design-system` — author a GDD for each MVP system
- `/review-all-gdds` — cross-system consistency check
- `/gate-check` — validate readiness before architecture work
**Architecture phase:**
- `/create-architecture` — produce the master architecture blueprint and Required ADR list
- `/architecture-decision (×N)` — record key technical decisions, following the Required ADR list
- `/create-control-manifest` — compile decisions into an actionable rules sheet
- `/architecture-review` — validate architecture coverage
**Pre-Production phase:**
- `/ux-design` — author UX specs for key screens (main menu, HUD, core interactions)
- `/vertical-slice` — production-quality end-to-end build to validate the full game loop
- `/playtest-report (×1+)` — document each vertical slice playtest session
- `/create-epics` — map systems to epics
- `/create-stories` — break epics into implementable stories
- `/sprint-plan` — plan the first sprint
**Production phase:** → pick up stories with `/dev-story`
3. Name the **immediate next step only** — their pick from step 2. Do not list
the full pipeline here; Phase 3d has not yet asked how much process the user
wants, and that answer changes the path. Say: "I'll lay out the full path
once I know how much process you want — two quick questions away."
#### If D: Existing work
@@ -167,9 +145,38 @@ The user needs creative exploration before anything else.
---
## Phase 3c: Write Initial Stage File
## Phase 3c: Write Initial Stage
After confirming the starting path (and before asking about review mode), write the initial stage to `production/stage.txt`. Create the `production/` directory if it does not exist.
After confirming the starting path, write the initial stage to BOTH `project.yaml` (primary) AND `production/stage.txt` (legacy fallback for hooks that haven't migrated yet). Create the `production/` directory if it does not exist.
In `project.yaml`, ensure a `project:` block exists with `stage: [value]`.
- **If `project.yaml` already exists**: Read it first (the Edit tool requires the
file to have been read in this session), then use the Edit tool to add/update
the `project:` block, placing it immediately after the `framework:` block.
- **If `project.yaml` does not exist** at the repo root: create it with the Write
tool using this v1.1 minimal template (replace `[value]` and the date):
```yaml
# CCGS project configuration — single source of truth for project settings.
# Schema: grep the `## <key>` section of .claude/docs/effects-map.md —
# it is ~31k tokens whole, ~900 per section. Do not open it entire.
schema_version: 1
framework:
version: 1.1.0
last_upgraded: <YYYY-MM-DD>
project:
stage: [value]
```
**Do not seed `modes.review_mode` here.** It is a rigor-fronted knob —
`modes.rigor` supplies its value, so an explicit value here would shadow the
rigor expansion and pin the review mode regardless of the rigor the user picks
in Phase 3d. `modes.rigor` itself is omitted for a related reason: Phase 3d skips
its question when the key is already set, so seeding it would suppress that
question. Tests Y.3 and Y.6 lock both in.
Then also write the same single-line stage name to `production/stage.txt` (no trailing newline) so legacy tooling still works.
Stage mapping:
- **Path A, B, or C (starting from scratch)**: write `Concept`
@@ -177,40 +184,156 @@ Stage mapping:
- **Path D, existing project with GDDs but no architecture documents**: write `Systems Design`
- **Path D, existing project with full architecture (ADRs, architecture doc)**: write `Technical Setup`
Do this silently — no "May I write?" needed for this single-line file.
Do this silently — no "May I write?" needed for these stage anchors.
Say: "I've set `production/stage.txt` to `[stage]` — this anchors your status line and stage detection."
Say: "I've set `project.stage` to `[stage]` (and updated `production/stage.txt`) — this anchors your status line and stage detection."
---
## Phase 3b: Set Review Mode
## Phase 3d: Set Rigor
Check if `production/review-mode.txt` already exists.
Check whether `modes.rigor` is already set in `project.yaml`. **If it is**, show
it — "Rigor is set to `[current]`." — and proceed to **Phase 3e**. Do not ask
again. Either way, **carry the resolved value forward** — Phase 4 branches its
recommended path on it.
**If it exists**: Read it and show the current mode — "Review mode is set to `[current]`." — then proceed to Phase 4. Do not ask again.
**If it is not set**: first pick a recommendation, then ask.
**If it does not exist**: Use `AskUserQuestion`:
**Seed the recommendation** from what the user described in Phase 2, using the
archetype presets in `.claude/docs/settings-guidance.md § 2–3`:
- Map their concept to an archetype (e.g. "open-world RPG with crafting and
factions" → systems-heavy → `full`; "a small weekend puzzler" → `minimal`).
- If the user has **no concept at all** (Path A, or a Path B hint with nothing in
§3's signal table), recommend the jam/prototype option (`minimal`) and add:
"You can raise this after `/brainstorm` once the concept is clearer —
`/settings` changes it anytime."
- **A Path B hint still counts as a description.** "Still exploring" is about
having no signal, not about which path the user picked. If the vague idea trips
§3's signals — "some kind of open-world survival sim" hits open-world, sim and
survival — seed from the signal, not from the path, and say why in the user's
own terms. Recommending `minimal` for a described systems-heavy game is the
mismatch Phase 4 would then have to flag, caused here.
- If nothing in the description points either way, recommend the middle option
(`standard`, the documented default).
- **Prompt**: "One setup choice: how much design review would you want as you work through the workflow?"
Then use `AskUserQuestion`. Order the options so the **recommended** archetype is
first and append ` (Recommended)` to its label (per the AskUserQuestion
convention); the other two follow in any order.
- **Prompt**: "What best describes what you're building? This sets how much process
the project carries — you can change it anytime with `/settings`."
- **Options** (base labels — the recommended one also gets ` (Recommended)`):
- `Jam / prototype / first game` — Short docs, coarse stories, evidence optional. **~4 steps to your first line of code instead of ~18.** Shipping beats recording; design lives in your head. The trade: no GDDs, so design problems surface in code rather than before it.
- `Several systems that affect each other` — Balanced docs, normal story size, standard QA evidence. **Expect ~8 design documents and roughly an hour of design work before your first line of code.** Worth paying when systems interact and a design mistake is expensive to unpick once it is in code. **Intending to finish is not the test** — most small games ship faster on the jam path and can move up later with `/settings`.
- `Big systems-heavy or team project` — Thorough docs, fine-grained stories, evidence required everywhere. Many interacting systems (open-world, sim, RPG), a firm release date, or shared ownership.
Value mapping (ignore any ` (Recommended)` suffix on the first option):
`Jam / prototype / first game` → `minimal`, `Several systems that affect each other` → `standard`,
`Big systems-heavy or team project` → `full`.
Write `modes.rigor` to `project.yaml` immediately after the user selects — no
separate "May I write?" needed, as the write is a direct consequence of the
selection. Use the Edit tool to add it under the `modes:` block. There is **no
legacy mirror file** for this setting, so this is a single write, not a dual-write.
Then say: "Set `modes.rigor` to `[choice]`. That drives six settings —
`modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`,
`modes.review_mode` (director-review depth), and `team.size` (how many agents are
active on team tasks) — a lighter rigor means fewer reviews, a smaller active
team, and fewer tokens. Run `/settings` to see the exact value each one takes, or
set any of them explicitly to override just that one."
**Why this is asked here.** These six knobs each change what skills produce, and
before `rigor` existed `/start` never asked about any of them — so every project
silently ran at defaults the user had never seen. Asking once, at onboarding, is
the only point where the answer is cheap; skipping this question puts the project
back where it was.
---
## Phase 3e: Set Automation Mode
Check whether `modes.automation` is already set in `project.yaml`. **If it is**,
show it — "Automation is set to `[current]`." — and proceed to Phase 4. Do not
ask again.
**If it is not set**: Use `AskUserQuestion`:
- **Prompt**: "Last one: how much should I confirm with you as we work?"
- **Options**:
- `Full` — Director specialists review at each key workflow step. Best for teams, learning the workflow, or when you want thorough feedback on every decision.
- `Lean (recommended)` — Directors only at phase gate transitions (/gate-check). Skips per-skill reviews. Balanced approach for solo devs and small teams.
- `Solo` — No director reviews at all. Maximum speed. Best for game jams, prototypes, or if the reviews feel like overhead.
- `Collaborative` — I ask before each significant step and show drafts before writing. Most control; best while you are learning the workflow and want to see everything.
- `Guided (recommended)` — I decide the small stuff and proceed, but still stop for the big calls (scope changes, file deletions, schema changes). Far fewer interruptions than collaborative, without giving up control of the decisions that matter.
- `Autonomous` — I proceed and log decisions rather than asking, except for the always-ask categories. Fastest to run, but it makes every call itself and costs more tokens; best for trusted, well-scoped runs.
Write the choice to `production/review-mode.txt` immediately after the user
selects — no separate "May I write?" needed, as the write is a direct
consequence of the selection:
- `Full` → write `full`
- `Lean (recommended)` → write `lean`
- `Solo` → write `solo`
Value mapping: `Collaborative` → `collaborative`, `Guided (recommended)` →
`guided`, `Autonomous` → `autonomous`.
Create the `production/` directory if it does not exist.
Write `modes.automation` to `project.yaml` immediately after the user selects —
no separate "May I write?" needed, as the write is a direct consequence of the
selection. Use the Edit tool to add it under the `modes:` block. There is **no
legacy mirror file** for this setting.
Then say: "Set `modes.automation` to `[choice]`. See
`.claude/docs/automation-modes.md` for exactly what each mode asks vs. proceeds
on. `guided` and `autonomous` still always stop for the `automation_always_ask`
categories (scope changes, file deletions, schema changes)."
**Why this is asked here.** `modes.automation` controls how often every skill
stops to confirm. A project that wants to move fast should not have to discover
the knob after fifty approval prompts — that is the frustration this setting
answers. Asked once, at onboarding, like the others. Do **not** seed
`modes.automation` into the Phase 3c template: Phase 3e skips when the key is
already set, so seeding it would suppress its own question (the collision Y.3
and Y.6 guard for the other knobs).
---
## Phase 4: Confirm Before Proceeding
## Phase 4: Show the Path, Then Confirm
After presenting the recommended path, use `AskUserQuestion` to ask the user which step they'd like to take first. Never auto-run the next skill.
**Now** present the recommended path — after Phase 3d, so it can match the rigor
the user actually chose. Print **one** of the three below, using the `modes.rigor`
value resolved or written in Phase 3d; if it is somehow still unset, use
`standard` (its documented default) rather than skipping the path. (Paths A/B/C
only; path D users are retrofitting an existing project and were given their
path in Phase 3.)
Say first: "Here's your path at `rigor: [chosen]`. Every skill still runs at any
level — rigor changes what's *required*, not what's allowed. So at `minimal` you can
still call `/art-bible`, `/ux-design`, `/qa-plan` or anything else the moment you want
it — nothing is locked, it simply is not demanded up front. And if one system alone
deserves more care, raise just that one with
`workflow_overrides.system_overrides.<system>` rather than the whole project."
**If `minimal` — 4 steps to running code:**
- `/setup-engine` — configure the engine
- `/brainstorm` — produce the one-page `design/game-brief.md` (the lean-tier design artifact; it replaces the full concept doc, systems decomposition, and per-system GDDs)
- `/create-stories` — turn the brief's MVP list into implementable stories (the epic is implicit — no separate `/create-epics` or `/sprint-plan`; the brief's build order is the plan)
- `/dev-story` — **first line of game code**
**If `standard` (default) — the full pipeline:**
- **Concept:** `/setup-engine` → `/brainstorm` → `/prototype` → `/art-bible` → `/map-systems` → `/design-system` (×N systems) → `/review-all-gdds` → `/gate-check`
- **Architecture:** `/create-architecture` → `/architecture-decision` (×N) → `/create-control-manifest` → `/architecture-review`
- **Pre-Production:** `/ux-design` → `/create-epics` → `/create-stories` → `/sprint-plan`
- **Production:** `/dev-story`
**If `full` — the full pipeline plus validation builds:**
- Everything in `standard`, plus `/vertical-slice` and `/playtest-report` (×1+)
in Pre-Production, and `/design-review` after each GDD.
> **Do not present the minimal path as lesser.** It is the tier's documented
> floor (`.claude/docs/workflow-modes.md` — "engine choice and a filled
> `design/game-brief.md` are required before code starts … everything else can
> be skipped"), not a degraded mode. Equally, do not oversell it: at `minimal`
> there are no GDDs to catch design problems before they reach code, which is
> the trade being made.
If the user picked a rigor that contradicts what they described in Phase 2 —
overriding the seeded recommendation, e.g. choosing `minimal` after describing a
multi-year commercial project, or `full` for a weekend jam — apply the "mismatch"
trigger in `.claude/docs/settings-guidance.md § 4`: say so once, in one sentence,
and offer `/settings` to change it. Do not re-ask.
Then use `AskUserQuestion` to ask which step they'd like to take first. Never auto-run the next skill.
- **Prompt**: "Would you like to start with [recommended first step]?"
- **Options**:
@@ -230,14 +353,18 @@ Verdict: **COMPLETE** — user oriented and handed off to next step.
## Edge Cases
- **User picks D but project is empty**: Gently redirect — "It looks like the project is a fresh template with no artifacts yet. Would Path A or B be a better fit?"
- **User picks A but project has code**: Mention what you found — "I noticed there's already code in `src/`. Did you mean to pick D (existing work)?"
- **User is returning (engine configured, concept exists)**: Skip onboarding entirely — "It looks like you're already set up! Your engine is [X] and you have a game concept at `design/gdd/game-concept.md`. Review mode: `[read from production/review-mode.txt, or 'lean (default)' if missing]`. Want to pick up where you left off? Try `/sprint-plan` or just tell me what you'd like to work on."
- **User picks A but project has code**: Mention what you found — "I noticed there's already code in `[code root]`. Did you mean to pick D (existing work)?"
- **User is returning (engine configured, concept exists)**: Skip onboarding entirely — "It looks like you're already set up! Your engine is [X] and you have a game concept at `design/gdd/game-concept.md` (or a game brief at `design/game-brief.md`). Review mode: `[resolve modes.review_mode — an explicit value if set, otherwise it follows modes.rigor: minimal→solo, standard→lean, full→full]`. Want to pick up where you left off? Try `/sprint-plan` or just tell me what you'd like to work on."
- **User doesn't fit any option**: Let them describe their situation in their own words and adapt.
---
## Collaborative Protocol
**Applies in `collaborative` mode (the default).** For `guided` and
`autonomous` modes, see `.claude/docs/automation-modes.md` — the rules below
describe what collaborative mode requires, not universal behavior.
1. **Ask first** — never assume the user's state or intent
2. **Present options** — give clear paths, not mandates
3. **User decides** — they pick the direction
+86
View File
@@ -0,0 +1,86 @@
# /story-done — Handoff Contract
## Role in Pipeline
Closes the implementation loop for a single story by verifying every acceptance criterion, checking test evidence, detecting GDD/ADR deviations, and — after user approval — updating the story file to `Status: Complete` with a `## Completion Notes` section.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `production/epics/**/*.md` (the story file) | `Status:` (expected: `In Progress`, or `Ready` if `/dev-story` was skipped — `/dev-story` sets `In Progress`, and `/story-done` is the only skill that writes `Status: Complete`), `Type:`, `Manifest Version`, TR-ID(s), ADR reference(s), `## Acceptance Criteria`, list of files to create/modify, `## Test Evidence` path | No — status and completion notes written after approval |
| `docs/architecture/tr-registry.yaml` | Entry per TR-ID with current `requirement` text | Yes |
| GDD section referenced by each TR-ID | Acceptance criteria and key rules for cross-check | Yes |
| `docs/architecture/adr-NNNN-[slug].md` (referenced ADR) | `## Decision`, `## Consequences` | Yes |
| `docs/architecture/control-manifest.md` | `Manifest Version:` header date, forbidden patterns | Yes (existence checked; absent = skip staleness check) |
| `production/session-state/active.md` | Active story path (used when no argument given) | No — session extract appended |
### Test Evidence Files (presence checked, not pre-required to exist — absence triggers gate)
| Story Type | Expected Location |
|------------|------------------|
| Logic | `tests/unit/[system]/[story-slug]_test.[ext]` |
| Integration | `tests/integration/[system]/[story-slug]_test.[ext]` OR `production/session-logs/` playtest record |
| Visual/Feel | `production/qa/evidence/[story-slug]-evidence.md` + a retained screenshot |
| UI | `production/qa/evidence/[story-slug]-evidence.md` + a retained screenshot of each screen touched |
| Config/Data | `production/qa/smoke-*.md` |
### Preconditions
- The story file must be findable either by argument path, in `production/session-state/active.md`, or in the current sprint file as `IN PROGRESS`
- Implementation must have been attempted (source files listed in the story's "files to create/modify" should exist) — this skill does not implement; it verifies
- For Logic and Integration stories, the test file at the `## Test Evidence` path must **exist** before a COMPLETE verdict is possible — unless `testing.strict` in `project.yaml` sets that type to advisory (`testing.strict.logic`/`.integration: false`), in which case a missing test is recorded as a warning but does not block
- For Visual/Feel and UI stories, a retained screenshot **and** an evidence doc must exist under `production/qa/evidence/` before a COMPLETE verdict is possible — unless `testing.strict.visual`/`.ui` is set to `false`, in which case the gap is recorded as a warning but does not block
- **This skill does not execute the test.** Phase 3 checks existence with `Glob`; nothing runs. A test that exists and FAILS satisfies the gate, so a failing test cannot block a COMPLETE verdict here — this gate is existence, not "exist and pass". Pass/fail is established by `/gate-check` and `/smoke-check`, both of which run a suite and both of which come after story closure. See the note under Phase 3 of `SKILL.md`.
## Verdicts Emitted
`COMPLETE` / `COMPLETE WITH NOTES` / `NOT ASSESSED` / `BLOCKED`.
`NOT ASSESSED` outranks `COMPLETE` — one or more acceptance criteria could not
be evaluated at all, which is not the same as evaluating them and finding them
met. Precedence is `BLOCKED`, then `NOT ASSESSED`, then `COMPLETE WITH NOTES`,
then `COMPLETE`; see the verdict section of `SKILL.md`. This contract listed no
verdict set at all, so a reader had nothing to branch on.
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `production/epics/**/*.md` (the story file) | `Status: Complete`, `## Completion Notes` block (date, criteria count, deviations, test evidence path, code review status) | updated after explicit user approval |
| `production/sprint-status.yaml` | `status: done`, `completed: [date]`, top-level `updated` field | updated silently alongside story file if file exists |
| `docs/tech-debt-register.md` | Advisory deviation entries (if user confirms) | appended if advisory deviations exist and user agrees |
| `production/session-state/active.md` | `## Session Extract — /story-done [date]` block: verdict, story path, tech debt count, next recommended story | appended (created if absent) |
### Output Guarantees
- `Status: Complete` is written only when verdict is COMPLETE or COMPLETE WITH NOTES and the user explicitly approves
- `## Completion Notes` always contains: completion date, criteria pass count, deviation summary, test evidence path (or "None required"), code review status
- Session state always records the final verdict and the next recommended story path
## Immutability Rules
- READS but does NOT modify: `docs/architecture/tr-registry.yaml`, `docs/architecture/adr-NNNN-[slug].md` (Decision + Consequences only), GDD sections, `docs/architecture/control-manifest.md`, source files in `src/` (Grep only), test files in `tests/` (run via Bash; not edited)
- MODIFIES: the story `.md` file (status + completion notes), `production/sprint-status.yaml` (if exists), `production/session-state/active.md` (append), `docs/tech-debt-register.md` (append, only with user approval)
- Does NOT write to the code root or `tests/` under any circumstances
## Hard Constraints (Never Violate)
- Never sets `Status: Complete` without explicit user approval ("May I update the story file?")
- Never marks a Logic story Complete on a missing unit test when its resolved gate level is BLOCKING — the level is BLOCKING by default and whenever `testing.strict.logic` is `true`; it is ADVISORY only when `testing.strict.logic` is explicitly `false`
- Never marks an Integration story Complete on missing evidence (integration test file or playtest session log) when its resolved gate level is BLOCKING — BLOCKING by default and under `testing.strict.integration: true`; ADVISORY only under an explicit `false`
- Never marks a Visual/Feel or UI story Complete on a missing retained screenshot in `production/qa/evidence/` when its resolved gate level is BLOCKING — BLOCKING by default and under `testing.strict.visual`/`.ui: true`; ADVISORY only under an explicit `false`. A written description of a visual check is not a substitute for the image
- Never auto-fixes failing acceptance criteria — report failures and ask the user what to do
- Never proceeds to Phase 7 (file update) when the verdict is BLOCKED — list blockers and offer help resolving them
- Never silently overrides a BLOCKED verdict — if the user insists on advancing despite blockers, document the override risk explicitly in `## Completion Notes`
## Downstream Skill Expects
**Next skill:** `/gate-check` (Production → Polish gate, or end-of-sprint review)
- It will read: story files in `production/epics/` checking `Status: Complete` and presence of `## Completion Notes`
- It will read: `tests/unit/` and `tests/integration/` for test file presence and will run the test suite via Bash
- It assumes: every Complete Logic story whose `testing.strict.logic` gate resolved to BLOCKING (the default) has a corresponding test file that **exists**; under an explicit `testing.strict.logic: false` a Logic story may be Complete with the test gap documented in `## Completion Notes`
> **Existence, not passing.** `/story-done` checks that the test file exists with `Glob` and runs nothing, so a Complete Logic story may carry a test that fails. `/gate-check` running the suite is the FIRST point at which pass/fail is established, so it must never treat a Complete status as evidence the tests passed — it has to run them. That is also why an unconfigured test runner is `NOT ASSESSED` there rather than a silent skip: with no run, nothing upstream has verified the story either.
- It assumes: Visual/Feel and UI stories that are Complete have both an evidence doc and a retained screenshot in `production/qa/evidence/` — that gate is BLOCKING by default; only under an explicit `testing.strict.visual`/`.ui: false` may such a story be Complete with the deviation documented in `## Completion Notes`
- It will read: `production/sprint-status.yaml` for `status: done` entries if that file exists
## Known Fragile Points
- The story's `## Test Evidence` section must contain the exact file path written by `/dev-story`; a path mismatch causes a false BLOCKING result even if the test file exists under a slightly different name
- If `Type:` is absent from the story header, test evidence gate enforcement is ADVISORY only — stories can slip through without tests
- Manifest version staleness check is skipped if `docs/architecture/control-manifest.md` does not exist; the check being skipped is noted in the report but is non-blocking
- `production/sprint-status.yaml` update is silent (no separate approval); if that file uses a different key structure than expected, the update silently fails and sprint tracking becomes stale
- The traceability table escalation rule (>50% UNTESTED = BLOCKING) can be triggered by deferred Visual/Feel criteria that are legitimately not automatable — ensure deferred criteria are explicitly marked `DEFERRED` (not left as unchecked) to avoid false escalation
+266 -42
View File
@@ -1,12 +1,19 @@
---
name: story-done
description: "End-of-story completion review. Reads the story file, verifies each acceptance criterion against the implementation, checks for GDD/ADR deviations, prompts code review, updates story status to Complete, and surfaces the next ready story from the sprint."
description: "End-of-story completion review — verifies each acceptance criterion, checks GDD/ADR deviations, prompts code review, updates status."
argument-hint: "[story-file-path] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, AskUserQuestion, Task
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, AskUserQuestion, Agent
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,story_granularity,qa.level,testing.strict,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Story Done
This skill closes the loop between design and implementation. Run it at the end
@@ -21,12 +28,37 @@ forgotten, and the story file reflects actual completion status.
## Phase 1: Find the Story
Resolve the review mode (once, store for all gate spawns this run):
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Workflow tier**: resolved per the story's system (per
`.claude/docs/workflow-modes.md`) — **the GDD filename stem** of the story's
`GDD:` path (`design/gdd/<stem>.md` → `<stem>`), with the `[system]` segment of
its `TR-[system]-NNN` ID accepted only as a fallback alias: use the
`system_overrides` row for that system if the block lists one, else the
project value. It governs which Phase 4 deviation checks run — see Phase 4.
**Workflow companion — `modes.story_granularity`** (resolved above — supplied by
`modes.rigor` unless set explicitly): cadence expectation only — story-done fires **every 3–5 days** at
`coarse`, **every 1–2 days** at `balanced`, **multiple times/day** at `fine`. It
does not change any completion check.
**`qa.level`**: controls whether test *evidence is required*, where
`testing.strict` controls whether a failure blocks and `workflow` controls which
docs exist. `modes.rigor` sets `qa.level` and `workflow` together; set either
explicitly to vary it alone. `testing.strict` is not fronted by `rigor` at all.
At `minimal`, no evidence is required → skip the Test Evidence
Requirement check (Phase 3), the >50%-untested traceability escalation, and the
Phase 4b QA gate entirely; the acceptance-criteria verification still runs. At
`standard`, the story's own type requires evidence; at `full`, every type does.
`testing.strict` then decides whether present-but-failing evidence blocks.
(`rigor: minimal` sets both; `qa.level: minimal` on its own leaves the workflow
tier where it was.)
**If a file path is provided** (e.g., `/story-done production/epics/core/story-damage-calculator.md`):
read that file directly.
@@ -59,13 +91,19 @@ Read the full story file. Extract and hold in context:
- **Estimated vs actual scope** — if an estimate was noted
Also read:
- `docs/architecture/tr-registry.yaml` — look up each TR-ID in the story.
Read the *current* `requirement` text from the registry entry. This is the
source of truth for what the GDD required — do not use any requirement text
that may be quoted inline in the story (it may be stale).
- `docs/architecture/tr-registry.yaml` — grep the story's TR-IDs
(`Grep pattern="id: <each TR-ID>" path="docs/architecture/tr-registry.yaml" output_mode="content" -A 6`),
not a full read of the registry. Read the *current* `requirement` text from each
matched entry. This is the source of truth for what the GDD required — do not use any
requirement text that may be quoted inline in the story (it may be stale).
- The referenced GDD section — just the acceptance criteria and key rules, not
the full document. Use this to cross-check the registry text is still accurate.
- The referenced ADR(s) — just the Decision and Consequences sections
- The referenced ADR(s) — **just the `## Decision` and `## Consequences`
sections, never an unbounded full read.** Map headings first
(`Grep pattern="^## " path="docs/architecture/[adr-file].md" output_mode="content" -n`),
then bounded-`Read` only those two spans. This is the exact same content
Phase 4 item 3's ADR constraints check needs — hold it here, do not
re-read it there.
- `docs/architecture/control-manifest.md` header — extract the current
`Manifest Version:` date (used in Phase 4 staleness check)
@@ -82,7 +120,7 @@ three methods:
- **Test pass check**: if a test file path is mentioned, run it via `Bash`.
- **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 `src/`
- **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.
@@ -118,6 +156,12 @@ For each acceptance criterion in the story:
- **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.
2. Produce a traceability table:
@@ -126,10 +170,12 @@ For each acceptance criterion in the story:
|-----------|------|--------|
| AC-1: [criterion text] | tests/unit/test_foo.gd::test_bar | COVERED |
| AC-2: [criterion text] | Manual playtest confirmation | COVERED |
| AC-3: [criterion text] | — | UNTESTED |
| AC-3: [criterion text] | production/qa/evidence/[slug]/01-shop-open.png | COVERED |
| AC-4: [criterion text] | — | UNTESTED |
```
3. Apply these escalation rules:
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
@@ -144,38 +190,118 @@ For each acceptance criterion in the story:
### Test Evidence Requirement
Based on the Story Type extracted in Phase 2, check for required evidence:
**First apply `qa.level` (resolved in Phase 1).** At `minimal`, no evidence is
required — skip this entire subsection (no gate from test evidence; the verdict
rests on acceptance-criteria verification alone). At `standard`, require evidence
for the story's own type. At `full`, require evidence for every story type. Only
when evidence is required does the `testing.strict` resolution below apply.
| Story Type | Required Evidence | Gate Level |
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 | BLOCKING |
| **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** | Screenshot + sign-off in `production/qa/evidence/` | ADVISORY |
| **UI** | Manual walkthrough doc OR interaction test in `production/qa/evidence/` | ADVISORY |
| **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
> because their `allowed-tools` has no `Bash`, this skill HAS `Bash` — the limit
> here is the instruction, not the grant. 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 as **BLOCKING**: "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."
- 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 as **BLOCKING** (same rule as Logic).
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 file
referencing this story.
- If none: flag as **ADVISORY** — "No manual test evidence found. Create `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template and obtain sign-off before final closure."
- If found: read the file and check the sign-off table for unchecked boxes. Grep for lines matching `| .* | .* | .* | \[ \] Approved` (a sign-off row with an unchecked checkbox). If any unchecked sign-off rows are found: flag as **ADVISORY** — "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."
- If all sign-off rows show `[x] Approved` or equivalent: note "Evidence file found and all sign-offs complete — ADVISORY passed."
**For Visual/Feel and UI stories**: glob `production/qa/evidence/` for both an
evidence doc referencing this story and a retained screenshot for it (`*.png`,
`*.jpg`, `*.gif`).
- If neither is found: flag at the resolved gate level — "No visual evidence found. Capture a screenshot of each screen or effect this story touched, save it under `production/qa/evidence/`, create `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template, and obtain sign-off before final closure."
- If the evidence doc exists but no screenshot is retained beside it: flag at the resolved gate level — "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."
- If found: read the file and check the sign-off table for unchecked boxes. Grep for lines matching `| .* | .* | .* | \[ \] Approved` (a sign-off row with an unchecked checkbox). If any unchecked sign-off rows are found: flag at the resolved gate level — "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."
- If the doc, the screenshot and all `[x] Approved` sign-off rows are present: note "Evidence doc and retained screenshot found, all 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` summary (the session extract in `production/session-state/active.md`,
or 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."
**For Config/Data stories**: check for any `production/qa/smoke-*.md` file.
If none: flag as **ADVISORY** — "No smoke check report found. Run `/smoke-check`."
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]`
@@ -189,6 +315,20 @@ Any BLOCKING test evidence gap prevents the COMPLETE verdict in Phase 6.
Compare the implementation against the design documents.
> **Workflow tier adjustment** (resolved in Phase 1, per the story's system).
> Checks 1 (GDD rules) and 3 (ADR constraints) below are the `full` baseline:
> - **`full`** — run both: full GDD traceability against the current TR text +
> the ADR constraints check.
> - **`standard`** — run the GDD rules check against the **5 required sections**;
> run the ADR constraints check only where a **critical ADR** governs the story.
> - **`minimal`** — **acceptance-criteria check only**: skip checks 1 and 3 (no
> GDD/ADR traceability expected). Checks 2 (manifest), 4 (hardcoded values), and
> 5 (scope) still run as written.
>
> This adjustment governs only the Phase 4 *deviation* checks. The test-evidence
> gates (Phase 3 traceability, Phase 4b QA coverage) are governed by `qa.level`
> and `testing.strict`, not `workflow` — they run independently of the tier here.
Run these checks automatically:
1. **GDD rules check**: Using the current requirement text from `tr-registry.yaml`
@@ -206,9 +346,10 @@ Run these checks automatically:
is v[current-date]. New rules may apply. Run /story-readiness to check.`
- If control-manifest.md does not exist → skip this check.
3. **ADR constraints check**: Read the referenced ADR's Decision section. Check
for forbidden patterns from `docs/architecture/control-manifest.md` (if it
exists). `Grep` for patterns explicitly forbidden in the ADR.
3. **ADR constraints check**: Use the ADR's `## Decision` section already
loaded in Phase 2 — do not read the ADR file again. Check for forbidden
patterns from `docs/architecture/control-manifest.md` (if it exists).
`Grep` for patterns explicitly forbidden in the ADR.
4. **Hardcoded values check**: `Grep` the implemented files for numeric literals
in gameplay logic that should be in data files.
@@ -229,12 +370,16 @@ For each deviation found, categorize:
## Phase 4b: QA Coverage Gate
**Skip this phase entirely at `qa.level: minimal`** (resolved in Phase 1) — no
test evidence is required, so there is no coverage to review. Note: "QL-TEST-COVERAGE
skipped — qa.level minimal." Proceed to Phase 5.
**Review mode check** — apply before spawning QL-TEST-COVERAGE:
- `solo` → skip. Note: "QL-TEST-COVERAGE skipped — Solo mode." Proceed to Phase 5.
- `lean` → skip (not a PHASE-GATE). Note: "QL-TEST-COVERAGE skipped — Lean mode." Proceed to Phase 5.
- `full` → spawn as normal.
After completing the deviation checks in Phase 4, spawn `qa-lead` via Task using gate **QL-TEST-COVERAGE** (`.claude/docs/director-gates.md`).
After completing the deviation checks in Phase 4, spawn `qa-lead` via `Agent` using gate **QL-TEST-COVERAGE** (`.claude/docs/director-gates/ql-test-coverage.md`).
Pass:
- The story file path and story type
@@ -266,7 +411,7 @@ Skip this phase for Config/Data stories (no code tests required).
- Record the answer in the completion notes (Phase 7). All three options proceed to Phase 6.
- `full` → spawn as normal.
Spawn `lead-programmer` via Task using gate **LP-CODE-REVIEW** (`.claude/docs/director-gates.md`).
Spawn `lead-programmer` via `Agent` using gate **LP-CODE-REVIEW** (`.claude/docs/director-gates/lp-code-review.md`).
Pass: implementation file paths, story file path, relevant GDD section, governing ADR.
@@ -314,21 +459,92 @@ Before updating any files, present the full report:
[All changes within stated scope] OR:
- Extra files touched: [list] — [note whether valid or scope creep]
### Verdict: COMPLETE / COMPLETE WITH NOTES / BLOCKED
### Verdict: COMPLETE / COMPLETE WITH NOTES / NOT ASSESSED / BLOCKED
```
**Verdict definitions:**
- **COMPLETE**: all criteria pass, no blocking deviations
- **COMPLETE WITH NOTES**: all criteria pass, advisory deviations documented
- **NOT ASSESSED**: one or more acceptance criteria could not be evaluated at
all — name which, and why
- **BLOCKED**: failing criteria or blocking deviations must be resolved first
If the verdict is **BLOCKED**: do not proceed to Phase 7. List what must be
fixed. Offer to help fix the blocking items.
**`NOT ASSESSED` — the story nobody could verify.** Rank: it **outranks COMPLETE
and COMPLETE WITH NOTES** (a review that could not evaluate a criterion has not
shown the criterion is met) and **ranks below BLOCKED** (a criterion known to
fail is more actionable than one nobody could check, and demoting it would bury
it). It is not a gentler BLOCKED: "this acceptance criterion fails" and "I could
not tell whether it passes" send the reader to different fixes.
**Verdict precedence — first matching rule wins**, evaluated in this order:
**BLOCKED**, then **NOT ASSESSED**, then **COMPLETE WITH NOTES**, then
**COMPLETE**. A run with both a failing criterion and an unassessable one is
BLOCKED. Stating the order mechanically, rather than leaving it to be inferred
from the rank sentence, is what keeps two reviewers from grading the same story
differently.
Emit it when any of:
- An acceptance criterion **cannot be evaluated at all** — it names no observable
outcome, so no evidence could settle it either way.
> **Not the same as Phase 3's `DEFERRED`.** A criterion that is evaluable but
> needs a playtest is `DEFERRED — requires playtest session`, it does **not**
> block, and Phase 3 keeps ownership of it. This trigger is for a criterion no
> session could ever settle as written. If Phase 3 already marked it DEFERRED,
> that classification stands and this trigger does not fire.
- The **test evidence is present but unreadable or unclassifiable** — corrupt,
empty, or of a type that cannot be determined.
> **Absent evidence is Phase 3's, not this trigger's.** Phase 3 resolves a
> missing file through `testing.strict`: BLOCKING types produce **BLOCKED**,
> ADVISORY types produce **COMPLETE WITH NOTES**. Both outrank or are already
> decided, so re-routing "absent" here would silently override an explicit
> advisory ruling. *Unreadable* is the genuinely unassessable case, and it is
> the only one this trigger claims.
- **`/test-evidence-review` returned `NOT ASSESSED`** for this story — applicable
only when that skill was actually run against it, which this skill does not do
itself. It
propagates: that skill's whole point is that "could not check" is not
"checked and fine", and collapsing its unknown into a COMPLETE here would undo
the distinction one skill downstream. `coding-standards.md` marks Logic and
Integration evidence BLOCKING, so this is the path where an unverifiable story
would otherwise acquire a verdict saying somebody verified it.
- A **deviation's severity cannot be determined** because the GDD or ADR it
would be judged against is missing.
A `NOT ASSESSED` verdict takes the same Phase 7 path as BLOCKED: do not
automatically proceed, list what could not be checked and what would make it
checkable. Closing anyway remains the user's explicit call, and stays gated by
Phase 7's `scope_changes` always-ask rule.
If the verdict is **BLOCKED**: do not *automatically* proceed to Phase 7. List
what must be fixed and offer to help fix the blocking items. This is the
default path, not an absolute stop — the user may still explicitly ask to
close the story anyway despite the blockers. That request is what routes to
Phase 7's menu below, and Phase 7's own `scope_changes` always-ask rule is
exactly what stands between that request and a silent close in autonomous
mode. Do not treat "do not automatically proceed" as "Phase 7 is now
unreachable" — it is reachable, on request, and gated when reached.
---
## Phase 7: Update Story Status
**Reached one of two ways**: normally, immediately after a COMPLETE or
COMPLETE-WITH-NOTES verdict in Phase 6; or, after a BLOCKED **or NOT ASSESSED**
verdict, only if the user explicitly asks to close the story despite the
blockers (Phase 6 does not advance here on its own in either case).
**Automation note**: This is the story-completion gate. Closing a story whose
verdict is BLOCKED (failing acceptance criteria) **or NOT ASSESSED** (criteria
nobody could evaluate) — the "Accept deviations as-is and close anyway" option —
is a `scope_changes` decision. Call
`is_always_ask_category scope_changes`; when it returns 0 (the default), this
gate prompts via `AskUserQuestion` **regardless of `modes.automation`** —
autonomous mode must NOT silently close a BLOCKED story, even when the user's
own request is what got you here. For a COMPLETE or COMPLETE-WITH-NOTES
verdict, autonomous mode may pick "Close the story (Recommended)" and record
it via `log_decision`.
Use `AskUserQuestion` before writing anything:
- Prompt: "Verification complete. How do you want to proceed?"
- Options:
@@ -370,7 +586,7 @@ If "Fix first": stop here and list what the user flagged. Do not write any files
```
Suggested commit:
git add [src/ and tests/ files changed during implementation] [story-file-path]
git add [code-root and tests/ files changed during implementation] [story-file-path]
git commit -m "feat: [story title] ([TR-ID])"
```
@@ -382,7 +598,7 @@ After updating the story file, silently append to
`production/session-state/active.md`:
## Session Extract — /story-done [date]
- Verdict: [COMPLETE / COMPLETE WITH NOTES / BLOCKED]
- Verdict: [COMPLETE / COMPLETE WITH NOTES / NOT ASSESSED / BLOCKED]
- Story: [story file path] — [story title]
- Tech debt logged: [N items, or "None"]
- Next recommended: [next ready story title and path, or "None identified"]
@@ -440,13 +656,21 @@ If no more stories are ready but Must Have stories are still In Progress (not Co
## Collaborative Protocol
**In `collaborative` mode (the default).** For `guided` and `autonomous` modes,
see `.claude/docs/automation-modes.md` — the rules below describe collaborative
behavior. The BLOCKED-override close (Phase 7) always prompts regardless of mode
(it's a `scope_changes` always-ask decision).
- **Never mark a story complete without user approval** — Phase 7 requires an
explicit "yes" before any file is edited.
- **Never auto-fix failing criteria** — report them and ask what to do.
- **Deviations are facts, not judgments** — present them neutrally; the user
decides if they are acceptable.
- **BLOCKED verdict is advisory** — the user can override and mark complete
anyway; document the risk explicitly if they do.
- **BLOCKED and NOT ASSESSED verdicts are advisory** — the user can override and
mark complete anyway; document the risk explicitly if they do. For NOT
ASSESSED, the documented risk is that the criterion was never evaluated, not
that it failed — record which criteria those were, so the gap is recoverable
later rather than closed over.
- Use `AskUserQuestion` for the code review prompt and for batching manual
criteria confirmations.
@@ -0,0 +1,71 @@
# /story-readiness — Handoff Contract
## Role in Pipeline
Validates that a story file contains everything a developer needs to begin
implementation and produces a READY / NEEDS WORK / BLOCKED / NOT ASSESSED verdict — sits between
`/create-stories` and `/dev-story`, acting as a blocking gate before any code is written.
## Inputs Required
### Files That Must Exist
| File | Required Fields / Sections | Read-Only? |
|------|---------------------------|-----------|
| `production/epics/[epic-slug]/story-NNN-[slug].md` | All header fields (`Status:`, `Layer:`, `Type:`, `Manifest Version:`), `## Context` (GDD path, TR-ID, ADR reference, Engine Notes, Control Manifest Rules), `## Acceptance Criteria`, `## Test Evidence`, `## Dependencies`, `## Out of Scope` | Yes |
| `docs/architecture/control-manifest.md` | `Manifest Version:` date in header, layer rules | Yes (if exists) |
| `docs/architecture/tr-registry.yaml` | `id`, `status` fields per TR entry | Yes (if exists) |
| `docs/architecture/adr-NNNN-[slug].md` (all ADRs referenced in stories) | `Status:` field | Yes |
| `design/gdd/systems-index.md` | Which systems have approved GDDs | Yes |
### Preconditions
- The story file being validated was produced by `/create-stories` (or follows the same format)
- For `sprint` scope: a sprint file exists in `production/sprints/` with story path references
- For `all` scope: `production/epics/` directory exists and contains story files
## Outputs Produced
### Files Written
None. This skill is strictly read-only and produces no file modifications under any circumstance.
### Output Guarantees
- A verdict of READY, NEEDS WORK, BLOCKED or NOT ASSESSED is produced for every story file evaluated. `NOT ASSESSED` is not a synonym for `BLOCKED`: BLOCKED names a real, listable obstacle, while NOT ASSESSED means the story could not be evaluated at all. An empty scope yields `NOT ASSESSED — no stories in scope`, never a `Ready: 0 / Needs Work: 0 / Blocked: 0` summary over an empty list
- Every non-READY verdict includes a specific gap list with fix instructions for each failing checklist item
- Every BLOCKED verdict names the specific blocker (missing dependency story path, Proposed ADR ID, or unresolved design question marker)
- For `sprint` scope: a sprint-level escalation warning is prepended if any Must Have story is not READY
- The skill offers to draft missing sections in conversation but never uses Write or Edit tools
## Immutability Rules
- READS but does NOT modify: story files, `docs/architecture/control-manifest.md`, `docs/architecture/tr-registry.yaml`, all ADR files, `design/gdd/systems-index.md`, sprint files, any referenced asset files (existence-only Glob checks)
- MODIFIES: nothing
## Hard Constraints (Never Violate)
- Never use Write or Edit tools under any circumstances
- Never draft corrections directly into files — offer drafts in conversation only
- Never mark a story READY if its governing ADR has `Status: Proposed`
- Never mark a story READY if a dependency story file is missing or has `Status: Draft`
- Never re-read the same ADR file multiple times in one run — cache ADR statuses after the first read
- Never penalize a story for missing `Manifest Version:` if `control-manifest.md` does not exist
- Never penalize a story for missing TR-ID if `tr-registry.yaml` does not exist
## Downstream Skill Expects
**Next skill:** /dev-story
It will rely on this skill's verdict as follows:
- If verdict is READY: `/dev-story` proceeds with implementation using the story file as its source of truth
- If verdict is NEEDS WORK or BLOCKED: `/dev-story` must not be run until the story is corrected and re-validated
- `/dev-story` reads the same story fields this skill validates — a READY verdict is an implicit guarantee that those fields are present, parseable, and internally consistent:
- `Type:` field is set to a valid story type
- `## Acceptance Criteria` contains specific, testable checkbox items
- `## Test Evidence` specifies a concrete evidence path
- The governing ADR exists and has `Status: Accepted`
- `Manifest Version:` matches the current control manifest
- `TR-ID` in `## Context` is present and resolves in `docs/architecture/tr-registry.yaml` (when the registry exists)
- `## Dependencies` section is present (may say "None")
- `## Out of Scope` section is present (checked for existence; `/dev-story` uses it to enforce implementation boundaries)
## Known Fragile Points
- If `control-manifest.md` is regenerated with a new `Manifest Version:` date, every story that embeds the old date will fail the manifest version check — a bulk update of all story `Manifest Version:` fields is required before stories can pass readiness again
- If an ADR is silently renamed or moved after stories reference it by ID, the ADR file-existence check will BLOCK those stories even though the decision content is unchanged
- The manifest version comparison is a string date match, not a semantic version comparison — if the date format changes (e.g., from `2026-01-15` to `Jan 15 2026`), all stories will fail the check regardless of actual currency
- Asset existence checks use Glob — on Windows, path separator mismatches (`\` vs `/`) may cause a Glob miss that incorrectly flags an asset as missing
- The TR-ID status check auto-passes if the registry does not exist, which means stories written before TR tracking was introduced will always pass this check even if they contain invalid or placeholder IDs like `TR-[system]-???`
- For `sprint` scope, the skill depends on sprint file formatting to extract story paths — if the sprint file format changes, story paths may not be parsed and the scope silently reduces to zero stories validated
+128 -19
View File
@@ -1,12 +1,18 @@
---
name: story-readiness
description: "Validate that a story file is implementation-ready. Checks for embedded GDD requirements, ADR references, engine notes, clear acceptance criteria, and no open design questions. Produces READY / NEEDS WORK / BLOCKED verdict with specific gaps. Use when user says 'is this story ready', 'can I start on this story', 'is story X ready to implement'."
description: "Is a story implementation-ready? Checks clear acceptance criteria, open questions, ADR refs. READY/NEEDS WORK/BLOCKED/NOT ASSESSED."
argument-hint: "[story-file-path or 'all' or 'sprint']"
user-invocable: true
allowed-tools: Read, Glob, Grep, AskUserQuestion, Task
allowed-tools: Read, Glob, Grep, AskUserQuestion, Agent
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,workflow,qa.level,testing.strict,system_overrides`
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
# Story Readiness
This skill validates that a story file contains everything a developer needs
@@ -16,20 +22,53 @@ no ambiguous acceptance criteria. Run it before assigning a story.
**This skill is read-only.** It never edits story files. It reports findings
and asks whether the user wants help filling gaps.
**Output:** Verdict per story (READY / NEEDS WORK / BLOCKED) with a specific
**Output:** Verdict per story (READY / NEEDS WORK / BLOCKED / NOT ASSESSED) with a specific
> **`NOT ASSESSED` is not a synonym for `BLOCKED`.** `BLOCKED` is a
> finding about the story — a Proposed ADR, an unresolved dependency — and it
> tells the reader exactly what to clear. Use `NOT ASSESSED` when the story could
> not be evaluated at all: the file is unreadable or unparseable, or a referenced
> ADR or design document cannot be located, so the checks below cannot run.
> Collapsing that into `BLOCKED` reports a blocker that does not exist and hides
> the one that does — the reader chases a phantom ADR instead of a missing file.
> `READY` must never be reachable for a story that was not actually evaluated.
>
> **Precedence — first matching rule wins**, in this order: **BLOCKED**, then
> **NEEDS WORK**, then **NOT ASSESSED**, then **READY**. `NOT ASSESSED` outranks
> `READY` (a story that could not be evaluated has not been shown ready) and
> ranks **below** both failure verdicts (a known blocker is more actionable than
> an unknown, and demoting it behind an access problem buries it). A story with
> both a real blocker and an unevaluable check is `BLOCKED` — the blocker is the
> actionable finding. This half of the rank has to be stated: the rule above
> establishes only that `READY` is unreachable, which would leave the ordering
> against `BLOCKED` to inference.
gap list for each non-ready story.
---
## Phase 0: Resolve Review Mode
Resolve the review mode once at startup (store for all gate spawns this run):
1. If skill was called with `--review [full|lean|solo]` → use that value
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern and mode definitions. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
See `.claude/docs/director-gates.md` for the full check pattern and mode definitions.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Resolve the workflow tier per story** (per `.claude/docs/workflow-modes.md`):
for the system a story belongs to (**the GDD filename stem** of its `GDD:` path;
the `[system]` segment of a `TR-[system]-NNN` ID is a fallback alias only), use the
`system_overrides` row for that system if the block lists one, else the
project value. When validating multiple stories (`all` / `sprint` scope),
resolve **per story** — different systems may sit at different tiers. The tier
sets which checklist sections block — see the note in Section 3.
**`qa.level`**: controls whether a test requirement is
validated. At `minimal`, the "Test evidence requirement is clear" item
auto-passes (no requirement validated); at `standard`, validate the per-type test
requirement (strictness from `testing.strict`); at `full`, also validate a
coverage target. Distinct axis from `workflow`.
---
@@ -52,6 +91,31 @@ If no argument is given, use `AskUserQuestion`:
Report the scope before proceeding: "Validating [N] story files."
> **If the scope resolves to ZERO story files, stop and report
> `NOT ASSESSED — no stories in scope`.** Name which scope was searched and
> which path was empty (`production/epics/**/*.md`, the sprint file's story
> list, or the specific path given), and route: `/create-epics [layer]` then
> `/create-stories [epic-slug]`.
>
> **The zero-scope path is mandatory.** Without it an empty glob falls through
> to the Section 5 aggregate template and renders `Ready: 0 /
> Needs Work: 0 / Blocked: 0` above an empty list — **indistinguishable from
> "I checked every story and none needed work"**. It is the core failure of this
> framework exactly: a scan that finds nothing because there was nothing to
> scan, reported the same way as a clean result. Three zeros read as a healthy
> sprint.
>
> Note what made this survive: `NOT ASSESSED` was already in this skill's
> vocabulary, but the body scoped it to **per-story** evaluation failures (an
> unreadable or unparseable file, a missing referenced ADR). The verdict existed;
> the case that most needs it had no route to it. It is a recurring shape — a
> correct fix that did not reach one surface.
>
> **A zero-story sprint scope is not the same as an absent sprint file.** If
> `production/sprints/` has no file at all, say that instead — "no sprint plan
> found" and "the sprint plan lists no stories" send the reader to different
> fixes, and Section 7 already draws that distinction for the handoff block.
---
## 2. Load Supporting Context
@@ -59,16 +123,27 @@ Report the scope before proceeding: "Validating [N] story files."
Before checking any stories, load reference documents once (not per-story):
- `design/gdd/systems-index.md` — to know which systems have approved GDDs
- `docs/architecture/control-manifest.md` — to know which manifest rules exist
(if the file does not exist, note it as missing once; do not re-flag per story)
Also extract the `Manifest Version:` date from the header block if the file exists.
- `docs/architecture/control-manifest.md` — story-readiness needs only the header
`Manifest Version:` date (its manifest check is existence + version, not the rule
bodies), so grep it (`Grep pattern="Manifest Version" path="docs/architecture/control-manifest.md"`)
rather than a full read. If the file does not exist, note it as missing once; do not
re-flag per story.
- `docs/architecture/tr-registry.yaml` — index all entries by `id`. Used to
validate TR-IDs in stories. If the file does not exist, note it once; TR-ID
checks will auto-pass for all stories (registry predates stories, so missing
registry means stories are from before TR tracking was introduced).
- All ADR status fields — for each unique ADR referenced across the stories being
checked, read the ADR file and note its `Status:` field. Cache these so you
don't re-read the same ADR for every story.
- All ADR status fields — resolve these with **one scan, not one read per ADR**.
A `Status:` value is a single line; reading whole ADR files to find it costs the
entire architecture corpus, and in `all` scope that multiplies across every
story in the repo:
```
Grep pattern="^## Status" glob="docs/architecture/adr-*.md" output_mode="content" -A 3
```
Establish the denominator first (glob `docs/architecture/adr-*.md`, count **N**)
and interpret against it: **0 matches with N > 0 means malformed ADRs, not
"no Accepted ADRs"** — report "run `/architecture-decision [file] retrofit`"
rather than failing every story's ADR check. Never treat an unreadable status as
a failed one. Cache the resulting map; do not re-scan per story.
- The current sprint file (if scope is `sprint`) — to identify Must Have /
Should Have priority for escalation decisions
@@ -79,6 +154,19 @@ Before checking any stories, load reference documents once (not per-story):
For each story file, evaluate every item below. A story is READY only if all
items pass or are explicitly marked N/A with a stated reason.
> **Workflow tier adjustment** (resolved in Phase 0, per the story's system). The
> full checklist below is the `full` baseline:
> - **`full`** — every item is blocking (TR registry + ADR + control manifest
> fully validated).
> - **`standard`** — **Design Completeness** and **Scope Clarity** stay blocking.
> In **Architecture Completeness**, only a **critical (Foundation-layer) ADR**
> that is missing or `Proposed` BLOCKS; a missing non-critical ADR, or an absent
> "ADR referenced" note, is **advisory** (NEEDS WORK note, not BLOCKED). The
> TR-ID and manifest items are advisory.
> - **`minimal`** — **acceptance-criteria check only**: evaluate Design
> Completeness and Scope Clarity. Treat the entire **Architecture Completeness**
> section as N/A — do not flag missing ADR / TR-ID / manifest references.
### Design Completeness
- [ ] **GDD requirement referenced**: The story includes a `design/gdd/` path
@@ -103,6 +191,10 @@ items pass or are explicitly marked N/A with a stated reason.
### Architecture Completeness
> The `BLOCKED` / fail outcomes in this section are the `full` baseline. Apply the
> tier note above: at `standard` only a missing/Proposed **critical** ADR BLOCKS
> (other items advisory); at `minimal` treat this entire section as N/A.
- [ ] **ADR referenced or N/A stated**: The story references at least one ADR,
OR explicitly states "No ADR applies" with a brief reason.
A story with no ADR reference and no explicit N/A note fails this check.
@@ -192,9 +284,24 @@ items pass or are explicitly marked N/A with a stated reason.
identifying the test category (Logic / Integration / Visual/Feel / UI / Config/Data).
Without this, test evidence requirements cannot be enforced at story close.
Fix: Add `Type: [Logic|Integration|Visual/Feel|UI|Config/Data]` to the story header.
- [ ] **Test evidence requirement is clear**: If the Story Type is set, the story
includes a `## Test Evidence` section stating where evidence will be stored
- [ ] **Test evidence requirement is clear** *(auto-pass at `qa.level: minimal` — no
test evidence is required, so this item never blocks)*: If the Story Type is set,
the story includes a `## Test Evidence` section stating where evidence will be stored
(test file path for Logic/Integration, or evidence doc path for Visual/Feel/UI).
Resolve this item's gate level from the `testing.strict` block **resolved in
Phase 0** — not by reading `project.yaml`, which would ignore a developer's
locally-overridden value. Map the Story Type to a key (Logic→`logic`,
Integration→`integration`, Visual/Feel→`visual`, UI→`ui`,
Config/Data→`config`) and take
`testing.strict.<key>`; use it only if its value is `true` or `false`
(case-insensitive). If the key is absent, empty, or holds any other value, read
`testing.strict` as a plain boolean (legacy single-value form); if that too is
absent or invalid, default to strict for Logic, Integration, Visual/Feel and UI,
and advisory for Config/Data. Surface any unrecognized value to the user.
- At a **strict** gate level, a missing `## Test Evidence` section marks the
story **NEEDS WORK**.
- At an **advisory** gate level, a missing section is listed as a gap but does
not by itself downgrade the verdict from READY.
Fix: Add `## Test Evidence` with the expected evidence location for the story's type.
---
@@ -203,7 +310,9 @@ items pass or are explicitly marked N/A with a stated reason.
Assign one of three verdicts per story:
**READY** — All checklist items pass or have explicit N/A justifications.
**READY** — All checklist items pass, have explicit N/A justifications, or are
advisory-level gaps (a checklist item whose gate level resolved to advisory via
`testing.strict`). Advisory gaps are still listed under Gaps in the output.
The story can be assigned immediately.
**NEEDS WORK** — One or more checklist items fail, but all dependency stories
@@ -320,7 +429,7 @@ If any are found, surface up to 3:
Run `/story-readiness [path]` to validate before starting.
```
If no sprint file exists or no other ready stories are found, skip this section silently.
If no sprint file exists, or no other ready stories are found, say which — `Next ready stories: no sprint file found` or `Next ready stories: none ready in [sprint]` — rather than omitting the section. The two mean different things (nothing to read versus nothing ready) and an omitted section reads as neither.
---
@@ -332,7 +441,7 @@ Apply the review mode resolved in Phase 0 before spawning QL-STORY-READY:
- `lean` → skip. Note: "QL-STORY-READY skipped — Lean mode." Proceed to close.
- `full` → spawn as normal.
Spawn `qa-lead` via Task using gate **QL-STORY-READY** (`.claude/docs/director-gates.md`).
Spawn `qa-lead` via `Agent` using gate **QL-STORY-READY** (`.claude/docs/director-gates/ql-story-ready.md`).
Pass the following context:
- Story title
+81 -24
View File
@@ -1,9 +1,9 @@
---
name: team-audio
description: "Orchestrate audio team: audio-director + sound-designer + technical-artist + gameplay-programmer for full audio pipeline from direction to implementation."
description: "Orchestrate the audio team — audio-director, sound-designer, technical-artist, gameplay-programmer — direction through implementation."
argument-hint: "[feature or area to design audio for] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
@@ -15,20 +15,58 @@ When this skill is invoked with an argument, orchestrate the audio team through
**Decision Points:** At each step transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next step.
In `collaborative` mode, the user must approve before moving to the next step.
In `guided` mode the pipeline advances automatically unless a step is BLOCKED;
in `autonomous` mode it runs end to end, recording each step outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `sound-designer` only. Other agents consulted via the sound-designer, not spawned separately.
- **`small`**: + `audio-director` + `technical-artist`.
- **`studio`**: + `localization-lead` + per-system audio reviewers.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Step 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
1. **Read the argument** for the target feature or area (e.g., `combat`,
`main menu`, `forest biome`, `boss encounter`).
@@ -41,14 +79,18 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: audio-director` — Sonic identity, emotional tone, audio palette
- `subagent_type: sound-designer` — SFX specifications, audio events, mixing groups
- `subagent_type: technical-artist` — Audio middleware, bus structure, memory budgets
- `subagent_type: [primary engine specialist]` — Validate audio integration patterns for the engine
- `subagent_type: gameplay-programmer` — Audio manager, gameplay triggers, adaptive music
Always provide full context in each agent's prompt (feature description, existing audio assets, design doc references).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
3. **Orchestrate the audio team** in sequence:
@@ -83,13 +125,13 @@ Spawn the `technical-artist` agent to:
- Plan streaming vs preloaded asset strategy
- Design any audio-reactive visual effects
Spawn the **primary engine specialist** in parallel (from `.claude/docs/technical-preferences.md` Engine Specialists) to validate the integration approach:
Spawn the **primary engine specialist** in parallel (`<engine>-specialist` derived from `engine.name` — Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`; fall back to the Primary line of `## Engine Specialists` in `.claude/docs/technical-preferences.md`) to validate the integration approach:
- Is the proposed audio middleware integration idiomatic for the engine? (e.g., Godot's built-in AudioStreamPlayer vs FMOD, Unity's Audio Mixer vs Wwise, Unreal's MetaSounds vs FMOD)
- Any engine-specific audio node/component patterns that should be used?
- Known audio system changes in the pinned engine version that affect the integration plan?
- Output: engine audio integration notes to merge with the technical-artist's plan
If no engine is configured, skip the specialist spawn.
If no engine is configured, skip the specialist spawn. **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
### Step 4: Code Integration (gameplay-programmer)
Spawn the `gameplay-programmer` agent to:
@@ -101,7 +143,16 @@ Spawn the `gameplay-programmer` agent to:
4. **Compile the audio design document** combining all team outputs.
5. **Save to** `design/audio/audio-[feature].md`.
5. **Save to** `design/audio/audio-[feature].md` — **but ask first.** `design/` is
NOT one of the three directories the bounded write exception covers
(`production/`, `docs/`, `tests/`), so a sub-agent handed this path must
prompt, and one has done exactly that. Do not
resolve that by widening the exception. Instead, follow the same pattern
`team-level` uses: **you** already hold every sub-agent's output, so compile
the document yourself and ask directly via `AskUserQuestion` — "May I write the
audio design to `design/audio/audio-[feature].md`?" — then write it on
approval. Sub-agent working artifacts stay under `production/` where the
exception does reach them.
Note: If `design/audio/` does not exist, the sub-agent writing the document should create it (the directory will be created automatically when the file is written).
@@ -117,8 +168,12 @@ Verdict: **BLOCKED** — [reason]
## File Write Protocol
All file writes (audio design docs, SFX specs, implementation files) are delegated
to sub-agents spawned via Task. Each sub-agent enforces the "May I write to [path]?"
protocol. This orchestrator does not write files directly.
to sub-agents spawned via `Agent`. Those writes follow the **bounded exception**
documented above under "Why this does not violate the Collaboration Protocol" —
the path is one you named, the artifact is new under `production/`, `docs/` or
`tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent does **not**
prompt per write inside those bounds; outside them it must ask. This orchestrator
does not write files directly.
## Next Steps
@@ -128,15 +183,17 @@ protocol. This orchestrator does not write files directly.
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
+100 -23
View File
@@ -1,9 +1,9 @@
---
name: team-combat
description: "Orchestrate the combat team: coordinates game-designer, gameplay-programmer, ai-programmer, technical-artist, sound-designer, and qa-tester to design, implement, and validate a combat feature end-to-end."
description: "Orchestrate the combat team — game-designer, gameplay-programmer, ai-programmer, technical-artist, sound-designer, qa-tester — design through implement and validate."
argument-hint: "[combat feature description] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
**Argument check:** If no combat feature description is provided, output:
@@ -15,20 +15,58 @@ When this skill is invoked with a valid argument, orchestrate the combat team th
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `gameplay-programmer` runs the pipeline; escalate `ai-programmer` only if the feature flags AI work. Other Team Composition agents are consulted via the gameplay-programmer, not spawned separately.
- **`small`**: the full Team Composition pipeline below, as documented.
- **`studio`**: full pipeline + engine sub-specialists + an adversarial review pass.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
## Team Composition
- **game-designer** — Design the mechanic, define formulas and edge cases
@@ -36,12 +74,12 @@ Store the resolved mode for use in all subsequent phases.
- **ai-programmer** — Implement NPC/enemy AI behavior for the feature
- **technical-artist** — Create VFX, shader effects, and visual feedback
- **sound-designer** — Define audio events, impact sounds, and ambient combat audio
- **engine specialist** (primary) — Validate architecture and implementation patterns are idiomatic for the engine (read from `.claude/docs/technical-preferences.md` Engine Specialists section)
- **engine specialist** (primary) — Validate architecture and implementation patterns are idiomatic for the engine (the primary specialist is `<engine>-specialist` from `engine.name` — Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`; fall back to the Primary line of `## Engine Specialists` in `technical-preferences.md`)
- **qa-tester** — Write test cases and validate the implementation
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: game-designer` — Design the mechanic, define formulas and edge cases
- `subagent_type: gameplay-programmer` — Implement the core gameplay code
- `subagent_type: ai-programmer` — Implement NPC/enemy AI behavior
@@ -50,7 +88,36 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: [primary engine specialist]` — Engine idiom validation for architecture and implementation
- `subagent_type: qa-tester` — Write test cases and validate implementation
Always provide full context in each agent's prompt (design doc path, relevant code files, constraints). Launch independent agents in parallel where the pipeline allows it (e.g., Phase 3 agents can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
**Substitute a real path for `[path]`.** Every phase that produces an artifact
names one; most are fixed by the skill that already reads them:
| Phase / agent | Writes to | Destination fixed by |
|---|---|---|
| 1 game-designer | `design/gdd/[feature].md` | the GDD convention |
| 2 gameplay-programmer | `docs/architecture/[feature]-sketch.md` | see note below |
| 2 engine specialist | `docs/architecture/[feature]-engine-notes.md` | see note below |
| 5 qa-tester (test cases) | `production/qa/test-cases/[feature]-cases.md` | `/team-qa` Phase 4 |
| 5 qa-tester (bugs) | `production/qa/bugs/BUG-[NNN]-[slug].md` | `/team-qa` Phase 5 |
Phase 6 is a spoken status report, not an artifact — no path, and none needed.
> **Every phase above names a concrete destination, deliberately.** The Error
> Recovery Protocol below says "a named artifact that is not on disk is a failed
> phase" — a check that cannot run when no path was named.
>
> **The two `docs/architecture/` entries are a judgement call, not a convention.**
> That directory holds ADRs (`adr-NNNN-*.md`); a sketch is a precursor to one, not
> one itself, and **nothing in the repo reads either file**. Say so when
> reporting, so the sketch is understood as a record rather than an input to a
> later gate.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (e.g., Phase 3 agents can run simultaneously).
## Pipeline
@@ -79,7 +146,11 @@ Use `AskUserQuestion`:
- `[B] Revise the architecture first — I'll describe what needs to change`
- `[C] Stop here — I'll continue later`
Only spawn implementation agents if user selects [A].
Only spawn implementation agents if user selects [A]. (In `guided`/`autonomous`
mode this architecture gate is a normal phase transition — proceed to
implementation unless the architecture sketch came back BLOCKED, recording the
decision via `log_decision` in autonomous mode. The gate is not a release-
critical or irreversible decision, so it follows the standard pipeline rule.)
### Phase 3: Implementation (parallel where possible)
Delegate in parallel:
@@ -107,15 +178,17 @@ Delegate to **qa-tester**:
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
@@ -126,8 +199,12 @@ Common blockers:
## File Write Protocol
All file writes (design documents, implementation files, test cases) are
delegated to sub-agents spawned via Task. Each sub-agent enforces the
"May I write to [path]?" protocol. This orchestrator does not write files directly.
delegated to sub-agents spawned via `Agent`. Those writes follow the **bounded
exception** documented above under "Why this does not violate the Collaboration
Protocol" — the path is one you named, the artifact is new under `production/`,
`docs/` or `tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent
does **not** prompt per write inside those bounds; outside them it must ask.
This orchestrator does not write files directly.
## Output
+82 -28
View File
@@ -1,9 +1,9 @@
---
name: team-level
description: "Orchestrate level design team: level-designer + narrative-director + world-builder + art-director + systems-designer + qa-tester for complete area/level creation."
description: "Orchestrate the level team — level-designer, narrative-director, world-builder, art-director, systems-designer, qa-tester — for complete area creation."
argument-hint: "[level name or area to design] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
@@ -12,20 +12,58 @@ When this skill is invoked:
**Decision Points:** At each step transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next step.
In `collaborative` mode, the user must approve before moving to the next step.
In `guided` mode the pipeline advances automatically unless a step is BLOCKED;
in `autonomous` mode it runs end to end, recording each step outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `level-designer` + `gameplay-programmer`. Other agents consulted via these two, not spawned separately.
- **`small`**: + `systems-designer` + `art-director`.
- **`studio`**: + `narrative-director` + `world-builder` + `accessibility-specialist`.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Step 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
1. **Read the argument** for the target level or area (e.g., `tutorial`,
`forest dungeon`, `hub town`, `final boss arena`).
@@ -39,7 +77,7 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: narrative-director` — Narrative purpose, characters, emotional arc
- `subagent_type: world-builder` — Lore context, environmental storytelling, world rules
- `subagent_type: level-designer` — Spatial layout, pacing, encounters, navigation
@@ -48,13 +86,17 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: accessibility-specialist` — Navigation clarity, colorblind safety, cognitive load
- `subagent_type: qa-tester` — Test cases, boundary testing, playtest checklist
Always provide full context in each agent's prompt (game concept, pillars, existing level docs, narrative docs).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
3. **Orchestrate the level design team** in sequence:
### Step 1: Narrative + Visual Direction (narrative-director + world-builder + art-director, parallel)
Spawn all three agents simultaneously — issue all three Task calls before waiting for any result.
Spawn all three agents simultaneously — issue all three `Agent` calls before waiting for any result.
Spawn the `narrative-director` agent to:
- Define the narrative purpose of this area (what story beats happen here?)
@@ -148,12 +190,15 @@ Spawn the `qa-tester` agent to:
4. **Compile the level design document** combining all team outputs into the
level design template format.
After all subagent outputs are collected, spawn `level-designer` via Task to compile and write the final document:
- Pass: all subagent outputs (verbatim), the level brief, game pillars, relevant GDD sections
- Ask level-designer to: compile into the level design document format, then request user approval before writing ("May I write the compiled level design to design/levels/[level-name].md?")
- The orchestrator does NOT call Write directly for the final document.
The orchestrator already holds every sub-agent's output — **compile the document
itself; do not re-spawn `level-designer` and re-send all outputs verbatim.** That
second spawn pays a fresh agent's overhead plus a full re-transmission of context
the orchestrator already has, to move text it is already holding. After compiling
into the level-design template format, ask the user directly via
`AskUserQuestion`: "May I write the compiled level design to
`design/levels/[level-name].md`?" On approval, write it.
5. **Save to** `design/levels/[level-name].md` (handled by the level-designer subagent after user approval — see above).
5. **Save to** `design/levels/[level-name].md` after that approval.
6. **Output a summary** with: area overview, encounter count, estimated asset
list, narrative beats, any cross-team dependencies or open questions, open
@@ -162,9 +207,16 @@ After all subagent outputs are collected, spawn `level-designer` via Task to com
## File Write Protocol
All file writes (level design docs, narrative docs, test checklists) are delegated
to sub-agents spawned via Task. Each sub-agent enforces the "May I write to [path]?"
protocol. This orchestrator does not write files directly.
Per-agent artifacts (narrative docs, test checklists) are written by the
sub-agent that produced them, under the **bounded exception** documented above
under "Why this does not violate the Collaboration Protocol" — the path is one
you named, the artifact is new under `production/`, `docs/` or `tests/`, and the
phase is gated by an `AskUserQuestion`. A sub-agent does **not** prompt per write
inside those bounds; outside them it must ask. The **one exception is the final
compiled level-design document**: the
orchestrator already holds every input, so it compiles and writes that file
itself after its own "May I write …?" prompt (Step 4) — re-spawning an agent
just to write text the orchestrator is already holding is pure overhead.
Verdict: **COMPLETE** — level design document produced and all team outputs compiled.
Verdict: **BLOCKED** — one or more agents blocked; partial report produced with unresolved items listed.
@@ -177,15 +229,17 @@ Verdict: **BLOCKED** — one or more agents blocked; partial report produced wit
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
+81 -22
View File
@@ -1,9 +1,9 @@
---
name: team-live-ops
description: "Orchestrate the live-ops team for post-launch content planning: coordinates live-ops-designer, economy-designer, analytics-engineer, community-manager, writer, and narrative-director to design and plan a season, event, or live content update."
description: "Orchestrate the live-ops team — live-ops-designer, economy-designer, analytics-engineer, community-manager, writer — for a season or live event."
argument-hint: "[season name or event description] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
**Argument check:** If no season name or event description is provided, output:
@@ -15,20 +15,58 @@ When this skill is invoked with a valid argument, orchestrate the live-ops team
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `live-ops-designer` + `economy-designer`. Other agents consulted via these two, not spawned separately.
- **`small`**: + `analytics-engineer` + `community-manager` (the full pipeline as documented).
- **`studio`**: + `writer` + `narrative-director` + per-season reviews.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
## Team Composition
- **live-ops-designer** — Season structure, event cadence, retention mechanics, battle pass
@@ -40,7 +78,7 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: live-ops-designer` — Season/event structure and retention mechanics
- `subagent_type: economy-designer` — Live economy balance and reward pricing
- `subagent_type: analytics-engineer` — Success metrics, A/B tests, event instrumentation
@@ -48,7 +86,13 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: narrative-director` — Seasonal theme and narrative framing
- `subagent_type: writer` — All player-facing text: event descriptions, item names, copy
Always provide full context in each agent's prompt (game concept path, existing season docs, ethics policy path, current economy state). Launch independent agents in parallel where the pipeline allows it (Phases 3 and 4 can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (Phases 3 and 4 can run simultaneously).
## Pipeline
@@ -121,30 +165,45 @@ Ask the user to approve the season plan before delegating to production teams. I
## Output Documents
All documents save to `design/live-ops/`:
All documents save to `design/live-ops/` — **but the orchestrator asks before
writing them.** `design/` is NOT one of the three directories the bounded write
exception covers (`production/`, `docs/`, `tests/`), so a sub-agent handed one of
these paths must prompt. Do not widen the exception to silence that.
Follow `team-level`'s pattern instead: sub-agents write their working artifacts
under `production/`, where the exception does reach them; **you** compile the
final documents and ask via `AskUserQuestion` — "May I write the season plan to
`design/live-ops/…`?" — writing them only on approval.
Paths:
- `seasons/S[N]_[name].md` — Season design document (from Phase 1-3)
- `seasons/S[N]_[name]_analytics.md` — Analytics plan (from Phase 4)
- `seasons/S[N]_[name]_comms.md` — Communication calendar (from Phase 6)
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
If a BLOCKED state is unresolvable, end with Verdict: **BLOCKED** instead of COMPLETE.
## File Write Protocol
All file writes (season design docs, analytics plans, communication calendars) are
delegated to sub-agents spawned via Task. Each sub-agent enforces the
"May I write to [path]?" protocol. This orchestrator does not write files directly.
delegated to sub-agents spawned via `Agent`. Those writes follow the **bounded
exception** documented above under "Why this does not violate the Collaboration
Protocol" — the path is one you named, the artifact is new under `production/`,
`docs/` or `tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent
does **not** prompt per write inside those bounds; outside them it must ask.
This orchestrator does not write files directly.
## Output
+98 -22
View File
@@ -1,9 +1,9 @@
---
name: team-narrative
description: "Orchestrate the narrative team: coordinates narrative-director, writer, world-builder, and level-designer to create cohesive story content, world lore, and narrative-driven level design."
description: "Orchestrate the narrative team — narrative-director, writer, world-builder, level-designer — for story, world lore, narrative-driven levels."
argument-hint: "[narrative content description] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
If no argument is provided, output usage guidance and exit without spawning any agents:
@@ -14,20 +14,58 @@ When this skill is invoked with an argument, orchestrate the narrative team thro
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `writer` only; `narrative-director` invoked only on an explicit pillar conflict. Other agents consulted via the writer, not spawned separately.
- **`small`**: `narrative-director` + `writer` + (per review_mode) `localization-lead`, `world-builder`.
- **`studio`**: all narrative agents active + per-system writer reviews.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
## Team Composition
- **narrative-director** — Story arcs, character design, dialogue strategy, narrative vision
@@ -39,7 +77,7 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: narrative-director` — Story arcs, character design, narrative vision
- `subagent_type: writer` — Dialogue writing, lore entries, in-game text
- `subagent_type: world-builder` — World rules, faction design, history, geography
@@ -47,7 +85,33 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: level-designer` — Level layouts that serve the narrative, pacing
- `subagent_type: localization-lead` — Localization readiness — flags non-localizable strings, cultural assumptions, and i18n gaps
Always provide full context in each agent's prompt (narrative brief, lore dependencies, character profiles). Launch independent agents in parallel where the pipeline allows it (e.g., Phase 2 agents can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
**Substitute a real path for `[path]` — this skill's destination is
`design/narrative/`.** Name it per agent, one file each:
| Agent | Writes to |
|---|---|
| narrative-director | `design/narrative/[content-slug]-brief.md` |
| world-builder | `design/narrative/lore/[topic].md` |
| writer | `design/narrative/dialogue/[scene-slug].md` |
| art-director | `design/narrative/[content-slug]-visual-direction.md` |
> **The destination is not a free choice.** `design/narrative/` is read by
> `/asset-spec`, `/design-review`, `/localize`, `/onboard`,
> `/project-stage-detect`, `/team-level` and the `cd-narrative` director gate.
> An artifact written anywhere else is invisible to all seven.
>
> The `[path]` contract above has a precondition: the path is one *you* named. A
> skill that states the contract but names no concrete destination leaves every
> run to invent one, which defeats it. `/team-qa` Phase 4 carries the same
> requirement for the same reason.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (e.g., Phase 2 agents can run simultaneously).
## Pipeline
@@ -60,11 +124,17 @@ Delegate to **narrative-director**:
- Output: narrative brief with story requirements
### Phase 2: World Foundation (parallel)
Delegate in parallel — issue all three Task calls simultaneously before waiting for any result:
Delegate in parallel — issue all three `Agent` calls simultaneously before waiting for any result:
- **world-builder**: Create or update lore entries for factions, locations, and history relevant to this content. Cross-reference against existing lore for contradictions. Set canon level for new entries.
- **writer**: Draft character dialogue using voice profiles. Ensure all lines are under 120 characters, use named placeholders for variables, and are localization-ready.
- **art-director**: Define character visual design direction for key characters appearing in this content (silhouette, visual archetype, distinguishing features). Specify environmental visual storytelling elements for each key space (prop composition, lighting notes, spatial arrangement). Define tone palette and cinematic direction for any cutscenes or scripted sequences.
**Phase gate:** collect all three Phase 2 outputs, then apply the Decision Points
rule before starting Phase 3 — present the lore, dialogue, and visual direction
summaries and capture approval via `AskUserQuestion` in `collaborative` mode
(auto-advance in `guided` unless a result is BLOCKED; `log_decision` in
`autonomous`).
### Phase 3: Level Narrative Integration
Delegate to **level-designer**:
- Review the narrative brief and lore foundation
@@ -87,15 +157,17 @@ Delegate in parallel:
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
@@ -106,8 +178,12 @@ Common blockers:
## File Write Protocol
All file writes (narrative docs, dialogue files, lore entries) are delegated to
sub-agents spawned via Task. Each sub-agent enforces the "May I write to [path]?"
protocol. This orchestrator does not write files directly.
sub-agents spawned via `Agent`. Those writes follow the **bounded exception**
documented above under "Why this does not violate the Collaboration Protocol" —
the path is one you named, the artifact is new under `production/`, `docs/` or
`tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent does **not**
prompt per write inside those bounds; outside them it must ask. This orchestrator
does not write files directly.
## Output
+94 -21
View File
@@ -1,9 +1,9 @@
---
name: team-polish
description: "Orchestrate the polish team: coordinates performance-analyst, technical-artist, sound-designer, and qa-tester to optimize, polish, and harden a feature or area for release quality."
description: "Orchestrate the polish team — performance-analyst, technical-artist, sound-designer, qa-tester — to optimize and harden a feature or area."
argument-hint: "[feature or area to polish] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
If no argument is provided, output usage guidance and exit without spawning any agents:
@@ -14,20 +14,58 @@ When this skill is invoked with an argument, orchestrate the polish team through
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `performance-analyst` + `technical-artist`. Other agents consulted via these two, not spawned separately.
- **`small`**: + `sound-designer` + `qa-tester` (the full pipeline as documented).
- **`studio`**: full pipeline + engine sub-specialists + an adversarial review pass.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
**Director gate skip rule**: Before spawning any Tier 1 director or lead for review (outside of PHASE-GATE triggers), apply the resolved mode: skip if solo mode; skip if lean mode and this is not a PHASE-GATE.
@@ -41,7 +79,7 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: performance-analyst` — Profiling, optimization, memory analysis
- `subagent_type: engine-programmer` — Engine-level fixes for rendering, memory, resource loading
- `subagent_type: technical-artist` — VFX polish, shader optimization, visual quality
@@ -49,7 +87,36 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: tools-programmer` — Content pipeline and editor tool verification
- `subagent_type: qa-tester` — Edge case testing, regression testing, soak testing
Always provide full context in each agent's prompt (target feature/area, performance budgets, known issues). Launch independent agents in parallel where the pipeline allows it (e.g., Phases 3 and 4 can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
**Substitute a real path for `[path]` — this skill's destination is
`production/polish/`.** Name it per agent, one file each:
| Agent | Writes to |
|---|---|
| performance-analyst | `production/polish/[area]-report-[date].md` |
| technical-artist | `production/polish/[area]-render-notes-[date].md` |
| engine-programmer | `production/polish/[area]-engine-fixes-[date].md` |
| sound-designer | `production/polish/[area]-audio-notes-[date].md` |
| qa-tester | `production/polish/[area]-verification-[date].md` |
> **Why `production/` and not `docs/`.** These are date-stamped measurements of
> one run, the same shape as `production/qa/smoke-[date].md` — not durable
> specifications like `docs/architecture/`. Keeping them beside the other
> point-in-time process artifacts is what makes a later comparison possible.
>
> The `[path]` contract above has a precondition: the path is one *you* named, so
> a concrete destination must be stated here or every run invents one. Unlike
> `/team-qa` and `/team-narrative`, whose destinations are fixed by their
> consumers, this location has no reader in the repo and was chosen deliberately.
> **Nothing reads `production/polish/` yet** — say so when reporting, so the user
> knows the report is a record rather than an input to a later gate.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (e.g., Phases 3 and 4 can run simultaneously).
## Pipeline
@@ -107,15 +174,17 @@ Delegate to **qa-tester**:
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
@@ -126,8 +195,12 @@ Common blockers:
## File Write Protocol
All file writes (performance reports, test results, evidence docs) are delegated to
sub-agents spawned via Task. Each sub-agent enforces the "May I write to [path]?"
protocol. This orchestrator does not write files directly.
sub-agents spawned via `Agent`. Those writes follow the **bounded exception**
documented above under "Why this does not violate the Collaboration Protocol" —
the path is one you named, the artifact is new under `production/`, `docs/` or
`tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent does **not**
prompt per write inside those bounds; outside them it must ask. This orchestrator
does not write files directly.
## Output
+123 -26
View File
@@ -1,11 +1,10 @@
---
name: team-qa
description: "Orchestrate the QA team through a full testing cycle. Coordinates qa-lead (strategy + test plan) and qa-tester (test case writing + bug reporting) to produce a complete QA package for a sprint or feature. Covers: test plan generation, test case writing, smoke check gate, manual QA execution, and sign-off report."
description: "Orchestrate the QA team through a full testing cycle — qa-lead strategy and test plan, qa-tester case writing, execution, sign-off."
argument-hint: "[sprint | feature: system-name] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion
model: sonnet
agent: qa-lead
---
When this skill is invoked, orchestrate the QA team through a structured testing cycle.
@@ -13,20 +12,58 @@ When this skill is invoked, orchestrate the QA team through a structured testing
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `qa-tester` only; `qa-lead` invoked at phase gates only.
- **`small`**: `qa-lead` + `qa-tester` pipeline (as documented).
- **`studio`**: `qa-lead` + per-story `qa-tester` spawn + sign-off.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
## Team Composition
@@ -35,11 +72,17 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: qa-lead` — Strategy, planning, classification, sign-off
- `subagent_type: qa-tester` — Test case writing and bug report writing
Always provide full context in each agent's prompt (story file paths, QA plan path, scope constraints). Launch independent qa-tester tasks in parallel where possible (e.g., multiple stories in Phase 5 can be scaffolded simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent qa-tester tasks in parallel where possible (e.g., multiple stories in Phase 5 can be scaffolded simultaneously).
## Pipeline
@@ -52,14 +95,14 @@ Before doing anything else, gather the full scope:
- If argument is `feature: [system-name]`: glob story files tagged for that system
- If no argument: read `production/session-state/active.md` and `production/sprint-status.yaml` (if present) to infer the active sprint
2. Read `production/stage.txt` to confirm the current project phase.
2. Read `project.stage` from `project.yaml` (fallback `production/stage.txt`) to confirm the current project phase.
3. Count stories found and report to the user:
> "QA cycle starting for [sprint/feature]. Found [N] stories. Current stage: [stage]. Ready to begin QA strategy?"
### Phase 2: QA Strategy (qa-lead)
Spawn `qa-lead` via Task to review all in-scope stories and produce a QA strategy.
Spawn `qa-lead` via `Agent` to review all in-scope stories and produce a QA strategy.
Prompt the qa-lead to:
- Read each story file
@@ -117,11 +160,20 @@ Write only after receiving approval.
For each story requiring manual QA (Visual/Feel, UI, Integration without automated tests):
Spawn `qa-tester` via Task for each story (run in parallel where possible), providing:
Spawn `qa-tester` via `Agent` for each story (run in parallel where possible), providing:
- The story file path
- The relevant section of the QA plan for that story
- The GDD acceptance criteria for the system being tested (if available)
- Instructions to write detailed test cases covering all acceptance criteria
- **The output path: `production/qa/test-cases/[story-slug]-cases.md`.** Name it
explicitly in the prompt, one per story.
> **Why the path is stated here rather than left to the orchestrator.** The
> bounded write exception above holds only when "the path is one **you** named in
> the prompt". This is the phase that spawns agents *in parallel*, so it is where
> an unnamed destination does the most damage: each agent improvises its own, and
> two runs file the same artifact in two places. The phase reads correctly right
> up until two agents need somewhere to put their output.
Each test case set should include:
- **Preconditions**: game state required before testing begins
@@ -157,7 +209,28 @@ options:
- "BLOCKED — cannot test yet (reason)"
```
After each FAIL result: use `AskUserQuestion` to collect the failure description, then spawn `qa-tester` via Task to write a formal bug report in `production/qa/bugs/`.
After each FAIL result: use `AskUserQuestion` to collect the failure description, then spawn `qa-tester` via `Agent` to write a formal bug report in `production/qa/bugs/`.
**After each PASS or PASS WITH NOTES on a Visual/Feel or UI story, write the
evidence artifact** to `production/qa/evidence/[story-slug]-evidence.md`, from
`.claude/docs/templates/test-evidence.md`, carrying the sign-off table intact.
Save the screenshot you took while testing into the same directory and reference
it from the doc — `/story-done` checks for a retained image, not just the
write-up.
> **This is not optional bookkeeping — it is the artifact the next skill gates
> on.** `/story-done` globs `production/qa/evidence/` for Visual/Feel and UI
> stories and reads the sign-off table; `/story-readiness`,
> `/test-evidence-review` and `gate-release` read the same directory. Write
> anywhere else and a story can pass a full manual QA cycle here, then be told by
> `/story-done` that no visual evidence exists. Visual/Feel and UI gates are
> **BLOCKING by default**, so that is a deadlock — QA passed, story cannot
> close. It is a merely confusing flag only where `testing.strict.ui` or
> `.visual` has been explicitly set to `false`.
>
> Leave the sign-off rows **unchecked** unless the sign-off actually happened in
> this session. An evidence file with pre-ticked approvals is worse than none: it
> converts a missing signature into a recorded one.
Bug report naming: `BUG-[NNN]-[short-slug].md` (increment NNN from existing bugs in the directory).
@@ -169,7 +242,7 @@ After collecting all results, summarize:
### Phase 6: QA Sign-Off Report
Spawn `qa-lead` via Task to produce the sign-off report using all results from Phases 4–6.
Spawn `qa-lead` via `Agent` to produce the sign-off report using all results from Phases 4–6.
The sign-off report format:
@@ -188,7 +261,7 @@ The sign-off report format:
|----|-------|----------|--------|
| BUG-001 | [story] | S2 | Open |
### Verdict: APPROVED / APPROVED WITH CONDITIONS / NOT APPROVED
### Verdict: NOT ASSESSED / APPROVED / APPROVED WITH CONDITIONS / NOT APPROVED
**Conditions** (if any): [list what must be fixed before the build advances]
@@ -197,11 +270,33 @@ The sign-off report format:
```
Verdict rules:
**Precondition, checked first.** APPROVED and APPROVED WITH CONDITIONS both
require that **every story in scope produced executed evidence** — a test that
ran, or a manual case that was walked. If any story is BLOCKED, unexecuted, or
has no evidence, the verdict is **NOT ASSESSED** and the other three rules are
not evaluated.
- **NOT ASSESSED — NO EVIDENCE**: One or more stories produced no executed
evidence (BLOCKED, tests not written, cases not walked, or smoke check FAIL /
UNKNOWN). This is **not** a pass and **not** a fail; it means QA did not
happen. Say which stories and why.
- **APPROVED**: All stories PASS or PASS WITH NOTES; no S1/S2 bugs open
- **APPROVED WITH CONDITIONS**: S3/S4 bugs open, or PASS WITH NOTES issues documented; no S1/S2 bugs
- **NOT APPROVED**: Any S1/S2 bugs open; or stories FAIL without documented workaround
> **Why the precondition exists.** The three rules below it assume
> every story resolves to PASS or FAIL. A sprint where nothing was executed
> trips none of the NOT APPROVED conditions and **vacuously satisfies "no S1/S2
> bugs open"** — because zero executed tests means zero observed failures. Read
> literally, and without this precondition, the rules let a completely untested
> build reach APPROVED — a `qa-lead` reaching NOT APPROVED on intent would find
> the letter of the rules did not support it. A
> sign-off asserts verified quality; without this precondition the rules cannot
> tell "verified good" from "never looked".
Next step guidance by verdict:
- NOT ASSESSED: "QA did not run to completion. Produce the missing evidence — write the Logic tests, walk the manual cases, run `/smoke-check` — then re-run `/team-qa`. Do not advance the build on this verdict."
- APPROVED: "Build is ready for the next phase. Run `/gate-check` to validate advancement."
- APPROVED WITH CONDITIONS: "Resolve conditions before advancing. S3/S4 bugs may be deferred to polish."
- NOT APPROVED: "Resolve S1/S2 bugs and re-run `/team-qa` or targeted manual QA before advancing."
@@ -212,15 +307,17 @@ Write only after receiving approval.
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
+114 -24
View File
@@ -1,9 +1,9 @@
---
name: team-release
description: "Orchestrate the release team: coordinates release-manager, qa-lead, devops-engineer, and producer to execute a release from candidate to deployment."
description: "Orchestrate the release team — release-manager, qa-lead, devops-engineer, producer — to execute a release from candidate to deployment."
argument-hint: "[version number or 'next'] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
**Argument check:** If no version number is provided:
@@ -16,20 +16,58 @@ When this skill is invoked, orchestrate the release team through a structured pi
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `release-manager` only. Other agents consulted via the release-manager, not spawned separately.
- **`small`**: + `producer` + `devops-engineer` + `qa-lead`.
- **`studio`**: + `security-engineer` + `analytics-engineer` + `localization-lead`.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Phase 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
## Team Composition
- **release-manager** — Release branch, versioning, changelog, deployment
@@ -42,7 +80,7 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: release-manager` — Release branch, versioning, changelog, deployment
- `subagent_type: qa-lead` — Test sign-off, regression suite, release quality gate
- `subagent_type: devops-engineer` — Build pipeline, artifacts, deployment automation
@@ -52,7 +90,35 @@ Use the Task tool to spawn each team member as a subagent:
- `subagent_type: producer` — Go/no-go decision, stakeholder communication
- `subagent_type: network-programmer` — Netcode stability sign-off (invoke if game has multiplayer)
Always provide full context in each agent's prompt (version number, milestone status, known issues). Launch independent agents in parallel where the pipeline allows it (e.g., Phase 3 agents can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
**Substitute a real path for `[path]`.** One file per phase under
`production/releases/`, except the two whose homes are fixed elsewhere:
| Phase / agent | Writes to | Destination fixed by |
|---|---|---|
| 1 producer | `production/releases/release-plan-[version].md` | this skill |
| 2 release-manager | `production/releases/release-checklist-[version].md` | `/release-checklist` |
| 3 qa-lead | `production/releases/qa-gate-[version].md` | this skill |
| 4 specialists | `production/releases/signoff-[version].md` | this skill |
| 5 go/no-go | `production/releases/go-no-go-[version].md` | this skill |
| 6 community-manager | `docs/patch-notes/[version].md` | `/patch-notes` |
| 7 release-manager | `production/releases/release-report-[version].md` | this skill |
> **Every one of those seven outputs needs a stated destination.**
> `production/releases/` is where `/release-checklist` already writes, and
> `docs/patch-notes/[version].md` is where `/patch-notes` already writes, so the
> release record lands in one place regardless of which skill produced it.
>
> **A separate file per phase, not one appended record.** Phase 3 and Phase 4
> spawn agents in parallel; two agents appending to one file race, and the loser's
> section vanishes silently.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (e.g., Phase 3 agents can run simultaneously).
## Pipeline
@@ -109,11 +175,21 @@ After the user selects "Override NO-GO with documented rationale":
- Only then proceed to Phase 6.
### Phase 6: Deployment (if GO)
Delegate to **release-manager** + **devops-engineer**:
**This phase always requires explicit user approval regardless of
`modes.automation` — including `autonomous` mode.** Production deployment is
irreversible and high-stakes; it is NOT covered by the configurable
`automation_always_ask` categories, so this skill guards it unconditionally.
Before tagging or deploying, use `AskUserQuestion`:
- Prompt: "Producer verdict is GO. Execute Phase 6 — tag, deploy to staging,
deploy to production?"
- Options: `[A] Yes, deploy` / `[B] Staging only — hold production` / `[C] Stop here`
Only after explicit approval, delegate to **release-manager** + **devops-engineer**:
- Tag the release in version control
- Generate changelog using `/changelog`
- Deploy to staging for final smoke test
- Deploy to production
- Deploy to production (only if the user approved production above)
- Human team action: Monitor dashboards and error rates for 48 hours post-release. Schedule a follow-up retrospective using `/retrospective` at the 48-hour mark.
Delegate to **community-manager** (in parallel with deployment):
@@ -132,15 +208,17 @@ Delegate to **community-manager** (in parallel with deployment):
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
@@ -151,8 +229,20 @@ Common blockers:
## File Write Protocol
All file writes (release checklists, changelogs, patch notes, deployment scripts) are
delegated to sub-agents and sub-skills. Each enforces the "May I write to [path]?"
protocol. This orchestrator does not write files directly.
delegated to sub-agents and sub-skills. The two follow **different** rules, and the
distinction matters here more than anywhere else in the pipeline:
- **Sub-agents spawned via `Agent`** follow the **bounded exception** documented above
under "Why this does not violate the Collaboration Protocol" — the path is one you
named, the artifact is new under `production/`, `docs/` or `tests/`, and the phase
is gated by an `AskUserQuestion`. A sub-agent does **not** prompt per write inside
those bounds; outside them it must ask.
- **Sub-skills** are not sub-agents and the exception does not reach them. They
follow the normal Collaboration Protocol and ask before writing.
This orchestrator does not write files directly. Nothing here authorises an
outward-facing or irreversible action — tags, pushes, builds and storefront changes
require explicit confirmation regardless of which rule above applies.
## Output
@@ -165,4 +255,4 @@ Verdict: **BLOCKED** — release halted; go/no-go was NO or a hard blocker is un
- Monitor post-release dashboards for 48 hours.
- Run `/retrospective` if significant issues occurred during the release.
- Update `production/stage.txt` to `Live` after successful deployment.
- Update `project.stage` in `project.yaml` to `Release` after successful deployment (also write `Release` to `production/stage.txt` for backward compatibility with hooks that haven't migrated). `Release` is the terminal stage in the `project.stage` enum — there is no post-launch stage value. Record live/post-launch status in the release report, not in `project.stage`.
+109 -25
View File
@@ -1,9 +1,9 @@
---
name: team-ui
description: "Orchestrate the UI team through the full UX pipeline: from UX spec authoring through visual design, implementation, review, and polish. Integrates with /ux-design, /ux-review, and studio UX templates."
description: "Orchestrate the UI team through the UX pipeline — authoring, visual design, implementation, review, polish. Uses /ux-design, /ux-review, studio templates."
argument-hint: "[UI feature description] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, TodoWrite
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate
model: sonnet
---
When this skill is invoked, orchestrate the UI team through a structured pipeline.
@@ -11,20 +11,58 @@ When this skill is invoked, orchestrate the UI team through a structured pipelin
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
the user with the subagent's proposals as selectable options. Write the agent's
full analysis in conversation, then capture the decision with concise labels.
The user must approve before moving to the next phase.
In `collaborative` mode, the user must approve before moving to the next phase.
In `guided` mode the pipeline advances automatically unless a phase is BLOCKED;
in `autonomous` mode it runs end to end, recording each phase outcome via
`log_decision`. Decisions in `automation_always_ask` categories
(`is_always_ask_category` helper) always prompt regardless of mode. See
`.claude/docs/automation-modes.md`.
## Phase 0: Resolve Review Mode
## Phase 0: Resolve Config
1. If `--review [mode]` was passed as an argument, use that mode.
2. Else read `production/review-mode.txt` — use whatever is written there.
3. Else default to `lean`.
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation,team.size`
Modes:
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
defaults in `.claude/docs/config-resolution.md`.
`review_mode` sets gate depth:
- `full` — spawn all director and lead gates as described
- `lean` — skip director gates unless they are PHASE-GATE type (CD-PHASE-GATE, TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE)
- `solo` — skip all director gate spawning entirely; run the skill without any agent gates
Store the resolved mode for use in all subsequent phases.
`automation` drives the Decision Points note above. See the Decision Points note above and
`.claude/docs/automation-modes.md` for how each mode changes pipeline behavior.
**`team.size`**: which agents are active (orthogonal to review_mode gate-depth and workflow docs).
- **`individual`** (default): `ui-programmer` + `ux-designer`. Other agents consulted via these two, not spawned separately.
- **`small`**: + `accessibility-specialist` + `art-director`.
- **`studio`**: + engine UI specialist + an adversarial review pass.
Directors (CD/TD/PR) still spawn at phase gates regardless of size; a non-core agent needed at `individual` routes through the nearest active core agent with an informational note. **"Phase gate" means any phase that ends in an `AskUserQuestion` decision point before the pipeline advances** — not every phase. Apply the test literally: if the phase below has no decision point, it is not a gate, and an agent restricted to "phase gates only" is not spawned for it. This active-set scoping applies throughout the pipeline below: any phase that names an agent outside the active set routes through the nearest core agent rather than spawning it.
**Announce the active set before Step 1 — never let the collapse be silent.**
Before spawning anything, state in one line which agents this run will actually
spawn, and which the pipeline below names but will **not** spawn at the resolved
`team.size`. For example:
> `Active set (team.size: <resolved>): <the agents listed for that size above>.`
> `Not spawned this run: <every other agent this pipeline names> — consulted`
> `through <nearest active core agent>. Raise team.size (or modes.rigor) to widen.`
Fill it from the `team.size` list directly above and the agents this file's own
pipeline names — not from an example. Both sets differ per orchestrator.
The pipeline below reads as a multi-agent fan-out and at the shipped default it
is one or two agents — `team-release` names eight and runs one, `team-narrative`
names six across five phases and runs `writer` alone. **The collapse is correct**:
`team.size` is rigor-fronted and the narrow default is the token lever, measured
at roughly 10x. What was wrong is that nothing said so, so a reader could not
distinguish a correctly-collapsed run from a broken pipeline, and the per-agent
"routes through the nearest core agent with an informational note" rule above
fires at routing time and never states the shape of the run as a whole.
This is the same rule as the skipped-check reporting elsewhere in this file: **a constraint that is enforced but never surfaced is
indistinguishable, to the person reading the output, from one that was never
enforced.**
**Director gate skip rule**: Before spawning creative-director, art-director, or any other Tier 1/2 director for review (outside of PHASE-GATE triggers), apply the resolved mode: skip if solo mode; skip if lean mode and this is not a PHASE-GATE.
@@ -32,9 +70,14 @@ Store the resolved mode for use in all subsequent phases.
- **ux-designer** — User flows, wireframes, accessibility, input handling
- **ui-programmer** — UI framework, screens, widgets, data binding, implementation
- **art-director** — Visual style, layout polish, consistency with art bible
- **engine UI specialist** — Validates UI implementation patterns against engine-specific best practices (read from `.claude/docs/technical-preferences.md` Engine Specialists → UI Specialist)
- **engine UI specialist** — Validates UI implementation patterns against engine-specific best practices (`specialists.ui` from `project.yaml`; if absent, the UI Specialist line of `## Engine Specialists` in `.claude/docs/technical-preferences.md`)
- **accessibility-specialist** — Audits accessibility compliance at Phase 4
> **`specialists.ui: null` means UNSET.** Treat it as absent and skip the engine
> UI specialist; never spawn `null` as an agent name. The v1.0 migration writes
> the whole `specialists` block whenever any one member is set, so `null` here is
> ordinary — and the config reader returns it as the non-empty string `"null"`.
**Templates used by this pipeline:**
- `ux-spec.md` — Standard screen/flow UX specification
- `hud-design.md` — HUD-specific UX specification
@@ -43,14 +86,20 @@ Store the resolved mode for use in all subsequent phases.
## How to Delegate
Use the Task tool to spawn each team member as a subagent:
Use the `Agent` tool to spawn each team member as a subagent:
- `subagent_type: ux-designer` — User flows, wireframes, accessibility, input handling
- `subagent_type: ui-programmer` — UI framework, screens, widgets, data binding
- `subagent_type: art-director` — Visual style, layout polish, art bible consistency
- `subagent_type: [UI engine specialist]` — Engine-specific UI pattern validation (e.g., unity-ui-specialist, ue-umg-specialist, godot-specialist)
- `subagent_type: accessibility-specialist` — Accessibility compliance audit
Always provide full context in each agent's prompt (feature requirements, existing UI patterns, platform targets). Launch independent agents in parallel where the pipeline allows it (e.g., Phase 4 review agents can run simultaneously).
**Brief each agent — do not dump context.** Read the shared inputs **once** and pass a distilled brief inline: the lines each agent actually needs, never a file path for a document you have already read (an agent handed a path re-reads the whole file). Pass a path only for a document you have not read and only that agent needs.
**End every agent prompt with a return contract:** "Write your full output to `[path]` — that named path is your write authorisation under the bounded exception below, so write it without a separate approval prompt. Return **only** (1) the path written, (2) a ≤5-bullet summary of decisions, (3) any BLOCKED/CONCERNS items, one line each. Do not restate the documents you read." Without it, an agent returns everything it read back into this session.
> **Why this does not violate the Collaboration Protocol.** `CLAUDE.md` requires an agent to ask "May I write this to [filepath]?" before Write/Edit. A subagent spawned here writes **without** asking, and that is a deliberate, bounded exception rather than an oversight — the same call already made for `consistency-check` appending to `active.md`. The exception holds only when all three are true: (1) the path is one **you** named in the prompt, so the user approved the destination when they approved the phase; (2) it is a new artifact under `production/`, `docs/` or `tests/`, never an edit to existing source or config; (3) the phase that produced it is itself gated by an `AskUserQuestion` before the pipeline advances. Outside those three, the agent must ask. **Do not "fix" this by asking per subagent** — a prompt per agent per phase makes an orchestrator unusable, which is why the exception exists.
Launch independent agents in parallel where the pipeline allows it (e.g., Phase 4 review agents can run simultaneously).
## Pipeline
@@ -63,6 +112,30 @@ Before designing anything, read and synthesize:
- `design/ux/interaction-patterns.md` — existing patterns to reuse (not reinvent)
- `design/accessibility-requirements.md` — committed accessibility tier (e.g., Basic, Enhanced, Full)
**Report the status of every document above before designing anything.** Phase 1a
reads five inputs; for a long time only the pattern library was guarded, and the
other four could be absent without anything noticing. List each as
present or ABSENT.
**`design/accessibility-requirements.md` is the one that must not pass silently.**
It carries the committed accessibility tier, which **Phase 3 implements against**
and **Phase 4 gates on** ("verify compliance against the committed accessibility
tier … flag any violations as blockers"). If the file is missing there is no tier,
so that gate has no criterion and would pass while checking nothing — a gate made
of an absent standard, the same shape as an assertion that can never fail. When it
is absent:
- Say so here, and carry it forward: **Phase 4 must report
`Accessibility: NOT ASSESSED — no committed tier (design/accessibility-requirements.md absent)`
and must NOT report the accessibility gate as passed.**
- The ux-designer states which tier they designed against as an explicit
assumption, so a later reader can see it was assumed rather than committed.
- Recommend `/ux-design accessibility` to establish the tier.
Absence of `design/gdd/game-concept.md`, `design/player-journey.md` or
`design/ux/hud.md` is not blocking, but name each missing one in the brief you
pass to the ux-designer so they design knowing what context they lack, rather
than inferring it.
**If `design/ux/interaction-patterns.md` does not exist**, surface the gap immediately:
> "interaction-patterns.md does not exist — no existing patterns to reuse."
@@ -104,13 +177,13 @@ Delegate to **art-director**:
### Phase 3: Implementation
Before implementation begins, spawn the **engine UI specialist** (from `.claude/docs/technical-preferences.md` Engine Specialists → UI Specialist) to review the UX spec and visual design spec for engine-specific implementation guidance:
Before implementation begins, spawn the **engine UI specialist** (`specialists.ui` from `project.yaml`; if absent, the UI Specialist line of `## Engine Specialists` in `.claude/docs/technical-preferences.md`) to review the UX spec and visual design spec for engine-specific implementation guidance:
- Which engine UI framework should be used for this screen? (e.g., UI Toolkit vs UGUI in Unity, Control nodes vs CanvasLayer in Godot, UMG vs CommonUI in Unreal)
- Any engine-specific gotchas for the proposed layout or interaction patterns?
- Recommended widget/node structure for the engine?
- Output: engine UI implementation notes to hand off to ui-programmer before they begin
If no engine is configured, skip this step.
If no engine is configured, skip this step. **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
Delegate to **ui-programmer**:
- Implement the UI following the UX spec and visual design spec
@@ -128,7 +201,7 @@ Delegate to **ui-programmer**:
Delegate in parallel:
- **ux-designer**: Verify implementation matches wireframes and interaction spec. Test keyboard-only and gamepad-only navigation. Check accessibility features function correctly.
- **art-director**: Verify visual consistency with art bible. Check at minimum and maximum supported resolutions.
- **accessibility-specialist**: Verify compliance against the committed accessibility tier documented in `design/accessibility-requirements.md`. Flag any violations as blockers.
- **accessibility-specialist**: Verify compliance against the committed accessibility tier documented in `design/accessibility-requirements.md`. Flag any violations as blockers. **If that file is absent there is no committed tier, so this gate has no criterion: report `Accessibility: NOT ASSESSED — no committed tier (design/accessibility-requirements.md absent)` and do NOT report the gate as passed**. Carry forward whatever tier Phase 1a recorded as assumed, and say plainly that it was assumed.
All three review streams must report before proceeding to Phase 5.
@@ -150,15 +223,17 @@ All three review streams must report before proceeding to Phase 5.
## Error Recovery Protocol
If any spawned agent (via Task) returns BLOCKED, errors, or cannot complete:
**First, verify the artifact.** If the return contract named a path, check the
path exists before treating the phase as done — **a named artifact that is not
on disk is a failed phase, however fluent the response reads.** An agent can
burn a full phase and return a plausible preamble having written nothing, which
is neither BLOCKED nor an error nor "cannot complete", so the trigger below
never fires. Resume it naming the unmet contract; the context is
usually still there.
1. **Surface immediately**: Report "[AgentName]: BLOCKED — [reason]" to the user before continuing to dependent phases
2. **Assess dependencies**: Check whether the blocked agent's output is required by subsequent phases. If yes, do not proceed past that dependency point without user input.
3. **Offer options** via AskUserQuestion with choices:
- Skip this agent and note the gap in the final report
- Retry with narrower scope
- Stop here and resolve the blocker first
4. **Always produce a partial report** — output whatever was completed. Never discard work because one agent blocked.
If any spawned agent returns BLOCKED, errors, or cannot complete: **surface it
immediately, don't proceed past a dependency it blocks, and always produce a
partial report.** Full procedure: `.claude/docs/error-recovery-protocol.md`.
Common blockers:
- Input file missing (story not found, GDD absent) → redirect to the skill that creates it
@@ -169,8 +244,17 @@ Common blockers:
## File Write Protocol
All file writes (UX specs, interaction pattern library updates, implementation files) are
delegated to sub-agents and sub-skills (`/ux-design`, `ui-programmer`). Each enforces the
"May I write to [path]?" protocol. This orchestrator does not write files directly.
delegated to sub-agents and sub-skills. The two follow **different** rules:
- **Sub-agents spawned via `Agent`** (e.g. `ui-programmer`) follow the **bounded
exception** documented above under "Why this does not violate the Collaboration
Protocol" — the path is one you named, the artifact is new under `production/`,
`docs/` or `tests/`, and the phase is gated by an `AskUserQuestion`. A sub-agent
does **not** prompt per write inside those bounds; outside them it must ask.
- **Sub-skills** (`/ux-design`) are not sub-agents and the exception does not reach
them. They follow the normal Collaboration Protocol and ask before writing.
This orchestrator does not write files directly.
## Output
+25 -1
View File
@@ -1,12 +1,20 @@
---
name: tech-debt
description: "Track, categorize, and prioritize technical debt across the codebase. Scans for debt indicators, maintains a debt register, and recommends repayment scheduling."
description: "Track, categorize and prioritize technical debt across the codebase — scans for debt indicators, maintains a register."
argument-hint: "[scan|add|prioritize|report]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
## Phase 1: Parse Subcommand
Determine the mode from the argument:
@@ -41,6 +49,22 @@ Categorize each finding:
- **Dependency Debt**: Outdated packages, deprecated APIs, version conflicts
- **Performance Debt**: Known slow paths, unoptimized queries, memory issues
**Before presenting anything, establish that there was something to scan.**
Count the source files the scan actually covered. If that count is **zero** —
no `src/` directory, or it holds no source files — report:
> **NOT ASSESSED — no source files to scan.** `src/` contains no code, so
> "no debt indicators found" would be a statement about an empty search, not
> about the codebase. Run this once implementation is under way.
and stop. Do not write to the register and do not emit a COMPLETE verdict.
The distinction is the whole point of the scan: **zero findings over 400 files
is a clean codebase; zero findings over zero files is no information at all.**
Rendering both as "COMPLETE — scan findings written to register" reads as the
first. State the denominator whenever findings are reported,
including when it is large and the count is genuinely zero.
Present the findings to the user.
Ask: "May I write these findings to `docs/tech-debt-register.md`?"
+83 -17
View File
@@ -1,12 +1,20 @@
---
name: test-evidence-review
description: "Quality review of test files and manual evidence documents. Goes beyond existence checks — evaluates assertion coverage, edge case handling, naming conventions, and evidence completeness. Produces ADEQUATE/INCOMPLETE/MISSING verdict per story. Run before QA sign-off or on demand."
description: "Quality review of test files and evidence — goes beyond existence, evaluates assertion coverage. ADEQUATE/INCOMPLETE/MISSING/NOT ASSESSED per story."
argument-hint: "[story-path | sprint | system-name]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Test Evidence Review
`/smoke-check` verifies that test files **exist** and **pass**. This skill
@@ -40,17 +48,45 @@ Based on the argument:
**Single story**: Read the story file directly. Extract: Story Type, Test
Evidence section, story slug, system name.
**Sprint**: Read the most recently modified file in `production/sprints/`.
Extract the list of story file paths from the sprint plan. Read each story file.
**Sprint**: Read the most recently modified file in `production/sprints/`; extract
the list of story file paths from the sprint plan.
**System**: Glob `production/epics/[system-name]/story-*.md`. Read each.
**System**: Glob `production/epics/[system-name]/story-*.md`.
For each story, collect:
- `Type:` field (Logic / Integration / Visual/Feel / UI / Config/Data)
- `## Test Evidence` section — the stated expected test file path or evidence doc
- Story slug (from file name)
- System name (from directory path)
- Acceptance Criteria list (all checkbox items)
> **If the resolved scope contains ZERO stories, stop here.** Report
> `NOT ASSESSED — no stories in scope`, name which scope was searched and which
> path was empty, and route: no sprint file → `/sprint-plan new`; a sprint plan
> listing no stories → `/create-stories [epic-slug]`; a `[system-name]` glob that
> matched nothing → name the glob. Do not continue to Section 3.
>
> **Guard the empty scope, not just the per-story unknown.** The verdict
> vocabulary here — ADEQUATE / INCOMPLETE / MISSING — needs a "could not check"
> value, or an unverifiable story acquires a verdict claiming somebody verified
> it; that is what `NOT ASSESSED` is for. **But giving the per-story unknown a
> home does nothing for the empty-scope unknown.** With no stories
> the Section 6 report renders an empty Summary table and ends
> `BLOCKING items: 0 / ADVISORY items: 0` — which reads as *everything reviewed,
> all fine*. This skill gates story closure, and `coding-standards.md` marks Logic,
> Integration, Visual/Feel and UI evidence BLOCKING, so a false-clean closes stories nobody
> reviewed.
>
> This is a recurring shape: the sophisticated inner rule present, the outer
> boundary unguarded. Ask it of any skill that aggregates —
> **what does this emit when the set is empty?**
For the resulting story set, collect the fields below with **targeted section
greps, not a full read of each story**:
```
Grep pattern="## Test Evidence" glob="production/epics/**/story-*.md" output_mode="content" -A 8
Grep pattern="## Acceptance Criteria" glob="production/epics/**/story-*.md" output_mode="content" -A 15
```
- **Story Type** (Logic / Integration / Visual/Feel / UI / Config/Data) and the
stated evidence path — both live under `## Test Evidence`, so the first grep's
`-A 8` captures them.
- Acceptance Criteria list — the `## Acceptance Criteria` block from the second grep.
- Story slug (from the file name) and System (from the directory path) — no read.
Full-read a story only when its Test Evidence section is missing or ambiguous.
(In Sprint mode, scope the globs to the sprint plan's story paths.)
---
@@ -141,11 +177,13 @@ closed without all required sign-offs.
### Screenshot / artefact completeness
For Visual/Feel stories: check whether screenshot file paths are referenced
in the evidence doc. If referenced, Glob for them to confirm they exist.
For Visual/Feel stories: Glob `production/qa/evidence/` for a retained image
(`*.png`, `*.jpg`, `*.gif`) belonging to this story. A doc that describes a
visual check but retains no image is INCOMPLETE — this gate is BLOCKING by
default, and a description is an assertion rather than evidence.
For UI stories: check whether a walkthrough sequence (step-by-step interaction
log) is present.
For UI stories: require the same retained screenshot of each screen touched,
plus a walkthrough sequence (step-by-step interaction log).
### Date coverage
@@ -165,8 +203,36 @@ For each story, assign a verdict:
| **ADEQUATE** | Test/evidence exists, passes quality checks, all criteria covered |
| **INCOMPLETE** | Test/evidence exists but has quality gaps (thin assertions, missing sign-offs) |
| **MISSING** | No test or evidence found for a story type that requires it |
| **NOT ASSESSED** | The review could not be performed for this story — see below |
The overall sprint/system verdict is the worst story verdict present.
> **`NOT ASSESSED` is required, and it is not a softer `MISSING`.**
> The other three verdicts all presume the review actually ran. `MISSING` means
> *I looked and there was nothing there* — a real, reportable failure. It must
> never be used for *I could not look*, which is not a finding about the story
> at all. Use `NOT ASSESSED` when:
>
> - the story's **type cannot be determined**, so the required evidence is
> unknown (the type→evidence mapping in `.claude/docs/coding-standards.md` is
> what makes any other verdict meaningful);
> - the evidence path is named but **unreadable or outside this run's scope**;
> - the story file itself could not be parsed.
>
> **Say which of those it was, per story.** A reader cannot act on a bare
> `NOT ASSESSED`, and the whole point of separating it from `MISSING` is that
> the two have different fixes: one needs a test written, the other needs the
> reviewer given access or the story classified.
The overall sprint/system verdict is the worst story verdict present, and
**`NOT ASSESSED` outranks `ADEQUATE`**: a run that could not assess part of its
scope has not established that the scope is adequate. It does not outrank
`INCOMPLETE` or `MISSING` — a known failure is more actionable than an unknown,
and demoting a real failure behind an access problem would bury it.
> Why this needed saying: evidence review **gates story completion**, and
> `coding-standards.md` makes Logic, Integration, Visual/Feel and UI evidence BLOCKING. A verdict
> vocabulary with no way to express "I could not check" forces every unknown
> into one of three claims about the story — which is how a story nobody
> verified acquires a verdict that says somebody did.
```markdown
## Test Evidence Review
@@ -174,13 +240,13 @@ The overall sprint/system verdict is the worst story verdict present.
> **Date**: [date]
> **Scope**: [single story path | Sprint [N] | [system name]]
> **Stories reviewed**: [N]
> **Overall verdict**: ADEQUATE / INCOMPLETE / MISSING
> **Overall verdict**: ADEQUATE / INCOMPLETE / MISSING / NOT ASSESSED
---
### Story-by-Story Results
#### [Story Title] — [Type] — [ADEQUATE/INCOMPLETE/MISSING]
#### [Story Title] — [Type] — [ADEQUATE/INCOMPLETE/MISSING/NOT ASSESSED]
**Test/evidence path**: `[path]` (found) / (not found)
+9 -1
View File
@@ -1,12 +1,20 @@
---
name: test-flakiness
description: "Detect non-deterministic (flaky) tests by reading CI run logs or test result history. Aggregates pass rates per test, identifies intermittent failures, recommends quarantine or fix, and maintains a flaky test registry. Best run during Polish phase or after multiple CI runs."
description: "Find flaky tests from CI logs — aggregates pass rates, spots intermittent failures, recommends quarantine. After multiple runs."
argument-hint: "[ci-log-path | scan | registry]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Test Flakiness Detection
A flaky test is one that sometimes passes and sometimes fails without any code
+76 -17
View File
@@ -1,12 +1,20 @@
---
name: test-helpers
description: "Generate engine-specific test helper libraries for the project's test suite. Reads existing test patterns and produces tests/helpers/ with assertion utilities, factory functions, and mock objects tailored to the project's systems. Reduces boilerplate in new test files."
description: "Generate engine-specific test helper libraries — assertion utilities, factory functions, mocks in tests/helpers/. Reduces boilerplate."
argument-hint: "[system-name | all | scaffold]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Test Helpers
Writing test cases is faster and more consistent when common setup, teardown,
@@ -23,6 +31,36 @@ and systems — so every developer writes less boilerplate and more assertions.
---
## Assertions: use the project's test framework, never bare `assert()`
**Generated helpers must assert through the configured test framework's assertion
API**, resolved from `testing.framework` — not through GDScript's built-in
`assert()`.
Two things go wrong with a bare `assert()` in a helper, and both are silent:
1. **It aborts the run instead of failing the test.** A framework assertion
records a failure and continues, so one broken expectation yields one red test.
A bare `assert()` halts execution, so the first failure hides every result
after it.
2. **It is stripped in release builds.** A helper library built on `assert()`
stops asserting entirely in exactly the build you most want checked, and does
so without any error — the tests still "pass".
**Look up the assertion form for the configured framework before generating
code.** Do not copy the forms in this file or in other skills' examples as
authoritative — they are illustrative and have drifted (`assert_eq`,
`assert_true` and `assert_that` all appear across the repo). If you cannot
confirm the correct API for the project's framework, say so and generate no
helper rather than guessing.
**Helpers must not extend the framework's test-suite base class.** A file in
`tests/helpers/` that extends the suite type is discovered by the runner as a
test suite containing zero tests. Helpers are plain classes; only real test files
extend the suite.
---
## 1. Parse Arguments
**Modes:**
@@ -37,12 +75,12 @@ and systems — so every developer writes less boilerplate and more assertions.
## 2. Detect Engine and Language
Read `.claude/docs/technical-preferences.md` and extract:
- `Engine:` value
- `Language:` value
- `Framework:` from the Testing section
Read from `project.yaml` first, falling back to `.claude/docs/technical-preferences.md` for any key that is absent or empty:
- `engine.name` (else the `Engine:` value)
- `engine.language` (else the `Language:` value)
- `testing.framework` (else `Framework:` from the Testing section)
If engine is not configured: "Engine not configured. Run `/setup-engine` first."
If the engine is not configured in either source: "Engine not configured. Run `/setup-engine` first."
---
@@ -74,15 +112,32 @@ Also read:
### Godot 4 (GDUnit4 / GDScript)
> **`FAIL_IF(...)` in the example below is a PLACEHOLDER, not an API.** It marks
> the one line you must resolve from the project's actual test framework before
> emitting any of this, per the rule in §2. Substitute the framework's real
> failure call — the form that **registers a failure with the runner and lets the
> suite continue** — and delete the marker comment.
>
> **It is deliberately not spelled `assert_that`, `assert_eq` or `assert_true`.**
> All three appear somewhere in this repo, they disagree, and **GdUnit4's API is
> not covered by `docs/engine-reference/`** — so writing any of them here would be
> asserting an API this repo cannot source, in the file whose whole job is to stop
> people doing that. If you cannot confirm the correct call for the configured
> framework, §2 already tells you the answer: **generate no helper.** An
> unresolved `FAIL_IF` reaching disk is a bug; a missing helper is a task.
>
> Worked examples must obey §2 too — a bare `assert()` here would be the exact
> form §2 forbids, sixty lines below §2 forbidding it. A rule stated in prose
> does not reach its own worked example unless someone makes it.
**Base helper** (`tests/helpers/game_assertions.gd`):
```gdscript
## Game-specific assertion utilities for [Project Name] tests.
## Extends GdUnitAssertions with domain-specific helpers.
## Domain-specific helpers built on the project's test framework.
##
## Usage:
## var assert = GameAssertions.new()
## assert.health_in_range(entity, 0, entity.max_health)
## Usage (static — no instance needed):
## GameAssertions.assert_in_range(entity.health, 0, entity.max_health, "health")
class_name GameAssertions
extends RefCounted
@@ -95,8 +150,9 @@ static func assert_in_range(
max_val: float,
label: String = "value"
) -> void:
assert(
value >= min_val and value <= max_val,
# FRAMEWORK ASSERT — resolve per the rule above; do not emit `assert()`.
FAIL_IF(
not (value >= min_val and value <= max_val),
"%s %.2f is outside expected range [%.2f, %.2f]" % [label, value, min_val, max_val]
)
@@ -110,7 +166,8 @@ static func assert_signal_emitted(
var emitted := false
obj.connect(signal_name, func(_args): emitted = true)
action.call()
assert(emitted, "Expected signal '%s' to be emitted, but it was not." % signal_name)
# FRAMEWORK ASSERT — resolve per the rule above; do not emit `assert()`.
FAIL_IF(not emitted, "Expected signal '%s' to be emitted, but it was not." % signal_name)
## Assert that a callable does NOT emit a signal.
static func assert_signal_not_emitted(
@@ -121,12 +178,14 @@ static func assert_signal_not_emitted(
var emitted := false
obj.connect(signal_name, func(_args): emitted = true)
action.call()
assert(not emitted, "Expected signal '%s' NOT to be emitted, but it was." % signal_name)
# FRAMEWORK ASSERT — resolve per the rule above; do not emit `assert()`.
FAIL_IF(emitted, "Expected signal '%s' NOT to be emitted, but it was." % signal_name)
## Assert a node exists at path within a parent.
static func assert_node_exists(parent: Node, path: NodePath) -> void:
assert(
parent.has_node(path),
# FRAMEWORK ASSERT — resolve per the rule above; do not emit `assert()`.
FAIL_IF(
not parent.has_node(path),
"Expected node at path '%s' to exist." % str(path)
)
```
@@ -303,7 +362,7 @@ namespace GameTestHelpers
For `[system-name]` or `all` modes, generate a helper per system:
Read the system's GDD to extract:
Read only the GDD sections this needs — `Grep pattern="^## (Formulas|Edge Cases|Detailed Rules|Detailed Design)" path="design/gdd/[system].md" output_mode="content" -A 30` — rather than a full read (every peer skill section-greps GDDs; in `all` mode a full read multiplies across each system's 400+-line GDD). Extract:
- Data types (entity types, component names)
- Formula variables and their bounds
- Common test scenarios mentioned in Edge Cases
+37 -8
View File
@@ -1,12 +1,20 @@
---
name: test-setup
description: "Scaffold the test framework and CI/CD pipeline for the project's engine. Creates the tests/ directory structure, engine-specific test runner configuration, and GitHub Actions workflow. Run once during Technical Setup phase before the first sprint begins."
description: "Scaffold the test framework and CI — tests/ directory, engine test runner, GitHub Actions workflow. Once, before the first sprint."
argument-hint: "[force]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Bash, Write
model: sonnet
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation`
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
every file write follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
# Test Setup
This skill scaffolds the automated testing infrastructure for the project.
@@ -25,8 +33,12 @@ A test framework installed at sprint four costs 3 sprints.
## Phase 1: Detect Engine and Existing State
1. **Read engine config**:
- Read `.claude/docs/technical-preferences.md` and extract the `Engine:` value.
- If engine is not configured (`[TO BE CONFIGURED]`), stop:
- Read `engine.name` from `project.yaml`; if that key is absent or empty
(including when `project.yaml` has no `engine:` block), fall back to the
`Engine:` value in `.claude/docs/technical-preferences.md`.
- If neither source yields a configured engine (project.yaml `engine.name`
absent/empty and technical-preferences.md shows `[TO BE CONFIGURED]` or is
missing), stop:
"Engine not configured. Run `/setup-engine` first, then re-run `/test-setup`."
2. **Check for existing test infrastructure**:
@@ -61,9 +73,11 @@ tests/
unit/ — Isolated unit tests for formulas, state, and logic
integration/ — Cross-system tests and save/load round-trips
smoke/ — Critical path test list (15-minute manual gate)
evidence/ — Screenshot and manual test sign-off records
README.md — Test framework documentation
production/qa/
evidence/ — Screenshot and manual test sign-off records
[Engine-specific files — see per-engine details below]
.github/workflows/tests.yml — CI: run tests on every push to main
@@ -74,7 +88,11 @@ Estimated time: ~5 minutes to create all files.
Ask: "May I create these files? I will not overwrite any test files that
already exist at these paths."
Do not proceed without approval.
**At `collaborative` and `guided`** — do not proceed without approval. These are
**new** files, and `automation-modes.md:81` gates new-file writes in `guided` too,
so the answer is the same in both modes. **At `autonomous`** — create them and log
the decision; do not block. An unconditional gate here would read as "block even
in autonomous" and contradict this skill's own header.
---
@@ -99,9 +117,20 @@ tests/
unit/ # Isolated unit tests (formulas, state machines, logic)
integration/ # Cross-system and save/load tests
smoke/ # Critical path test list for /smoke-check gate
```
```
production/qa/
evidence/ # Screenshot logs and manual test sign-off records
```
> **Manual evidence lives under `production/qa/evidence/`, not `tests/`.** That is
> where every consumer reads it — `/smoke-check`, `/test-evidence-review`,
> `/qa-plan`, and the evidence table in `.claude/docs/coding-standards.md`. This
> scaffold and this skill's completion summary must name the same path: listing
> `tests/evidence/` here while the summary reports `production/qa/evidence/`
> creates a directory nothing reads and skips the one everything does.
## Running Tests
[Engine-specific command — see below]
@@ -118,8 +147,8 @@ tests/
|---|---|---|
| Logic | Automated unit test — must pass | `tests/unit/[system]/` |
| Integration | Integration test OR playtest doc | `tests/integration/[system]/` |
| Visual/Feel | Screenshot + lead sign-off | `tests/evidence/` |
| UI | Manual walkthrough OR interaction test | `tests/evidence/` |
| Visual/Feel | Screenshot + lead sign-off | `production/qa/evidence/` |
| UI | Manual walkthrough OR interaction test | `production/qa/evidence/` |
| Config/Data | Smoke check pass | `production/qa/smoke-*.md` |
## CI
@@ -391,7 +420,7 @@ Files created:
- tests/unit/ (directory)
- tests/integration/ (directory)
- tests/smoke/critical-paths.md
- tests/evidence/ (directory)
- production/qa/evidence/ (directory)
[engine-specific files]
- .github/workflows/tests.yml
+207 -429
View File
@@ -1,29 +1,73 @@
---
name: ux-design
description: "Guided, section-by-section UX spec authoring for a screen, flow, or HUD. Reads game concept, player journey, and relevant GDDs to provide context-aware design guidance. Produces ux-spec.md (per screen/flow) or hud-design.md using the studio templates."
argument-hint: "[screen/flow name] or 'hud' or 'patterns'"
description: "Section-by-section UX spec authoring for a screen, flow or HUD. Reads the player journey to provide context; also project-wide accessibility."
argument-hint: "[screen/flow name] or 'hud' or 'patterns' or 'accessibility'"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, Task
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, Agent
model: sonnet
agent: ux-designer
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys automation,workflow,docs.density`
Resolved above — use as-is. No block → defaults in
`.claude/docs/config-resolution.md`.
When this skill is invoked:
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
**Authoring guidance**: the skeletons below are self-contained — author from them
directly. When a section needs depth (worked examples, pattern catalogs,
accessibility criteria), the matching guide has it:
| Producing | Guide |
|---|---|
| UX spec | `.claude/docs/templates/guidance/ux-spec-guide.md` |
| HUD design | `.claude/docs/templates/guidance/hud-design-guide.md` |
| Interaction patterns | `.claude/docs/templates/guidance/interaction-pattern-library-guide.md` (routes to three topic files) |
| Accessibility requirements | `.claude/docs/templates/guidance/accessibility-requirements-guide.md` |
**Load a guide per-section, never whole** — each is organised by section and the
pointers in the templates name the exact section to read.
**`workflow`** (see `.claude/docs/workflow-modes.md`):
- `full` — a UX spec is required per screen.
- `standard` — core screens only (main menu, HUD, primary game loop).
- `minimal` — not required. Can still be run voluntarily.
**`docs.density`** — it controls per-section *depth*, where `workflow`
controls which screens are specced. `modes.rigor` sets both together; set
`docs.density` explicitly to vary depth alone: `terse` = wireframe descriptions +
interaction bullets; `balanced` = wireframes + paragraph descriptions of flows
(default); `thorough` = full prose including user-research summaries and
alternative flow considerations. Apply it to every section you author.
## 1. Parse Arguments & Determine Mode
Three authoring modes exist based on the argument:
Four authoring modes exist based on the argument:
| Argument | Mode | Output file |
|----------|------|-------------|
| `hud` | HUD design | `design/ux/hud.md` |
| `patterns` | Interaction pattern library | `design/ux/interaction-patterns.md` |
| `accessibility` | Project-wide accessibility requirements | `design/accessibility-requirements.md` |
| Any other value (e.g., `main-menu`, `inventory`) | UX spec for a screen or flow | `design/ux/[argument].md` |
| No argument | Ask the user | (see below) |
> **`accessibility` is the only mode that writes outside `design/ux/`.** Its
> output is a project-wide standard the per-screen specs consult, not a spec for
> one screen — `.claude/docs/workflow-catalog.yaml`, the Pre-Production and
> Polish gates, and `/architecture-review` all check
> `design/accessibility-requirements.md` at that exact path. Do not "tidy" it
> under `design/ux/`: every one of those checks would stop matching, and the
> Technical Setup → Pre-Production gate would become unpassable again.
**If no argument is provided**, do not fail — ask instead. Use `AskUserQuestion`:
- "What are we designing today?"
- Options: "A specific screen or flow (I'll name it)", "The game HUD", "The interaction pattern library", "I'm not sure — help me figure it out"
- Options: "A specific screen or flow (I'll name it)", "The game HUD", "The interaction pattern library", "The project-wide accessibility requirements", "I'm not sure — help me figure it out"
If the user selects "I'll name it" or types a screen name, normalize it to kebab-case
for the filename (e.g., "Main Menu" becomes `main-menu`).
@@ -56,7 +100,12 @@ If the player journey file does not exist, note the gap and proceed:
> journey session after this spec is drafted."
Also add to the UX spec's Open Questions section:
> "Player journey map not yet created. Template available at `.claude/docs/templates/player-journey.md`. Run `/ux-design` Phase 2b or create it manually to establish player context for this screen."
> "Player journey map not yet created. Author it from the template at `.claude/docs/templates/player-journey.md` to establish player context for this screen."
> **Do not tell the user to "run `/ux-design` Phase 2b" to create it.** Phase 2b
> is this step — the one that *reads* the file. That remediation is circular: it
> sends the user back to the check that just reported the gap. No skill
> writes `design/player-journey.md`; it is hand-authored from its template.
### 2c: GDD UI Requirements
@@ -66,8 +115,19 @@ UI Requirements section references this screen by name or category.
These GDD UI Requirements are the **requirements input** to this spec. Collect them
as a list of constraints the spec must satisfy.
If designing the HUD, read ALL GDD UI Requirements sections — the HUD aggregates
requirements from every system.
If designing the HUD, you need the UI Requirements of **every** system — the HUD
aggregates them. Collect them with one scan rather than opening each GDD:
```
Grep pattern="^#+ .*UI Requirements" glob="design/gdd/*.md" output_mode="content" -A 20
```
Establish the denominator first (glob `design/gdd/*.md`, count **N**) and check
the match count against it. **A GDD with no UI Requirements section is not a GDD
with no UI needs** — it may predate the section. List the unmatched ones and
confirm with the user that they are genuinely headless before excluding them
from the HUD's requirement set; a HUD that silently omits a system's readout is
the exact failure this aggregation exists to prevent.
### 2d: Existing UX Specs
@@ -94,17 +154,23 @@ must satisfy the accessibility tier committed to there.
### 2h: Input Method (from Project Config)
Read `.claude/docs/technical-preferences.md` and extract the `## Input & Platform`
section. Store these values for use throughout the skill — they drive the
Interaction Map and inform accessibility requirements:
Read the `platform` block from `project.yaml`; if `project.yaml` has no
`platform` block, fall back to the `## Input & Platform` section of
`.claude/docs/technical-preferences.md`. Store these values for use throughout
the skill — they drive the Interaction Map and inform accessibility
requirements:
- **Input Methods** — e.g., Keyboard/Mouse, Gamepad, Touch, Mixed
- **Primary Input** — the dominant input for this game
- **Gamepad Support** — Full / Partial / None
- **Touch Support** — Full / Partial / None
- **Target Platforms** — for safe zone and aspect ratio decisions
- **Primary Input** — `platform.primary_input` — the dominant input for this game
- **Gamepad Support** — `platform.gamepad_support` — Full / Partial / None
- **Touch Support** — `platform.touch_support` — Full / Partial / None
- **Target Platforms** — `platform.targets` — for safe zone and aspect ratio decisions
- **Input Methods** — the set of supported methods. When reading from
`project.yaml`, derive it: keyboard/mouse if `PC` or `Web` is in `targets`;
gamepad if gamepad support is Full/Partial; touch if touch support is
Full/Partial; plus the primary input. When falling back to
`technical-preferences.md`, use its explicit Input Methods field.
If the section is unconfigured (`[TO BE CONFIGURED]`), ask once:
If neither source is configured, ask once:
> "Input methods aren't configured yet. What does this game target?"
> Options: "Keyboard/Mouse only", "Gamepad only", "Both (PC + Console)", "Touch (mobile)", "All of the above"
>
@@ -124,7 +190,7 @@ Before any design work, present a brief summary to the user:
> - Related screens already specced: [list, or "none yet"]
> - Known patterns available: [count, or "no pattern library yet"]
> - Accessibility tier: [from requirements doc, or "not yet defined"]
> - Input methods: [from technical-preferences.md, or "asked above"]
> - Input methods: [derived from the `project.yaml` platform block, or "asked above"]
Then ask: "Anything else I should read before we start, or shall we proceed?"
@@ -170,7 +236,9 @@ Proceed to Phase 3 (Create File Skeleton) as normal.
Once the user confirms, **immediately** create the output file with empty section
headers. This ensures incremental writes have a target and work survives interruptions.
Ask: "May I create the skeleton file at `design/ux/[filename].md`?"
Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except in
`accessibility` mode, where the path is `design/accessibility-requirements.md`
(see the mode table in Section 1; it is deliberately not under `design/ux/`).
---
@@ -396,10 +464,102 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?"
---
### Skeleton for Accessibility Requirements
Section list mirrors `.claude/docs/templates/accessibility-requirements.md` — if
the template gains or loses a section, this skeleton follows it, not the reverse.
```markdown
# Accessibility Requirements
> **Status**: In Design
> **Author**: [user + ux-designer]
> **Last Updated**: [today's date]
> **Template**: Accessibility Requirements
## Accessibility Tier Definition
[To be designed]
---
## Visual Accessibility
[To be designed]
---
## Motor Accessibility
[To be designed]
---
## Cognitive Accessibility
[To be designed]
---
## Auditory Accessibility
[To be designed]
---
## Platform Accessibility API Integration
[To be designed]
---
## Per-Feature Accessibility Matrix
[To be designed]
---
## Accessibility Test Plan
[To be designed]
---
## Known Intentional Limitations
[To be designed]
---
## Audit History
[To be designed]
---
## External Resources
[To be designed]
---
## Open Questions
[To be designed]
```
> **The tier commitment is the gated part.** `gate-pre-production.md` requires
> the file to exist *with an accessibility tier committed*, and
> `gate-production.md` checks that tier is addressed in every key screen spec.
> A skeleton whose Tier Definition is still `[To be designed]` satisfies the
> glob but not the gate — author that section first.
---
After writing the skeleton, update `production/session-state/active.md` with:
- Task: Designing [screen/flow name] UX spec
- Current section: Starting (skeleton created)
- File: design/ux/[filename].md
- File: design/ux/[filename].md (or `design/accessibility-requirements.md` in `accessibility` mode)
---
@@ -432,413 +592,27 @@ After writing each section, update `production/session-state/active.md`.
---
### Section Guidance: UX Spec Mode
#### Section A: Purpose & Player Need
This section is the foundation. Every other decision flows from it.
**Questions to ask**:
- "What player goal does this screen serve? What is the player trying to DO here?"
- "What would go wrong if this screen didn't exist or was hard to use?"
- "Complete this sentence: 'The player arrives at this screen wanting to ___.' "
Cross-reference the player journey context gathered in Phase 2. The stated purpose
must align with the journey phase and emotional state.
---
#### Section B: Player Context on Arrival
**Questions to ask**:
- "When in the game does a player first encounter this screen?"
- "What were they just doing immediately before reaching this screen?"
- "What emotional state should the design assume? (calm, stressed, curious, time-pressured)"
- "Do players arrive at this screen voluntarily, or are they sent here by the game?"
Offer to map this against the journey phases if the player journey doc exists.
---
#### Section B2: Navigation Position
Where does this screen sit in the game's navigation hierarchy? This is a one-paragraph orientation map — not a full flow diagram.
**Questions to ask**:
- "Is this screen accessed from the main menu, from pause, from within gameplay, or from another screen?"
- "Is it a top-level destination (always reachable) or a context-dependent one (only accessible in certain states)?"
- "Can the player reach this screen from more than one place in the game?"
Present as: "This screen lives at: [root] → [parent] → [this screen]" plus any alternate entry paths.
---
#### Section B3: Entry & Exit Points
Map every way the player can arrive at and leave this screen.
**Questions to ask**:
- "What are all the ways a player can reach this screen?" (List each trigger: button press, game event, redirect from another screen, etc.)
- "What can the player do to exit? What happens when they do?" (Back button, confirm action, timeout, game event)
- "Are there any exits that are one-way — where the player cannot return to this screen without starting over?"
Present as two tables:
| Entry Source | Trigger | Player carries this context |
|---|---|---|
| [screen/event] | [how] | [state/data they arrive with] |
| Exit Destination | Trigger | Notes |
|---|---|---|
| [screen/event] | [how] | [any irreversible state changes] |
---
#### Section C: Layout Specification
This is the largest and most interactive section. Work through it in sub-sections:
**Sub-section 1 — Information Hierarchy** (establish this before any layout):
- Ask the user to list every piece of information this screen must communicate.
- Then ask them to rank the items: "What is the single most important thing a player
needs to see first? What is second? What can be discovered rather than immediately visible?"
- Present the resulting hierarchy for approval before moving to zones.
**Sub-section 2 — Layout Zones**:
- Based on the information hierarchy, propose rough screen zones (header, content
area, action bar, sidebar, etc.).
- Offer 2-3 zone arrangements with rationale for each. Reference platform and
input context gathered from game concept.
- Use `AskUserQuestion` to capture the choice:
- "Which zone arrangement fits best?"
- Options: [the 2-3 named arrangements you just presented] + "None — build a custom arrangement"
**Sub-section 3 — Component Inventory**:
- For each zone, list the UI components it contains. For each component, note:
- Component type (button, list, card, stat display, input field, etc.)
- Content it displays
- Whether it is interactive
- If it uses an existing pattern from the library (reference by pattern name)
- If it introduces a new pattern (flag for later addition to the library)
**Sub-section 4 — ASCII Wireframe**:
- Offer to generate an ASCII wireframe based on the zone layout and component list.
- Use `AskUserQuestion`: "Want an ASCII wireframe as part of this spec?"
- Options: "Yes, include one", "No, I'll attach a separate file"
- If yes, produce the wireframe in conversation first. Ask for feedback before
writing it to file.
---
#### Section D: States & Variants
Guide the user to think beyond the happy path.
**Questions to ask** (work through these one at a time):
- "What does this screen look like the very first time a player sees it, when there
is no data yet? (empty state)"
- "What happens when something goes wrong — an error, a failed action, a missing
resource? (error state)"
- "Is there ever a loading wait on this screen? If so, what does it show? (loading state)"
- "Are there any player progression states that change what this screen shows? For
example, locked content, premium content, or tutorial-mode overlays?"
- "Does this screen behave differently on any supported platform? (platform variant)"
Present the collected states as a table for approval:
| State / Variant | Trigger | What Changes |
|-----------------|---------|--------------|
| Default | Normal load | — |
| Empty | No data available | [content area description] |
| [etc.] | [trigger] | [changes] |
---
#### Section E: Interaction Map
For each interactive component identified in the Layout Specification, define:
- The action (tap, click, press, hold, scroll, drag)
- The platform input(s) that trigger it (mouse click, gamepad A, keyboard Enter)
- The immediate feedback (visual, audio, haptic)
- The outcome (navigation target, state change, data write)
Use the input methods loaded from `technical-preferences.md` in Phase 2h — do
not ask the user again. State them upfront: "Mapping interactions for:
[Input Methods from tech-prefs]. Covering [Gamepad Support] gamepad support."
Work through components one at a time rather than asking for all at once.
For navigation actions (going to another screen), verify the target matches
an existing UX spec or note it as a spec dependency.
---
#### Section E2: Events Fired
For every player action in the Interaction Map, document the corresponding event the game or analytics system should fire — or explicitly note "no event" if none applies.
**Questions to ask**:
- "For each action, should the game fire an analytics event, trigger a game-state change, or both?"
- "Are there any actions that should NOT fire an event — and is that a deliberate choice?"
Present as a table alongside the Interaction Map:
| Player Action | Event Fired | Payload / Data |
|---|---|---|
| [action] | [EventName] or none | [data passed with event] |
Flag any action that modifies persistent game state (save data, progress, economy) — these need explicit attention from the architecture team.
---
#### Section E3: Transitions & Animations
Specify how the screen enters and exits, and how it responds to state changes.
**Questions to ask**:
- "How does this screen appear? (fade in, slide from right, instant pop, scale from button)"
- "How does it dismiss? (fade out, slide back, cut)"
- "Are there any in-screen state transitions that need animation? (loading spinner, success state, error flash)"
- "Is there any animation that could cause motion sickness — and does the game have a reduced-motion option?"
Minimum required:
- Screen enter transition
- Screen exit transition
- At least one state-change animation if the screen has multiple states
---
#### Section F: Data Requirements
Cross-reference the GDD UI Requirements sections gathered in Phase 2.
For each piece of information the screen displays, ask:
- "Where does this data come from? Which system owns it?"
- "Does this screen need to write data back, or is it read-only?"
- "Is any of this data time-sensitive or real-time? (health bars, cooldown timers)"
Flag any case where the UI would need to own or manage game state as an architectural
concern. UX specs define what the UI needs; they do not dictate how the data is
delivered. That is an architecture decision.
Present the data requirements as a table:
| Data | Source System | Read / Write | Notes |
|------|--------------|--------------|-------|
| [item] | [system] | Read | — |
| [item] | [system] | Write | [concern if any] |
---
#### Section G: Accessibility
Cross-reference `design/accessibility-requirements.md` if it exists.
Walk through the ux-designer agent's standard checklist for this screen:
- Keyboard-only navigation path through all interactive elements
- Gamepad navigation order (if applicable)
- Text contrast and minimum readable font sizes
- Color-independent communication (no information conveyed by color alone)
- Screen reader considerations for any non-text elements
- Any motion or animation that needs a reduced-motion alternative
If no accessibility tier has been defined for this project, note the gap in the UX spec's Open Questions section:
> "Accessibility tier not yet defined — consider WCAG-AA as a baseline. Run `/gate-check` to see whether this blocks any phase gates."
Then continue to the next section without stopping.
---
#### Section H: Localization Considerations
Document constraints that affect how this screen behaves when text is translated.
**Questions to ask**:
- "Which text elements on this screen are the longest? What is the maximum character count that fits the layout?"
- "Are there any elements where text length is layout-critical — e.g., a button label that must stay on one line?"
- "Are there any elements that display numbers, dates, or currencies that need locale-specific formatting?"
Note: aim to flag any element where a 40% text expansion (common in translations from English to German or French) would break the layout. Mark those as HIGH PRIORITY for the localization engineer.
---
#### Section I: Acceptance Criteria
Write at least 5 specific, testable criteria that a QA tester can verify without reading any other design document. These become the pass/fail conditions for `/story-done`.
**Format**: Use checkboxes. Each criterion must be verifiable by a human tester:
```
- [ ] Screen opens within [X]ms from [trigger]
- [ ] [Element] displays correctly at [minimum] and [maximum] values
- [ ] [Navigation action] correctly routes to [destination screen]
- [ ] Error state appears when [condition] and shows [specific message or icon]
- [ ] Keyboard/gamepad navigation reaches all interactive elements in logical order
- [ ] [Accessibility requirement] is met — e.g., "all interactive elements have focus indicators"
```
**Minimum required**:
- 1 performance criterion (load/open time)
- 1 navigation criterion (at least one entry or exit path verified)
- 1 error/empty state criterion
- 1 accessibility criterion (per committed tier)
- 1 criterion specific to this screen's core purpose
Use `AskUserQuestion` to confirm:
- "Do these acceptance criteria cover what would make this screen 'done' for your QA process?"
- Options: "Yes — these are solid", "Add one more criterion", "Remove or rephrase one"
---
### Section Guidance: HUD Design Mode
HUD design follows a different order from UX spec mode. Begin with philosophy;
do not touch layout until the information architecture is complete.
#### Section A: HUD Philosophy
Ask the user to describe the game's relationship with on-screen information in
1-2 sentences.
Offer framing examples to help:
- "Nearly HUD-free — atmosphere requires unobstructed immersion (e.g., Hollow Knight, Firewatch)"
- "Minimal but present — only critical information visible, everything else contextual (e.g., Dark Souls)"
- "Information-dense — all decision-relevant data always visible (e.g., Diablo IV, StarCraft II)"
- "Adaptive — HUD density responds to combat state, exploration mode, menus (e.g., God of War)"
This philosophy becomes the design constraint for every subsequent HUD decision.
If a proposed element conflicts with the stated philosophy, surface that conflict.
---
#### Section B: Information Architecture
Complete this before any layout work. Do not skip it.
**Step 1 — Full information inventory**:
Pull all information from GDD UI Requirements sections gathered in Phase 2.
Present the full list: "These are all the things your game systems say they need
to communicate to the player on screen."
**Step 2 — Categorization**:
For each item, ask the user to categorize it:
| Category | Description |
|----------|-------------|
| **Must Show** | Always visible, player needs it for core decisions |
| **Contextual** | Visible only when relevant (in combat, near interactable, etc.) |
| **On Demand** | Player must actively request it (toggle, hold button) |
| **Hidden** | Communicated through world/audio, never on-screen text |
Use `AskUserQuestion` to step through items in groups of 3-4, not all at once.
This is the most consequential design decision in the HUD — do not rush it.
**Conflict check**: If the information philosophy (Section A) says "nearly HUD-free"
but the Must Show list is growing long, surface the conflict explicitly:
> "The current Must Show list has [N] items. That may conflict with the HUD-free
> philosophy. Options: reduce the Must Show list, revise the philosophy, or define
> a hybrid approach where HUD is absent in exploration and present in combat."
---
#### Section C: Layout Zones
Only after the information architecture is approved, design layout zones.
Base layout on:
- Which items are Must Show (they drive the permanent zone decisions)
- Where player attention naturally goes during gameplay (center-screen for action games,
corners for strategy games)
- Platform and aspect ratio targets
Offer 2-3 zone arrangements. Include rationale based on the HUD philosophy and the
categorization from Section B.
---
#### Section D: HUD Elements
For each element in the layout, specify:
- Element name and category (Must Show / Contextual / On Demand)
- Content displayed
- Visual form (bar, number, icon, counter, map)
- Update behavior (real-time, event-driven, player-queried)
- Contextual trigger (if not always visible)
- Animation behavior (does it pulse when low? Fade in? Slam in?)
Work element by element. Reference the interaction pattern library if relevant patterns
exist for status displays, resource bars, or cooldown indicators.
---
#### Sections E, F, G: Dynamic Behaviors, Platform Variants, Accessibility
These follow the same structure as the UX spec equivalents. See UX Spec section
guidance for D (States/Variants), E (Interactions), and G (Accessibility).
For the HUD specifically, emphasize:
- Dynamic Behaviors: what causes the HUD to change density mid-gameplay?
- Platform Variants: does mobile/console require different element sizes or positions?
---
### Section Guidance: Interaction Pattern Library Mode
Pattern library authoring is additive and catalog-driven, not linear.
#### Phase 1: Catalog Existing Patterns
Glob `design/ux/*.md` (excluding `interaction-patterns.md`) and read the Component
Inventory and Interaction Map sections of each spec. Extract every interaction
pattern used.
Present the extracted list: "Based on existing UX specs, these patterns are already
in use in the game:"
- [Pattern name]: used in [screen], [screen]
- [etc.]
Ask: "Are there patterns you know exist but aren't in existing specs yet? List any
additional ones now."
---
#### Phase 2: Formalize Each Pattern
For each pattern (existing or new), document:
```markdown
### [Pattern Name]
**Category**: Navigation / Input / Feedback / Data Display / Modal / Overlay / [other]
**Used In**: [list of screens]
**Description**: [One paragraph explaining what this pattern is and when to use it]
**Specification**:
- [Component behavior]
- [Input mapping]
- [Visual/audio feedback]
- [Accessibility requirements for this pattern]
**When to Use**: [Conditions where this pattern is appropriate]
**When NOT to Use**: [Conditions where another pattern is more appropriate]
**Reference**: [Screenshot path or ASCII example, if available]
```
Work through patterns in groups. Use `AskUserQuestion`:
- "How do you want to work through these patterns?"
- Options: "Draft the first batch from existing specs (faster)", "Define them one by one (more control)", "Start with the most-used pattern first"
---
#### Phase 3: Identify Gaps
After cataloging known patterns, ask:
- "Are there screens or interactions planned that would need patterns not yet
in this library?"
- "Are there any patterns in existing specs that feel inconsistent with each
other and should be consolidated?"
Document gaps in the Gaps section for follow-up.
### Section guidance — read the ONE file for the active mode
Per-section authoring guidance lives in its own file per mode. **When you reach
Phase 4, read only the file matching the mode resolved in Section 1; never load
the other two.**
| Mode | Guidance file |
|------|---------------|
| UX Spec (screen or flow) | `.claude/skills/ux-design/references/sections-ux-spec.md` |
| HUD Design | `.claude/skills/ux-design/references/sections-hud.md` |
| Interaction Pattern Library | `.claude/skills/ux-design/references/sections-patterns.md` |
| Accessibility Requirements | `.claude/docs/templates/guidance/accessibility-requirements-guide.md` |
> The accessibility guidance lives under `templates/guidance/` rather than this
> skill's `references/` because the template it documents
> (`.claude/docs/templates/accessibility-requirements.md`) is consumed by
> `/ux-review` and the gate files too. Same rule applies: load only the part
> covering the section you are authoring, never the whole file.
Apply `docs.density` (Section 1) to whatever that file tells you to author — it
controls the depth of each section, not which sections exist.
---
@@ -942,7 +716,7 @@ specific sub-topics, additional context or coordination may be needed:
| Narrative/lore visible in the UI | `narrative-director` — for flavor text, item names, lore panels |
| Accessibility tier decisions | Handled by this session — owned by ux-designer |
When delegating to another agent via the Task tool:
When delegating to another agent via the `Agent` tool:
- Provide: screen name, game concept summary, the specific question needing expert input
- The agent returns analysis to this session
- This session presents the agent's output to the user
@@ -953,6 +727,10 @@ When delegating to another agent via the Task tool:
## Collaborative Protocol
**In `collaborative` mode (the default).** For `guided` and `autonomous` modes,
see the per-mode rules in `.claude/docs/automation-modes.md` — the steps below
describe what collaborative mode requires, not what applies universally.
This skill follows the collaborative design principle at every step:
1. **Question -> Options -> Decision -> Draft -> Approval** for every section
@@ -0,0 +1,120 @@
> Section-authoring guidance, loaded by `/ux-design` for the ACTIVE MODE ONLY.
> Never load the other two — one mode applies per invocation.
# Section Guidance — HUD Design Mode
HUD design follows a different order from UX spec mode. Begin with philosophy;
do not touch layout until the information architecture is complete.
#### Section A: HUD Philosophy
Ask the user to describe the game's relationship with on-screen information in
1-2 sentences.
Offer framing examples to help:
- "Nearly HUD-free — atmosphere requires unobstructed immersion (e.g., Hollow Knight, Firewatch)"
- "Minimal but present — only critical information visible, everything else contextual (e.g., Dark Souls)"
- "Information-dense — all decision-relevant data always visible (e.g., Diablo IV, StarCraft II)"
- "Adaptive — HUD density responds to combat state, exploration mode, menus (e.g., God of War)"
This philosophy becomes the design constraint for every subsequent HUD decision.
If a proposed element conflicts with the stated philosophy, surface that conflict.
---
#### Section B: Information Architecture
Complete this before any layout work. Do not skip it.
**Step 1 — Full information inventory**:
Pull all information from GDD UI Requirements sections gathered in Phase 2.
Present the full list: "These are all the things your game systems say they need
to communicate to the player on screen."
**Step 2 — Categorization**:
For each item, ask the user to categorize it:
| Category | Description |
|----------|-------------|
| **Must Show** | Always visible, player needs it for core decisions |
| **Contextual** | Visible only when relevant (in combat, near interactable, etc.) |
| **On Demand** | Player must actively request it (toggle, hold button) |
| **Hidden** | Communicated through world/audio, never on-screen text |
Use `AskUserQuestion` to step through items in groups of 3-4, not all at once.
This is the most consequential design decision in the HUD — do not rush it.
**Conflict check**: If the information philosophy (Section A) says "nearly HUD-free"
but the Must Show list is growing long, surface the conflict explicitly:
> "The current Must Show list has [N] items. That may conflict with the HUD-free
> philosophy. Options: reduce the Must Show list, revise the philosophy, or define
> a hybrid approach where HUD is absent in exploration and present in combat."
---
#### Section C: Layout Zones
Only after the information architecture is approved, design layout zones.
Base layout on:
- Which items are Must Show (they drive the permanent zone decisions)
- Where player attention naturally goes during gameplay (center-screen for action games,
corners for strategy games)
- Platform and aspect ratio targets
Offer 2-3 zone arrangements. Include rationale based on the HUD philosophy and the
categorization from Section B.
---
#### Section D: HUD Elements
For each element in the layout, specify:
- Element name and category (Must Show / Contextual / On Demand)
- Content displayed
- Visual form (bar, number, icon, counter, map)
- Update behavior (real-time, event-driven, player-queried)
- Contextual trigger (if not always visible)
- Animation behavior (does it pulse when low? Fade in? Slam in?)
Work element by element. Reference the interaction pattern library if relevant patterns
exist for status displays, resource bars, or cooldown indicators.
---
#### Sections E, F, G: Dynamic Behaviors, Platform Variants, Accessibility
These parallel the UX spec's States, Interaction, and Accessibility sections.
The guidance you need is below — **do not load `sections-ux-spec.md`; one mode
file applies per invocation.** For the HUD, apply it as follows.
**Dynamic Behaviors (states over time).** Beyond the happy path, capture what
changes the HUD mid-gameplay and present it as a table for approval:
| State / Variant | Trigger | What Changes |
|-----------------|---------|--------------|
| Default | Normal play | — |
| Low-resource | Health/ammo/etc. below threshold | [element pulses, recolors, …] |
| Empty / no-data | Element has nothing to show | [hidden, or placeholder] |
| [etc.] | [trigger] | [changes] |
Ask specifically: what causes the HUD to change density mid-gameplay
(combat vs. exploration), and what fades, pulses, or slams in on each transition?
**Platform Variants.** Does mobile/console require different element sizes or
positions? Note per-platform overrides — touch targets, safe-area insets, and
whether any element moves or is dropped on a given platform.
**Accessibility.** Cross-reference `design/accessibility-requirements.md` if it
exists, then walk this checklist for the HUD:
- Gamepad/keyboard focus order for any interactive HUD element
- Text contrast and minimum readable font sizes at gameplay distance
- Color-independent communication (no state conveyed by color alone — a
low-health cue must not be red-only)
- Reduced-motion alternative for any pulsing/flashing HUD animation
- Screen-reader considerations for non-text indicators
If no accessibility tier has been defined for this project, note the gap in the
HUD design's Open Questions section (WCAG-AA is a reasonable baseline) and
continue without stopping.
@@ -0,0 +1,63 @@
> Section-authoring guidance, loaded by `/ux-design` for the ACTIVE MODE ONLY.
> Never load the other two — one mode applies per invocation.
# Section Guidance — Interaction Pattern Library Mode
Pattern library authoring is additive and catalog-driven, not linear.
#### Phase 1: Catalog Existing Patterns
Glob `design/ux/*.md` (excluding `interaction-patterns.md`) and read the Component
Inventory and Interaction Map sections of each spec. Extract every interaction
pattern used.
Present the extracted list: "Based on existing UX specs, these patterns are already
in use in the game:"
- [Pattern name]: used in [screen], [screen]
- [etc.]
Ask: "Are there patterns you know exist but aren't in existing specs yet? List any
additional ones now."
---
#### Phase 2: Formalize Each Pattern
For each pattern (existing or new), document:
```markdown
### [Pattern Name]
**Category**: Navigation / Input / Feedback / Data Display / Modal / Overlay / [other]
**Used In**: [list of screens]
**Description**: [One paragraph explaining what this pattern is and when to use it]
**Specification**:
- [Component behavior]
- [Input mapping]
- [Visual/audio feedback]
- [Accessibility requirements for this pattern]
**When to Use**: [Conditions where this pattern is appropriate]
**When NOT to Use**: [Conditions where another pattern is more appropriate]
**Reference**: [Screenshot path or ASCII example, if available]
```
Work through patterns in groups. Use `AskUserQuestion`:
- "How do you want to work through these patterns?"
- Options: "Draft the first batch from existing specs (faster)", "Define them one by one (more control)", "Start with the most-used pattern first"
---
#### Phase 3: Identify Gaps
After cataloging known patterns, ask:
- "Are there screens or interactions planned that would need patterns not yet
in this library?"
- "Are there any patterns in existing specs that feel inconsistent with each
other and should be consolidated?"
Document gaps in the Gaps section for follow-up.
@@ -0,0 +1,257 @@
> Section-authoring guidance, loaded by `/ux-design` for the ACTIVE MODE ONLY.
> Never load the other two — one mode applies per invocation.
# Section Guidance — UX Spec Mode
#### Section A: Purpose & Player Need
This section is the foundation. Every other decision flows from it.
**Questions to ask**:
- "What player goal does this screen serve? What is the player trying to DO here?"
- "What would go wrong if this screen didn't exist or was hard to use?"
- "Complete this sentence: 'The player arrives at this screen wanting to ___.' "
Cross-reference the player journey context gathered in Phase 2. The stated purpose
must align with the journey phase and emotional state.
---
#### Section B: Player Context on Arrival
**Questions to ask**:
- "When in the game does a player first encounter this screen?"
- "What were they just doing immediately before reaching this screen?"
- "What emotional state should the design assume? (calm, stressed, curious, time-pressured)"
- "Do players arrive at this screen voluntarily, or are they sent here by the game?"
Offer to map this against the journey phases if the player journey doc exists.
---
#### Section B2: Navigation Position
Where does this screen sit in the game's navigation hierarchy? This is a one-paragraph orientation map — not a full flow diagram.
**Questions to ask**:
- "Is this screen accessed from the main menu, from pause, from within gameplay, or from another screen?"
- "Is it a top-level destination (always reachable) or a context-dependent one (only accessible in certain states)?"
- "Can the player reach this screen from more than one place in the game?"
Present as: "This screen lives at: [root] → [parent] → [this screen]" plus any alternate entry paths.
---
#### Section B3: Entry & Exit Points
Map every way the player can arrive at and leave this screen.
**Questions to ask**:
- "What are all the ways a player can reach this screen?" (List each trigger: button press, game event, redirect from another screen, etc.)
- "What can the player do to exit? What happens when they do?" (Back button, confirm action, timeout, game event)
- "Are there any exits that are one-way — where the player cannot return to this screen without starting over?"
Present as two tables:
| Entry Source | Trigger | Player carries this context |
|---|---|---|
| [screen/event] | [how] | [state/data they arrive with] |
| Exit Destination | Trigger | Notes |
|---|---|---|
| [screen/event] | [how] | [any irreversible state changes] |
---
#### Section C: Layout Specification
This is the largest and most interactive section. Work through it in sub-sections:
**Sub-section 1 — Information Hierarchy** (establish this before any layout):
- Ask the user to list every piece of information this screen must communicate.
- Then ask them to rank the items: "What is the single most important thing a player
needs to see first? What is second? What can be discovered rather than immediately visible?"
- Present the resulting hierarchy for approval before moving to zones.
**Sub-section 2 — Layout Zones**:
- Based on the information hierarchy, propose rough screen zones (header, content
area, action bar, sidebar, etc.).
- Offer 2-3 zone arrangements with rationale for each. Reference platform and
input context gathered from game concept.
- Use `AskUserQuestion` to capture the choice:
- "Which zone arrangement fits best?"
- Options: [the 2-3 named arrangements you just presented] + "None — build a custom arrangement"
**Sub-section 3 — Component Inventory**:
- For each zone, list the UI components it contains. For each component, note:
- Component type (button, list, card, stat display, input field, etc.)
- Content it displays
- Whether it is interactive
- If it uses an existing pattern from the library (reference by pattern name)
- If it introduces a new pattern (flag for later addition to the library)
**Sub-section 4 — ASCII Wireframe**:
- Offer to generate an ASCII wireframe based on the zone layout and component list.
- Use `AskUserQuestion`: "Want an ASCII wireframe as part of this spec?"
- Options: "Yes, include one", "No, I'll attach a separate file"
- If yes, produce the wireframe in conversation first. Ask for feedback before
writing it to file.
---
#### Section D: States & Variants
Guide the user to think beyond the happy path.
**Questions to ask** (work through these one at a time):
- "What does this screen look like the very first time a player sees it, when there
is no data yet? (empty state)"
- "What happens when something goes wrong — an error, a failed action, a missing
resource? (error state)"
- "Is there ever a loading wait on this screen? If so, what does it show? (loading state)"
- "Are there any player progression states that change what this screen shows? For
example, locked content, premium content, or tutorial-mode overlays?"
- "Does this screen behave differently on any supported platform? (platform variant)"
Present the collected states as a table for approval:
| State / Variant | Trigger | What Changes |
|-----------------|---------|--------------|
| Default | Normal load | — |
| Empty | No data available | [content area description] |
| [etc.] | [trigger] | [changes] |
---
#### Section E: Interaction Map
For each interactive component identified in the Layout Specification, define:
- The action (tap, click, press, hold, scroll, drag)
- The platform input(s) that trigger it (mouse click, gamepad A, keyboard Enter)
- The immediate feedback (visual, audio, haptic)
- The outcome (navigation target, state change, data write)
Use the input methods resolved in Phase 2h — do
not ask the user again. State them upfront: "Mapping interactions for:
[Input Methods resolved in Phase 2h]. Covering [Gamepad Support] gamepad support."
Work through components one at a time rather than asking for all at once.
For navigation actions (going to another screen), verify the target matches
an existing UX spec or note it as a spec dependency.
---
#### Section E2: Events Fired
For every player action in the Interaction Map, document the corresponding event the game or analytics system should fire — or explicitly note "no event" if none applies.
**Questions to ask**:
- "For each action, should the game fire an analytics event, trigger a game-state change, or both?"
- "Are there any actions that should NOT fire an event — and is that a deliberate choice?"
Present as a table alongside the Interaction Map:
| Player Action | Event Fired | Payload / Data |
|---|---|---|
| [action] | [EventName] or none | [data passed with event] |
Flag any action that modifies persistent game state (save data, progress, economy) — these need explicit attention from the architecture team.
---
#### Section E3: Transitions & Animations
Specify how the screen enters and exits, and how it responds to state changes.
**Questions to ask**:
- "How does this screen appear? (fade in, slide from right, instant pop, scale from button)"
- "How does it dismiss? (fade out, slide back, cut)"
- "Are there any in-screen state transitions that need animation? (loading spinner, success state, error flash)"
- "Is there any animation that could cause motion sickness — and does the game have a reduced-motion option?"
Minimum required:
- Screen enter transition
- Screen exit transition
- At least one state-change animation if the screen has multiple states
---
#### Section F: Data Requirements
Cross-reference the GDD UI Requirements sections gathered in Phase 2.
For each piece of information the screen displays, ask:
- "Where does this data come from? Which system owns it?"
- "Does this screen need to write data back, or is it read-only?"
- "Is any of this data time-sensitive or real-time? (health bars, cooldown timers)"
Flag any case where the UI would need to own or manage game state as an architectural
concern. UX specs define what the UI needs; they do not dictate how the data is
delivered. That is an architecture decision.
Present the data requirements as a table:
| Data | Source System | Read / Write | Notes |
|------|--------------|--------------|-------|
| [item] | [system] | Read | — |
| [item] | [system] | Write | [concern if any] |
---
#### Section G: Accessibility
Cross-reference `design/accessibility-requirements.md` if it exists.
Walk through the ux-designer agent's standard checklist for this screen:
- Keyboard-only navigation path through all interactive elements
- Gamepad navigation order (if applicable)
- Text contrast and minimum readable font sizes
- Color-independent communication (no information conveyed by color alone)
- Screen reader considerations for any non-text elements
- Any motion or animation that needs a reduced-motion alternative
If no accessibility tier has been defined for this project, note the gap in the UX spec's Open Questions section:
> "Accessibility tier not yet defined — consider WCAG-AA as a baseline. Run `/gate-check` to see whether this blocks any phase gates."
Then continue to the next section without stopping.
---
#### Section H: Localization Considerations
Document constraints that affect how this screen behaves when text is translated.
**Questions to ask**:
- "Which text elements on this screen are the longest? What is the maximum character count that fits the layout?"
- "Are there any elements where text length is layout-critical — e.g., a button label that must stay on one line?"
- "Are there any elements that display numbers, dates, or currencies that need locale-specific formatting?"
Note: aim to flag any element where a 40% text expansion (common in translations from English to German or French) would break the layout. Mark those as HIGH PRIORITY for the localization engineer.
---
#### Section I: Acceptance Criteria
Write at least 5 specific, testable criteria that a QA tester can verify without reading any other design document. These become the pass/fail conditions for `/story-done`.
**Format**: Use checkboxes. Each criterion must be verifiable by a human tester:
```
- [ ] Screen opens within [X]ms from [trigger]
- [ ] [Element] displays correctly at [minimum] and [maximum] values
- [ ] [Navigation action] correctly routes to [destination screen]
- [ ] Error state appears when [condition] and shows [specific message or icon]
- [ ] Keyboard/gamepad navigation reaches all interactive elements in logical order
- [ ] [Accessibility requirement] is met — e.g., "all interactive elements have focus indicators"
```
**Minimum required**:
- 1 performance criterion (load/open time)
- 1 navigation criterion (at least one entry or exit path verified)
- 1 error/empty state criterion
- 1 accessibility criterion (per committed tier)
- 1 criterion specific to this screen's core purpose
Use `AskUserQuestion` to confirm:
- "Do these acceptance criteria cover what would make this screen 'done' for your QA process?"
- Options: "Yes — these are solid", "Add one more criterion", "Remove or rephrase one"
+44 -8
View File
@@ -1,11 +1,10 @@
---
name: ux-review
description: "Validates a UX spec, HUD design, or interaction pattern library for completeness, accessibility compliance, GDD alignment, and implementation readiness. Produces APPROVED / NEEDS REVISION / MAJOR REVISION NEEDED verdict with specific gaps."
description: "Validate a UX spec, HUD design or pattern library — accessibility, GDD alignment, readiness. APPROVED / NOT ASSESSED / NEEDS REVISION / MAJOR REVISION NEEDED."
argument-hint: "[file-path or 'all' or 'hud' or 'patterns']"
user-invocable: true
allowed-tools: Read, Glob, Grep
model: sonnet
agent: ux-designer
---
## Overview
@@ -23,10 +22,19 @@ the `/team-ui` pipeline.
**Verdict levels:**
- **APPROVED** — spec is complete, consistent, and implementation-ready
- **NOT ASSESSED** — one or more review dimensions had no criterion to check
against, or the spec could not be read; name which
- **NEEDS REVISION** — specific gaps found; fix before handoff but not a full redesign
- **MAJOR REVISION NEEDED** — fundamental issues with scope, player need, or
completeness; needs significant rework
**`NOT ASSESSED` ranks above APPROVED and below the two revision verdicts.** A
review that could not evaluate a dimension has not shown the spec is
implementation-ready; but a gap somebody found is more actionable than one nobody
could look for, so it must not displace them. Emit it when the spec file cannot
be read, when a checklist dimension has no source of truth to compare against, or
when the accessibility tier is uncommitted (below).
---
## Phase 1: Parse Arguments
@@ -47,10 +55,18 @@ full detail for each.
Before validating any spec, load:
1. **Input & Platform config**: Read `.claude/docs/technical-preferences.md` and
extract `## Input & Platform`. This is the authoritative source for which input
methods the game supports — use it to drive the Input Method Coverage checks in
Phase 3A, not the spec's own header. If unconfigured, fall back to the spec header.
1. **Input & Platform config**: Read the `platform` block from `project.yaml`
(`platform.targets`, `platform.primary_input`, `platform.gamepad_support`,
`platform.touch_support`); if `project.yaml` has no `platform` block, fall
back to the `## Input & Platform` section of
`.claude/docs/technical-preferences.md`. For the set of supported input
methods: when reading from `project.yaml`, derive it — keyboard/mouse if
`PC` or `Web` is in `targets`; gamepad if `gamepad_support` is Full or
Partial; touch if `touch_support` is Full or Partial; plus `primary_input`.
When falling back to `technical-preferences.md`, use its explicit Input
Methods field instead. This is the authoritative source for the Input Method
Coverage checks in Phase 3A — not the spec's own header. If neither source is
configured, fall back to the spec header.
2. The accessibility tier committed to in `design/accessibility-requirements.md`
(if it exists)
3. The interaction pattern library at `design/ux/interaction-patterns.md` (if
@@ -223,20 +239,36 @@ Run all checks against a `hud-design.md`-based document.
- GDD [name] UI Requirements — [X/Y requirements covered]
- Missing: [list any uncovered GDD requirements]
### Accessibility: [COMPLIANT / GAPS / NON-COMPLIANT]
### Accessibility: [COMPLIANT / GAPS / NON-COMPLIANT / NOT ASSESSED]
- Target tier: [tier]
- [list specific accessibility findings]
> **If `design/accessibility-requirements.md` is absent there is no committed
> tier, so this dimension has no criterion.** Report
> `Accessibility: NOT ASSESSED — no committed tier (design/accessibility-requirements.md absent)`
> and do NOT report it as COMPLIANT — a gate compared against an absent standard
> passes the way an assertion that can never fail passes. The same rule lives in
> `/team-ui` Phase 4 and is mirrored here so the two cannot drift. If the spec's own
> header states a tier, carry it forward as an **assumption** and say plainly that
> it was assumed rather than committed. Recommend `/ux-design accessibility` to
> establish the tier.
### Pattern Library: [CONSISTENT / INCONSISTENCIES FOUND]
- [findings]
### Verdict: APPROVED / NEEDS REVISION / MAJOR REVISION NEEDED
### Verdict: APPROVED / NOT ASSESSED / NEEDS REVISION / MAJOR REVISION NEEDED
**Blocking issues**: [N] — must be resolved before implementation
**Advisory issues**: [N] — recommended but not blocking
**Dimensions not assessed**: [N] — [name each, and what would make it checkable]
[For APPROVED]: This spec is ready for handoff to `/team-ui` Phase 2
(Visual Design).
[For NOT ASSESSED]: [N] of the four review dimensions could not be evaluated:
[name them]. The spec may well be sound — this review cannot say either way for
those dimensions. [For each: the one input that would make it checkable.]
Handoff to `/team-ui` is not recommended on this result.
[For NEEDS REVISION]: Address the [N] blocking issues above, then re-run
`/ux-review`.
@@ -252,6 +284,10 @@ This skill is READ-ONLY — it never edits or writes files. It reports findings
After delivering the verdict:
- For **APPROVED**: suggest running `/team-ui` to begin implementation coordination
- For **NOT ASSESSED**: name the missing input per dimension and offer to help
produce it (`/ux-design accessibility` for an uncommitted tier, the GDD path
for absent UI requirements). Do not re-run the review against the same missing
inputs and report a different verdict — only new inputs change this one
- For **NEEDS REVISION**: offer to help fix specific gaps ("Would you like me to
help draft the missing error state?") — but do not auto-fix; wait for user
instruction
+15 -11
View File
@@ -1,14 +1,17 @@
---
name: vertical-slice
description: "Pre-Production validation — build a production-quality end-to-end build to confirm the full game loop is achievable before committing to Production. Run after GDDs, architecture, and UX specs are complete. Produces a PROCEED/PIVOT/KILL verdict that gates the Pre-Production → Production transition."
description: "Pre-production validation — end-to-end build to confirm the full loop is achievable before committing to Production. After GDDs, architecture, UX specs."
argument-hint: "[--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion
model: sonnet
agent: prototyper
isolation: worktree
---
!`source "${CLAUDE_PROJECT_DIR:-.}/.claude/hooks/yaml-helper.sh" 2>/dev/null && resolve_config --keys review_mode,automation`
## Purpose
The **vertical slice** answers a different question from the concept prototype:
@@ -36,12 +39,13 @@ whether the core idea is worth designing, run `/prototype` (concept prototype) i
## Phase 1: Resolve Review Mode and Load Context
Resolve the review mode:
1. If `--review [full|lean|solo]` was passed → use that
2. Else read `production/review-mode.txt` → use that value
3. Else → default to `lean`
See `.claude/docs/director-gates.md` for the full check pattern.
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
(collaborative asks always · guided major-only · autonomous logs and proceeds;
`automation_always_ask` categories always prompt).
Read the following files to understand the full design intent:
- `CLAUDE.md` — tech stack and engine
@@ -118,7 +122,7 @@ If yes, create the directory. Every file must begin with:
**Quality standards** — higher than concept prototype, not full production:
- Follow architecture layers from `docs/architecture/control-manifest.md`
- Naming conventions from `.claude/docs/technical-preferences.md`
- Naming conventions — `naming.*` from `project.yaml`; for any key absent or empty (including when `project.yaml` has no `naming` block), from `.claude/docs/technical-preferences.md`
- No hardcoded gameplay values — use constants or config files
- Basic error handling on critical paths
- Placeholder art acceptable; representative art preferred
@@ -260,8 +264,8 @@ the project — cross-reference it with sprint estimates.
**Review mode check:**
- `solo` → skip. Note: "CD-PLAYTEST skipped — Solo mode."
- `lean` → skip (not a PHASE-GATE). Note: "CD-PLAYTEST skipped — Lean mode."
- `full` → spawn `creative-director` via Task using gate **CD-PLAYTEST**
(`.claude/docs/director-gates.md`).
- `full` → spawn `creative-director` via `Agent` using gate **CD-PLAYTEST**
(`.claude/docs/director-gates/cd-playtest.md`).
Pass: the full REPORT.md content, the validation question, game pillars and core
fantasy from `design/gdd/game-concept.md`.