mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-17 02:37:07 +00:00
Release 1.1.2 — the default path works end to end
Fix release for 1.1.1: the minimal path end to end, engine commands that run on Godot, Unity and Unreal, hook warnings you can see, and verdicts that say when they could not check. Details in CHANGELOG.md; upgrade steps in UPGRADING.md (v1.1.1 → v1.1.2). Fixes #67 Fixes #131 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7ed2c3e9c4
commit
b21fa0f7f2
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Bash, Write, AskUserQuestion, Bash(bash "*/.cla
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,automation_always_ask,workflow`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,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
|
||||
@@ -31,7 +31,7 @@ wrong internal format.
|
||||
|
||||
**Argument modes:**
|
||||
|
||||
**Audit mode:** `$ARGUMENTS[0]` (blank = `full`)
|
||||
**Audit mode:** `$ARGUMENTS` (blank = `full`)
|
||||
|
||||
- **No argument / `full`**: Complete audit — all artifact types
|
||||
- **`gdds`**: GDD format compliance only
|
||||
@@ -98,6 +98,8 @@ 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).
|
||||
Steps 2e (the Engine reference row only), 2f (project config) and 2g (v1.0
|
||||
migration check) run at every tier.
|
||||
|
||||
### 2a: GDD Format Audit
|
||||
|
||||
@@ -129,8 +131,10 @@ informational):
|
||||
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.
|
||||
- **`minimal`** — GDDs are not expected; audit `design/game-brief.md` instead,
|
||||
against `.claude/docs/templates/game-brief.md`: each of the six required fields
|
||||
present and not a placeholder; the three one-liners advisory. 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.
|
||||
@@ -203,6 +207,10 @@ For each story file found:
|
||||
| Engine reference | `docs/engine-reference/[engine]/VERSION.md` | HIGH — ADR engine checks blind |
|
||||
| Architecture traceability | `docs/architecture/requirements-traceability.md` | MEDIUM — no persistent matrix |
|
||||
|
||||
At `workflow: minimal` only the Engine reference row applies. The TR registry,
|
||||
control manifest and its version stamp, sprint status, stage file and
|
||||
traceability matrix are not on the minimal path, so their absence is not a gap.
|
||||
|
||||
### 2f: Project Config Audit
|
||||
|
||||
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):
|
||||
@@ -231,7 +239,12 @@ the framework's own test suite:
|
||||
bash .claude/scripts/migrate-v1-config.sh --dry-run
|
||||
```
|
||||
|
||||
Report what it lists. If the user approves, run it without `--dry-run`. It
|
||||
The dry run writes nothing; record what it lists for the report. Do not run the
|
||||
converter during the audit — Phase 2 reads silently. The migration is
|
||||
classified BLOCKING in Phase 3, heads the plan, and **Phase 7 offers it as the
|
||||
first action**: report what the dry run listed, then ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`." 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`.
|
||||
|
||||
@@ -323,7 +336,13 @@ 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 `project.stage` in `project.yaml` (and legacy `stage.txt`) authoritatively
|
||||
5. Run `/gate-check [phase]` (the gate into the phase the project is in; at Concept there is none — Concept is the default stage, nothing to run) → writes `project.stage` in `project.yaml` (and legacy `stage.txt`) authoritatively
|
||||
|
||||
**At `workflow: minimal` the plan prescribes none of this sequence.** None of it
|
||||
is on the minimal path: ADRs are not expected, the brief's build order is the
|
||||
plan (no `/sprint-plan`), and nothing there runs `/gate-check`. The plan's
|
||||
Step 3 says so in one line and names the path's next step instead —
|
||||
`/create-stories` when no stories exist, else `/dev-story`.
|
||||
|
||||
**Existing stories** — note explicitly:
|
||||
> "Existing stories continue to work with all template skills — all new format
|
||||
@@ -408,6 +427,10 @@ Re-run `/adopt` anytime to check remaining gaps.
|
||||
|
||||
## Step 3: Bootstrap Infrastructure
|
||||
|
||||
[At `workflow: minimal`, replace 3a–3d with one line: "Not on the minimal path —
|
||||
the brief's build order is the plan. Next: `/create-stories` (or `/dev-story`
|
||||
once stories exist)."]
|
||||
|
||||
### 3a. Register existing requirements (creates tr-registry.yaml)
|
||||
Run `/architecture-review` — even if ADRs already exist, this run bootstraps
|
||||
the TR registry from your existing GDDs and ADRs.
|
||||
@@ -425,7 +448,8 @@ Run `/sprint-plan update`
|
||||
- [ ] production/sprint-status.yaml created
|
||||
|
||||
### 3d. Set authoritative project stage
|
||||
Run `/gate-check [current-phase]`
|
||||
Run `/gate-check [current-phase]` (the gate into the phase the project is in;
|
||||
at Concept there is none — Concept is the default stage, nothing to run)
|
||||
**Time**: 5 min
|
||||
- [ ] `project.stage` in `project.yaml` written (legacy `production/stage.txt` also updated)
|
||||
|
||||
@@ -460,33 +484,19 @@ are resolved. The new run will reflect the current state of the project.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6b: Set Review Mode
|
||||
## Phase 6b: Report Review Mode
|
||||
|
||||
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`.
|
||||
**Do not write a review mode.** `modes.review_mode` is one of the six knobs
|
||||
`modes.rigor` fronts: pinning it in `project.yaml` shadows the rigor expansion, and
|
||||
the legacy `production/review-mode.txt` sits *above* that expansion in resolution,
|
||||
so either write would freeze director-review depth for good — the rule `/start`
|
||||
and `project.yaml`'s header comment both state.
|
||||
|
||||
**If a mode is already set**: Note the current mode — "Review mode is already set to `[current]`." — skip the prompt.
|
||||
|
||||
**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**:
|
||||
- `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 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 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.
|
||||
Report the value the bootstrap above resolved instead: "Review mode resolves to
|
||||
`[value]` — from `modes.rigor`, unless something pins it." If the user wants a
|
||||
different depth, point them to changing `modes.rigor`, or to pinning it on purpose
|
||||
with `/settings --local modes.review_mode=<full|lean|solo>` (a personal override in
|
||||
`project.local.yaml`).
|
||||
|
||||
---
|
||||
|
||||
@@ -496,6 +506,11 @@ After writing the plan, don't stop there. Pick the single highest-priority gap
|
||||
and offer to handle it immediately using `AskUserQuestion`. Choose the first
|
||||
branch that applies:
|
||||
|
||||
**If Phase 2g found a v1.0 project needing migration:** offer the converter run
|
||||
described there — report what the dry run listed and ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`."
|
||||
Every other fix reads config through it, so it comes first.
|
||||
|
||||
**If there are parenthetical status values in systems-index.md:**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent fix is `systems-index.md` — [N] rows have parenthetical status
|
||||
@@ -523,6 +538,15 @@ Use `AskUserQuestion`:
|
||||
- "Do all [N] GDDs one by one"
|
||||
- "I'll handle GDDs myself"
|
||||
|
||||
**Otherwise, if any BLOCKING or HIGH gap remains** (one no branch above names —
|
||||
e.g. a missing TR registry):
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent remaining gap is [first BLOCKING or HIGH item in the plan] —
|
||||
[one line on what it breaks]. Start on it now?"
|
||||
- "Yes — start on [item]"
|
||||
- "Show me that plan item first"
|
||||
- "Done — leave me with the plan"
|
||||
|
||||
**If no BLOCKING or HIGH gaps exist:**
|
||||
Use `AskUserQuestion`:
|
||||
- "No blocking gaps — this project is template-compatible. What next?"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# /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.
|
||||
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/` as `Proposed`. Its `accept` mode is the only route to `Accepted`, and acceptance is what unblocks the 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
|
||||
@@ -21,30 +21,30 @@ nothing is indistinguishable from a check that passed.
|
||||
| `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 |
|
||||
| `project.yaml` | `engine.name` — derives the primary specialist (`<engine>-specialist`) to spawn for validation (Step 5.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)
|
||||
- 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 3a 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/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` | 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
|
||||
- `## Status` is always present. Authoring writes `Proposed`; retrofit writes the status the user gives, except that an `Accepted` answer is written as `Proposed` and handed to acceptance mode. Only acceptance mode writes `Accepted`, after its dependency check and the user's confirmation
|
||||
- `## 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
|
||||
- Engine specialist validation (Step 5.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)
|
||||
@@ -53,10 +53,10 @@ nothing is indistinguishable from a check that passed.
|
||||
|
||||
## 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 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`. Retrofit mode's `Accepted` answer, for a decision already in force, is written as `Proposed` and handed to this route. 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 proceeds past the architectural stance conflict check (Step 3a) 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?"
|
||||
@@ -71,12 +71,12 @@ nothing is indistinguishable from a check that passed.
|
||||
- `## 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)
|
||||
- `### Implementation Guidelines` (under `## Decision`) — the concrete "must / must never" patterns programmer agents follow; the ADR template carries this subsection
|
||||
- `## 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)
|
||||
- `### Implementation Guidelines` (under `## Decision`, verbatim)
|
||||
- `## Engine Compatibility` (post-cutoff API risks, verification required)
|
||||
- `## ADR Dependencies` (to detect if this ADR's dependencies are unresolved)
|
||||
|
||||
@@ -87,8 +87,8 @@ nothing is indistinguishable from a check that passed.
|
||||
|
||||
## 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
|
||||
- Acceptance mode moves a story from `Blocked` to `Ready` only when the story file, under `production/epics/`, contains a Blocked Status line in any of the forms `/create-stories` writes (`> **Status**: Blocked`, `**Status:** Blocked`, `Status: Blocked`) and this ADR's id. A story blocked pending this ADR that never names its id is not found, and stays `Blocked` until it is updated by hand
|
||||
- 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
|
||||
- Engine specialist validation (Step 5.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`
|
||||
|
||||
@@ -3,7 +3,7 @@ name: architecture-decision
|
||||
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, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/architecture-decision/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, Bash(wc -c *), Bash(bash "*/.claude/skills/architecture-decision/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -26,16 +26,15 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
`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.
|
||||
- **`individual`** (default): `technical-director` (TD-ADR) + the engine-specialist.
|
||||
- **`small`** and **`studio`**: the same two. This skill spawns no engine
|
||||
sub-specialist and no adversarial reviewer at any size.
|
||||
|
||||
**`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` =
|
||||
`terse` (the default, via `rigor: minimal`) = decision + alternatives as bullets, one line of rationale each;
|
||||
`balanced` = paragraph per section with light rationale (`rigor: standard`); `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
|
||||
@@ -57,6 +56,9 @@ Enter **retrofit mode**:
|
||||
- `## ADR Dependencies` — HIGH if missing: dependency ordering breaks
|
||||
- `## Engine Compatibility` — HIGH if missing: post-cutoff risk unknown
|
||||
- `## GDD Requirements Addressed` — MEDIUM if missing: traceability lost
|
||||
- `## Date` — MEDIUM if missing, and no `## Last Verified` either: `/create-stories`
|
||||
stamps stories with it and `/dev-story` compares against it, so without it a
|
||||
story can never tell whether the ADR changed
|
||||
3. Present to the user:
|
||||
```
|
||||
## Retrofit: [ADR title]
|
||||
@@ -72,9 +74,14 @@ Enter **retrofit mode**:
|
||||
✗ Engine Compatibility — HIGH
|
||||
```
|
||||
4. Ask: "Shall I add the [N] missing sections? I will not modify any existing content."
|
||||
If no: write nothing, and report the missing sections by name.
|
||||
5. If yes:
|
||||
- For **Status**: ask the user — "What is the current status of this decision?"
|
||||
Options: "Proposed", "Accepted", "Deprecated", "Superseded by ADR-XXXX"
|
||||
An `Accepted` answer — a decision already in force — is not written as
|
||||
given: write `Proposed`, add the other missing sections, then run
|
||||
acceptance mode (below) on this ADR. Its dependency check, confirmation and
|
||||
story unblocking apply here too; it stays the only path that sets `Accepted`.
|
||||
- For **ADR Dependencies**: ask — "Does this decision depend on any other ADR?
|
||||
Does it enable or block any other ADR or epic?" Accept "None" for each field.
|
||||
- For **Engine Compatibility**: read the engine reference docs (same as Step 1 below)
|
||||
@@ -82,9 +89,12 @@ Enter **retrofit mode**:
|
||||
- For **GDD Requirements Addressed**: ask — "Which GDD systems motivated this decision?
|
||||
What specific requirement in each GDD does this ADR address?"
|
||||
- Append each missing section to the ADR file using the Edit tool.
|
||||
- For **Date** (counted only when there is no `## Last Verified`): append
|
||||
`## Date` with today's date — even when it is the only missing section, the
|
||||
case `/dev-story` sends you here for — and say that it records the retrofit,
|
||||
not when the decision was made.
|
||||
- **Never modify any existing section.** Only append or fill absent sections.
|
||||
6. After adding all missing sections, update the ADR's `## Date` field if it is absent.
|
||||
7. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
|
||||
6. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
|
||||
has its Status and Dependencies fields."
|
||||
|
||||
**If the argument starts with `accept` followed by an ADR id**
|
||||
@@ -134,25 +144,37 @@ enter and never leave.
|
||||
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.
|
||||
every story for a Blocked Status line —
|
||||
`Grep pattern="Status\**:\**\s*Blocked" path="production/epics" glob="**/story-*.md" output_mode="files_with_matches"`,
|
||||
which matches `> **Status**: Blocked` (the form `/create-stories` writes),
|
||||
`**Status:** Blocked` and `Status: Blocked` — and keep the files that name
|
||||
this ADR's id as the reason they are blocked. That pairing is what "blocked
|
||||
pending this ADR" means — a story blocked for an unrelated reason will not
|
||||
name it. Leave out a story that names this ADR only as the successor to point
|
||||
at (`point the story at ADR-NNNN`, the note for a `Deprecated` or
|
||||
`Superseded` ADR): it is still governed by the old ADR, and accepting the
|
||||
successor does not re-point it.
|
||||
> **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
|
||||
> never gets picked up.
|
||||
|
||||
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
|
||||
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Leave an existing
|
||||
`## Date` as it is: it records when the ADR was written, and `/create-stories`
|
||||
stamps stories with it (or `## Last Verified`), so rewriting it on acceptance
|
||||
would make every story drafted against the Proposed ADR look out of date to
|
||||
`/dev-story`. **If that section is absent, add it** with today's date — 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.
|
||||
8. Report what moved: the ADR (and its `## Date`, if one was added), and every
|
||||
story that became Ready.
|
||||
|
||||
If NOT in retrofit or acceptance mode, proceed to Step 1 below (normal ADR authoring).
|
||||
|
||||
@@ -273,7 +295,7 @@ ADR in `docs/architecture/` on the chance one is relevant:
|
||||
```
|
||||
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).
|
||||
this size.
|
||||
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.
|
||||
@@ -489,7 +511,7 @@ to implement it.]
|
||||
|
||||
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.
|
||||
- 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
|
||||
@@ -505,7 +527,9 @@ to implement it.]
|
||||
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
|
||||
- On CONCERNS: show them to the user verbatim and ask with the standard options from `director-gates.md` — `Revise flagged items` / `Accept and proceed` / `Discuss further`. Revise the flagged Decision or Alternatives sections only on `Revise flagged items`.
|
||||
- On REJECT: show the blockers verbatim and revise the Decision or Alternatives sections before proceeding.
|
||||
- A revised draft still reaches the user through the write approval below; nothing is written before it. A `NOT ASSESSED` answer is not an approval — name the missing input (`director-gates.md`).
|
||||
|
||||
5.7. **GDD Sync Check** — Before presenting the write approval, scan all GDDs
|
||||
referenced in the "GDD Requirements Addressed" section for naming inconsistencies
|
||||
|
||||
@@ -148,7 +148,7 @@ not the same finding:
|
||||
|---|---|---|
|
||||
| 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. |
|
||||
| **0 matches, N_adr > 0** | **Malformed ADRs**, not "no architecture". | "[N_adr] ADRs found, none carries a scannable section — run `/architecture-decision retrofit [file]` 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.
|
||||
@@ -312,8 +312,11 @@ Full-read a story only when its Test Evidence section is missing or ambiguous.
|
||||
|
||||
### Step 3b-2 — Load test files
|
||||
|
||||
Glob `tests/unit/**/*_test.*` and `tests/integration/**/*_test.*`.
|
||||
Build an index: system → [test file paths].
|
||||
Glob the engine's test root (`.claude/docs/directory-structure.md`): Godot
|
||||
`tests/unit/**/*_test.*` and `tests/integration/**/*_test.*`; Unity
|
||||
`Assets/Tests/**/*Tests.cs`; Unreal `Source/*/Private/Tests/**/*.cpp`. With no
|
||||
engine configured, say the test index could not be built rather than reading an
|
||||
empty glob as "no tests". Build an index: system → [test file paths].
|
||||
|
||||
For each test file path from Step 3b-1, confirm via Glob whether the file
|
||||
actually exists. Note MISSING if the stated path does not exist.
|
||||
@@ -472,7 +475,7 @@ Post-Cutoff API Conflicts:
|
||||
|
||||
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.
|
||||
- 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)
|
||||
@@ -617,11 +620,16 @@ FAIL: Critical gaps (Foundation/Core layer requirements uncovered),
|
||||
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.
|
||||
- **Phase 6 could not run** — no `docs/architecture/architecture.md`. It must
|
||||
appear as a named `NOT ASSESSED` **line item** in the report rather than as
|
||||
absent findings. ADR traceability can still be complete, so a CONCERNS or FAIL
|
||||
finding elsewhere still stands; but in `full` mode, whose scope includes
|
||||
Phase 6, the verdict cannot be PASS — a review that could not look at part of
|
||||
its scope has not shown that part is sound, so it is NOT ASSESSED.
|
||||
- **No engine is configured** (`full` and `engine` modes) — Phase 5 has no pinned
|
||||
engine reference to audit the ADRs against, and the specialist consultation was
|
||||
skipped. Record the `Engine validation: NOT ASSESSED` line item; like Phase 6
|
||||
above, it keeps the verdict from PASS.
|
||||
|
||||
Do not resolve any of these to PASS on the grounds that no gap was *found*. No
|
||||
gap was looked for.
|
||||
@@ -639,10 +647,15 @@ gap was looked for.
|
||||
|
||||
Use `AskUserQuestion` for the write approval:
|
||||
- "Review complete. What would you like to write?"
|
||||
- [A] Write all three files (review report + traceability index + TR registry)
|
||||
- [A] Write all three files — review report (`docs/architecture/architecture-review-[date].md`), traceability index (`docs/architecture/requirements-traceability.md`), TR registry (`docs/architecture/tr-registry.yaml`)
|
||||
- [B] Write review report only — `docs/architecture/architecture-review-[date].md`
|
||||
- [C] Don't write anything yet — I need to review the findings first
|
||||
|
||||
When Phase 4 found a 🔴 conflict and `docs/consistency-failures.md` exists, name
|
||||
that file in option [A] as well — "…and append [N] conflict entr(y/ies) to
|
||||
`docs/consistency-failures.md`". Only [A] appends there (see Reflexion Log
|
||||
Update); [B] writes the report and nothing else.
|
||||
|
||||
### RTM Output (rtm mode only)
|
||||
|
||||
For `rtm` mode, use `AskUserQuestion`:
|
||||
@@ -725,8 +738,9 @@ across every subsequent architecture review.
|
||||
|
||||
### Reflexion Log Update
|
||||
|
||||
After writing the review report, append any 🔴 CONFLICT entries found in Phase 4
|
||||
to `docs/consistency-failures.md` (if the file exists):
|
||||
When the user chose Phase 8's [A] — the option that named this file — append
|
||||
any 🔴 CONFLICT entries found in Phase 4 to `docs/consistency-failures.md` (if
|
||||
the file exists), after writing the review report:
|
||||
|
||||
```markdown
|
||||
### [YYYY-MM-DD] — /architecture-review — 🔴 CONFLICT
|
||||
@@ -747,7 +761,7 @@ After writing all approved files, silently append to
|
||||
`production/session-state/active.md`:
|
||||
|
||||
## Session Extract — /architecture-review [date]
|
||||
- Verdict: [PASS / CONCERNS / FAIL]
|
||||
- Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
- Requirements: [N] total — [X] covered, [Y] partial, [Z] gaps
|
||||
- New TR-IDs registered: [N, or "None"]
|
||||
- GDD revision flags: [comma-separated GDD names, or "None"]
|
||||
@@ -757,7 +771,9 @@ After writing all approved files, silently append to
|
||||
If `active.md` does not exist, create it with this block as the initial content.
|
||||
Confirm in conversation: "Session state updated."
|
||||
|
||||
The traceability index format:
|
||||
The traceability index — written to `docs/architecture/requirements-traceability.md`,
|
||||
the path `/propagate-design-change` and the Pre-Production gate read; `rtm` mode
|
||||
later extends the same file with story and test columns — uses this format:
|
||||
|
||||
```markdown
|
||||
# Architecture Traceability Index
|
||||
@@ -789,7 +805,7 @@ After completing the review and writing approved files, present:
|
||||
1. **Immediate actions**: List the top 3 ADRs to create (highest-impact gaps first,
|
||||
Foundation layer before Feature layer)
|
||||
2. **Pre-gate checklist**: Check whether these exist via Glob and mark each ✅ or ❌:
|
||||
- `tests/unit/` and `tests/integration/` directories — if ❌: run `/test-setup`
|
||||
- the engine's test root — `tests/unit/` and `tests/integration/` (Godot), `Assets/Tests/EditMode/` and `Assets/Tests/PlayMode/` (Unity), `Source/<Module>/Private/Tests/` (Unreal) — if ❌: run `/test-setup`
|
||||
- `.github/workflows/tests.yml` — if ❌: run `/test-setup`
|
||||
- `design/accessibility-requirements.md` — if ❌: run `/ux-design`
|
||||
- `design/ux/interaction-patterns.md` — if ❌: run `/ux-design`
|
||||
@@ -837,8 +853,8 @@ partial report** (retry scope here = fewer GDDs / single-system). Full procedure
|
||||
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
|
||||
2. **Show the matrix** — present the full traceability matrix before any write
|
||||
approval; let the user see the state
|
||||
3. **Don't guess** — if a requirement is ambiguous, ask: "Is [X] a technical
|
||||
requirement or a design preference?"
|
||||
4. **Draft before approval** — always show the content that will be written (the
|
||||
|
||||
@@ -25,9 +25,9 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
**`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
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = each section a bulleted list of
|
||||
constraints + references; `balanced` = paragraphs explaining each visual choice
|
||||
(default); `thorough` = full prose including style explorations, references, and
|
||||
(`rigor: standard`); `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`):
|
||||
@@ -37,10 +37,13 @@ rationale per choice. Apply it to every section you author.
|
||||
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:
|
||||
Read `design/gdd/game-concept.md` — or `design/game-brief.md`, the one-page brief
|
||||
that replaces it at `rigor: minimal`. If neither exists, fail with:
|
||||
> "No game concept found. Run `/brainstorm` first — the art bible is authored after the game concept is approved."
|
||||
|
||||
Extract from game-concept.md:
|
||||
Extract from game-concept.md (from the brief: working title, pitch, "Who it's for /
|
||||
what they feel" line and "Art & audio direction" line — it has no pillars, Visual
|
||||
Identity Anchor or platform):
|
||||
- Game title (working title)
|
||||
- Core fantasy and elevator pitch
|
||||
- Game pillars (all of them)
|
||||
@@ -71,21 +74,32 @@ Grep pattern="\[To be designed\]|\[TBD\]|\[To be written\]|^_?TODO" path="design
|
||||
Section | Status
|
||||
--------|--------
|
||||
1. Visual Identity Statement | [Complete / Empty / Placeholder]
|
||||
2. Color Palette | ...
|
||||
3. Lighting & Atmosphere | ...
|
||||
4. Character Art Direction | ...
|
||||
5. Environment & Level Art | ...
|
||||
6. UI Visual Language | ...
|
||||
7. VFX & Particle Style | ...
|
||||
2. Mood & Atmosphere | ...
|
||||
3. Shape Language | ...
|
||||
4. Color System | ...
|
||||
5. Character Design Direction | ...
|
||||
6. Environment Design Language | ...
|
||||
7. UI/HUD Visual Direction | ...
|
||||
8. Asset Standards | ...
|
||||
9. Style Prohibitions | ...
|
||||
9. Reference Direction | ...
|
||||
```
|
||||
|
||||
- Present this table to the user:
|
||||
> "Found existing art bible at `design/art/art-bible.md`. [N] sections are complete, [M] need content. I'll work on the incomplete sections only — existing content will not be touched."
|
||||
- Only work on sections with Status: Empty or Placeholder. Do not re-author sections that are already complete.
|
||||
|
||||
If the file does not exist, this is a fresh authoring session — proceed normally.
|
||||
If the file does not exist, this is a fresh authoring session. The first
|
||||
approved section creates the file from `.claude/docs/templates/art-bible.md`,
|
||||
whose nine `## N. Name` headings are the ones retrofit mode reads — ask first:
|
||||
"May I create `design/art/art-bible.md` from the art bible template?" Each
|
||||
approved section then replaces its own `[To be designed]` line with `Edit`;
|
||||
keep the headings as the template has them.
|
||||
|
||||
**A section's approval names its write.** Every section is approved through an
|
||||
`AskUserQuestion` whose approving option is `[A] Lock this in and write it to
|
||||
design/art/art-bible.md` (Section 1's full option list is below). Choosing it is
|
||||
the approval to write that section; no section is written without it, fresh or
|
||||
retrofit.
|
||||
|
||||
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`.
|
||||
|
||||
@@ -119,6 +133,11 @@ Use `AskUserQuestion` with two tabs:
|
||||
If the game-concept.md has a Visual Identity Anchor section, note it:
|
||||
> "Found a visual identity anchor from brainstorm: '[anchor name] — [one-line rule]'. I'll use this as the foundation for the art bible."
|
||||
|
||||
**Author only the sections in the chosen scope.** Phases 2–4 run only the
|
||||
sections inside it — for `Resume`, the Empty and Placeholder rows of the
|
||||
retrofit table — and skip every other section, and any phase left with none.
|
||||
Phase 6 names each section not authored this run and why.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Visual Identity Foundation (Sections 1–4)
|
||||
@@ -151,10 +170,10 @@ If a visual anchor exists from game-concept.md: present it and ask:
|
||||
|
||||
**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."
|
||||
- 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. (From a one-page brief, which has no pillars, anchor them in its pitch and "what they feel" line.)"
|
||||
|
||||
Present the art-director's draft to the user. Use `AskUserQuestion`:
|
||||
- Options: `[A] Lock this in` / `[B] Revise the one-liner` / `[C] Revise a supporting principle` / `[D] Describe my own direction`
|
||||
- Options: `[A] Lock this in and write it to design/art/art-bible.md` / `[B] Revise the one-liner` / `[C] Revise a supporting principle` / `[D] Describe my own direction`
|
||||
|
||||
Write the approved section to file immediately.
|
||||
|
||||
@@ -261,7 +280,7 @@ Write the approved section to file.
|
||||
- **`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 (`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.
|
||||
If any art preference conflicts with a technical constraint (e.g., art-director wants 4K textures but performance budget requires 2K for mobile), surface the conflict explicitly with both positions — the ideal and the constrained standard, and the tradeoff. Do NOT silently resolve it — use `AskUserQuestion` to let the user pick (options: the ideal standard, the constrained standard, or document both and let per-asset judgment apply). Ambiguity in asset standards is where production costs are born.
|
||||
|
||||
Write the approved section to file.
|
||||
|
||||
@@ -280,21 +299,46 @@ Write the approved section to file.
|
||||
## Phase 5: Art Director Sign-Off
|
||||
|
||||
**Review mode check** — apply before spawning AD-ART-BIBLE:
|
||||
- `solo` → skip. Note: "AD-ART-BIBLE skipped — Solo mode." Proceed to Phase 6.
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "AD-ART-BIBLE skipped — Lean mode." Proceed to Phase 6.
|
||||
- `solo` → skip. Note: "AD-ART-BIBLE skipped — Solo mode." Then record the skip
|
||||
(below) and proceed to Phase 6.
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "AD-ART-BIBLE skipped — Lean mode."
|
||||
Then record the skip (below) and 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 `Agent` using gate **AD-ART-BIBLE** (`.claude/docs/director-gates/ad-art-bible.md`).
|
||||
On either skip, ask "May I record the skipped sign-off in
|
||||
`design/art/art-bible.md`'s header?" and, on yes, replace the header's
|
||||
`> **Art Director Sign-Off (AD-ART-BIBLE)**: [Not yet reviewed]` with
|
||||
`> **Art Director Sign-Off (AD-ART-BIBLE)**: SKIPPED [date] — [solo|lean] mode`
|
||||
— the gate accepts either form as a recorded sign-off.
|
||||
|
||||
Pass: art bible file path, game pillars, visual identity anchor.
|
||||
After all sections are complete (or the scoped set from Phase 1 is complete), spawn `art-director` via `Agent` using gate **AD-ART-BIBLE** (`.claude/docs/director-gates/ad-art-bible.md`).
|
||||
|
||||
Handle verdict per standard rules in `director-gates.md`. Record the verdict in the art bible's status header:
|
||||
`> **Art Director Sign-Off (AD-ART-BIBLE)**: APPROVED [date] / CONCERNS (accepted) [date] / REVISED [date]`
|
||||
Pass: the art bible path (`design/art/art-bible.md`); the game pillars and core
|
||||
fantasy; the platform and performance constraints (`platform.*` and
|
||||
`performance.*` from `project.yaml`, falling back to
|
||||
`.claude/docs/technical-preferences.md`); and the visual identity anchor. When
|
||||
Phase 0 read the one-page brief, pass its pitch and "what they feel" line as the
|
||||
pillars and fantasy, and its "Art & audio direction" line as the anchor.
|
||||
|
||||
Handle verdict per standard rules in `director-gates.md`.
|
||||
On `Revise flagged items`, or to resolve a REJECT, the section's own specialist
|
||||
— `art-director`, with `ux-designer` for Section 7 and `technical-artist` for
|
||||
Section 8 — re-drafts each flagged section, which is then presented, approved
|
||||
and written like any other section before `REVISED [date]` is recorded.
|
||||
A `NOT ASSESSED` answer is never an approval: name the missing input, then
|
||||
supply it and re-run the gate, or record `NOT ASSESSED`.
|
||||
Record the verdict in the art bible's status header:
|
||||
`> **Art Director Sign-Off (AD-ART-BIBLE)**: APPROVED [date] / CONCERNS (accepted) [date] / REVISED [date] / NOT ASSESSED [date] — [missing input]`
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Close
|
||||
|
||||
First, name each of the nine sections not authored this run and why — outside
|
||||
the chosen scope, or already complete — e.g. *"Not authored this run: sections
|
||||
5–9 (outside the chosen scope; `standard` requires 1–4)."* A run that stopped
|
||||
after Section 4 must not read like a finished bible.
|
||||
|
||||
Before presenting next steps, check project state:
|
||||
- Does `design/gdd/systems-index.md` exist? → map-systems 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
|
||||
@@ -304,6 +348,10 @@ Before presenting next steps, check project state:
|
||||
|
||||
Use `AskUserQuestion` for next steps. Only include options that are genuinely next based on the state check above:
|
||||
|
||||
At `workflow: minimal`, the pool is `/create-stories` (no stories yet) or
|
||||
`/dev-story [next story]`, plus Stop here — the GDD/architecture pool below is
|
||||
`standard`/`full` only.
|
||||
|
||||
**Option pool — include only if not already done:**
|
||||
- `[_] Run /map-systems — decompose the concept into systems before writing GDDs` (skip if systems-index.md exists)
|
||||
- `[_] Run /setup-engine — configure the engine (asset standards may need revisiting after engine is set)` (skip if engine configured)
|
||||
@@ -316,7 +364,7 @@ Use `AskUserQuestion` for next steps. Only include options that are genuinely ne
|
||||
|
||||
Assign letters A, B, C… only to the options actually included. Mark the most logical pipeline-advancing option as `(recommended)`.
|
||||
|
||||
> **Always include** `/create-architecture` and Stop here as options — these are always valid next steps once the art bible is complete.
|
||||
> **Always include** (`standard`/`full` only) `/create-architecture` and Stop here as options — these are always valid next steps once the art bible is complete.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: asset-audit
|
||||
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, Bash
|
||||
allowed-tools: Read, Glob, Grep, Bash(stat *), Bash(file *), Bash(od *), Bash(wc *), Bash(du *)
|
||||
model: sonnet
|
||||
# Read-only diagnostic skill — no specialist agent delegation needed
|
||||
---
|
||||
@@ -13,7 +13,9 @@ model: sonnet
|
||||
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.
|
||||
`stat` or a binary header read, so the read-only measuring commands (`stat`,
|
||||
`file`, `od`, `wc`, `du`) are pre-approved above; list files with Glob. Anything
|
||||
else asks first.
|
||||
|
||||
**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:
|
||||
@@ -55,19 +57,35 @@ 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.
|
||||
Read the art bible's Asset Standards section (`design/art/art-bible.md`) and any
|
||||
asset standards in the relevant design docs — size budgets and format rules come
|
||||
from there. The naming patterns are the ones in Phase 3 below, unless the art
|
||||
bible states its own.
|
||||
|
||||
If neither states a size budget — or there is no art bible — the Size section is
|
||||
`NOT ASSESSED — no size budget set`, and the report names `/art-bible`, whose
|
||||
Asset Standards section sets budgets, formats and the naming convention.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Scan Asset Directories
|
||||
|
||||
Scan the target asset directory using Glob:
|
||||
Assets live under the engine's asset root: `assets/` on Godot, `Assets/` on
|
||||
Unity, `Content/` on Unreal. Resolve the engine and its code root per
|
||||
`.claude/docs/code-root-resolution.md`; that code root is the one Phase 3's
|
||||
orphan and missing-asset searches read. If it is unresolved, stop:
|
||||
`NOT ASSESSED — engine unresolved`, naming `/setup-engine`.
|
||||
|
||||
- `assets/art/**/*` for art assets
|
||||
- `assets/audio/**/*` for audio assets
|
||||
- `assets/vfx/**/*` for VFX assets
|
||||
- `assets/shaders/**/*` for shaders
|
||||
- `assets/data/**/*` for data files
|
||||
Scan the asset root using Glob:
|
||||
|
||||
- **Godot** — `assets/art/**/*`, `assets/audio/**/*`, `assets/vfx/**/*`,
|
||||
`assets/shaders/**/*`, `assets/data/**/*`
|
||||
- **Unity** — `Assets/**/*`, leaving out scripts (`*.cs`, `*.asmdef`) and `*.meta` files
|
||||
- **Unreal** — `Content/**/*.uasset` and `Content/**/*.umap`
|
||||
|
||||
The files matched are `Total assets scanned`. If there are none, the checks on
|
||||
scanned files — Naming, Size, Format, Orphaned — are
|
||||
`NOT ASSESSED — no assets under <asset root>`; the missing-asset search still runs.
|
||||
|
||||
---
|
||||
|
||||
@@ -78,14 +96,29 @@ Scan the target asset directory using Glob:
|
||||
- Audio: `[category]_[context]_[name]_[variant].[ext]`
|
||||
- All files must be lowercase with underscores
|
||||
|
||||
These are Godot's conventions. Unity and Unreal name assets in PascalCase, so on
|
||||
those engines check names only against a naming rule the art bible states; with
|
||||
none, Naming is `NOT ASSESSED — no naming rule for <engine>` (name `/art-bible`).
|
||||
|
||||
**File standards:**
|
||||
- Textures: Power-of-two dimensions, correct format (PNG for UI, compressed for 3D), within size budget
|
||||
- Audio: Correct sample rate, format (OGG for SFX, OGG/MP3 for music), within duration limits
|
||||
- Audio: Correct sample rate, format (OGG for SFX, OGG/MP3 for music), within duration limits.
|
||||
`file` reports an audio file's format and sample rate but not its length, and no
|
||||
pre-approved tool here does; a duration budget is therefore
|
||||
`NOT ASSESSED — duration not measurable here`, naming the files it covers.
|
||||
- Data: Valid JSON/YAML, schema-compliant
|
||||
|
||||
**Orphaned assets:** Search code for references to each asset file. Flag any with no references.
|
||||
On Unreal an asset file (`.uasset`, `.umap`) does not keep its source file's
|
||||
format or dimensions, so Format is `NOT ASSESSED` there; its size is still measured.
|
||||
|
||||
**Missing assets:** Search code for asset references and verify the files exist.
|
||||
**Orphaned assets:** Search the code root for references to each asset file. Flag any with no references.
|
||||
|
||||
**Missing assets:** Search the code root for asset references and verify the files exist.
|
||||
|
||||
Both searches need code: if the code root holds no source files, Orphaned and
|
||||
Missing are `NOT ASSESSED — no code to search`. On Unity and Unreal most asset
|
||||
references live in scenes, prefabs and other assets rather than code, so an
|
||||
asset no code names may still be in use: Orphaned is `NOT ASSESSED` there.
|
||||
|
||||
---
|
||||
|
||||
@@ -101,7 +134,7 @@ Scan the target asset directory using Glob:
|
||||
- **Format violations**: [N]
|
||||
- **Orphaned assets**: [N]
|
||||
- **Missing assets**: [N]
|
||||
- **Overall health**: [NOT ASSESSED / CLEAN / MINOR ISSUES / NEEDS ATTENTION]
|
||||
- **Sections not assessed**: [none | each section and why]
|
||||
|
||||
## Naming Violations
|
||||
| File | Expected Pattern | Issue |
|
||||
@@ -124,17 +157,29 @@ Scan the target asset directory using Glob:
|
||||
|-------------------|---------------|
|
||||
|
||||
## Recommendations
|
||||
[Prioritized list of fixes]
|
||||
[Prioritized list of fixes, one per violation, each naming the change — the
|
||||
target resolution or compression for a size violation, the corrected name for a
|
||||
naming violation, the target format for a format violation]
|
||||
|
||||
## Verdict: [NOT ASSESSED / COMPLIANT / WARNINGS / NON-COMPLIANT]
|
||||
```
|
||||
|
||||
Choose the verdict by the findings, first match wins:
|
||||
- **NON-COMPLIANT** — any size violation, or any asset that code references but that does not exist
|
||||
- **WARNINGS** — only naming, format or orphaned-asset findings
|
||||
- **NOT ASSESSED** — the audit did not cover its scope: no data at all (the path
|
||||
above), zero assets scanned, or any section `NOT ASSESSED` — name which. It
|
||||
ranks below the two finding verdicts, because a measured violation is more
|
||||
actionable than a gap, and above COMPLIANT
|
||||
- **COMPLIANT** — at least one asset scanned, every section assessed, no findings
|
||||
|
||||
This skill is read-only — it produces a report but does not write files.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Next Steps
|
||||
|
||||
- Fix naming violations using the patterns defined in CLAUDE.md.
|
||||
- Fix naming violations using the Phase 3 patterns (or the art bible's, where it states its own).
|
||||
- If standards were missing, run `/art-bible` to write its Asset Standards section.
|
||||
- Delete confirmed orphaned assets after manual review.
|
||||
- Run `/content-audit` to cross-check asset counts against GDD-specified requirements.
|
||||
|
||||
@@ -118,7 +118,8 @@ Write the file:
|
||||
After writing, tell the user:
|
||||
> "Entity inventory saved. Next steps:
|
||||
> - Run `/ux-design [screen name]` for each UI screen in the inventory
|
||||
> - Run `/asset-spec entity:[name]` to spec each visual entity
|
||||
> - Run `/asset-spec system:[name]`, `level:[name]` or `character:[name]` for each
|
||||
> visual entity — whichever of the three the entity belongs to
|
||||
> - Or run `/asset-spec` again to work through the inventory one item at a time"
|
||||
|
||||
---
|
||||
@@ -131,8 +132,9 @@ Extract:
|
||||
- **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
|
||||
`resolve_config --keys review_mode`, which applies the full chain; with nothing
|
||||
set it follows `modes.rigor` — `solo` at `minimal` (the default), `lean` at
|
||||
`standard`, `full` at `full`. A `--review` argument overrides it for this
|
||||
run only.
|
||||
|
||||
**Mode behavior:**
|
||||
@@ -149,6 +151,18 @@ 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."
|
||||
|
||||
**Exception — the minimal path.** If there is no art bible but
|
||||
`design/game-brief.md` exists (at `rigor: minimal` no art bible is required),
|
||||
do not fail: anchor the specs in the brief's **Art & audio direction** line,
|
||||
and say so at the top of the output — "Anchored to the brief's one-line art
|
||||
direction; there is no art bible, so colour, shape and asset-standard rules
|
||||
below are proposals, not constraints." Offer `/art-bible` once, as optional.
|
||||
The written spec follows the same anchor: its header reads
|
||||
`> **Art direction**: design/game-brief.md (Art & audio direction) — no art bible`
|
||||
in place of the `> **Art Bible**:` line, each asset carries
|
||||
`**Brief anchor:** [the brief line applied]` in place of the **Art Bible
|
||||
Anchors** block, and no spec cites an Art Bible section or §8 tier.
|
||||
Extract: Visual Identity Statement, Color System (semantic colors), Shape Language, Asset Standards (art bible Section 8 — dimensions, formats, polycount budgets, texture resolution tiers).
|
||||
|
||||
- **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.
|
||||
@@ -165,6 +179,7 @@ Read all source material **before** asking the user anything.
|
||||
- If [A]: the user's description becomes the source. Brief answers produce concise specs; detailed answers produce detailed specs. Accept whatever level of detail the user provides and work from it.
|
||||
|
||||
### Optional reads:
|
||||
- **This target's existing spec**: if `design/assets/specs/[target-name]-assets.md` exists, read it — this is a re-run, and Phase 2 proposes only what is new or changed since (Phase 5 updates the file in place).
|
||||
- **Existing manifest**: Read `design/assets/asset-manifest.md` if it exists — extract already-specced assets for this target to avoid duplicates.
|
||||
- **Related specs**: Glob `design/assets/specs/*.md` — scan for assets that could be shared (e.g., a common UI element specced for one system might apply here too).
|
||||
|
||||
@@ -222,6 +237,12 @@ Spawn specialist agents based on review mode. **Issue all `Agent` calls simultan
|
||||
|
||||
### Solo mode — skip both. Derive specs from art bible rules alone, noting that technical constraints were not validated.
|
||||
|
||||
**Announce every skipped agent by name in the output**, before the specs:
|
||||
"technical-artist skipped — Lean mode: technical constraints not validated." /
|
||||
"art-director and technical-artist skipped — Solo mode: specs derived in this
|
||||
session; technical constraints not validated." A spec drafted without an agent
|
||||
must not read like one an agent reviewed.
|
||||
|
||||
**Collect both responses before Phase 4.** If any conflict exists between art-director and technical-artist (e.g., art-director specifies 4K textures but technical-artist flags the engine budget requires 512px), surface it explicitly — do NOT silently resolve.
|
||||
|
||||
---
|
||||
@@ -269,6 +290,12 @@ If [C]: ask what direction to change. Re-spawn the relevant agent with the updat
|
||||
|
||||
After approval, ask: "May I write the spec to `design/assets/specs/[target-name]-assets.md`?"
|
||||
|
||||
**If that file already exists** (a re-run for the same target), update it in
|
||||
place — never overwrite it wholesale. Keep its existing `ASSET-NNN` blocks and
|
||||
IDs, apply only the changes the user approved, and append new assets with the
|
||||
next project-wide IDs. Show what changes, then ask "May I update
|
||||
`design/assets/specs/[target-name]-assets.md`?" instead of "May I write".
|
||||
|
||||
Write the file with:
|
||||
|
||||
```markdown
|
||||
@@ -303,7 +330,7 @@ Then update `design/assets/asset-manifest.md`. If it doesn't exist, create it:
|
||||
| ASSET-001 | [name] | [category] | Needed | design/assets/specs/[target]-assets.md |
|
||||
```
|
||||
|
||||
If the manifest already exists, append the new context block and update the Progress Summary counts.
|
||||
If the manifest already exists, append the new context block — on a re-run for this target, add the new rows to its existing block instead of appending a second one — and update the Progress Summary counts.
|
||||
|
||||
Ask: "May I update `design/assets/asset-manifest.md`?"
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ the two happened — a reader cannot tell from a green result.
|
||||
|
||||
## Phase 1: Identify Balance Domain
|
||||
|
||||
Determine the balance domain from `$ARGUMENTS[0]`:
|
||||
Determine the balance domain from `$ARGUMENTS` — the whole string, since a data-file path may contain spaces:
|
||||
|
||||
- **Combat** → weapon/ability DPS, time-to-kill, damage type interactions
|
||||
- **Economy** → resource faucets/sinks, acquisition rates, item pricing
|
||||
@@ -85,11 +85,24 @@ Then read the GDD for the system from `design/gdd/` to understand intended desig
|
||||
targets, tuning knobs, and expected value ranges — for anything the registry did
|
||||
not already supply. This is the baseline for "correct" behaviour.
|
||||
|
||||
If the data files are FOUND but neither source gives targets for this domain,
|
||||
the sections that judge against targets (Outliers Detected, and Progression
|
||||
Analysis where the domain has a curve) are `NOT ASSESSED — NO DATA`. Each one names what was missing — the
|
||||
GDD it looked for in `design/gdd/`, and whether the registry was absent or empty
|
||||
— and names `/design-system`, which writes both.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Perform Analysis
|
||||
|
||||
Run domain-specific checks:
|
||||
**Every domain: compare each value with its target.** For each named value in the
|
||||
data files, take its target from Phase 3 — a registry constant's `value`, a
|
||||
registry formula's `output_range`, or the range the GDD states — and compare. A
|
||||
value outside its target is a row in Outliers Detected (`player_damage_base` 140
|
||||
against 90–110). A value with no target anywhere is neither in range nor an
|
||||
outlier: list it under Values That Need Attention as `no stated range — not judged`.
|
||||
|
||||
Then run domain-specific checks:
|
||||
|
||||
**Combat balance:**
|
||||
- Calculate DPS for all weapons/abilities at each power tier
|
||||
@@ -148,6 +161,19 @@ Run domain-specific checks:
|
||||
[Specific values with suggested adjustments and rationale]
|
||||
```
|
||||
|
||||
Choose the Health Summary by the worst finding, first match wins:
|
||||
- **CRITICAL ISSUES** — a degenerate strategy (one choice dominates every
|
||||
alternative), a progression that stalls or cannot be completed, or an economy
|
||||
loop with no sink
|
||||
- **CONCERNS** — outliers or curve problems a tuning pass can fix, with no
|
||||
finding of the critical kind
|
||||
- **NOT ASSESSED** — nothing to analyze (the no-data path above), a section that
|
||||
needs targets is `NOT ASSESSED — NO DATA`, or a value had no stated range to
|
||||
judge it against; name which. It ranks below the two finding verdicts, because
|
||||
a measured problem is more actionable than a gap, and above HEALTHY
|
||||
- **HEALTHY** — every value judged against a stated target, no outliers, no
|
||||
degenerate strategies, progression within the stated targets
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Fix & Verify Cycle
|
||||
|
||||
@@ -22,8 +22,8 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
**`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` =
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = pillar bullets + concept bullets;
|
||||
`balanced` = pillars + concept with brief rationale (`rigor: standard`); `thorough` =
|
||||
pillars + concept + extensive rationale + alternatives. Apply it to every section
|
||||
you author.
|
||||
|
||||
@@ -44,7 +44,7 @@ The `workflow` tier resolved above governs this skill's output:
|
||||
|
||||
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-page template `.claude/docs/templates/game-brief.md` (6 required fields + 3
|
||||
one-liners). If `design/game-brief.md` already exists, read it and resume/refine
|
||||
rather than restart.
|
||||
|
||||
@@ -54,12 +54,15 @@ rather than restart.
|
||||
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.
|
||||
- **Player goal & fail state** — what the player is trying to do, and how they
|
||||
lose or fail. `/create-stories` turns it into each story's acceptance criteria.
|
||||
- **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).
|
||||
- **Who it's for / what they feel**, **Art & audio direction** and **Reference
|
||||
game** (the shipped game it is closest to, and the ~10% of it the MVP keeps) —
|
||||
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
|
||||
@@ -301,13 +304,13 @@ revision and lock them in without a second confirmation round.
|
||||
- **`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`:
|
||||
Collect both verdicts. When CD-PILLARS returns APPROVE, present them together using a two-tab `AskUserQuestion`:
|
||||
- Tab **"Pillars"**: present creative-director feedback. Options mirror the standard CD-PILLARS handling — `Lock in as-is` / `Revise [specific pillar]` / `Discuss further`.
|
||||
- Tab **"Visual anchor"**: present the art-director's 2-3 named visual direction options. Options: each named direction (one per option) + `Combine elements across directions` + `Describe my own direction`.
|
||||
- Tab **"Visual anchor"**: present the art-director's 2-3 named visual direction options. Options: each named direction (one per option) + `Combine elements across directions` + `Describe my own direction`. On **STRONG**, mark the dominant direction `(Recommended)`. On **CONCERNS** (the pillars do not yet differentiate a visual identity), show the art-director's reason instead of directions and offer `Revise pillars` / `Describe my own direction`.
|
||||
|
||||
The user's selected visual anchor (the named direction or their custom description) is stored as the **Visual Identity Anchor** — it will be written into the game-concept document and becomes the foundation of the art bible.
|
||||
|
||||
If the creative-director returns CONCERNS or REJECT on pillars, resolve pillar issues before asking for the visual anchor selection — visual direction should flow from confirmed pillars.
|
||||
If the creative-director returns CONCERNS or REJECT on pillars, resolve pillar issues before asking for the visual anchor selection — visual direction should flow from confirmed pillars. Ask the Pillars question on its own first (same options, no Visual anchor tab); once the pillars are resolved, ask the Visual anchor question on its own. **NOT ASSESSED** from either gate (it lacked an input — `.claude/docs/director-gates.md`) is not an approval: name what was missing, and supply it and re-run that gate; failing that, treat a CD-PILLARS NOT ASSESSED like CONCERNS, and with no art-director directions offer only `Describe my own direction`.
|
||||
|
||||
---
|
||||
|
||||
@@ -361,7 +364,7 @@ Ground the concept in reality:
|
||||
|
||||
Pass: core loop description, platform target, engine choice (or "undecided"), list of identified technical risks.
|
||||
|
||||
Present the assessment to the user. If HIGH RISK, offer to revisit scope before finalising. If CONCERNS, note them and continue.
|
||||
Present the assessment to the user. If HIGH RISK, offer to revisit scope before finalising. If CONCERNS, note them and continue. If NOT ASSESSED, name the missing input and record feasibility as not assessed in the concept's risks — never as VIABLE.
|
||||
|
||||
**Review mode check** — apply before spawning PR-SCOPE:
|
||||
- `solo` → skip. Note: "PR-SCOPE skipped — Solo mode." Proceed to document generation.
|
||||
@@ -370,9 +373,15 @@ Present the assessment to the user. If HIGH RISK, offer to revisit scope before
|
||||
|
||||
**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.
|
||||
Pass: full vision scope, MVP definition, the scope tiers (what ships if time runs out), timeline estimate, team size.
|
||||
|
||||
Present the assessment to the user. If UNREALISTIC, offer to adjust the MVP definition or scope tiers before writing the document.
|
||||
Present the assessment to the user. PR-SCOPE answers REALISTIC / OPTIMISTIC /
|
||||
UNREALISTIC. If UNREALISTIC, ask via `AskUserQuestion` whether to adjust the MVP
|
||||
definition or scope tiers before writing the document or keep them — the user
|
||||
decides; the concept is never rejected for it. If OPTIMISTIC, show the
|
||||
producer's suggested adjustments and ask whether to apply them before writing. If NOT ASSESSED, name
|
||||
the missing input (a timeline or team size, say) and ask for it and re-run the
|
||||
gate, or record scope as not assessed — never as REALISTIC.
|
||||
|
||||
---
|
||||
|
||||
@@ -459,4 +468,4 @@ After the game concept is written, follow the pre-production pipeline in order:
|
||||
4. `/design-system [first-system]` — author per-system GDDs in dependency order
|
||||
5. `/create-architecture` — produce the master architecture blueprint
|
||||
6. `/architecture-review` — bootstrap TR registry and Requirements Traceability Matrix
|
||||
7. `/gate-check pre-production` — validate readiness before committing to production
|
||||
7. `/gate-check pre-production` — validate readiness for Pre-Production (the `systems-design` and `technical-setup` gates come first, at their own phase boundaries)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: bug-report
|
||||
description: "Structured bug report from a description, or analyze code for potential bugs. Reproduction steps, severity."
|
||||
argument-hint: "[description] | analyze [path-to-file]"
|
||||
argument-hint: "[description] | analyze [path-to-file] | verify [BUG-ID] | close [BUG-ID]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, Bash(bash "*/.claude/skills/bug-report/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Bash, Write, Edit, AskUserQuestion, Bash(bash "*/.claude/skills/bug-report/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -42,22 +42,15 @@ If no argument is provided, ask the user for a bug description before proceeding
|
||||
## Summary
|
||||
**Title**: [Concise, descriptive title]
|
||||
**ID**: BUG-[NNNN]
|
||||
**Severity**: [S1-Critical / S2-Major / S3-Minor / S4-Trivial]
|
||||
**Severity**: [S1-Critical / S2-High / S3-Medium / S4-Low]
|
||||
**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]
|
||||
**Reporter**: [the reporter's name as the user gives it, else `—`; never an email address or account ID taken from the session]
|
||||
|
||||
## Classification
|
||||
- **Category**: [Gameplay / UI / Audio / Visual / Performance / Crash / Network]
|
||||
- **System**: [Which game system is affected]
|
||||
- **System**: [Which game system is affected — when the bug spans systems, the one whose code must change; the others go under Related systems]
|
||||
- **Frequency**: [Always / Often (>50%) / Sometimes (10-50%) / Rare (<10%)]
|
||||
- **Regression**: [Yes/No/Unknown -- was this working before?]
|
||||
|
||||
@@ -93,6 +86,11 @@ If no argument is provided, ask the user for a bug description before proceeding
|
||||
[Any additional context or observations]
|
||||
```
|
||||
|
||||
The **Severity** and **Priority** labels use `/bug-triage`'s S and P numbers and
|
||||
names, which it parses out of this file. `P4-Won't fix` is its `P4 — Won't fix /
|
||||
Deferred` (an accepted risk), not a wishlist. If you change either ladder, change
|
||||
`.claude/skills/bug-triage/SKILL.md` too.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2B: Analyze Mode
|
||||
@@ -107,19 +105,29 @@ If no argument is provided, ask the user for a bug description before proceeding
|
||||
|
||||
## Phase 2C: Verify Mode
|
||||
|
||||
Read `production/qa/bugs/[BUG-ID].md`. Extract the reproduction steps and expected result.
|
||||
**Find the bug file by its number**, here and in close mode: Glob
|
||||
`production/qa/bugs/BUG-*.md` and take the file whose number matches `[BUG-ID]`,
|
||||
whatever its zero-padding — an older three-digit file with a slug is found by
|
||||
its number too. If none
|
||||
matches, stop: "No bug [BUG-ID] in `production/qa/bugs/`." Verdict: **BLOCKED**
|
||||
— no such bug.
|
||||
|
||||
Read that file. Extract the reproduction steps and expected result.
|
||||
|
||||
1. **Re-run reproduction steps** — use Grep/Glob to check whether the root cause code path still exists as described. If the fix removed or changed it, note the change.
|
||||
2. **Run the related test** — if the bug's system has a test file in `tests/`, run it via Bash and report pass/fail.
|
||||
2. **Run the related test** — if the bug's system has a test file in the engine's test root (`tests/` Godot, `Assets/Tests/` Unity, `Source/<Module>/Private/Tests/` Unreal — `.claude/docs/directory-structure.md`), run it via Bash with `commands.test` from `project.yaml`, narrowed to the affected suite where the runner allows — never a runner line written from memory, which drops the flags the engine needs (gdUnit4 hangs without `--remote-debug tcp://127.0.0.1:0`) — and report pass/fail. `commands.test` unset → no test ran: name the unset key and go on to step 3.
|
||||
3. **Check for regression** — grep the codebase for any new occurrence of the pattern that caused the bug.
|
||||
4. **Manual verification** — when no related test ran (none covers the bug — the usual case where `qa.level` waives tests — `commands.test` is unset, or the run did not complete), or the bug's Category is Visual or UI, whose look no automated test checks, ask via `AskUserQuestion`: "Did you play the reproduction steps in [bug file] on a build with the fix? Which build?" —
|
||||
`[No longer occurs]` / `[Still occurs]` / `[Not played yet]`.
|
||||
Record the answer and the build as the user gives them; a changed code path is never taken as their answer.
|
||||
|
||||
Produce a verification verdict:
|
||||
|
||||
- **VERIFIED FIXED** — reproduction steps no longer produce the bug; related tests pass
|
||||
- **STILL PRESENT** — bug reproduces as described; fix did not resolve the issue
|
||||
- **CANNOT VERIFY** — automated checks inconclusive; manual playtest required
|
||||
- **VERIFIED FIXED** — the bug is gone by every check that applies: any related test ran and passed, and, where step 4 asked, the user answered `[No longer occurs]` for a named build. With no test run, that play alone is the verification — a manual one, recorded as such: `[user], manual, build [X]`. A changed code path on its own is never a pass
|
||||
- **STILL PRESENT** — a related test fails on the bug's case, or the user answered `[Still occurs]`; the fix did not resolve the issue
|
||||
- **CANNOT VERIFY** — step 4 was answered `[Not played yet]`: name what is missing or could not run (no related test, `commands.test` unset, a run that did not complete, a Visual or UI bug), and say that playing the reproduction steps settles it — run `/bug-report verify [BUG-ID]` again once played
|
||||
|
||||
Ask: "May I update `production/qa/bugs/[BUG-ID].md` to set Status: Verified Fixed / Still Present / Cannot Verify?"
|
||||
Ask: "May I update `production/qa/bugs/[bug file]` to set Status: Verified Fixed / Still Present / Cannot Verify?" — naming the file found above, whatever its padding or slug. With the Status, write a `**Verified by**:` line under it: `[test file(s)] — ran and passed`, or `[user], manual, build [X]` for a manual verification.
|
||||
|
||||
If STILL PRESENT: reopen the bug, set Status back to Open, and suggest re-running `/hotfix [BUG-ID]`.
|
||||
|
||||
@@ -127,24 +135,24 @@ If STILL PRESENT: reopen the bug, set Status back to Open, and suggest re-runnin
|
||||
|
||||
## Phase 2D: Close Mode
|
||||
|
||||
Read `production/qa/bugs/[BUG-ID].md`. Confirm Status is `Verified Fixed` before closing. If status is anything else, stop: "Bug [ID] must be Verified Fixed before it can be closed. Run `/bug-report verify [BUG-ID]` first."
|
||||
Read the bug file, found by its number as in verify mode. Confirm Status is `Verified Fixed` before closing. If status is anything else, stop: "Bug [ID] must be Verified Fixed before it can be closed. Run `/bug-report verify [BUG-ID]` first."
|
||||
|
||||
Append a closure record to the bug file:
|
||||
Show the closure record below and the Status change, then ask: "May I update `production/qa/bugs/[bug file]` to mark it Closed?" Nothing is written before a yes; on no, stop — the bug stays Verified Fixed.
|
||||
|
||||
On yes, append the closure record to the bug file:
|
||||
|
||||
```markdown
|
||||
## Closure Record
|
||||
**Closed**: [date]
|
||||
**Resolution**: Fixed — [one-line description of what was changed]
|
||||
**Fix commit / PR**: [if known]
|
||||
**Verified by**: qa-tester
|
||||
**Verified by**: [the verify record's `**Verified by**:` line — the test that ran and passed, or "[user], manual, build [X]"]
|
||||
**Closed by**: [user]
|
||||
**Regression test**: [test file path, or "Manual verification"]
|
||||
**Regression test**: [test file path, or "Manual verification" when verify recorded a manual play]
|
||||
**Status**: Closed
|
||||
```
|
||||
|
||||
Update the top-level `**Status**: Open` field to `**Status**: Closed`.
|
||||
|
||||
Ask: "May I update `production/qa/bugs/[BUG-ID].md` to mark it Closed?"
|
||||
Then update the top-level `**Status**:` field to `**Status**: Closed`.
|
||||
|
||||
After closing, check `production/qa/bug-triage-*.md` — if the bug appears in an open triage report, note: "Bug [ID] is referenced in the triage report. Run `/bug-triage` to refresh the open bug count."
|
||||
|
||||
@@ -154,7 +162,14 @@ After closing, check `production/qa/bug-triage-*.md` — if the bug appears in a
|
||||
|
||||
Present the completed bug report(s) to the user.
|
||||
|
||||
Ask: "May I write this to `production/qa/bugs/BUG-[NNNN].md`?"
|
||||
**Allocate the ID** before asking: Glob `production/qa/bugs/BUG-*.md`, take the
|
||||
highest number and add 1, zero-padded to four digits (`BUG-0001` when there are
|
||||
none). Several reports in one run (analyze mode) take consecutive IDs from
|
||||
there, one each — never the same ID twice.
|
||||
|
||||
Ask: "May I write this to `production/qa/bugs/BUG-[NNNN].md`?" For several
|
||||
reports, ask once and name every file: "May I write these to
|
||||
`production/qa/bugs/BUG-[NNNN].md`, `production/qa/bugs/BUG-[NNNN+1].md`, …?"
|
||||
|
||||
If yes, write the file, creating the directory if needed. Verdict: **COMPLETE** — bug report filed.
|
||||
|
||||
@@ -174,6 +189,9 @@ After saving, suggest based on mode:
|
||||
- Run `/bug-report verify [BUG-ID]` — confirm the fix actually works before closing
|
||||
- Never mark a bug closed without verification — a fix that doesn't verify is still Open
|
||||
|
||||
**After verify returns CANNOT VERIFY:**
|
||||
- Play the reproduction steps on a build with the fix, then run `/bug-report verify [BUG-ID]` again and answer its question
|
||||
|
||||
**After verify returns VERIFIED FIXED:**
|
||||
- Run `/bug-report close [BUG-ID]` — write the closure record and update status
|
||||
- Run `/bug-triage` to refresh the open bug count and remove it from the active list
|
||||
|
||||
@@ -56,7 +56,7 @@ If no bug files found:
|
||||
> different location, adjust the glob pattern. If no bugs exist yet, there is
|
||||
> nothing to triage."
|
||||
|
||||
Stop and report. Do not proceed if no bugs exist.
|
||||
Stop and report. Do not proceed if no bugs exist. Verdict: **COMPLETE** — no bug files in `production/qa/bugs/`; nothing to triage.
|
||||
|
||||
**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:
|
||||
@@ -185,7 +185,7 @@ After classifying all bugs, generate trend metrics:
|
||||
|
||||
| ID | System | Severity | Summary | Assigned to | Story |
|
||||
|----|--------|----------|---------|-------------|-------|
|
||||
| BUG-NNN | [system] | S[1-4] | [one-line description] | [sprint] | [story path] |
|
||||
| BUG-NNNN | [system] | S[1-4] | [one-line description] | [sprint] | [story path] |
|
||||
|
||||
---
|
||||
|
||||
@@ -193,7 +193,7 @@ After classifying all bugs, generate trend metrics:
|
||||
|
||||
| ID | System | Severity | Summary | Target Sprint |
|
||||
|----|--------|----------|---------|---------------|
|
||||
| BUG-NNN | [system] | S[1-4] | [one-line description] | Sprint [N+1] |
|
||||
| BUG-NNNN | [system] | S[1-4] | [one-line description] | Sprint [N+1] |
|
||||
|
||||
---
|
||||
|
||||
@@ -201,7 +201,7 @@ After classifying all bugs, generate trend metrics:
|
||||
|
||||
| ID | System | Severity | Summary | Disposition |
|
||||
|----|--------|----------|---------|-------------|
|
||||
| BUG-NNN | [system] | S4 | [one-line description] | Backlog |
|
||||
| BUG-NNNN | [system] | S4 | [one-line description] | Backlog |
|
||||
|
||||
---
|
||||
|
||||
@@ -235,7 +235,9 @@ After classifying all bugs, generate trend metrics:
|
||||
|
||||
## 6. Write and Gate
|
||||
|
||||
Present the report in conversation, then ask:
|
||||
Present the report in conversation. If any bug is a P4 candidate, first ask
|
||||
"Are these acceptable as Won't Fix?" and keep its disposition `P4 candidate`
|
||||
until the user answers. Then ask:
|
||||
|
||||
"May I write this triage report to `production/qa/bug-triage-[date].md`?"
|
||||
|
||||
@@ -246,7 +248,9 @@ After writing:
|
||||
can be considered healthy. Run `/sprint-status` to see current capacity."
|
||||
- If regression bugs exist: "Regressions found — consider re-opening the
|
||||
affected stories in sprint tracking and running `/smoke-check` to re-gate."
|
||||
- If no P1 bugs exist: "No P1 bugs — build is in good shape for QA hand-off." Verdict: **COMPLETE** — triage report written.
|
||||
- If no P1 bugs exist: "No P1 bugs — build is in good shape for QA hand-off."
|
||||
|
||||
Then, whether or not P1 bugs exist: Verdict: **COMPLETE** — triage report written.
|
||||
|
||||
If user declined write: Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ Recent tags (newest first):
|
||||
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.
|
||||
1. Read the injected commit subjects above. **If there are none — the log is
|
||||
empty or git is unavailable — skip this check**: there is nothing to
|
||||
classify, and Phase 1's no-history branch is the right stop.
|
||||
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**
|
||||
@@ -53,14 +55,18 @@ check governs is whether that output is usable, not whether it is fetched.
|
||||
> 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.
|
||||
`design/` and the code root (`src/`, `Assets/` or `Source/`) 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
|
||||
> "The git history in this repo does not appear to belong to [game]: 0 of the [N]
|
||||
> recent commits are Game commits. 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."
|
||||
|
||||
Verdict: **BLOCKED** — stop here without generating a changelog.
|
||||
|
||||
**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
|
||||
@@ -85,6 +91,13 @@ Read the argument for the target version or sprint number. If a version is given
|
||||
|
||||
Verify the repository is initialized: run `git rev-parse --is-inside-work-tree` to confirm git is available. If not a git repo, inform the user and abort gracefully.
|
||||
|
||||
**If there is no history to read** — not a git repository, or no commits yet:
|
||||
|
||||
> "No git history found. A changelog is built from commits — commit the work
|
||||
> first, or supply the change list directly."
|
||||
|
||||
Verdict: **BLOCKED** — stop here without generating a changelog.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Gather Change Data
|
||||
@@ -115,6 +128,7 @@ Categorize every change into one of these categories:
|
||||
- **Improvements**: Enhancements to existing features, UX improvements, performance gains
|
||||
- **Bug Fixes**: Corrections to broken behavior
|
||||
- **Balance Changes**: Tuning of gameplay values, difficulty, economy
|
||||
- **Technical Debt / Refactoring**: Refactors and cleanup of the game's code that change nothing the player sees — a commit that says it refactors, cleans up or tidies, and names no fix, feature or tuning. Internal changelog only; never in the player-facing one
|
||||
- **Known Issues**: Issues the team is aware of but have not yet resolved
|
||||
- **Miscellaneous**: Changes that do not fit the above categories, or commits whose messages are too vague to classify confidently
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: code-review
|
||||
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, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/code-review/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Bash(git log *), Agent, AskUserQuestion, Bash(bash "*/.claude/skills/code-review/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -68,28 +68,32 @@ 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.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: ADR Compliance Check
|
||||
|
||||
**Argument:** `/code-review [file(s)]` may optionally include a story file path as the last argument (e.g., `/code-review src/combat/attack.gd production/epics/combat/story-001.md`). If a story path is provided, read it to extract the governing ADR reference.
|
||||
**Argument:** `/code-review [file(s)]` may optionally include a story file path as the last argument (e.g., `/code-review Assets/Scripts/Combat/Attack.cs production/epics/combat/story-001.md`). If a story path is provided, read it to extract the governing ADR reference.
|
||||
|
||||
Search for ADR references in, in priority order:
|
||||
1. The story file (if provided as argument)
|
||||
2. Header comments at the top of the implementation files
|
||||
3. Commit messages referencing these files (`git log --oneline -- [file]`)
|
||||
|
||||
Look for patterns like `ADR-NNN` or `docs/architecture/ADR-`.
|
||||
Look for patterns like `ADR-NNNN` or `docs/architecture/adr-` (either case).
|
||||
|
||||
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, 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`:
|
||||
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. 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.
|
||||
|
||||
A referenced ADR whose file is missing, or that cannot be read, makes ADR
|
||||
Compliance `NOT ASSESSED — [ADR] could not be read`: name it. No reference at
|
||||
all is `NO ADRS FOUND`, a different result.
|
||||
|
||||
From those two sections, classify any deviation:
|
||||
|
||||
- **ARCHITECTURAL VIOLATION** (BLOCKING): Uses a pattern explicitly rejected in the ADR
|
||||
@@ -155,7 +159,7 @@ Spawn all applicable specialists simultaneously via `Agent` — do not wait for
|
||||
> 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
|
||||
> diagnosing existing code. 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
|
||||
@@ -201,7 +205,7 @@ Collect all specialist findings before producing output.
|
||||
### Engine Specialist Findings: [N/A — no engine configured / CLEAN / ISSUES FOUND]
|
||||
[Findings from engine specialist(s), or "No engine configured." if skipped]
|
||||
|
||||
### Testability: [N/A — Visual/Feel or Config story / TESTABLE / GAPS / BLOCKING]
|
||||
### Testability: [N/A — no story path given / N/A — Visual/Feel or Config story / TESTABLE / GAPS / BLOCKING]
|
||||
[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]
|
||||
|
||||
@@ -209,7 +213,7 @@ Collect all specialist findings before producing output.
|
||||
[List each ADR checked, result, and any deviations with severity]
|
||||
|
||||
### Standards Compliance: [X/6 passing]
|
||||
[List failures with line references]
|
||||
[List failures with line references; a missing doc comment names the method or class]
|
||||
|
||||
### Architecture: [NOT ASSESSED / CLEAN / MINOR ISSUES / VIOLATIONS FOUND]
|
||||
[List specific architectural concerns]
|
||||
@@ -232,6 +236,20 @@ Collect all specialist findings before producing output.
|
||||
### Verdict: [NOT ASSESSED / APPROVED / APPROVED WITH SUGGESTIONS / CHANGES REQUIRED]
|
||||
```
|
||||
|
||||
Choose the verdict, first match wins:
|
||||
- **CHANGES REQUIRED** — anything under Required Changes
|
||||
- **NOT ASSESSED** — nothing to review (the no-data path above), the engine
|
||||
specialist review did not run — no engine configured, or a specialist that
|
||||
could not be spawned — or any report section reads `NOT ASSESSED` (ADR
|
||||
Compliance with a referenced ADR that could not be read, Architecture, SOLID);
|
||||
name which. NOT ASSESSED ranks below CHANGES REQUIRED, because a known
|
||||
defect is more actionable than a skipped check, and above both approvals: a
|
||||
review that skipped the engine check has not approved the code. (`NO ADRS
|
||||
FOUND` is not NOT ASSESSED: with no ADR to check, it does not stop an
|
||||
approval.)
|
||||
- **APPROVED WITH SUGGESTIONS** — only Suggestions
|
||||
- **APPROVED** — no required changes and no suggestions
|
||||
|
||||
This skill is read-only — no files are written.
|
||||
|
||||
---
|
||||
@@ -239,15 +257,22 @@ This skill is read-only — no files are written.
|
||||
## Phase 9: Next Steps
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "Code review complete — verdict: [NOT ASSESSED / APPROVED / CHANGES REQUIRED / MAJOR REVISION]. How would you like to proceed?"
|
||||
- Prompt: "Code review complete — verdict: [NOT ASSESSED / APPROVED / APPROVED WITH SUGGESTIONS / CHANGES REQUIRED]. How would you like to proceed?" (the Phase 8 verdict, word for word)
|
||||
- Options (adjust based on verdict):
|
||||
- If APPROVED:
|
||||
- `[A] Run /story-done to mark the story complete`
|
||||
- `[B] Stop here`
|
||||
- If CHANGES REQUIRED or MAJOR REVISION:
|
||||
- If APPROVED WITH SUGGESTIONS:
|
||||
- `[A] Apply the suggestions, then run /story-done`
|
||||
- `[B] Run /story-done now — suggestions noted for later`
|
||||
- `[C] Stop here`
|
||||
- If CHANGES REQUIRED:
|
||||
- `[A] Fix the issues and re-run /code-review`
|
||||
- `[B] Run /story-done anyway with noted exceptions`
|
||||
- `[C] Stop here`
|
||||
- If NOT ASSESSED:
|
||||
- `[A] Fix what stopped the review (point me at the code, run /setup-engine, or fix the unreadable ADR reference), then re-run /code-review`
|
||||
- `[B] Stop here`
|
||||
|
||||
If an ARCHITECTURAL VIOLATION is found:
|
||||
- If the violation contradicts an **existing ADR**: fix the implementation to comply with `docs/architecture/[adr-file].md`. If the design has legitimately changed, run `/architecture-decision` to formally *revise* the existing ADR — do not create a competing one.
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion, Bash(bash "
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,system_overrides`
|
||||
|
||||
|
||||
|
||||
@@ -36,9 +36,13 @@ 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`):
|
||||
**`workflow`** (see `.claude/docs/workflow-modes.md`), applied per GDD at its
|
||||
**effective** tier — the `system_overrides` row for that GDD's system (its
|
||||
filename stem) when the block lists one, else the project value:
|
||||
- `full` — full entity-registry cross-check against all GDD sections.
|
||||
- `standard` — cross-check against the required sections only.
|
||||
- `standard` — cross-check against the required sections only. The report's
|
||||
Scope line says so, and each value stated for a registered name outside those
|
||||
sections is listed as not checked at this tier (Phase 3 applies this).
|
||||
- `minimal` — not meaningful (no GDDs to check).
|
||||
|
||||
## Phase 1: Parse Arguments and Load Registry
|
||||
@@ -59,7 +63,8 @@ If the file does not exist or has no entries:
|
||||
> "Entity registry is empty. Run `/design-system` to write GDDs — the registry
|
||||
> is populated automatically after each GDD is completed. Nothing to check yet."
|
||||
|
||||
Stop and exit.
|
||||
Verdict: **NOT ASSESSED — entity registry empty**. Stop: nothing was compared,
|
||||
so there is no PASS to give and nothing to write.
|
||||
|
||||
Build four lookup tables from the registry:
|
||||
- **entity_map**: `{ name → { source, attributes, referenced_by } }`
|
||||
@@ -73,6 +78,11 @@ Registry loaded: [N] entities, [N] items, [N] formulas, [N] constants
|
||||
Scope: [full | since-last-review | entity:name]
|
||||
```
|
||||
|
||||
For `entity:<name>` or `item:<name>`, if the registry has no entry by that name
|
||||
the verdict is **NOT ASSESSED — `<name>` is not in the registry**: list the
|
||||
closest registered names and stop. Checking an unregistered name compares
|
||||
nothing, and that is not a PASS.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Locate In-Scope GDDs
|
||||
@@ -81,8 +91,10 @@ Scope: [full | since-last-review | entity:name]
|
||||
Glob pattern="design/gdd/*.md"
|
||||
```
|
||||
|
||||
Exclude: `game-concept.md`, `systems-index.md`, `game-pillars.md` — these are
|
||||
not system GDDs.
|
||||
Exclude the docs that live in `design/gdd/` but are not system GDDs:
|
||||
`game-concept.md`, `systems-index.md`, `game-pillars.md`, `gameplay-tags.md`,
|
||||
`entity-registry.md`, `fixture-swap-ledger.md`, `sound-bible.md` and any
|
||||
`gdd-cross-review-*.md` (the report `/review-all-gdds` writes here).
|
||||
|
||||
For `since-last-review` mode:
|
||||
```bash
|
||||
@@ -91,7 +103,10 @@ git log --name-only --pretty=format: -- design/gdd/ | grep "\.md$" | sort -u
|
||||
Limit to GDDs modified since the most recent `design/gdd/gdd-cross-review-*.md`
|
||||
file's creation date.
|
||||
|
||||
Report the in-scope GDD list before scanning.
|
||||
Report the in-scope GDD list before scanning. **If the list is empty** — no system
|
||||
GDDs exist, or `since-last-review` found none changed — the verdict is
|
||||
**NOT ASSESSED — no GDDs in scope**: say which filter produced zero, and stop.
|
||||
A scan of nothing finds no conflicts, and that is not a PASS.
|
||||
|
||||
---
|
||||
|
||||
@@ -105,6 +120,19 @@ This is the core optimization: instead of reading 10 GDDs × 400 lines each
|
||||
(4,000 lines), you grep 50 entity names × 10 GDDs (50 targeted searches,
|
||||
each returning ~10 lines on a hit).
|
||||
|
||||
**In a GDD whose effective tier is `standard`, compare only hits under a
|
||||
required section.** The effective tier is per GDD: `system_overrides.<stem>`
|
||||
replaces the project tier for that GDD in either direction (a `full` row makes
|
||||
every section compared). Grep each such GDD once for `^## ` to get its headings
|
||||
and line numbers, and file every name hit under the nearest heading above it:
|
||||
only hits under Overview, Detailed Rules / Detailed Design, Formulas, Edge
|
||||
Cases, Dependencies or Acceptance Criteria are compared — plus Tuning Knobs when
|
||||
`project.yaml` sets `workflow_overrides.tuning_knobs: true` (read that flag
|
||||
once; it only ever adds the section). Any other hit (Tuning Knobs without the
|
||||
flag, Player Fantasy, any other section) raises no finding and is not logged;
|
||||
list each one that states a value (name, GDD, section) on the report's
|
||||
`Not checked at this tier` line.
|
||||
|
||||
### 3a: Entity Scan
|
||||
|
||||
For each entity in entity_map:
|
||||
@@ -193,6 +221,8 @@ For each conflict, classify:
|
||||
Date: [date]
|
||||
Registry entries checked: [N entities, N items, N formulas, N constants]
|
||||
GDDs scanned: [N] ([list names])
|
||||
Scope: [all GDD sections | required sections only — workflow: standard | per GDD — name each GDD whose effective tier differs, and its tier]
|
||||
Not checked at this tier: [each value stated outside the required sections (name, GDD, section) — or "none"; omit when every GDD is at `full`]
|
||||
|
||||
---
|
||||
|
||||
@@ -227,12 +257,15 @@ GDDs scanned: [N] ([list names])
|
||||
|
||||
---
|
||||
|
||||
Verdict: PASS | CONFLICTS FOUND
|
||||
Verdict: PASS | CONFLICTS FOUND | NOT ASSESSED
|
||||
```
|
||||
|
||||
**Verdict:**
|
||||
- **PASS** — no conflicts. Registry and GDDs agree on all checked values.
|
||||
- **CONFLICTS FOUND** — one or more conflicts detected. List resolution steps.
|
||||
- **NOT ASSESSED** — nothing was compared: the entity registry is empty or the
|
||||
named entity is not in it (Phase 1), or no GDDs were in scope (Phase 2). Say
|
||||
which.
|
||||
- **PASS** — no conflicts. Registry and GDDs agree on all checked values, across at least one GDD.
|
||||
|
||||
---
|
||||
|
||||
@@ -261,7 +294,9 @@ If conflicts remain unresolved: Verdict: **BLOCKED** — [N] conflicts need manu
|
||||
### 6b: Append to Reflexion Log
|
||||
|
||||
If any 🔴 CONFLICT entries were found (regardless of whether they were resolved),
|
||||
append an entry to `docs/consistency-failures.md` for each conflict:
|
||||
ask: "May I append [N] entries to `docs/consistency-failures.md` (creating it if
|
||||
absent)?" On yes, append an entry for each conflict; on no, say the conflicts
|
||||
were not logged.
|
||||
|
||||
```markdown
|
||||
### [YYYY-MM-DD] — /consistency-check — 🔴 CONFLICT
|
||||
@@ -285,7 +320,7 @@ If `docs/consistency-failures.md` does not exist, create it with this header bef
|
||||
|------|-------|-------|---------------|--------|
|
||||
```
|
||||
|
||||
Then append the new conflict entries. Never skip logging — a missing file is not a reason to lose conflict history.
|
||||
Then append the new conflict entries. Never skip logging on your own — a missing file is not a reason to lose conflict history; only the user's "no" is.
|
||||
|
||||
---
|
||||
|
||||
@@ -308,9 +343,8 @@ Then close with an `AskUserQuestion` widget:
|
||||
- **Prompt**: "Consistency check complete — [N] conflicts found. What next?"
|
||||
- **Options**:
|
||||
- `[A] Fix the highest-priority conflict now`
|
||||
- `[B] Save full report and stop`
|
||||
- `[C] Run /design-review on the most conflicted GDD`
|
||||
- `[D] Stop here`
|
||||
- `[B] Run /design-review on the most conflicted GDD`
|
||||
- `[C] Stop here`
|
||||
|
||||
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
|
||||
|
||||
@@ -37,7 +37,8 @@ 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.
|
||||
- `standard` — audit only specs in the required sections; list any count found
|
||||
outside them as not audited at this tier.
|
||||
- `minimal` — cannot run (no systems index exists).
|
||||
|
||||
## Insufficient input — check this before producing any report
|
||||
@@ -54,7 +55,7 @@ not a filled-in report.** Check first, and stop if the check fails.
|
||||
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.
|
||||
which skill produces it (`/map-systems` for `design/gdd/systems-index.md`, `/design-system` for the GDDs).
|
||||
|
||||
**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
|
||||
@@ -102,13 +103,10 @@ the two happened — a reader cannot tell from a green result.
|
||||
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.
|
||||
> **Keep the two scans separate.** `## Summary` matches every compliant GDD,
|
||||
> so a union with it narrows nothing, and a literal placeholder such as
|
||||
> `N enemies` matches no real GDD. 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
|
||||
@@ -117,15 +115,18 @@ the two happened — a reader cannot tell from a green result.
|
||||
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 **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.
|
||||
For a full audit: full-read the GDDs that **scan (b)** matched
|
||||
**and are not already fully covered by the registry entries from step 2**,
|
||||
plus every GDD scan (a) missed — **the fail-open rule wins over this
|
||||
narrowing**: a GDD with no `## Summary` is full-read even when scan (b) did
|
||||
not match it. Only a GDD that has a Summary and no content-count language (a
|
||||
pure mechanics GDD) is noted as "No auditable content counts" without a full
|
||||
read.
|
||||
|
||||
4. **Full-read in-scope GDD files** (or the single system GDD if a system
|
||||
name was given).
|
||||
|
||||
5. **For each GDD, extract explicit content counts or lists.** Look for patterns
|
||||
5. **For each GDD, extract explicit content counts or lists**, noting the `##` section each sits under — at `standard`, a count outside the required sections (`.claude/docs/workflow-modes.md`) goes on the "Not audited at this tier" list, never into the inventory. Look for patterns
|
||||
like:
|
||||
- "N enemies" / "enemy types:" / list of named enemies
|
||||
- "N levels" / "N areas" / "N maps" / "N stages"
|
||||
@@ -150,9 +151,23 @@ the two happened — a reader cannot tell from a green result.
|
||||
For each content type found in Phase 1, scan the relevant directories to count
|
||||
what has been implemented. Use Glob and Grep to locate files.
|
||||
|
||||
**On Unreal, content lives in `Content/`** — maps and data assets both — and the
|
||||
code root (`Source/<Module>/`) holds only C++. So on Unreal, every `assets/…` glob
|
||||
below also runs under `Content/` (`*.uasset` in place of the data extensions),
|
||||
and levels are `Content/**/*.umap`. Skipping this finds zero levels on every
|
||||
Unreal project and reports them NOT STARTED.
|
||||
|
||||
**On Unity, content lives under `Assets/`** (compare the case exactly —
|
||||
`.claude/docs/code-root-resolution.md`), and rarely in a `data/` folder. So on
|
||||
Unity every `assets/…` glob below also runs under `Assets/`, without requiring
|
||||
a `data/` segment — for items, `Assets/**/items/**`, `Assets/**/Items/**` and
|
||||
`Assets/**/*Item*.asset` — and data files include `.asset` (ScriptableObjects)
|
||||
and `.prefab`. Skipping this finds zero items, abilities, quests and dialogue
|
||||
on a Unity project and reports them NOT STARTED.
|
||||
|
||||
**Levels / Areas / Maps:**
|
||||
- Glob `assets/**/*.tscn`, `assets/**/*.unity`, `assets/**/*.umap`
|
||||
- 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.**
|
||||
- Glob the **code root** for scene files: `*.tscn` (Godot), `*.unity` (Unity); on Unreal, `Content/**/*.umap` instead (above). 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)
|
||||
@@ -215,6 +230,9 @@ Flag a system as `HIGH PRIORITY` in the report if:
|
||||
- Total content items found (sum of all Found column values)
|
||||
- Overall gap percentage: `(Specified - Found) / Specified * 100`
|
||||
|
||||
A row whose Found is `NOT ASSESSED` (code root unresolved) has no Gap or
|
||||
Status, is never `NOT STARTED`, and stays out of both totals; the summary names it.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Output
|
||||
@@ -232,7 +250,8 @@ If yes, write the file:
|
||||
- **Total specified**: [N] content items across [M] systems
|
||||
- **Total found**: [N]
|
||||
- **Gap**: [N] items ([X%] unimplemented)
|
||||
- **Scope**: [Full audit | System: name]
|
||||
- **Scope**: [Full audit | System: name] — [all GDD sections | required sections only (workflow: standard)]
|
||||
- **Not audited at this tier**: [counts found only outside the required sections — or "none"; omit at `full`]
|
||||
|
||||
> Note: Counts are approximations based on file scanning.
|
||||
> The audit cannot distinguish shipped content from editor/test assets.
|
||||
@@ -289,7 +308,13 @@ After the audit, recommend the highest-value follow-up actions:
|
||||
- If any system is `NOT STARTED` and MVP-tagged → "Run `/design-system [name]` to
|
||||
add missing content counts to the GDD before implementation begins."
|
||||
- If total gap is >50% → "Run `/sprint-plan` to allocate content work across upcoming sprints."
|
||||
- If backlog stories are needed → "Run `/create-stories [epic-slug]` for each HIGH PRIORITY gap."
|
||||
- If any system is flagged HIGH PRIORITY → "Run `/create-stories [epic-slug]` for each HIGH PRIORITY gap."
|
||||
- If `--summary` was used → "Run `/content-audit` (no flag) to write the full report to `docs/`."
|
||||
|
||||
Verdict: **COMPLETE** — content audit finished.
|
||||
Close with the verdict that matches the run:
|
||||
- Verdict: **COMPLETE** — content audit finished.
|
||||
- Verdict: **NOT ASSESSED — NO DATA** — a required input was absent (see the note at
|
||||
the top), nothing in scope gives a count (no registry entry, and every GDD is
|
||||
"Unspecified" or "No auditable content counts"), or a Found count could not be taken
|
||||
(`NOT ASSESSED — code root unresolved`); name which, and for missing counts
|
||||
name `/design-system`. Never print COMPLETE for a run that could not compute a gap.
|
||||
|
||||
@@ -3,7 +3,7 @@ name: create-architecture
|
||||
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, Agent, Bash(bash "*/.claude/skills/create-architecture/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, AskUserQuestion, Agent, Bash(bash "*/.claude/skills/create-architecture/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -32,9 +32,9 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
**`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,
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = layer diagrams + decision bullets,
|
||||
no essays; `balanced` = diagrams + paragraph explanations of layer choices
|
||||
(default); `thorough` = full prose with rationale, trade-offs, and alternatives
|
||||
(`rigor: standard`); `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`):
|
||||
@@ -207,6 +207,25 @@ Use `AskUserQuestion`:
|
||||
- `[B] Let me check the engine reference first — pause here`
|
||||
- `[C] Show me which domains are HIGH RISK and why`
|
||||
|
||||
### 0e. Existing Architecture Document
|
||||
|
||||
Glob `docs/architecture/architecture.md`. If it exists, this run updates it —
|
||||
it never replaces it unasked. Read its `## Document Status` block and its `##`
|
||||
headings, then use `AskUserQuestion`:
|
||||
- Prompt: "An architecture document already exists (v[N], [last updated]). What should this run do?"
|
||||
- Options: `[A] Update chosen sections in place` / `[B] Rewrite the whole document — replaces the existing file` / `[C] Stop`
|
||||
|
||||
On `[A]`, ask which sections. Phases 1–6 author only those and say which they
|
||||
skipped; Phase 7 replaces just those sections and raises `Version` to N+1,
|
||||
leaving every other section as it is. `[B]` runs the full walkthrough, and
|
||||
Phase 7's ask says it replaces the existing file.
|
||||
|
||||
A focus-area argument (`layers`, `data-flow`, `api-boundaries`, `adr-audit`)
|
||||
is `[A]` with that one section chosen: it runs only its phase (1, 3, 4 or 5),
|
||||
and Phase 7 writes that section. Phase 7b still runs on the updated document —
|
||||
an update is reviewed like a first draft, at the review modes that review one. With no existing document there is nothing to
|
||||
update — say so, and offer the full walkthrough instead.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: System Layer Mapping
|
||||
@@ -235,7 +254,8 @@ For each GDD system, ask:
|
||||
- What does it own exclusively? (data, state, behaviour)
|
||||
|
||||
Present the proposed layer assignment and ask for approval before proceeding to
|
||||
the next section. Write the approved layer map immediately to the skeleton file.
|
||||
the next section. Record the approved layer map in
|
||||
`production/session-state/active.md`; it goes into the document at Phase 7.
|
||||
|
||||
**Engine awareness check**: For each system assigned to the Core and Foundation
|
||||
layers, flag if it touches a HIGH or MEDIUM risk engine domain. Show the relevant
|
||||
@@ -264,7 +284,8 @@ relevant module reference doc. If an API is post-cutoff, flag it:
|
||||
Behaviour confirmed: [yes / NEEDS VERIFICATION]
|
||||
```
|
||||
|
||||
Get user approval on the ownership map before writing.
|
||||
Get user approval on the ownership map, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
|
||||
@@ -283,7 +304,8 @@ Use ASCII sequence diagrams where helpful. For each data flow:
|
||||
- State whether this is synchronous call, signal/event, or shared state
|
||||
- Flag any data flows that cross thread boundaries
|
||||
|
||||
Get user approval per scenario before writing.
|
||||
Get user approval on each scenario, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
|
||||
@@ -303,6 +325,9 @@ These become the contracts programmers implement against.
|
||||
`Node`, `Resource`, `Signal` in Godot), flag the version and verify the type
|
||||
exists and has not changed signature in the target engine version.
|
||||
|
||||
Get user approval on the API boundaries, then record them in
|
||||
`production/session-state/active.md`; they are written at Phase 7.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: ADR Audit + Traceability Check
|
||||
@@ -373,6 +398,10 @@ but don't yet. Group by priority:
|
||||
Once all sections are approved, write the complete document to
|
||||
`docs/architecture/architecture.md`.
|
||||
|
||||
In an update (Phase 0e `[A]`, or a focus-area argument), write only the chosen
|
||||
sections instead, replacing each in place with `Edit`, and raise `Version`; the
|
||||
ask below then names those sections and the version change.
|
||||
|
||||
Display a one-paragraph summary of what the document will contain (layers, modules, data flows, ADR gaps). Then use `AskUserQuestion`:
|
||||
- "All sections approved. May I write the master architecture document?"
|
||||
- [A] Yes — write to `docs/architecture/architecture.md` now
|
||||
@@ -426,14 +455,14 @@ derived from the game concept, GDDs, and technical preferences]
|
||||
|
||||
After writing the master architecture document, perform an explicit sign-off before handoff.
|
||||
|
||||
**Step 1 — Technical Director self-review** (this skill runs as technical-director):
|
||||
**Review mode check** — apply before spawning either gate:
|
||||
- `solo` → skip both. Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Solo mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `lean` → skip both (neither is a PHASE-GATE). Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Lean mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `full` → spawn both, in parallel.
|
||||
|
||||
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.
|
||||
**Step 1 — Spawn `technical-director` via `Agent` using gate TD-ARCHITECTURE (`.claude/docs/director-gates/td-architecture.md`):**
|
||||
|
||||
**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.
|
||||
Pass: the architecture document path (`docs/architecture/architecture.md`), the Technical Requirements Baseline (TR-IDs and count), the ADR list with statuses, and the Engine Knowledge Gap Inventory from Phase 0d. Issue this call and Step 2's before waiting for either result.
|
||||
|
||||
**Step 2 — Spawn `lead-programmer` via `Agent` using gate LP-FEASIBILITY (`.claude/docs/director-gates/lp-feasibility.md`):**
|
||||
|
||||
@@ -441,17 +470,20 @@ Pass: architecture document path, technical requirements baseline summary, ADR l
|
||||
|
||||
**Step 3 — Present both assessments to the user:**
|
||||
|
||||
Show the Technical Director assessment and Lead Programmer verdict side by side.
|
||||
Show the TD-ARCHITECTURE verdict (APPROVE / CONCERNS / REJECT) and the LP-FEASIBILITY verdict (FEASIBLE / CONCERNS / INFEASIBLE) side by side.
|
||||
|
||||
Use `AskUserQuestion` — "Technical Director and Lead Programmer have reviewed the architecture. How would you like to proceed?"
|
||||
Options: `Accept — proceed to handoff` / `Revise flagged items first` / `Discuss specific concerns`
|
||||
Options: `Accept — proceed to handoff` / `Revise flagged items first` / `Discuss specific concerns`.
|
||||
If either verdict is REJECT or INFEASIBLE, do not offer `Accept` — the blockers are revised (or discussed) first.
|
||||
`Revise flagged items first` re-drafts each flagged section and shows it for approval as in Phases 1–4; the revised document is then written once, through Phase 7's ask, and Step 4 records `REVISED after [verdict]`.
|
||||
A `NOT ASSESSED` answer is never recorded as `APPROVE` or `FEASIBLE`: Step 4 records it with the input that was missing (`director-gates.md`).
|
||||
|
||||
**Step 4 — Record sign-off in the architecture document:**
|
||||
|
||||
Update the Document Status section:
|
||||
```
|
||||
- Technical Director Sign-Off: [date] — APPROVED / APPROVED WITH CONDITIONS
|
||||
- Lead Programmer Feasibility: FEASIBLE / CONCERNS ACCEPTED / REVISED
|
||||
- TD-ARCHITECTURE: [date] — APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
- LP-FEASIBILITY: [date] — FEASIBLE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after INFEASIBLE / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
```
|
||||
|
||||
Show the proposed Document Status block inline, then use `AskUserQuestion`:
|
||||
@@ -471,7 +503,7 @@ Show the proposed Document Status block inline, then use `AskUserQuestion`:
|
||||
|
||||
## Architecture Complete
|
||||
|
||||
`docs/architecture/architecture.md` v1.0 — [TD verdict: APPROVED / APPROVED WITH CONCERNS / CONCERNS]. [One sentence on what the architecture covers.]
|
||||
`docs/architecture/architecture.md` v[N] — [TD-ARCHITECTURE: APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED / skipped — [mode] mode]. [One sentence on what the architecture covers.]
|
||||
|
||||
---
|
||||
|
||||
@@ -486,22 +518,25 @@ Show the proposed Document Status block inline, then use `AskUserQuestion`:
|
||||
**3. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence.]
|
||||
|
||||
**Then:** `/architecture-review`, and `/create-control-manifest` once it passes and those ADRs are Accepted — it turns them into the layer rules manifest.
|
||||
|
||||
List top 3 from Phase 6 in priority order. If fewer than 3 remain, list only what's outstanding.
|
||||
|
||||
---
|
||||
|
||||
## Gate-Check Readiness
|
||||
|
||||
> **Required before `/gate-check [stage]`:**
|
||||
> **Required before `/gate-check pre-production`:**
|
||||
> - [ ] Accept ADRs: [list Proposed ADR IDs that must be Accepted]
|
||||
> - [ ] Write ADRs: [list ADR IDs that must still be written]
|
||||
> - [ ] Run `/architecture-review` — writes the review report and the traceability index (`docs/architecture/requirements-traceability.md`) the gate reads
|
||||
> - [ ] Run `/test-setup` — scaffolds `tests/unit/`, `tests/integration/`, CI workflow, and an example test file
|
||||
> - [ ] Run `/ux-design` — creates `design/ux/interaction-patterns.md` and `design/accessibility-requirements.md`
|
||||
>
|
||||
> Run `/gate-check [stage]` when all boxes are checked.
|
||||
> Run `/gate-check pre-production` when all boxes are checked.
|
||||
|
||||
If nothing is blocking, write instead:
|
||||
> No blockers — run `/gate-check [stage]` now.
|
||||
> No blockers — run `/gate-check pre-production` now.
|
||||
|
||||
---
|
||||
|
||||
@@ -536,8 +571,13 @@ This skill follows the collaborative design principle at every phase:
|
||||
sufficient. Use the structured tool with labeled options [A]/[B]/[C] (write now /
|
||||
show full draft first / not yet). For multi-file changesets, list every file
|
||||
and what changes, then ask once grouped — not separate plain-text asks per file.
|
||||
6. **Incremental writing** — write each approved section immediately; do not
|
||||
accumulate everything and write at the end. This survives session crashes.
|
||||
6. **One write, after every section is approved** — the document is written once,
|
||||
at Phase 7; Phase 7b's Step 4 only updates its Document Status, after its own
|
||||
ask. Record each approved section's decisions in
|
||||
`production/session-state/active.md` as you go, so a crash loses no decision.
|
||||
A revision that Phase 7b forces is written the same way — once, after its
|
||||
re-drafted sections are approved — and an update (Phase 0e) writes only the
|
||||
sections it chose.
|
||||
|
||||
Never make a binding architectural decision without user input. If the user is
|
||||
unsure, present 2-4 options with pros/cons before asking them to decide.
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
---
|
||||
name: create-control-manifest
|
||||
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]"
|
||||
argument-hint: "[update — regenerate from current ADRs] [--review full|lean|solo]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-control-manifest/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
# Create Control Manifest
|
||||
|
||||
@@ -45,9 +46,9 @@ Interpret against N:
|
||||
|
||||
| Result | Meaning | Action |
|
||||
|---|---|---|
|
||||
| **N matches, some read `Accepted`** | Normal. | The Accepted set is **A**; proceed with A. |
|
||||
| **N matches, some read `Accepted`** | Normal. | The Accepted set is **A**; proceed with A. Name every ADR left out, with its status, in the Phase 4 preview — the user approves a manifest knowing what it does not cover. |
|
||||
| **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. |
|
||||
| **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 retrofit [file]` 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.
|
||||
|
||||
@@ -63,6 +64,12 @@ Interpret against N:
|
||||
forbidden API entries
|
||||
- Read `docs/engine-reference/[engine]/current-best-practices.md` if it exists
|
||||
|
||||
### Existing Artifacts
|
||||
- Glob `docs/architecture/control-manifest.md` (present → this run is a
|
||||
regeneration; Read it before the Phase 5 write, which overwrites it) and
|
||||
`production/epics/*/EPIC.md` (present → epics exist). Phase 6 picks its next
|
||||
step from both.
|
||||
|
||||
Report: "Loaded [N] Accepted ADRs, engine: [name + version]."
|
||||
|
||||
---
|
||||
@@ -120,7 +127,7 @@ If an ADR spans multiple layers, duplicate the rule into each relevant layer.
|
||||
|
||||
## 3. Add Global Rules
|
||||
|
||||
Combine rules that apply to all layers:
|
||||
Combine rules that apply to all layers. Each carries its source into the manifest, as a layer rule does — the `project.yaml` key, `technical-preferences.md`, or the engine-reference file:
|
||||
|
||||
### From project config (`project.yaml`, else `technical-preferences.md`):
|
||||
- Naming conventions — `naming.*`: classes, variables, signals/events, files, constants
|
||||
@@ -154,6 +161,7 @@ Before writing the manifest, present a summary to the user:
|
||||
## Control Manifest Preview
|
||||
Engine: [name + version]
|
||||
ADRs covered: [list ADR numbers]
|
||||
ADRs excluded: [ADR-NNNN ([status]), … — every ADR not in the Accepted set, or "None"]
|
||||
Total rules extracted:
|
||||
- Foundation layer: [N] required, [M] forbidden, [P] guardrails
|
||||
- Core layer: [N] required, [M] forbidden, [P] guardrails
|
||||
@@ -193,6 +201,7 @@ Apply the verdict:
|
||||
- **APPROVE** → proceed to Phase 5
|
||||
- **CONCERNS** → surface via `AskUserQuestion` with options: `Revise flagged rules` / `Accept and proceed` / `Discuss further`
|
||||
- **REJECT** → do not write the manifest; fix the flagged rules and re-present the summary
|
||||
- **NOT ASSESSED** [missing input] → not an approval (`.claude/docs/director-gates.md`): name what was missing, then supply it and re-run the gate — or, if the user chooses to go on without it, continue to Phase 5 and state `TD-MANIFEST: NOT ASSESSED — [input]` in the output and the final Verdict line
|
||||
|
||||
---
|
||||
|
||||
@@ -285,24 +294,24 @@ rule, see the referenced ADR.
|
||||
## Global Rules (All Layers)
|
||||
|
||||
### Naming Conventions
|
||||
| Element | Convention | 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] |
|
||||
| Element | Convention | Example | Source |
|
||||
|---------|-----------|---------|--------|
|
||||
| Classes | [from naming.* in project.yaml, else technical-preferences.md] | [example] | [`naming.classes` in project.yaml, or technical-preferences.md] |
|
||||
| Variables | [from naming.* in project.yaml, else technical-preferences.md] | [example] | [`naming.variables` in project.yaml, or technical-preferences.md] |
|
||||
| Signals/Events | [from naming.* in project.yaml, else technical-preferences.md] | [example] | [`naming.signals` in project.yaml, or technical-preferences.md] |
|
||||
| Files | [from naming.* in project.yaml, else technical-preferences.md] | [example] | [`naming.files` in project.yaml, or technical-preferences.md] |
|
||||
| Constants | [from naming.* in project.yaml, else technical-preferences.md] | [example] | [`naming.constants` in project.yaml, or technical-preferences.md] |
|
||||
|
||||
### Performance Budgets
|
||||
| Target | Value |
|
||||
|--------|-------|
|
||||
| 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] |
|
||||
| Target | Value | Source |
|
||||
|--------|-------|--------|
|
||||
| Framerate | [from performance.* in project.yaml, else technical-preferences.md] | [`performance.target_framerate` in project.yaml, or technical-preferences.md] |
|
||||
| Frame budget | [from performance.* in project.yaml, else technical-preferences.md] | [`performance.frame_budget_ms` in project.yaml, or technical-preferences.md] |
|
||||
| Draw calls | [from performance.* in project.yaml, else technical-preferences.md] | [`performance.draw_call_limit` in project.yaml, or technical-preferences.md] |
|
||||
| Memory ceiling | [from performance.* in project.yaml, else technical-preferences.md] | [`performance.memory_ceiling_mb` in project.yaml, or technical-preferences.md] |
|
||||
|
||||
### Approved Libraries / Addons
|
||||
- [library] — approved for [purpose]
|
||||
- [library] — approved for [purpose] — source: technical-preferences.md
|
||||
|
||||
### Forbidden APIs ([engine version])
|
||||
These APIs are deprecated or unverified for [engine + version]:
|
||||
@@ -310,7 +319,7 @@ These APIs are deprecated or unverified for [engine + version]:
|
||||
- Source: `docs/engine-reference/[engine]/deprecated-apis.md`
|
||||
|
||||
### Cross-Cutting Constraints
|
||||
- [constraint that applies everywhere, regardless of layer]
|
||||
- [constraint that applies everywhere, regardless of layer] — source: [ADR-NNNN, preference key or engine-reference file]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -18,6 +18,16 @@ traceability — sits between architecture review and story decomposition.
|
||||
| `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 |
|
||||
|
||||
> **Tier.** The rows above and the preconditions below are the `full` inputs.
|
||||
> SKILL.md relaxes them by `workflow`: at `standard`, GDDs need the 5 required
|
||||
> sections (+ conditional Formulas), only critical (Foundation-layer) ADRs are
|
||||
> expected and traced, and the control manifest is read if present, not required.
|
||||
> At `minimal` the skill is optional and off the path (`/create-stories`
|
||||
> synthesizes the epic itself); if run, it skips Steps 2a and 2b, reads only
|
||||
> `design/game-brief.md` (stopping if that is missing), takes its order from the
|
||||
> brief's Build order instead of `systems-index.md`, and requires no GDD, ADR,
|
||||
> architecture document, TR registry or control manifest.
|
||||
|
||||
### 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)
|
||||
@@ -30,7 +40,7 @@ traceability — sits between architecture review and story decomposition.
|
||||
| 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 |
|
||||
| `production/epics/index.md` | `Epic`, `Layer`, `System`, `GDD`, `Stories`, `Status` columns | Created, or a row added per new epic; an existing epic's row is updated in place and keeps its `Stories` value |
|
||||
|
||||
### Output Guarantees
|
||||
- Every EPIC.md contains a `## Governing ADRs` table with at least one row (or a documented note if none apply)
|
||||
@@ -38,19 +48,21 @@ traceability — sits between architecture review and story decomposition.
|
||||
- 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]`
|
||||
- The `Stories:` field reads `Not yet created — run /create-stories [epic-slug]` on a new epic; an EPIC.md that already existed is updated in place (after an update-or-skip ask) and keeps its `Stories:` line and `## Stories` table
|
||||
- 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
|
||||
- A PR-EPIC review that could not judge the epics (no milestone timeline or team capacity) is reported as `PR-EPIC: NOT ASSESSED — [input]` and never read as REALISTIC
|
||||
|
||||
## 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)
|
||||
- MODIFIES: `production/epics/[epic-slug]/EPIC.md` (creates, or updates in place keeping its Stories table), `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 overwrite an existing EPIC.md or reset its `## Stories` table — update it in place, or skip it
|
||||
- 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
|
||||
|
||||
@@ -66,11 +78,11 @@ It assumes:
|
||||
- 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)
|
||||
- `Status: Ready` does not by itself mean no stories exist — an EPIC.md updated in place keeps its stories; read its `Stories:` 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
|
||||
- `production/epics/index.md` rows are matched to epics by slug — an epic whose slug changes gets a new row, and the old row stays behind
|
||||
|
||||
@@ -3,7 +3,7 @@ name: create-epics
|
||||
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, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-epics/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-epics/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -28,7 +28,8 @@ will have changed.
|
||||
**Next step after each epic:** `/create-stories [epic-slug]`
|
||||
|
||||
**When to run:** After `/create-control-manifest` and `/architecture-review` pass
|
||||
(at `full`). At `standard`, critical ADRs + a control manifest suffice. At
|
||||
(at `full`). At `standard`, critical ADRs suffice, and a control manifest is
|
||||
read if present. 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.
|
||||
@@ -63,14 +64,14 @@ prerequisite expectations and consults
|
||||
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`.
|
||||
epic's story breakdown: expect **3–5** child stories per epic at `coarse` (the default, via `rigor: minimal`), **5–10**
|
||||
at `balanced` (`rigor: standard`), **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
|
||||
`terse` (the default, via `rigor: minimal`) = scope as bullets, one-line rationale; `balanced` = a scope paragraph
|
||||
with light rationale (`rigor: standard`); `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.
|
||||
|
||||
@@ -89,10 +90,17 @@ ADRs) are structural and stay whole at every density.
|
||||
|
||||
### Step 2a — Summary scan (fast, fail-open)
|
||||
|
||||
**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
|
||||
**At `minimal`, skip Steps 2a and 2b** — that tier decomposes from
|
||||
`design/game-brief.md` and has no GDDs by design (see the tier note below). Read
|
||||
the brief instead; if it is missing, report "No `design/game-brief.md` — run
|
||||
`/start` or `/brainstorm` first" and stop.
|
||||
|
||||
**At `standard` and `full`, 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`, any
|
||||
`gdd-cross-review-*.md`, `sound-bible.md` — the set `gdd-structure-check.sh`
|
||||
skips (the sound bible belongs in `design/audio/`; it is listed for projects
|
||||
that still keep it at the earlier location). 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.
|
||||
|
||||
@@ -134,8 +142,7 @@ Read for in-scope systems:
|
||||
```
|
||||
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.
|
||||
large ADR.
|
||||
- `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
|
||||
@@ -185,7 +192,7 @@ 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).
|
||||
not block or emit the untraced-requirements warning).
|
||||
- **`minimal`** — skip this check entirely (no TR registry / ADR expected).
|
||||
|
||||
- **Traced requirements**: TR-IDs that have an Accepted ADR covering them
|
||||
@@ -207,8 +214,10 @@ Present to user before writing anything:
|
||||
|
||||
If there are untraced requirements:
|
||||
> "⚠️ [N] requirements in [system] have no ADR. The epic can be created, but
|
||||
> stories for these requirements will be marked Blocked until ADRs exist.
|
||||
> Run `/architecture-decision` first, or proceed with placeholders."
|
||||
> `/create-stories` will write their stories with no governing ADR (`ADR: N/A`)
|
||||
> and `Status: Ready` — nothing downstream blocks them, so they would be
|
||||
> implemented without architectural guidance. Run `/architecture-decision` first
|
||||
> if they need a decision, or proceed and accept the gap."
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "Shall I create Epic: [name]?"
|
||||
@@ -232,7 +241,7 @@ Pass: the full epic structure summary (all epics, their scope summaries, governi
|
||||
|
||||
Present the producer's assessment.
|
||||
|
||||
If UNREALISTIC: offer to revise epic boundaries (split overscoped or merge underscoped epics). Revise and re-run the gate before writing.
|
||||
If UNREALISTIC: offer to revise epic boundaries (split overscoped or merge underscoped epics). Revise, present the revised epics again, and re-run the gate before writing.
|
||||
|
||||
If CONCERNS, use `AskUserQuestion`:
|
||||
- Prompt: "Producer raised concerns about the epic structure. How do you want to proceed?"
|
||||
@@ -242,16 +251,31 @@ If CONCERNS, use `AskUserQuestion`:
|
||||
- `[C] Stop — I want to reconsider the scope`
|
||||
|
||||
If [A]: proceed to Step 5.
|
||||
If [B]: revise epic definitions from Step 4 and re-run the producer gate.
|
||||
If [B]: revise epic definitions from Step 4, present the revised epics to the user again, then re-run the producer gate.
|
||||
If [C]: stop. Verdict: **BLOCKED** — user wants to reconsider epic scope.
|
||||
|
||||
If NOT ASSESSED [missing input] — e.g. no milestone timeline or team capacity — it
|
||||
is not a REALISTIC (`.claude/docs/director-gates.md`): name what was missing, then
|
||||
supply it and re-run the gate, or, if the user chooses to go on without it,
|
||||
proceed to Step 5 and state `PR-EPIC: NOT ASSESSED — [input]` in the output and
|
||||
the final Verdict line.
|
||||
|
||||
Do not write epic files until the producer gate resolves.
|
||||
|
||||
---
|
||||
|
||||
## 5. Write Epic Files
|
||||
|
||||
After approval, ask: "May I write the epic file to `production/epics/[epic-slug]/EPIC.md`?"
|
||||
**If `production/epics/[epic-slug]/EPIC.md` already exists, never overwrite it.**
|
||||
Ask instead: "An EPIC.md already exists for [name]. Update it in place, or skip
|
||||
it?" — `[A] Update in place — keep its Stories table, and update its index.md row` / `[B] Skip this epic`. An
|
||||
update rewrites only what this skill owns — the header fields other than
|
||||
`Stories`, `## Overview`, `## Governing ADRs`, `## GDD Requirements` and
|
||||
`## Definition of Done` — and leaves the `**Stories**` header line and any
|
||||
`## Stories` table exactly as they are: `/create-stories` wrote them, and
|
||||
resetting them to "Not yet created" orphans every story already in the directory.
|
||||
|
||||
For a new epic, after approval, ask: "May I write `production/epics/[epic-slug]/EPIC.md` and add its row to `production/epics/index.md` (creating it if absent)?"
|
||||
|
||||
After user confirms, write:
|
||||
|
||||
@@ -289,8 +313,8 @@ and the architecture module's stated responsibilities]
|
||||
This epic is complete when:
|
||||
- All stories are implemented, reviewed, and closed via `/story-done`
|
||||
- All acceptance criteria from `design/gdd/[filename].md` are verified
|
||||
- All Logic and Integration stories have passing test files in `tests/`
|
||||
- All Visual/Feel and UI stories have evidence docs with sign-off in `production/qa/evidence/`
|
||||
- All Logic and Integration stories have passing test files in [the test root — `tests/` on Godot, `Assets/Tests/` on Unity, `Source/<Module>/Private/Tests/` on Unreal]
|
||||
- All Visual/Feel and UI stories have retained screenshots in `production/qa/evidence/` — each screen touched for UI, plus a lead sign-off for Visual/Feel
|
||||
|
||||
## Next Step
|
||||
|
||||
@@ -299,7 +323,9 @@ Run `/create-stories [epic-slug]` to break this epic into implementable stories.
|
||||
|
||||
### Update `production/epics/index.md`
|
||||
|
||||
Create or update the master index:
|
||||
Create or update the master index. An epic that already has a row keeps it:
|
||||
update that row in place and keep its `Stories` value — never append a second
|
||||
row, and never reset `Stories` to `Not yet created`:
|
||||
|
||||
```markdown
|
||||
# Epics Index
|
||||
|
||||
@@ -16,6 +16,15 @@ and `/story-readiness` + `/dev-story`.
|
||||
| `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 |
|
||||
|
||||
> **Tier.** The rows above are the `standard`/`full` inputs. At `workflow: minimal`
|
||||
> the only input is `design/game-brief.md`: the skill writes
|
||||
> `production/epics/<slug>/EPIC.md` itself from the brief (or uses one that already
|
||||
> exists there, never rewriting it), needs no `/create-epics`
|
||||
> run, and reads no GDD, ADR, control manifest or TR registry. Each story traces to
|
||||
> `Brief MVP feature N` instead of a TR-ID, and its ADR lines read
|
||||
> `N/A (minimal — no ADRs)` (SKILL.md, the `minimal` branch of Step 2 and the
|
||||
> `minimal` field mapping in Step 6).
|
||||
|
||||
### 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)
|
||||
@@ -28,32 +37,33 @@ and `/story-readiness` + `/dev-story`.
|
||||
| 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 |
|
||||
| `production/epics/[epic-slug]/EPIC.md` | `## Stories` table replacing the "Not yet created" placeholder | Updated in-place; a return visit appends rows for new stories only. At `minimal`, when none exists yet, the skill creates it from the brief, after the write ask names it |
|
||||
| `production/epics/index.md` | The epic's `Stories` column set to `[N] stories` | Only when the index exists; otherwise the run prints `Epics index not updated: production/epics/index.md absent` |
|
||||
|
||||
### 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 a `TR-[system]-NNN` reference in its `## Context` section (or `TR-[system]-???` with a warning if the registry has no match) — at `minimal`, `Brief MVP feature N` instead
|
||||
- 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 `Status:` field — either `Ready` or `Blocked` (if the governing ADR is `Proposed`, `Deprecated` or `Superseded`)
|
||||
- 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 `Manifest Version:` field matching the date from `docs/architecture/control-manifest.md`'s header at time of writing — at `minimal`, `N/A (minimal — no control manifest)`
|
||||
- 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 `## Acceptance Criteria` section with at least one checkbox item copied from the GDD — at `minimal`, derived from `design/game-brief.md` (its Player goal & fail state and the MVP feature the story implements)
|
||||
- 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`
|
||||
- Stories with a `Proposed` ADR have `Status: Blocked` and a note: `BLOCKED: ADR-NNNN is Proposed — accept it with /architecture-decision accept ADR-NNNN once decided`; a `Deprecated` or `Superseded` ADR blocks the same way, naming its successor
|
||||
- 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)
|
||||
- MODIFIES: `production/epics/[epic-slug]/story-NNN-[slug].md` (creates), `production/epics/[epic-slug]/EPIC.md` (updates Stories section only; created at `minimal` when none exists yet), `production/epics/index.md` (the epic's row, when the index exists) — all after one write ask that names them
|
||||
|
||||
## 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 acceptance criteria — all criteria must come from the GDD (from `design/game-brief.md` at `minimal`)
|
||||
- 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 mark a story `Status: Ready` if its governing ADR has `Status: Proposed`, `Deprecated` or `Superseded`
|
||||
- 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
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ name: create-stories
|
||||
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, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-stories/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-stories/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow,docs.density,story_granularity,system_overrides`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow,docs.density,story_granularity,qa.level,system_overrides`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
|
||||
defaults in `.claude/docs/config-resolution.md`.
|
||||
@@ -26,7 +26,8 @@ then Core, and so on — matching the dependency order.
|
||||
**Output:** `production/epics/[epic-slug]/story-NNN-[slug].md` files
|
||||
|
||||
**Previous step:** `/create-epics [system]`
|
||||
**Next step after stories exist:** `/story-readiness [story-path]` then `/dev-story [story-path]`
|
||||
**Next step after stories exist:** `/story-readiness [story-path]` then `/dev-story [story-path]` —
|
||||
at `workflow: minimal`, `/dev-story [story-path]` directly (`/story-readiness` is not on the minimal path)
|
||||
|
||||
---
|
||||
|
||||
@@ -45,21 +46,27 @@ 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
|
||||
story's AC load: **5–10 ACs covering a whole feature** at `coarse` (the default, via `rigor: minimal`), **2–4 ACs
|
||||
covering one task** at `balanced` (`rigor: standard`), **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
|
||||
`terse` (the default, via `rigor: minimal`) = notes as bullets, no preamble; `balanced` = short context paragraph +
|
||||
notes (`rigor: standard`); `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
|
||||
- **A named epic that does not exist** — if `production/epics/[slug]/EPIC.md`
|
||||
(or the given path) is missing, stop at `standard`/`full`: "No epic at
|
||||
`production/epics/[slug]/EPIC.md`. Run `/create-epics` to create it, or check
|
||||
the slug with `ls production/epics/`." Do not decompose from a guess. At
|
||||
`minimal` there are no `/create-epics` epics to name and that skill is not on
|
||||
the path — say so, take Step 2's `minimal` branch, and name the slug it uses.
|
||||
- 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
|
||||
@@ -89,13 +96,29 @@ criteria are structural and are never trimmed by density.
|
||||
## 2. Load Everything for This Epic
|
||||
|
||||
> **`minimal` tier — synthesize the epic from the brief** (Option A). At
|
||||
> `minimal` there is no `/create-epics` step and no `EPIC.md`. Instead:
|
||||
> `minimal` there is no `/create-epics` step and usually no `EPIC.md`. Instead:
|
||||
> 0. **No `design/game-brief.md`?** Stop: "There is no brief to build stories
|
||||
> from yet — run `/brainstorm` first; it writes the one-page brief."
|
||||
> **An `EPIC.md` already at `production/epics/<slug>/`** — the named epic, or
|
||||
> the brief-title slug (`/create-epics` run anyway, or an earlier run of this
|
||||
> skill) — is the epic: use its scope, still traced to the brief, and never
|
||||
> rewrite it; Step 6 only appends its Stories table, and the Step 5 ask says
|
||||
> *update* `EPIC.md`.
|
||||
> **Stories already in `production/epics/<slug>/`?** This is a return visit —
|
||||
> `/help` sends a finished build order back here. Never rewrite an existing
|
||||
> `story-*.md` or the `EPIC.md`: read them, add stories only for brief items
|
||||
> they do not yet cover (or the new ones the user names), and number on from
|
||||
> the highest existing `story-NNN`. The one change `EPIC.md` gets is Step 6's:
|
||||
> a row per new story appended to its Stories table — existing rows and the
|
||||
> rest of the file stay as they are.
|
||||
> 1. Read `design/game-brief.md` in full (it is one page).
|
||||
> 2. Synthesize an implicit epic: write a lightweight
|
||||
> 2. Synthesize an implicit epic (first run only — a return visit keeps the
|
||||
> existing one): draft 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.
|
||||
> this is the container `/dev-story` and `/sprint-status` expect. It is written
|
||||
> in Step 6, with the stories, after the Step 5 ask names it — never before.
|
||||
> 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.
|
||||
@@ -112,8 +135,7 @@ For `standard`/`full` (a `/create-epics` epic exists), read in full (these are s
|
||||
**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:
|
||||
read a file. Per ADR:
|
||||
|
||||
1. **Map the headings** (cheap — line numbers only):
|
||||
```
|
||||
@@ -128,12 +150,13 @@ reads of the same file). Per ADR:
|
||||
- `## 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**:
|
||||
3. **Capture the `## Status` and the `## Last Verified` date** in one call:
|
||||
```
|
||||
Grep pattern="^## (Last Verified|Date)" path="docs/architecture/[adr-file].md" output_mode="content" -A 1
|
||||
Grep pattern="^## (Status|Last Verified|Date)" path="docs/architecture/[adr-file].md" output_mode="content" -A 2
|
||||
```
|
||||
Use `Last Verified`, falling back to `Date`, then to `unversioned` if both
|
||||
are absent. This becomes the story's `ADR Version` stamp — `/dev-story`
|
||||
The Status (Accepted / Proposed / …) is what Step 4 decides `Ready` vs
|
||||
`Blocked` on — never assume it. For the version, 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.
|
||||
|
||||
@@ -143,8 +166,8 @@ 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`.
|
||||
content directly and flag the ADR for
|
||||
`/architecture-decision retrofit [file]`.
|
||||
|
||||
**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.
|
||||
|
||||
@@ -191,7 +214,7 @@ For each GDD acceptance criterion:
|
||||
|
||||
**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,
|
||||
`balanced` target (`rigor: standard`) — at `coarse`, the default, 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.
|
||||
|
||||
@@ -200,7 +223,8 @@ For each story, determine:
|
||||
- **TR-ID**: look up in `tr-registry.yaml`. Use the stable ID. If no match, use `TR-[system]-???` and warn.
|
||||
- **Governing ADR**: which ADR governs how to implement this?
|
||||
- `Status: Accepted` → embed normally
|
||||
- `Status: Proposed` → set story `Status: Blocked` with note: "BLOCKED: ADR-NNNN is Proposed — run `/architecture-decision` to advance it"
|
||||
- `Status: Proposed` → set story `Status: Blocked` with note: "BLOCKED: ADR-NNNN is Proposed — accept it with `/architecture-decision accept ADR-NNNN` once decided"
|
||||
- `Deprecated` or `Superseded by ADR-XXXX` → set story `Status: Blocked` with note: "BLOCKED: ADR-NNNN is [status] — point the story at [successor] (edit its ADR field — `/create-stories` never rewrites an existing story) before implementing"
|
||||
- **Multiple ADRs apply**: List all governing ADRs in the story's `Governing ADRs:` field. Designate the one most directly controlling the implementation pattern as primary (first in the list). Others are listed as secondary references.
|
||||
- **No ADR applies at all**: Write `ADR: N/A — [brief reason, e.g. "pure data configuration, no architectural pattern required"]` in the story's ADR field. Do NOT leave the field blank — a blank ADR field means "not checked", not "not applicable".
|
||||
- **Story Type**: from Step 3 classification
|
||||
@@ -217,11 +241,18 @@ For each story, determine:
|
||||
|
||||
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. Require in the return:
|
||||
1. The QL-STORY-READY verdict per story (ADEQUATE / GAPS / INADEQUATE).
|
||||
Pass: the full story list inline — no story file exists yet, so the stories themselves stand in for the gate's story paths — with each story's acceptance criteria, story type, and TR-IDs with their requirement text from `tr-registry.yaml`; the epic's GDD acceptance criteria for reference. Require in the return:
|
||||
1. The QL-STORY-READY verdict per story (ADEQUATE / GAPS / INADEQUATE, or NOT ASSESSED naming a missing input).
|
||||
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 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.
|
||||
Present the assessment, then act on each story's verdict — the gate's own words, handled per `.claude/docs/director-gates.md`:
|
||||
|
||||
- **ADEQUATE** — keep the returned specs.
|
||||
- **GAPS** — use `AskUserQuestion`: `Revise flagged criteria` / `Accept and proceed` / `Discuss further`. Do not revise before the user chooses. On *Revise*, draft the revised criteria, show them, and re-request specs for just those stories in one follow-up call. On *Accept*, the criteria stay as written and the story carries no qa-lead specs — its `## QA Test Cases` reads `*Test cases not yet defined — run /qa-plan to generate them.*`
|
||||
- **INADEQUATE** — blocking: the story is not written as it stands. Revise its criteria with the user (draft, show, confirm), then re-request its specs; if the user will not revise it, drop it from this run and name it as dropped in the Step 5 list.
|
||||
- **NOT ASSESSED** [missing input] — not an ADEQUATE: name what was missing, then supply it and re-request that story's verdict, or write the story without qa-lead specs (the `/qa-plan` line above in its `## QA Test Cases`) and mark it `QL-STORY-READY: NOT ASSESSED — [input]` in the Step 5 list.
|
||||
|
||||
Untestable criteria cannot be implemented correctly, so a story carries qa-lead specs only once it is ADEQUATE.
|
||||
|
||||
**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.
|
||||
|
||||
@@ -264,13 +295,13 @@ Story 002: [title] — Integration — ADR-MMMM
|
||||
|
||||
Story 003: [title] — Visual/Feel — ADR-NNNN
|
||||
Covers: TR-[system]-004
|
||||
Evidence required: production/qa/evidence/[slug]-evidence.md
|
||||
Evidence required: retained screenshot in production/qa/evidence/ + sign-off in production/qa/evidence/[slug]-evidence.md
|
||||
|
||||
[N stories total: N Logic, N Integration, N Visual/Feel, N UI, N Config/Data]
|
||||
```
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "May I write these [N] stories to `production/epics/[epic-slug]/`?"
|
||||
- Prompt: "May I write these [N] stories to `production/epics/[epic-slug]/`, and update `production/epics/[epic-slug]/EPIC.md` and `production/epics/index.md`?" — name every file Step 6 touches: at `minimal` say *create* `EPIC.md` only when none exists yet (the Step 2 draft, shown with the stories), and leave `index.md` out when it does not exist.
|
||||
- Options: `[A] Yes — write all [N] stories` / `[B] Not yet — I want to review or adjust first`
|
||||
|
||||
---
|
||||
@@ -298,14 +329,13 @@ For each story, write `production/epics/[epic-slug]/story-[NNN]-[slug].md`:
|
||||
> > "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.
|
||||
> > `VERSION.md` rating of HIGH silently disables the specialist review.
|
||||
> > 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").
|
||||
> - Any **Test Evidence / DoD** line is governed by `qa.level`, not this template — at `qa.level: minimal` tests are **waived** (advisory, never "must exist and pass"), but a Visual/Feel or UI story's retained screenshot is not.
|
||||
|
||||
```markdown
|
||||
# Story [NNN]: [title]
|
||||
@@ -388,14 +418,14 @@ 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").*
|
||||
*Governed by `qa.level`: at `qa.level: minimal` tests are **waived** (advisory, never "must exist and pass"), but a Visual/Feel or UI story's retained screenshot is not.*
|
||||
|
||||
**Story Type**: [type]
|
||||
**Required evidence**:
|
||||
- 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
|
||||
- Visual/Feel: a retained screenshot in `production/qa/evidence/` + sign-off in `production/qa/evidence/[story-slug]-evidence.md`
|
||||
- UI: a retained screenshot of each screen touched, in `production/qa/evidence/`
|
||||
- Config/Data: smoke check pass (`production/qa/smoke-*.md`)
|
||||
|
||||
**Status**: [ ] Not yet created
|
||||
@@ -410,7 +440,10 @@ change meaning. This is what the programmer reads instead of the ADR.]
|
||||
|
||||
### Also update `production/epics/[epic-slug]/EPIC.md`
|
||||
|
||||
Replace the "Stories: Not yet created" line with a populated table:
|
||||
At `minimal` with no `EPIC.md` yet, this is where the Step 2 draft is written, with the
|
||||
table below. Otherwise replace the "Stories: Not yet created" line with a
|
||||
populated table; if the table already exists (a return visit), append a row per
|
||||
new story and leave the existing rows as they are:
|
||||
|
||||
```markdown
|
||||
## Stories
|
||||
@@ -423,7 +456,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, 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.
|
||||
Find the row in the index table matching this epic (by epic name or slug). Set its `Stories` column to `[N] stories`, where N is the epic's total story count after this run — the existing rows plus the ones just written, not only the new ones. If the index file does not exist, say so in one line — `Epics index not updated: production/epics/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.
|
||||
|
||||
---
|
||||
|
||||
@@ -433,14 +466,14 @@ Use `AskUserQuestion` to close with context-aware next steps:
|
||||
|
||||
Check:
|
||||
- Are there other epics in `production/epics/` without stories yet? List them.
|
||||
- Is this the last epic? If so, include `/sprint-plan` as an option.
|
||||
- Is this the last epic? If so, include `/sprint-plan` as an option — except at `workflow: minimal`, which has no sprints: the brief's build order is the plan.
|
||||
|
||||
Widget:
|
||||
- Prompt: "[N] stories written to `production/epics/[epic-slug]/`. What next?"
|
||||
- Options (include all that apply):
|
||||
- `[A] Start implementing — run /story-readiness [first-story-path]` (Recommended)
|
||||
- `[A] Start implementing — run /dev-story [first-story-path]` at `minimal`, `/story-readiness [first-story-path]` otherwise (Recommended)
|
||||
- `[B] Create stories for [next-epic-slug] — run /create-stories [slug]` (only if other epics have no stories yet)
|
||||
- `[C] Plan the sprint — run /sprint-plan new` (only if all epics have stories)
|
||||
- `[C] Plan the sprint — run /sprint-plan new` (only if all epics have stories, and never at `minimal`)
|
||||
- `[D] Stop here for this session`
|
||||
|
||||
Note in output: "Work through stories in order — each story's `Depends on:` field tells you what must be DONE before you can start it."
|
||||
@@ -462,5 +495,5 @@ describe what collaborative mode requires, not universal behavior.
|
||||
|
||||
After writing (or declining):
|
||||
|
||||
- **Verdict: COMPLETE** — [N] stories written to `production/epics/[epic-slug]/`. Run `/story-readiness` → `/dev-story` to begin implementation.
|
||||
- **Verdict: COMPLETE** — [N] stories written to `production/epics/[epic-slug]/`. Run `/dev-story` (at `minimal`) or `/story-readiness` → `/dev-story` to begin implementation.
|
||||
- **Verdict: BLOCKED** — user declined. No story files written.
|
||||
|
||||
@@ -116,18 +116,28 @@ Do not proceed to Phase 4 until the rollback plan is written.
|
||||
|
||||
## Phase 4: Implement Fixes
|
||||
|
||||
For each bug in the approved scope, spawn a focused implementation loop:
|
||||
For each code fix in the approved scope, spawn a focused implementation loop:
|
||||
|
||||
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.
|
||||
It returns, for each bug, the minimal fix and the files it would change —
|
||||
writing nothing.
|
||||
|
||||
3. Spawn `qa-tester` via `Agent` to verify: does the bug reproduce after the fix?
|
||||
2. Ask once, for the whole set: "May I apply these fixes? [BUG-ID → files, one
|
||||
line each]". No code changes before this approval.
|
||||
|
||||
For config/data-only fixes: make the change directly (no programmer agent needed). Confirm the value changed and re-run any relevant smoke test.
|
||||
3. On yes, hand each approved fix back to `lead-programmer` (a new `Agent` call
|
||||
carrying its plan) to implement it and run targeted tests with `commands.test`
|
||||
from `project.yaml`, narrowed to the affected suite where the runner allows —
|
||||
never a runner line written from memory. If `commands.test` is unset, say so
|
||||
and record `Tests: NOT RUN — commands.test unset` for that bug.
|
||||
|
||||
4. 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). First ask, naming the file and the change: "May I edit `[config file]` — `[key]`: [old value] → [new value]?" Confirm the value changed and re-run any relevant smoke test.
|
||||
|
||||
---
|
||||
|
||||
@@ -143,8 +153,8 @@ Spawn `qa-lead` via `Agent` with:
|
||||
Ask qa-lead to determine: **Is a targeted smoke check sufficient, or do any fixes touch systems that require a broader regression?**
|
||||
|
||||
Run the required QA scope:
|
||||
- **Targeted smoke check** — run `/smoke-check [affected-systems]`
|
||||
- **Broader regression** — run targeted tests in `tests/unit/` and `tests/integration/` for affected systems
|
||||
- **Targeted smoke check** — run `/smoke-check` (it takes no system argument)
|
||||
- **Broader regression** — run the affected systems' tests in the engine's test root (`tests/unit/` and `tests/integration/` Godot, `Assets/Tests/` Unity, `Source/<Module>/Private/Tests/` Unreal — `.claude/docs/directory-structure.md`) with `commands.test` from `project.yaml`, narrowed to the affected suites where the runner allows — never a runner line written from memory. If `commands.test` is unset, the broader regression is NOT ASSESSED; say so.
|
||||
|
||||
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.
|
||||
|
||||
@@ -175,12 +185,12 @@ one, which is the worst possible audience for an unverified change.
|
||||
### Bugs Fixed
|
||||
| BUG-ID | Severity | Description | Fix summary |
|
||||
|--------|----------|-------------|-------------|
|
||||
| BUG-NNN | S[1-4] | [description] | [one-line fix] |
|
||||
| BUG-NNNN | S[1-4] | [description] | [one-line fix] |
|
||||
|
||||
### Deferred to 1.1
|
||||
| BUG-ID | Severity | Description | Reason deferred |
|
||||
|--------|----------|-------------|-----------------|
|
||||
| BUG-NNN | S[1-4] | [description] | [reason] |
|
||||
| BUG-NNNN | S[1-4] | [description] | [reason] |
|
||||
|
||||
---
|
||||
|
||||
@@ -231,7 +241,7 @@ After the patch record is written:
|
||||
1. Run `/patch-notes` to generate the player-facing version of the patch notes
|
||||
2. Run `/bug-report verify [BUG-ID]` for each fixed bug after the patch is live
|
||||
3. Run `/bug-report close [BUG-ID]` for each verified fix
|
||||
4. Schedule a post-launch review 48–72 hours after launch using `/retrospective launch`
|
||||
4. Schedule a post-launch review 48–72 hours after launch using `/retrospective [milestone-name]` for the launch milestone in `production/milestones/`
|
||||
|
||||
**If any S1 bugs remain open after the patch:**
|
||||
> "⚠️ S1 bugs remain open and were not patched. These are accepted risks. Document them in the rollback plan trigger conditions — if they occur at scale, rollback may be preferable to a follow-up patch."
|
||||
@@ -249,5 +259,6 @@ Use `AskUserQuestion`:
|
||||
|
||||
- **Scope discipline is everything** — resist scope creep; every addition increases risk
|
||||
- **Rollback plan first, always** — a patch without a rollback plan is irresponsible
|
||||
- **Deferred is not forgotten** — every deferred bug gets a 1.1 ticket automatically
|
||||
- **Deferred is not forgotten** — every deferred bug is listed in the record's
|
||||
"Deferred to 1.1" table; run `/bug-triage` afterwards to schedule them into the 1.1 sprint
|
||||
- **Player communication is part of the patch** — `/patch-notes` is a required output, not optional
|
||||
|
||||
@@ -9,8 +9,11 @@ model: sonnet
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" 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`.
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. `--depth` is
|
||||
the pre-1.1 name for the same flag: treat `--depth <mode>` exactly as
|
||||
`--review <mode>`, and say once that it was renamed. Given both, `--review`
|
||||
wins and `--depth` is ignored — say so. No block → defaults in
|
||||
`.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
## Phase 0: Parse Arguments
|
||||
@@ -45,7 +48,7 @@ Resolved mode controls how thorough this review is:
|
||||
## Phase 1: Load Documents
|
||||
|
||||
**Freshness check first — a re-review of an unchanged document costs full
|
||||
price (~46k tokens, measured) and reproduces the same verdict.** Run:
|
||||
price 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"
|
||||
@@ -73,13 +76,9 @@ appear in the output and doesn't block the skip).
|
||||
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
|
||||
reading or re-analyzing unchanged sections.** A section-scoped re-review
|
||||
misses defects a full review finds, and saves little or nothing.
|
||||
"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
|
||||
@@ -109,7 +108,7 @@ 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.
|
||||
|
||||
**Lore/narrative alignment:** If `design/gdd/game-concept.md` or any file in `design/narrative/` exists, read it. Note any mechanical choices in this GDD that contradict established world rules, tone, or design pillars. Pass this context to `game-designer` in Phase 3b.
|
||||
**Lore/narrative alignment:** If `design/gdd/game-concept.md` (or, at `rigor: minimal`, the one-page brief `design/game-brief.md`) or any file in `design/narrative/` exists, read it. Note any mechanical choices in this GDD that contradict established world rules, tone, or design pillars. Pass this context to `game-designer` in Phase 3b.
|
||||
|
||||
**Prior review check:** Check whether `design/gdd/reviews/[doc-name]-review-log.md` exists. If it does, read the most recent entry — note what verdict was given and what blocking items were listed. This session is a re-review; track whether prior items were addressed.
|
||||
|
||||
@@ -159,6 +158,11 @@ spot-read any section the verdict actually turns on.
|
||||
- Are the rules precise enough for a programmer to implement without guessing?
|
||||
- Are there any "hand-wave" sections where details are missing?
|
||||
- Are performance implications considered?
|
||||
- Is every acceptance criterion independently testable? Flag each one that is
|
||||
not, quoting it — "feels balanced", "works correctly", "performs well" are not
|
||||
criteria — with a measurable rewrite. In `full` mode `qa-lead` also checks them
|
||||
(Phase 3b); in `lean` and `solo` no specialist runs, so this main-review check
|
||||
is the only one.
|
||||
|
||||
**Cross-system consistency:**
|
||||
- Does this conflict with any existing mechanic?
|
||||
@@ -230,8 +234,8 @@ Issue all `Agent` calls simultaneously. Do NOT spawn one at a time.
|
||||
|
||||
After all specialists respond, spawn `creative-director` as the **senior reviewer**:
|
||||
- Provide: the GDD, all specialist findings, any disagreements between them
|
||||
- Ask: "Synthesise these findings. What are the most important issues? Do you agree with the specialists? What is your overall verdict on this design?"
|
||||
- The creative-director's synthesis becomes the **final verdict** in Phase 4.
|
||||
- Ask: "Synthesise these findings. What are the most important issues? Do you agree with the specialists? What is your overall verdict on this design — APPROVED, NEEDS REVISION or MAJOR REVISION NEEDED?"
|
||||
- The creative-director's synthesis becomes the **final verdict** in Phase 4, in this skill's verdict words — never a director-gate word such as READY or REJECT.
|
||||
|
||||
### Step 4 — Surface disagreements
|
||||
|
||||
@@ -319,10 +323,16 @@ Use `AskUserQuestion` for ALL closing interactions. Never plain text.
|
||||
|
||||
If APPROVED (first-pass, no revision needed), proceed directly to the systems-index widget, review-log widget, then the final closing widget. Do not show a separate "what to do" widget — the final closing widget covers next steps.
|
||||
|
||||
If NEEDS REVISION or MAJOR REVISION NEEDED, options:
|
||||
If NOT ASSESSED, nothing was reviewed: offer no tracking update and go straight
|
||||
to the final closing widget, leading with the skill that produces the missing
|
||||
input (e.g. `/design-system [system]` for a GDD that does not exist).
|
||||
|
||||
If NEEDS REVISION or MAJOR REVISION NEEDED, build the options from the findings:
|
||||
- `[A] Revise the GDD now — address blocking items together`
|
||||
- `[B] Stop here — revise in a separate session`
|
||||
- `[C] Accept as-is and move on (only if all items are advisory)`
|
||||
- `[C] Accept as-is and move on` — include only when every finding is advisory
|
||||
(Required Before Implementation is empty). With any blocking item, offer [A]
|
||||
and [B] only.
|
||||
|
||||
**If user selects [A] — Revise now:**
|
||||
|
||||
@@ -334,7 +344,7 @@ After all revisions are complete, show a summary table (blocker → fix applied)
|
||||
- Note current context usage: if context is above ~50%, add: "(Recommended: /clear before re-review — this session has used X% context. A full re-review runs 5 agents and needs clean context.)"
|
||||
- Options:
|
||||
- `[A] Re-review in a new session — run /design-review [doc-path] after /clear`
|
||||
- `[B] Accept revisions and mark Approved — update systems index, skip re-review`
|
||||
- `[B] Accept revisions for now — mark In Review in the systems index; a re-review decides Approved`
|
||||
- `[C] Move to next system — /design-system [next-system] (#N in design order)`
|
||||
- `[D] Stop here`
|
||||
|
||||
@@ -355,7 +365,7 @@ If the review-log option is selected, append the same format as below. Execute b
|
||||
When the verdict is NEEDS REVISION or MAJOR REVISION NEEDED, use separate widgets as before:
|
||||
|
||||
Use a second `AskUserQuestion`:
|
||||
- Prompt: "May I update `design/gdd/systems-index.md` to mark [system] as [In Review / Approved]?"
|
||||
- Prompt: "May I update `design/gdd/systems-index.md` to mark [system] as [Needs Revision / In Review]?" — `Needs Revision` (that exact string) while the revisions are outstanding, `In Review` once they are applied and await re-review. This prompt never offers `Approved`: a revision verdict is not an approval.
|
||||
- Options: `[A] Yes — update it` / `[B] No — leave it as-is`
|
||||
|
||||
Use a third `AskUserQuestion`:
|
||||
@@ -397,12 +407,12 @@ verbatim).
|
||||
Once the systems-index and review-log widgets are answered, check project state and show one final `AskUserQuestion`:
|
||||
|
||||
Before building options, read:
|
||||
- `design/gdd/systems-index.md` — find any system with Status: In Review or NEEDS REVISION (other than the one just reviewed)
|
||||
- `design/gdd/systems-index.md` — find any system with Status: In Review or Needs Revision (other than the one just reviewed)
|
||||
- Count `.md` files in `design/gdd/` (excluding game-concept.md, systems-index.md) to determine if `/review-all-gdds` is worth offering (≥2 GDDs)
|
||||
- Find the next system with Status: Not Started in design order
|
||||
|
||||
Build the option list dynamically — only include options that are genuinely next:
|
||||
- `[_] Run /design-review [other-gdd-path] — [system name] is still [In Review / NEEDS REVISION]` (include if another GDD needs review)
|
||||
- `[_] Run /design-review [other-gdd-path] — [system name] is still [In Review / Needs Revision]` (include if another GDD needs review)
|
||||
- `[_] Run /consistency-check — verify this GDD's values don't conflict with existing GDDs` (always include if ≥1 other GDD exists)
|
||||
- `[_] Run /review-all-gdds — holistic design-theory review across all designed systems` (include if ≥2 GDDs exist)
|
||||
- `[_] Run /design-system [next-system] — next in design order` (always include, name the actual system)
|
||||
|
||||
@@ -27,9 +27,9 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
**`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,
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = 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
|
||||
(`rigor: standard`); `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
|
||||
@@ -207,7 +207,7 @@ From the systems index, identify:
|
||||
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
|
||||
Grep pattern="^## ([0-9]+\. )?(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
|
||||
@@ -564,6 +564,12 @@ it if absent, Edit to update it if present.
|
||||
|
||||
Each section has unique design considerations and may benefit from specialist agents:
|
||||
|
||||
**Every skipped spawn is announced.** When a section's review-mode check below
|
||||
skips its specialist — in `lean` as well as `solo` — print that section's note
|
||||
with the mode it ran in, e.g. "`creative-director` not consulted — Lean mode.
|
||||
Review manually before production." A section drafted without its specialist
|
||||
must say so in the output, whichever mode skipped it.
|
||||
|
||||
---
|
||||
|
||||
### Section A: Overview
|
||||
@@ -671,7 +677,7 @@ This is usually the largest section. Break it into sub-sections:
|
||||
- What can the player NOT do? (Constraints are as important as capabilities)
|
||||
|
||||
**Review mode check** (apply before spawning):
|
||||
- `solo` → skip this agent spawn. Draft the section without the specialist. Add a note: "Specialist agents not consulted — Solo mode. Review manually before production."
|
||||
- `solo` → skip this agent spawn. Draft the section without the specialist. Add a note naming them: "`[the Section 6 routing table's Primary and Supporting Agents for this category]` 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.
|
||||
|
||||
@@ -1029,10 +1035,17 @@ the source of truth). Verify:
|
||||
|
||||
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.
|
||||
Pass: completed GDD file path, game pillars (from `design/gdd/game-concept.md` or `design/gdd/game-pillars.md`; if there is neither, the pitch and "what they feel" line of `design/game-brief.md`), MDA aesthetics target, and the GDD's Player Fantasy section — or, when this tier did not author one, say so.
|
||||
|
||||
Handle verdict per the standard rules in `director-gates.md`. After resolution, record the verdict in the GDD Status header:
|
||||
`> **Creative Director Review (CD-GDD-ALIGN)**: APPROVED [date] / CONCERNS (accepted) [date] / REVISED [date]`
|
||||
Handle verdict per the standard rules in `director-gates.md`.
|
||||
On `Revise flagged items`, or to resolve a REJECT, each flagged section runs its
|
||||
section cycle again — its specialist consulted as that section's review-mode
|
||||
check says — and is re-approved through its "Approve the [Section Name]
|
||||
section?" widget before the Edit that writes it; then record `REVISED [date]`.
|
||||
A `NOT ASSESSED` answer is never an approval: name the missing input, then
|
||||
supply it and re-run the gate, or record `NOT ASSESSED`.
|
||||
After resolution, record the verdict in the GDD Status header:
|
||||
`> **Creative Director Review (CD-GDD-ALIGN)**: APPROVED [date] / CONCERNS (accepted) [date] / REVISED [date] / NOT ASSESSED [date] — [missing input]`
|
||||
|
||||
---
|
||||
|
||||
@@ -1125,7 +1138,7 @@ nothing else in §5 hints the file may be absent.
|
||||
- Read the systems index
|
||||
- Update the target system's row:
|
||||
- If design-review was run and verdict is APPROVED: Status → "Approved"
|
||||
- If design-review was run and verdict is NEEDS REVISION: Status → "In Review"
|
||||
- If design-review was run and verdict is NEEDS REVISION or MAJOR REVISION NEEDED: Status → "Needs Revision" (that exact string — `/design-review` sets "In Review" only once the revisions are applied)
|
||||
- If design-review was skipped: Status → "Designed" (pending review)
|
||||
- If the user chose "I'll review it myself first": Status → "Designed"
|
||||
- Design Doc: link to `design/gdd/[system-name].md`
|
||||
@@ -1272,4 +1285,4 @@ shows context at or above 70%. If so, append this notice to the response:
|
||||
- Run `/design-review design/gdd/[system-name].md` in a **fresh session** to validate the completed GDD independently
|
||||
- Run `/consistency-check` to verify this GDD's values don't conflict with other GDDs
|
||||
- Run `/map-systems next` to move to the next highest-priority undesigned system
|
||||
- Run `/gate-check pre-production` when all MVP GDDs are authored and reviewed
|
||||
- Run `/gate-check technical-setup` when all MVP GDDs are authored and reviewed
|
||||
|
||||
@@ -1,29 +1,34 @@
|
||||
# /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`.
|
||||
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 `/story-done` (with `/code-review` first at `standard`/`full`).
|
||||
|
||||
## 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 |
|
||||
| `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. On an ADR version mismatch answered `[A]` it sets `ADR Version` to the ADR's current version and refreshes `**ADR Decision Summary**` and `## Implementation Notes`; on a manifest mismatch answered `[A]`/`[B]` it sets `Manifest Version:` (and on `[B]` adds `Manifest-Note:`). 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/adr-NNNN-[slug].md` (referenced ADR) | `## Status`, `## Last Verified` (else `## Date`) — grepped; `## Decision` (with its `### Implementation Guidelines`), `## Engine Compatibility`, `## ADR Dependencies` — read only on a version mismatch answered `[A]` | Yes — the ADR is never edited; a mismatch updates the story's stamp, not the ADR |
|
||||
| `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 |
|
||||
|
||||
> **Tier.** SKILL.md Phase 2 decides by `workflow`: the TR registry is required at
|
||||
> `full`, optional at `standard` and not expected at `minimal`; a missing control
|
||||
> manifest warns at `full`/`standard` and is not expected at `minimal`; an ADR
|
||||
> blocks only when the story references one that is missing or `Proposed`.
|
||||
|
||||
### 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`
|
||||
- The target story must have `Status: Ready` (validated by `/story-readiness` at `standard`/`full`; at `minimal`, `/create-stories` writes stories `Ready` and `/story-readiness` is not on the path)
|
||||
- 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 accept [ADR-id]`; `Deprecated` or `Superseded` also blocks, naming the successor. A story whose ADR field reads `N/A` references none, at every tier
|
||||
- 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)
|
||||
- At `full`, `docs/architecture/tr-registry.yaml` must contain the story's TR-ID (optional at `standard`, not expected at `minimal`)
|
||||
- `docs/architecture/control-manifest.md` supplies the layer rules when present; a missing one warns and never stops the skill
|
||||
|
||||
## Outputs Produced
|
||||
|
||||
@@ -31,37 +36,40 @@ Bridges planning and code by loading the full context for a single story (story
|
||||
| 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) |
|
||||
| `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 per engine (`.claude/rules/test-standards.md`); no random seeds; no external I/O | created by sub-agent; path matches `## Test Evidence` in story |
|
||||
| `production/session-state/active.md` | `<!-- CHECKPOINT -->` block: current task (story path), next step, blocker, files in progress, run result | block overwritten, never appended (file created from `.claude/docs/templates/session-state.md` 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
|
||||
- Session state records files changed and the next recommended invocation (`/story-done`; `/code-review` first at `standard`/`full`) — on INCOMPLETE, `/dev-story` to resume; on BLOCKED, the unblocking action
|
||||
- The implementation summary states a **verification** result — what was run against the written code (Godot: `.claude/scripts/godot-parse-check.gd` over the changed scripts; Unity: `commands.smoke`; Unreal: the editor-target build) and its exit code. 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
|
||||
- At `qa.level: minimal` no test file is written, and for a Logic or Integration story the summary says so explicitly (`Test evidence: waived at qa.level: minimal`); UI and Visual/Feel stories get no waiver line, because their screenshot still applies. 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`
|
||||
- MODIFIES, via sub-agent: `<code root>/**` (new/updated source files; code root resolved per `.claude/docs/code-root-resolution.md`) and the engine's test root (the new test file; `tests/` on Godot)
|
||||
- MODIFIES, itself, each after an ask that names the file (in `collaborative` mode; `.claude/docs/automation-modes.md` governs the others): the story file's `Status:`, `Last Updated:`, `ADR Version`, `**ADR Decision Summary**`, `## Implementation Notes`, `Manifest Version:` and `Manifest-Note:` (see the story row above); the story's entry in `production/sprint-status.yaml` (`status: in-progress`, top-level `updated`); a dependency story's `Status:` (dependency option `[C]` only); a Config/Data story's data file; on Unity, `Assets/Scripts/ScreenshotOnArg.cs`, written verbatim from `.claude/docs/run-and-observe.md` when the project has none
|
||||
- MODIFIES without an ask: `production/session-state/active.md` — its `<!-- CHECKPOINT -->` block is overwritten, never appended
|
||||
- Sets the story file's own `Status` field to `In Progress` only (Phase 2, before
|
||||
spawning any agent). Closing the story being implemented is the exclusive
|
||||
responsibility of `/story-done`; the one other `Status` this skill writes is a
|
||||
dependency's `Complete` under option `[C]` (Hard Constraints)
|
||||
|
||||
## 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 marks a story `Status: Done` or `Status: Complete` on its own judgement — that belongs to `/story-done`. The one exception is a dependency the user states is already done (Phase 2 dependency option `[C]`): its `Status` is set to `Complete` only after "May I update [dependency path] Status to Complete?" is approved
|
||||
- Never begins implementation without loading the full context package (story, TR-ID from registry, ADR Decision + Implementation Guidelines — as distilled in the story, or re-read from the ADR after a mismatch answered `[A]` — control-manifest layer rules, engine prefs)
|
||||
- Never implements a story whose referenced ADR has `Status: Proposed`, `Deprecated` or `Superseded` — 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
|
||||
- Source and test files are written by sub-agents via `Agent`; this orchestrator writes none directly, except the verbatim `ScreenshotOnArg.cs` capture script on Unity, after an ask
|
||||
|
||||
## Downstream Skill Expects
|
||||
**Next skill:** `/story-done`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dev-story
|
||||
description: "Implement a story: ADR guidelines, right programmer agent, code plus test. After /story-readiness, before /code-review and /story-done."
|
||||
description: "Implement a story: ADR guidelines, right programmer agent, code plus test. Then /story-done (/story-readiness before, /code-review after, at standard/full)."
|
||||
argument-hint: "[story-path]"
|
||||
user-invocable: true
|
||||
disable-model-invocation: true
|
||||
@@ -29,9 +29,12 @@ drives implementation to completion — including writing the test.
|
||||
/story-done [path] ← verify and close it
|
||||
```
|
||||
|
||||
**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.
|
||||
**At `workflow: minimal`** the loop is `/dev-story [path]` → `/story-done [path]`:
|
||||
no QA plan, readiness check or sprint. `/story-done` names the next story.
|
||||
|
||||
**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`.
|
||||
**With a sprint plan, 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 under the project's **code root** + test file under the engine's **test root** (`tests/` Godot, `Assets/Tests/` Unity, `Source/<Module>/Private/Tests/` Unreal — `.claude/docs/directory-structure.md`). Resolve the code root from `engine.name` (`src/` Godot, `Assets/` Unity, `Source/<Module>/` Unreal) per `.claude/docs/code-root-resolution.md`.
|
||||
|
||||
---
|
||||
|
||||
@@ -48,8 +51,8 @@ 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**
|
||||
expected implementation cycle: **multi-day** at `coarse` (the default, via `rigor: minimal`; give the programmer
|
||||
subagent longer working context), **1–2 days** at `balanced` (`rigor: standard`), **hours**
|
||||
at `fine` (tighter context). It does not change the prerequisite gate.
|
||||
|
||||
**`qa.level`**: controls whether the programmer brief carries
|
||||
@@ -76,10 +79,10 @@ If not found, ask: "Which story are we implementing?" Glob
|
||||
| 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 |
|
||||
| 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." Also STOP if its `## Status` is `Proposed` — "ADR [path] is still Proposed. Accept it with `/architecture-decision accept [ADR-id]` before implementing." A story whose ADR field reads `N/A` (`N/A — [reason]`) references none — proceed. | **STOP only if the story references an ADR** and its file is missing/Proposed/Deprecated/Superseded; if it references none, proceed | no ADR required — proceed; **STOP only if the story references an ADR** whose file is missing/Proposed/Deprecated/Superseded |
|
||||
| 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 |
|
||||
|
||||
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.
|
||||
At `full`, if the TR registry is missing, or a referenced governing ADR is missing or `Proposed`, 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, `Proposed`, `Deprecated` or `Superseded`** 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 the story file and the TR registry simultaneously — these two are
|
||||
genuinely independent, unconditional reads. **The governing ADR is not part
|
||||
@@ -120,22 +123,30 @@ 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:
|
||||
**Check status and 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
|
||||
Grep pattern="^## (Status|Last Verified|Date)" path="docs/architecture/[adr-file].md" output_mode="content" -A 2
|
||||
```
|
||||
|
||||
Compare that date against the story's `**ADR Version**` field:
|
||||
The `## Status` line decides first: if it reads `Proposed`, the story is BLOCKED
|
||||
per the file-check table above — stop here, before any freshness comparison.
|
||||
`Deprecated` or `Superseded by ADR-XXXX` blocks the same way, at every tier:
|
||||
"ADR [path] is [status]; point the story at [successor] (edit its ADR field —
|
||||
`/create-stories` never rewrites an existing story) before implementing."
|
||||
|
||||
Then resolve the ADR's **current version** the way `/create-stories` stamped it:
|
||||
its `## Last Verified` date, else its `## Date`, else `unversioned`. Compare that
|
||||
value 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. |
|
||||
| Versions **match** (a date on both sides) | 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. |
|
||||
| Both read `unversioned` | The ADR has neither `## Last Verified` nor `## Date`. Consistent, not stale — but nothing to compare. | **Trust the story**; note "ADR carries no date; summary trusted unverified." in the Phase 6 summary, and recommend `/architecture-decision retrofit [file]`, which adds a missing `## Date`. |
|
||||
| The ADR resolves to `unversioned` but the story names a date | Ambiguous — the ADR lost the field the story was stamped from. | Treat as **mismatch** (below). |
|
||||
| Versions **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
|
||||
@@ -147,15 +158,14 @@ 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)`
|
||||
- `[A] Re-read the changed ADR sections, implement against current guidance, and refresh this story's ADR summary and ADR Version (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
|
||||
- **Under ~50KB** — read the whole file with one `Read` call. At this size one
|
||||
read is *cheaper* than the multi-grep path — 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,
|
||||
@@ -166,7 +176,11 @@ If **[A]**: first check the ADR's size — `Bash: wc -c "docs/architecture/[adr-
|
||||
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.
|
||||
Then make the story edit that option [A] names: set its `ADR Version` to the ADR's
|
||||
current version resolved above — not today's date, or the next run mismatches
|
||||
again — and replace its `**ADR Decision Summary**` and `## Implementation Notes`
|
||||
with the guidance you just read, so a later run that trusts the stamp is trusting
|
||||
current guidance.
|
||||
If **[B]**: proceed on the summary; record it in the Phase 6 "Deviations" summary.
|
||||
If **[C]**: stop. Do not spawn any agent.
|
||||
|
||||
@@ -182,7 +196,7 @@ If they differ, use `AskUserQuestion` before proceeding:
|
||||
- Prompt: "Story was written against manifest v[story-date]. Current manifest is v[current-date]. New rules may apply. How do you want to proceed?"
|
||||
- Options:
|
||||
- `[A] Update story manifest version and implement with current rules (Recommended)`
|
||||
- `[B] Implement with old rules — I accept the risk of non-compliance`
|
||||
- `[B] Implement with old rules — I accept the risk of non-compliance (the story records the current Manifest Version and a Manifest-Note)`
|
||||
- `[C] Stop here — I want to review the manifest diff first`
|
||||
|
||||
If [A]: edit the story file's `Manifest Version:` field to the current manifest date before spawning the programmer. Then read the manifest carefully for new rules.
|
||||
@@ -222,9 +236,16 @@ Read from `project.yaml` first, falling back to `.claude/docs/technical-preferen
|
||||
|
||||
### Mark Story In Progress
|
||||
|
||||
Silently update two things before spawning any agent:
|
||||
Before spawning any agent, mark the story In Progress. In `collaborative` mode
|
||||
ask once first — "May I mark this story In Progress? This sets `Status:` and
|
||||
`Last Updated:` in `[story-path]` and its entry in `production/sprint-status.yaml`."
|
||||
(leave the sprint-status file out of the question when it does not exist);
|
||||
`guided` and `autonomous` update these existing files without asking
|
||||
(`.claude/docs/automation-modes.md`). If the user declines, change neither file,
|
||||
print `Story not marked In Progress — declined` in the Phase 6 summary, and
|
||||
continue. Otherwise update two things:
|
||||
|
||||
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.
|
||||
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**: 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.
|
||||
|
||||
@@ -309,8 +330,7 @@ assumptions about post-cutoff engine APIs that need expert verification.
|
||||
> `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
|
||||
> rating of HIGH would skip this spawn without saying so. `/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.
|
||||
|
||||
@@ -324,7 +344,8 @@ Brief the agent with file paths and targeted reading instructions — do not ser
|
||||
|
||||
> **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
|
||||
> only where the story references one — at any tier, a story whose ADR field
|
||||
> reads `N/A` has no item 3. 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
|
||||
@@ -339,8 +360,8 @@ Brief the agent with file paths and targeted reading instructions — do not ser
|
||||
> 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.`
|
||||
> (absent), ADR guidance (story references no ADR), 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
|
||||
@@ -348,11 +369,11 @@ Brief the agent with file paths and targeted reading instructions — do not ser
|
||||
|
||||
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 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.
|
||||
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. After mismatch option `[A]`, pass the guidance freshly read from the ADR's `## Decision` (the text [A] just wrote into the story), never the stale summary the story carried before; after `[B]`, pass the story's summary and tell the agent it predates the current ADR.
|
||||
4. **Control manifest**: `docs/architecture/control-manifest.md` — read rules for the **[layer]** layer only
|
||||
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; **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.
|
||||
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 for a Logic or Integration story, tell the agent so explicitly — never a UI, Visual/Feel or Config/Data story, which this item never covered: *"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 naming per engine, from `.claude/rules/test-standards.md`: Godot `test_[scenario]_[expected]` in `[system]_[feature]_test.gd`; Unity `[Scenario]_[Expected]` in a `[System]Tests` class; Unreal `<Project>.[System].[Scenario]`. 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:
|
||||
@@ -364,9 +385,9 @@ The agent should:
|
||||
### Config/Data stories (no agent needed)
|
||||
|
||||
For Type: Config/Data stories, no programmer agent is required. The implementation
|
||||
is editing a data file. Read the story's acceptance criteria and make the specified
|
||||
changes to the data file directly. Note which values were changed and what they
|
||||
changed from/to.
|
||||
is editing a data file. Read the story's acceptance criteria, show the specified
|
||||
changes as from → to values, and ask "May I write to [data file path]?" before
|
||||
editing it directly. Note which values were changed and what they changed from/to.
|
||||
|
||||
### Visual/Feel stories
|
||||
|
||||
@@ -385,11 +406,13 @@ The test requirement was included in the Phase 4 programmer agent brief (item 7)
|
||||
|
||||
**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.
|
||||
missing test. **The Visual/Feel and UI screenshot line at the end of this phase
|
||||
still applies** — `qa.level` waives tests, never the look.
|
||||
|
||||
> **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:
|
||||
> 3). For a Logic or Integration story — the types Phase 4 item 7 briefs a test
|
||||
> for — emit the line:
|
||||
>
|
||||
> > *Test evidence: **waived** at `qa.level: minimal` — no test was required or
|
||||
> > written for this story.*
|
||||
@@ -443,7 +466,7 @@ 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."
|
||||
For Visual/Feel and UI stories, include in the Phase 6 summary: "Retained screenshot required under `production/qa/evidence/[story-slug]/` before this story can be closed — at the default BLOCKING level a story with no screenshot on disk is unverifiable." For Visual/Feel, add that the sign-off in `production/qa/evidence/[slug]-evidence.md` is also required.
|
||||
|
||||
---
|
||||
|
||||
@@ -461,10 +484,28 @@ 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.
|
||||
2. **Verify the output parses.** Run the check whose **exit code** answers the
|
||||
question — an exit 0 from a command that does not check is how broken code
|
||||
gets reported as clean:
|
||||
- **Godot:** `godot --headless --path . --import` once (it builds the class
|
||||
cache), then one run over every `.gd` the story added or changed:
|
||||
`godot --headless --path . -s res://.claude/scripts/godot-parse-check.gd -- res://<file>.gd …`.
|
||||
For `godot`, use the executable `commands.test` names, else the editor
|
||||
`engine.path` records, else `godot` on `PATH`; if none resolves, write
|
||||
`parse NOT VERIFIED — Godot executable not found`.
|
||||
Exit 1 means a script did not load — its `PARSE FAIL:` line names it, with
|
||||
Godot's error above. Do not use `--check-only`: it fails valid code that
|
||||
names an autoload. `--import` and `--quit-after` on their own exit 0 on a
|
||||
parse error — they are not parse checks.
|
||||
- **Unity:** `commands.smoke` (`-batchmode -quit -projectPath . -logFile -`)
|
||||
— exit 1 with `error CS…` lines when a script does not compile.
|
||||
- **Unreal:** build the editor target —
|
||||
`"<UE root>/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe" <Project>Editor Win64 Development -Project="<absolute path>/<Project>.uproject"`
|
||||
on Windows; on Linux `"<UE root>/Engine/Build/BatchFiles/Linux/Build.sh" <Project>Editor Linux Development -Project=…`,
|
||||
on macOS `…/Mac/Build.sh <Project>Editor Mac Development -Project=…` (from Epic's
|
||||
documentation — `docs/engine-reference/unreal/current-best-practices.md`, "Command Line").
|
||||
A compile error fails the build (`Result: Failed`, non-zero exit).
|
||||
Report what you ran, its exit code, and any error lines.
|
||||
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.
|
||||
@@ -477,6 +518,11 @@ Before collecting anything:
|
||||
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`.
|
||||
**On Unity** the capture needs the `ScreenshotOnArg.cs` script that file gives
|
||||
verbatim. If the project has none (Glob `Assets/**/ScreenshotOnArg.cs`), ask
|
||||
"May I write `Assets/Scripts/ScreenshotOnArg.cs`?" and write it exactly as
|
||||
given there before launching; if the user declines, nothing can capture —
|
||||
report `Run result: NOT VERIFIED — ScreenshotOnArg.cs not written`.
|
||||
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.
|
||||
@@ -506,7 +552,7 @@ Present a concise implementation summary:
|
||||
**Files changed**:
|
||||
- `<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*
|
||||
`qa.level: minimal` and print the Phase 5 waiver line instead (Logic/Integration)*
|
||||
|
||||
**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`
|
||||
@@ -521,27 +567,46 @@ Present a concise implementation summary:
|
||||
**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. *(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.
|
||||
**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 for a Logic or Integration story, and omit both for any other type. 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]`
|
||||
Ready for: `/story-done [story-path]` — at `standard`/`full`, `/code-review [file1] [file2]` first
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Update Session State
|
||||
|
||||
Silently append to `production/session-state/active.md`:
|
||||
Silently update the checkpoint in `production/session-state/active.md` —
|
||||
**overwrite the `<!-- CHECKPOINT -->` … `<!-- /CHECKPOINT -->` block, never
|
||||
append** (schema: `.claude/docs/templates/session-state.md`). `session-start.sh`
|
||||
shows exactly that block when the next session opens, so it is what a cold
|
||||
resume starts from:
|
||||
|
||||
```
|
||||
## Session Extract — /dev-story [date]
|
||||
- Story: [story-path] — [story title]
|
||||
- Files changed: [comma-separated list]
|
||||
- Test written: [path, or "None — Visual/Feel/Config story"]
|
||||
- Blockers: [None, or description]
|
||||
- Next: /code-review [files] then /story-done [story-path]
|
||||
<!-- CHECKPOINT -->
|
||||
**Updated:** [date]
|
||||
**Branch:** `[current git branch]`
|
||||
**Current task:** /dev-story — [story-path] ([story title])
|
||||
**Next step:** /story-done [story-path] (at standard/full: /code-review [files] first)
|
||||
**Blocked on:** [nothing, or the blocker]
|
||||
**Files in progress:** [files changed, comma-separated; test file included]
|
||||
**Run result:** [the Phase 6 `Run result:` line, verbatim — `/story-done` reads it here]
|
||||
**Open questions:** [none, or one line each]
|
||||
<!-- /CHECKPOINT -->
|
||||
```
|
||||
|
||||
Create `active.md` if it does not exist. Confirm: "Session state updated."
|
||||
**Next step** follows the Phase 6 result — the line above is the Implementation
|
||||
Complete one. On **INCOMPLETE** write
|
||||
`**Next step:** /dev-story [story-path] — resume: [the breakage Phase 6 named]`.
|
||||
On **BLOCKED** (Phase 2) write the unblocking action instead —
|
||||
`/architecture-decision accept ADR-NNNN`, the dependency story to finish, the
|
||||
manifest diff to review — and fill **Blocked on**. `/help` reads this line: a
|
||||
checkpoint that says `/story-done` tells it the work is written.
|
||||
|
||||
If `active.md` does not exist, create it from the template. If it exists with no
|
||||
markers (a file from before the schema), insert the template's STATUS and
|
||||
CHECKPOINT blocks at the top and leave the rest untouched. Confirm: "Session
|
||||
state updated."
|
||||
|
||||
---
|
||||
|
||||
@@ -561,7 +626,7 @@ 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
|
||||
- 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)
|
||||
- A *referenced* ADR's status is Proposed → do not implement; accept it with `/architecture-decision accept ADR-NNNN` once decided (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
|
||||
@@ -572,7 +637,14 @@ Common blockers:
|
||||
`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.
|
||||
- **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 writes only the following, each after an ask that names it:
|
||||
- the story's `Status:` / `Last Updated:` and its `production/sprint-status.yaml` entry — the one "May I mark this story In Progress?" ask (Phase 2)
|
||||
- the story's `ADR Version`, `**ADR Decision Summary**` and `## Implementation Notes` (ADR mismatch option [A]), and its `Manifest Version:` / `Manifest-Note:` (manifest option [A] or [B]) — each option names that edit, so choosing it is the ask
|
||||
- a dependency story's `Status: Complete` (dependency option [C], then "May I update [dependency path] Status to Complete?")
|
||||
- a Config/Data story's data file ("May I write to [path]?")
|
||||
- on Unity, `Assets/Scripts/ScreenshotOnArg.cs`, written verbatim from `.claude/docs/run-and-observe.md` ("May I write `Assets/Scripts/ScreenshotOnArg.cs`?", Phase 6)
|
||||
|
||||
The session-state checkpoint in `production/session-state/active.md` is the one write made without an ask.
|
||||
- **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.
|
||||
@@ -586,8 +658,11 @@ describe what collaborative mode requires, not universal behavior.
|
||||
- **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`
|
||||
- **Visual/Feel and UI looks are observed, not deferred** — the Phase 6 run
|
||||
retains the screenshot (each screen touched for UI; Visual/Feel also needs a
|
||||
lead sign-off before `/story-done`), and `qa.level` never waives either. Only
|
||||
the *feel* half of a Visual/Feel criterion — timing, weight, responsiveness —
|
||||
is marked DEFERRED, for `/team-qa`
|
||||
- **Ask before large structural decisions** — if the story requires an
|
||||
architectural pattern not covered by the ADR, surface it before implementing:
|
||||
"The ADR doesn't specify how to handle [case]. My plan is [X]. Proceed?"
|
||||
@@ -596,6 +671,6 @@ describe what collaborative mode requires, not universal behavior.
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
- Run `/code-review [file1] [file2]` to review the implementation before closing the story
|
||||
- At `standard`/`full`, run `/code-review [file1] [file2]` to review the implementation before closing the story (not part of the minimal loop)
|
||||
- Run `/story-done [story-path]` to verify acceptance criteria and mark the story complete
|
||||
- After all sprint stories are done: run `/team-qa sprint` for the full QA cycle before advancing the project stage
|
||||
- With a sprint plan, after all sprint stories are done: run `/team-qa sprint` for the full QA cycle before advancing the project stage. At `minimal`, `/story-done` names the next story instead
|
||||
|
||||
@@ -24,7 +24,10 @@ Identify files and modules that would need to change:
|
||||
- Assess complexity (size, dependency count, cyclomatic complexity)
|
||||
- Identify integration points with other systems
|
||||
- Check for existing test coverage in the affected areas
|
||||
- Read past sprint data from `production/sprints/` for similar completed tasks and historical velocity
|
||||
- Read past sprint data from `production/sprints/` for similar completed tasks and historical velocity.
|
||||
**If there is none**, say so under Notes and Assumptions — "No sprint history found;
|
||||
this estimate is not calibrated to the team's velocity" — and treat that as a risk
|
||||
in the confidence level, not as a silent padding of the figures.
|
||||
|
||||
---
|
||||
|
||||
@@ -130,3 +133,4 @@ This skill is read-only — no files are written. Verdict: **COMPLETE** — esti
|
||||
- The recommended budget should be the expected estimate, not the optimistic one
|
||||
- Round to half-day increments — estimating in hours implies false precision for tasks longer than a day
|
||||
- Do not pad estimates silently — call out risk explicitly so the team can decide
|
||||
- Confidence is Low whenever the approach is undecided or the core requirements are still TBD — a range built on an unmade decision is a guess
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# /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).
|
||||
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, or on CONCERNS when the user explicitly accepts the listed risks — writing the new stage name to `project.stage` in `project.yaml` (and legacy `production/stage.txt` for backward compatibility).
|
||||
|
||||
## Inputs Required
|
||||
|
||||
@@ -9,7 +9,7 @@ Validates whether the project is ready to advance from one development phase to
|
||||
| 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 |
|
||||
| `project.yaml` (`modes.workflow`, which follows `modes.rigor` — `minimal` by default; `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 |
|
||||
@@ -17,12 +17,12 @@ Validates whether the project is ready to advance from one development phase to
|
||||
### 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` |
|
||||
| Concept → Systems Design | `design/gdd/game-concept.md`; pillars either inside it **or** in an optional `design/gdd/game-pillars.md` — at the `minimal` tier, `design/game-brief.md` instead (pillars check drops) |
|
||||
| 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 |
|
||||
| Pre-Production → Production | `production/sprints/` (first sprint plan), `docs/architecture/control-manifest.md`, `production/epics/` (Foundation + Core layer epics), `design/ux/hud.md`, `design/ux/` key screen specs; recommended, not blocking: `prototypes/*-vertical-slice/REPORT.md` and its playtest in `production/qa/playtests/` — at the `minimal` tier, only a filled `design/game-brief.md` with its build order and stories under `production/epics/` (no sprint plan; the rest drops, the Vertical Slice items included — two checks on the current build replace them: the core loop is fun, and it runs end to end) |
|
||||
| Production → Polish | code-root subsystems (resolve per `.claude/docs/code-root-resolution.md`), the engine's test root — `tests/unit/` + `tests/integration/` (Godot), `Assets/Tests/` (Unity), `Source/<Module>/Private/Tests/` (Unreal) — with all Logic stories covered, `production/qa/smoke-*.md` (PASS or PASS WITH WARNINGS), `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, the newest full-scope `production/security/security-audit-*.md` (plus any later `quick` re-run) |
|
||||
|
||||
### 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
|
||||
@@ -34,48 +34,48 @@ Validates whether the project is ready to advance from one development phase to
|
||||
| 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 |
|
||||
| `project.yaml` (`project.stage`) + legacy `production/stage.txt` | New stage name (dual-write for backward compat) | written ONLY when the verdict is PASS and the user explicitly confirms, or the verdict is CONCERNS and the user explicitly accepts the listed risks; never written on FAIL or NOT ASSESSED |
|
||||
|
||||
### 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
|
||||
- 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 — plus an `### Accepted Risks` section (each concern, accepted by the user, dated) when the user advanced on CONCERNS
|
||||
- `project.stage` (and legacy `production/stage.txt`) is updated to the new stage name only on a confirmed PASS, or on CONCERNS after the user explicitly accepts the risks — 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)
|
||||
- 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 under the engine's test root (run via Bash)
|
||||
- MODIFIES: `project.yaml` (`project.stage` only) + legacy `production/stage.txt` (both on a confirmed PASS or an accepted CONCERNS override 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 writes stage (either `project.yaml` `project.stage` or legacy `production/stage.txt`) unless the verdict is PASS and the user has explicitly confirmed advancement, or the verdict is CONCERNS and the user has explicitly accepted every listed risk (recorded in the report's `### Accepted Risks`)
|
||||
- Never writes stage on a FAIL or NOT ASSESSED verdict under any circumstances — no override turns either into a stage change
|
||||
- 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
|
||||
- Never blocks the user from working — the verdict decides only whether the stage is written; a CONCERNS override records the accepted risks in the gate report
|
||||
- Never passes a director "none" for an artifact the target gate does not require yet — that is "not expected before [phase]" (or "not required at `workflow: [tier]`"), and not a finding; "none" is reserved for an artifact the gate asks for that does not exist
|
||||
- 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)
|
||||
- If any Vertical Slice Validation item is NO at the Pre-Production → Production gate, the verdict is automatically FAIL regardless of all other checks, at `full` and `standard`; at `minimal`, where the slice items drop, a "no" to either current-build check (the core loop is fun, it runs end to end) is FAIL the same way (tier reductions relax what must *exist*, never make a broken build 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
|
||||
- gate-check honors `modes.workflow` but is exempt from `modes.automation` — the collaborative prompting protocol (the Collaborative Protocol section) 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 |
|
||||
| Concept → Systems Design | `/map-systems` — or `/design-system` for the first system when `design/gdd/systems-index.md` already exists |
|
||||
| Systems Design → Technical Setup | `/create-architecture` first — the master architecture and the ADR work plan (it needs an engine, so `/setup-engine` if none is configured) — then `/architecture-decision` |
|
||||
| Technical Setup → Pre-Production | `/create-control-manifest` if `docs/architecture/control-manifest.md` does not exist yet, then `/vertical-slice`; `/create-epics` and `/create-stories` once the slice has validated the core loop |
|
||||
| Pre-Production → Production | `/dev-story`, `/sprint-plan`, `/story-readiness` |
|
||||
| Production → Polish | `/perf-profile`, `/playtest-report`, `/smoke-check` |
|
||||
| Polish → Release | `/launch-checklist`, `/release-checklist` |
|
||||
| Polish → Release | `/launch-checklist`, `/team-release` (the release checklist, changelog and security audit are done before this gate) |
|
||||
|
||||
- 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)
|
||||
- `/create-epics` reads `docs/architecture/control-manifest.md` — required at `full`, read if present at `standard` — and the Pre-Production → Production gate checks it
|
||||
|
||||
## 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
|
||||
- `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 `/gate-check`'s stage write
|
||||
- The Production → Polish gate runs the test suite via Bash. If the test runner command is not configured or fails to start (e.g. gdUnit4 is not installed at `addons/gdUnit4/`), 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
|
||||
|
||||
@@ -33,16 +33,16 @@ The project progresses through these stages:
|
||||
6. **Polish** — Performance, playtesting, bug fixing
|
||||
7. **Release** — Launch prep, certification
|
||||
|
||||
**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.
|
||||
**When a gate passes** (or the user explicitly accepts a CONCERNS verdict's risks — Section 6), 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.
|
||||
|
||||
---
|
||||
|
||||
## 1. Parse Arguments
|
||||
|
||||
**Target phase:** `$ARGUMENTS[0]` (blank = auto-detect current stage, then validate next transition)
|
||||
**Target phase:** `$ARGUMENTS` with any `--review <mode>` pair removed (blank = auto-detect current stage, then validate next transition). `/gate-check --review full` names no phase.
|
||||
|
||||
|
||||
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).
|
||||
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, the phase-gate directors still run (phase gates are the purpose of lean mode); how many of them run is set by `workflow` below.
|
||||
|
||||
**`workflow`** (per `.claude/docs/workflow-modes.md`):
|
||||
|
||||
@@ -54,16 +54,23 @@ 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.
|
||||
> checklist changes per tier; the collaborative prompting protocol (the
|
||||
> Collaborative Protocol section) 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).
|
||||
test-evidence and unit-test artifact items become non-required and the
|
||||
Section 3 `testing.strict` check is a no-op; the smoke check is not relaxed (Section 2b) —
|
||||
but at this level `/smoke-check` runs without game tests (its automated row reads
|
||||
WAIVED), so the build check (`commands.smoke`, else `commands.build`, when set) and
|
||||
the launch and critical-path checks are the floor — a build nobody launched is
|
||||
NOT ASSESSED — and a project with no tests can still pass. 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). The retained screenshots
|
||||
UI and Visual/Feel stories need are not test items: no `qa.level` relaxes them
|
||||
(Section 2b).
|
||||
|
||||
**`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
|
||||
@@ -123,6 +130,12 @@ across all of them:
|
||||
> 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.
|
||||
>
|
||||
> **It relaxes tests, not the look.** A UI story's retained screenshots, and a
|
||||
> Visual/Feel story's screenshots plus lead sign-off, are required at every
|
||||
> `qa.level` wherever the gate file asks for story evidence
|
||||
> (`.claude/docs/coding-standards.md`: tests are waived at `minimal`, the look
|
||||
> is not).
|
||||
>
|
||||
> **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
|
||||
@@ -133,8 +146,7 @@ across all of them:
|
||||
> 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.
|
||||
> then dropped the smoke check too, and one `modes.rigor` setting fires both.
|
||||
|
||||
> **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
|
||||
@@ -147,6 +159,13 @@ across all of them:
|
||||
> requires the emptiness to be visible in the output rather than inferable from
|
||||
> a silent green.
|
||||
>
|
||||
> **The one exception: a gate its tier reference file marks "not applicable" at
|
||||
> this tier** (Systems Design → Technical Setup at `workflow: minimal`). That is
|
||||
> not a gate with nothing left to check but a transition the tier does not have:
|
||||
> it PASSes with that file's note, printed in the report. The director panel
|
||||
> does not run for it — note "Director Panel skipped — gate not applicable at
|
||||
> `workflow: [tier]`" — and the Section 6 stage write still asks first.
|
||||
>
|
||||
> **`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
|
||||
@@ -155,12 +174,9 @@ across all of them:
|
||||
> 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.
|
||||
> project** — the Polish gate's `minimal` reduction drops everything outside its
|
||||
> floor, and "Performance is within budget" sits in the dropped remainder. A
|
||||
> setting that works only when a rule is disregarded is not wired.
|
||||
|
||||
### Per-system overrides (`workflow_overrides.system_overrides`)
|
||||
|
||||
@@ -241,6 +257,11 @@ 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.
|
||||
|
||||
At `workflow: minimal`, also run
|
||||
`bash .claude/scripts/artifact-check.sh --path minimal`: the brief and stories
|
||||
live on that path, not on any phase, and its `game-brief` and `create-stories`
|
||||
rows are this tier's floor.
|
||||
|
||||
It reads `workflow-catalog.yaml` — which already encodes each step's `glob`,
|
||||
`pattern`, `min_count` and `any_of` — and reports per step:
|
||||
|
||||
@@ -275,10 +296,12 @@ does not turn on.
|
||||
> 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 reports a passing automated suite → the engine's test root must actually
|
||||
> contain test files and the project must have a runner. "24 passed, 0 failed"
|
||||
> in a repo with no test files under that root — `tests/unit/` and
|
||||
> `tests/integration/` on Godot, `Assets/Tests/` on Unity,
|
||||
> `Source/<Module>/Private/Tests/` on Unreal — 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 →
|
||||
@@ -286,8 +309,7 @@ does not turn on.
|
||||
>
|
||||
> 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.
|
||||
> Existence plus a verdict-line grep would clear a fabricated report.
|
||||
|
||||
For code checks, verify directory structure and file counts.
|
||||
|
||||
@@ -299,7 +321,9 @@ If no file matches: at `full` mark the "cross-GDD review report exists" artifact
|
||||
`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.
|
||||
and must be resolved before advancing. A NOT ASSESSED verdict means that review
|
||||
could not compare the GDDs, so it satisfies nothing here: mark the item NOT
|
||||
ASSESSED for this gate, never passed.
|
||||
|
||||
### Quality Checks
|
||||
- For test checks: Run the test suite via `Bash` if a test runner is configured.
|
||||
@@ -310,8 +334,12 @@ and must be resolved before advancing.
|
||||
**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`.
|
||||
- **Logic** — unit-level failures (`tests/unit/` on Godot, Edit Mode on
|
||||
Unity), gated by `testing.strict.logic`.
|
||||
- **Integration** — failures in `tests/integration/` on Godot, Play Mode on
|
||||
Unity, gated by `testing.strict.integration`. On Unreal, where one root
|
||||
(`Source/<Module>/Private/Tests/`) holds both, classify a failure by its
|
||||
story's Type, or apply the stricter of the two levels when that is unknown.
|
||||
- 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
|
||||
@@ -369,6 +397,17 @@ For items that can't be automatically verified, **ask the user**:
|
||||
- "Performance profiling data isn't available. Would you like to run `/perf-profile`?"
|
||||
|
||||
**Never assume PASS for unverifiable items.** Mark them as MANUAL CHECK NEEDED.
|
||||
An answer resolves the item: "no" or "not yet" is a checked, failed item
|
||||
(CONCERNS or FAIL, naming the skill that closes it — `/design-review [doc]` for
|
||||
an unreviewed concept or GDD) — except a play question at the Production gate
|
||||
(a human has played the Vertical Slice; at `minimal`, the core loop is fun on
|
||||
the current build), where "not yet" means nobody has played it: NOT ASSESSED
|
||||
(`gate-production.md`). Only an unanswered item or "I don't know" stays
|
||||
MANUAL CHECK NEEDED, which Section 5 turns into NOT ASSESSED.
|
||||
|
||||
This applies to questions about the project's state. Declining an offer to
|
||||
produce missing data (e.g. `/perf-profile`) leaves the item NOT ASSESSED; at
|
||||
`performance.enforce: off` it stays out of the verdict.
|
||||
|
||||
---
|
||||
|
||||
@@ -413,37 +452,71 @@ Before generating the final verdict, spawn the directors for the resolved tier a
|
||||
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.
|
||||
Pass to each the target phase name, the resolved `workflow` tier, the target
|
||||
gate's required and recommended artifacts at the resolved tier (the loaded gate
|
||||
file's checklist after its tier reduction and the `qa.level` relaxation — what
|
||||
this gate asks for, not what a later one will), the list of artifacts present,
|
||||
and its gate's own context — named here, so this session never has to read the
|
||||
gate files:
|
||||
- **CD-PHASE-GATE**: the game pillars and core fantasy (from
|
||||
`design/gdd/game-concept.md`, else `design/game-brief.md`).
|
||||
- **TD-PHASE-GATE**: the architecture document path, the engine reference path
|
||||
(`docs/engine-reference/<engine>/VERSION.md`), and the ADR list.
|
||||
- **PR-PHASE-GATE**: the sprint and milestone artifacts present, `team.size` as
|
||||
resolved above (with the current sprint plan's capacity, if a plan exists), and
|
||||
the number of stories under `production/epics/` whose status is `Blocked`. At
|
||||
`workflow: minimal`, pass the Build order in `design/game-brief.md` as the plan — that
|
||||
tier has no sprint plan.
|
||||
- **AD-PHASE-GATE**: the art and visual artifacts present, the Visual Identity
|
||||
Anchor (from `design/gdd/game-concept.md`, else the "Art & audio direction"
|
||||
line of `design/game-brief.md`), and the art bible path.
|
||||
|
||||
Pass each context item as one of three things, so no director has to guess:
|
||||
- **Present** — its path or value (`0` blocked stories is a value).
|
||||
- **"none"** — the target gate (or an earlier one) requires or recommends it at
|
||||
this tier and it does not exist (no architecture document at
|
||||
`/gate-check pre-production`). For the director that is a fact about the
|
||||
project to judge, not a missing input.
|
||||
- **"not expected before [phase]"** — the target gate does not ask for it yet;
|
||||
name the phase whose gate first does (the architecture document and ADRs
|
||||
before Pre-Production, the sprint plan before Production). One this tier never
|
||||
requires is "not required at `workflow: [tier]`" (any sprint plan at
|
||||
`minimal`). Neither is ever passed as "none", and neither is a finding — a
|
||||
director judges readiness for the phase being entered, not a later one.
|
||||
|
||||
**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.
|
||||
not consulted. Raise `modes.rigor` to `full` (or set `modes.workflow: full`) for
|
||||
the complete panel." Name the setting the config block shows as `workflow`'s
|
||||
source: when `modes.workflow` is set on its own, raising `modes.rigor` does not
|
||||
change it. Never point to `--review full` for this — `--review` decides whether
|
||||
the panel runs, not how wide it is. 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:**
|
||||
**Collect every response from the directors that ran, then present the Director Panel summary** (one row per director that ran; name the ones `workflow` left out):
|
||||
|
||||
```
|
||||
## Director Panel Assessment
|
||||
|
||||
Creative Director: [READY / CONCERNS / NOT READY]
|
||||
Creative Director: [READY / CONCERNS / NOT READY / NOT ASSESSED]
|
||||
[feedback]
|
||||
|
||||
Technical Director: [READY / CONCERNS / NOT READY]
|
||||
Technical Director: [READY / CONCERNS / NOT READY / NOT ASSESSED]
|
||||
[feedback]
|
||||
|
||||
Producer: [READY / CONCERNS / NOT READY]
|
||||
Producer: [READY / CONCERNS / NOT READY / NOT ASSESSED]
|
||||
[feedback]
|
||||
|
||||
Art Director: [READY / CONCERNS / NOT READY]
|
||||
Art Director: [READY / CONCERNS / NOT READY / NOT ASSESSED]
|
||||
[feedback]
|
||||
```
|
||||
|
||||
**Apply to the verdict:**
|
||||
- Any director returns NOT READY → verdict is minimum FAIL (user may override with explicit acknowledgement)
|
||||
- Any director returns NOT READY → verdict is minimum FAIL (no override turns a FAIL into a stage change — Section 6)
|
||||
- Any director returns CONCERNS → verdict is minimum CONCERNS
|
||||
- All four READY → eligible for PASS (still subject to artifact and quality checks from Section 3)
|
||||
- Any director returns NOT ASSESSED (and none returned NOT READY or CONCERNS) → verdict at best NOT ASSESSED; name the input that director said was missing — it never counts as READY
|
||||
- Every director that ran returns READY → eligible for PASS (still subject to artifact and quality checks from Section 3)
|
||||
|
||||
---
|
||||
|
||||
@@ -456,7 +529,7 @@ Art Director: [READY / CONCERNS / NOT READY]
|
||||
**Checked by**: gate-check skill
|
||||
|
||||
### Required Artifacts: [X/Y present]
|
||||
- [x] design/gdd/game-concept.md — exists, 2.4KB
|
||||
- [x] design/gdd/game-concept.md (design/game-brief.md at `minimal`) — exists, 2.4KB
|
||||
- [ ] docs/architecture/ — MISSING (no ADRs found)
|
||||
- [x] production/sprints/ — exists, 1 sprint plan
|
||||
|
||||
@@ -476,10 +549,14 @@ Art Director: [READY / CONCERNS / NOT READY]
|
||||
|
||||
### 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
|
||||
- **CONCERNS**: Minor gaps exist but can be addressed during the next phase —
|
||||
the stage advances only if the user explicitly accepts them (Section 6)
|
||||
- **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
|
||||
|
||||
### Accepted Risks (only when the user advanced on CONCERNS)
|
||||
- [each concern, as listed above] — accepted by the user, [date]
|
||||
```
|
||||
|
||||
**`NOT ASSESSED` — when the gate could not look.** Rank: it **outranks PASS**
|
||||
@@ -606,6 +683,16 @@ Do NOT reference the draft verdict text — re-check specific files or ask the u
|
||||
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`.
|
||||
|
||||
**On CONCERNS, the user may override — explicitly.** Do not offer the stage
|
||||
write by default. If the user asks to advance anyway, list every concern and
|
||||
ask: "The gate returned CONCERNS. Accept these risks — [list] — and may I update
|
||||
`project.stage` in `project.yaml` to '[stage]' (and the legacy
|
||||
`production/stage.txt`)?" Only on an explicit yes, add the `### Accepted Risks`
|
||||
section to the gate report (each concern, accepted by the user, with the date)
|
||||
and write the stage as below. **A FAIL is never overridden into a stage change, and
|
||||
neither is NOT ASSESSED** — the blockers must be fixed, or the missing input
|
||||
produced, and the gate re-run.
|
||||
|
||||
### 6.1 Primary write — `project.yaml`
|
||||
|
||||
Set `project.stage` to the new stage name in `project.yaml` at the repo root.
|
||||
@@ -630,7 +717,7 @@ Set `project.stage` to the new stage name in `project.yaml` at the repo root.
|
||||
schema_version: 1
|
||||
|
||||
framework:
|
||||
version: 1.1.1
|
||||
version: 1.1.2
|
||||
last_upgraded: <YYYY-MM-DD>
|
||||
|
||||
project:
|
||||
@@ -638,7 +725,7 @@ Set `project.stage` to the new stage name in `project.yaml` at the repo root.
|
||||
```
|
||||
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.
|
||||
the review mode regardless of the project's rigor.
|
||||
|
||||
### 6.2 Legacy fallback write — `production/stage.txt`
|
||||
|
||||
@@ -654,7 +741,7 @@ After both writes, Read `project.yaml` and `production/stage.txt` and confirm bo
|
||||
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`)?"
|
||||
**Always ask before writing**: "Gate passed. May I update `project.stage` in `project.yaml` to 'Production' (and the legacy `production/stage.txt`)?" — on an accepted CONCERNS override, the explicit yes above is that ask.
|
||||
|
||||
### 6.4 Rigor-fit check (advisory — never affects the verdict)
|
||||
|
||||
@@ -675,9 +762,28 @@ setting yourself.
|
||||
|
||||
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:**
|
||||
**Tailor the options to the gate that just ran.** The argument names the phase
|
||||
being entered, so `/gate-check systems-design` is the Concept → Systems Design gate.
|
||||
|
||||
For **systems-design PASS**:
|
||||
**At `workflow: minimal`, skip the menus below.** They walk the phase ladder, and
|
||||
the minimal route is not the ladder: offer the first incomplete step of
|
||||
`paths.minimal` instead (the `--path minimal` rows from Section 3):
|
||||
`/setup-engine`, then `/brainstorm`, then `/create-stories`, then `/dev-story`
|
||||
on the next story — the route `/help` gives.
|
||||
|
||||
For **Concept → Systems Design** (`/gate-check systems-design`) PASS — option [A] is
|
||||
`/map-systems` when `design/gdd/systems-index.md` does not exist yet (many
|
||||
projects write it during Concept, as the workflow catalog orders it), otherwise
|
||||
`/design-system [first system in the index's design order]`:
|
||||
```
|
||||
Gate passed. What would you like to do next?
|
||||
[A] Run /map-systems — decompose the concept into systems and a design order (recommended next step)
|
||||
— or, when the systems index already exists: Run /design-system [first system] — author its GDD
|
||||
[B] Revisit the concept first — return here when it is settled
|
||||
[C] Stop here for this session
|
||||
```
|
||||
|
||||
For **Systems Design → Technical Setup** (`/gate-check technical-setup`) PASS:
|
||||
```
|
||||
Gate passed. What would you like to do next?
|
||||
[A] Run /create-architecture — produce your master architecture blueprint and ADR work plan (recommended next step)
|
||||
@@ -685,23 +791,23 @@ Gate passed. What would you like to do next?
|
||||
[C] Stop here for this session
|
||||
```
|
||||
|
||||
> **Note for systems-design PASS**: `/create-architecture` is the required next step before writing any ADRs. It produces the master architecture document and a prioritized list of ADRs to write. Running `/architecture-decision` without this step means writing ADRs without a blueprint — skip it at your own risk.
|
||||
> **Note for the Systems Design → Technical Setup PASS**: `/create-architecture` is the required next step before writing any ADRs. It produces the master architecture document and a prioritized list of ADRs to write. Running `/architecture-decision` without this step means writing ADRs without a blueprint — skip it at your own risk.
|
||||
|
||||
For **technical-setup PASS**:
|
||||
For **Technical Setup → Pre-Production** (`/gate-check pre-production`) PASS:
|
||||
```
|
||||
Gate passed. What would you like to do next?
|
||||
[A] Run /create-control-manifest — generate the layer rules manifest from your Accepted ADRs (do this first)
|
||||
[A] Run /create-control-manifest — generate the layer rules manifest from your Accepted ADRs (first, if docs/architecture/control-manifest.md does not exist yet)
|
||||
[B] Run /vertical-slice — build the Vertical Slice (do this before writing epics — validate fun first)
|
||||
[C] Write more ADRs first — run /architecture-decision [next-system]
|
||||
[D] Stop here for this session
|
||||
```
|
||||
|
||||
> **Note for technical-setup PASS**: The Pre-Production sequence is deliberately ordered
|
||||
> **Note for the Technical Setup → Pre-Production PASS**: The Pre-Production sequence is deliberately ordered
|
||||
> to validate fun before committing to detailed planning:
|
||||
>
|
||||
> 1. `/create-control-manifest` — extract technical rules from Accepted ADRs (required before epics)
|
||||
> 1. `/create-control-manifest` — extract technical rules from Accepted ADRs, if not done yet (`/create-epics` requires it at `full`)
|
||||
> 2. `/vertical-slice` — build the Vertical Slice **FIRST**, before writing epics or stories
|
||||
> 3. Playtest → `/playtest-report` — at least 1 session required to pass the Pre-Production gate; 3+ recommended before committing the full team
|
||||
> 3. Playtest → `/playtest-report` — at least 1 documented session, 3+ better before committing the full team. `/gate-check production` treats the slice as recommended: skipped → CONCERNS, unplayed → NOT ASSESSED
|
||||
> 4. `/ux-design [screen]` — UX specs for main menu, core HUD, pause menu (if not done)
|
||||
> 5. `/create-epics layer:foundation` then `/create-epics layer:core` — plan after fun is validated
|
||||
> 6. `/create-stories [epic-slug]` for each epic
|
||||
@@ -724,11 +830,12 @@ Based on the verdict, suggest specific next steps:
|
||||
- **No game concept?** → `/brainstorm` to create one
|
||||
- **No systems index?** → `/map-systems` to decompose the concept into systems
|
||||
- **Missing design docs?** → `/reverse-document` or delegate to `game-designer`
|
||||
- **Small design change needed?** → `/quick-design` for changes under ~4 hours (bypasses full GDD pipeline)
|
||||
- **Small design change needed?** → `/quick-design` for changes under about one week of implementation (bypasses full GDD pipeline)
|
||||
- **No UX specs?** → `/ux-design [screen name]` to author specs, or `/team-ui [feature]` for full pipeline
|
||||
- **UX specs not reviewed?** → `/ux-review [file]` or `/ux-review all` to validate
|
||||
- **No accessibility requirements doc?** → run `/ux-design` which creates both `design/accessibility-requirements.md` and `design/ux/interaction-patterns.md` in one step
|
||||
- **No interaction pattern library?** → `/ux-design patterns` to initialize it
|
||||
- **Concept or a GDD not reviewed?** → `/design-review [doc]`
|
||||
- **GDDs not cross-reviewed?** → `/review-all-gdds` (run after all MVP GDDs are individually approved)
|
||||
- **Cross-GDD consistency issues?** → fix flagged GDDs, then re-run `/review-all-gdds`
|
||||
- **No test framework?** → `/test-setup` to scaffold the framework for your engine
|
||||
@@ -757,6 +864,7 @@ Based on the verdict, suggest specific next steps:
|
||||
- **Need a quick sprint check?** → `/sprint-status` for current sprint progress snapshot
|
||||
- **Performance unknown?** → `/perf-profile`
|
||||
- **Not localized?** → `/localize`
|
||||
- **No security audit, or open CRITICAL/HIGH findings?** → `/security-audit` (after fixes, `/security-audit quick` to confirm)
|
||||
- **Ready for release?** → `/launch-checklist`
|
||||
|
||||
---
|
||||
@@ -768,12 +876,16 @@ This skill follows the collaborative design principle:
|
||||
1. **Scan first**: Check all artifacts and quality gates
|
||||
2. **Ask about unknowns**: Don't assume PASS for things you can't verify
|
||||
3. **Present findings**: Show the full checklist with status
|
||||
4. **User decides**: The verdict is a recommendation — the user makes the final call
|
||||
4. **User decides**: The verdict is a recommendation — the user makes the final call on
|
||||
what to do next; only the stage write is bound to it (Section 6)
|
||||
5. **Get approval**: "May I write this gate check report to production/gate-checks/?"
|
||||
6. **Never auto-fix**: If required artifacts are missing, report the FAIL verdict and
|
||||
name the skill to run (e.g. "run `/test-setup`"). Do NOT create missing files or
|
||||
re-run the gate automatically. Creating files to manufacture a PASS defeats the
|
||||
gate's purpose.
|
||||
|
||||
**Never** block a user from advancing — the verdict is advisory. Document the risks
|
||||
and let the user decide whether to proceed despite concerns.
|
||||
**Never** block a user from working — the verdict decides only whether this skill
|
||||
writes the new stage. On CONCERNS the user may advance by explicitly accepting the
|
||||
listed risks, which the report records (Section 6); on FAIL or NOT ASSESSED the
|
||||
stage stays where it is until a re-run passes, and nothing stops the user working
|
||||
on the blockers meanwhile.
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
- [ ] 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/`
|
||||
- [ ] Test files exist under the engine's test root — `tests/unit/` and `tests/integration/` (Godot), `Assets/Tests/EditMode/` and `Assets/Tests/PlayMode/` (Unity), `Source/<Module>/Private/Tests/` (Unreal) — covering Logic and Integration stories
|
||||
- [ ] All Logic stories from this sprint have corresponding unit test files in the engine's unit-test location (`tests/unit/`, `Assets/Tests/EditMode/` or `Source/<Module>/Private/Tests/`)
|
||||
- [ ] 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
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**Quality Checks:**
|
||||
- [ ] Tests are passing (run test suite via Bash)
|
||||
- [ ] No critical/blocker bugs in any bug tracker or known issues
|
||||
- [ ] No open S1 Critical 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)
|
||||
@@ -37,11 +37,11 @@ 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
|
||||
- **`full`** — core mechanics + Logic/Integration tests + smoke check (PASS or PASS WITH WARNINGS) + 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
|
||||
playtest + no open S1 Critical bugs** required
|
||||
- **`minimal`** — **smoke check + playable end-to-end + no open S1 Critical
|
||||
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
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
- [ ] 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
|
||||
- [ ] Test framework initialized: the engine's test root exists — `tests/unit/` and `tests/integration/` (Godot), `Assets/Tests/EditMode/` and `Assets/Tests/PlayMode/` (Unity), or `Source/<Module>/Private/Tests/` (Unreal); see `.claude/docs/directory-structure.md`
|
||||
- [ ] 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`
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
**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`
|
||||
- [ ] Art bible is complete (all 9 sections) and AD-ART-BIBLE sign-off verdict is recorded in `design/art/art-bible.md` — where `review_mode` skips that gate (`lean`, `solo`), a `SKIPPED` sign-off line `/art-bible` records stands in for it, and a header still reading `[Not yet reviewed]` on such a project reads "sign-off skipped — [mode] mode", never missing
|
||||
- [ ] 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`
|
||||
@@ -51,6 +51,10 @@
|
||||
> **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 built but its report says NOT ASSESSED** (nobody has played it) → it is not a
|
||||
> PROCEED, and its validation items were not checked (they are not NO): the Vertical Slice
|
||||
> Validation block does not run, so the FAIL rule above does not apply. The gate item is NOT
|
||||
> ASSESSED, never passed — and a "not yet" to "a human has played it" means the same.
|
||||
> - **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.
|
||||
@@ -63,16 +67,20 @@ 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**
|
||||
- **`full`** — sprint plan + complete (9-section) art bible + epics + UX specs + control manifest all required; **Vertical Slice keeps its Section 2 status** (see note) — its playtest is recommended, 1 documented session with 3+ better
|
||||
- **`standard`** — epics + sprint plan required; art bible complete + UX specs + control manifest → recommended; **Vertical Slice keeps its Section 2 status**
|
||||
- **`minimal`** — the minimal floor only: a filled **`design/game-brief.md`** with its build order, and **stories** under `production/epics/` (`workflow-modes.md` — the brief's build order is the plan, so there is **no sprint plan**); everything else **drops** — sprint plan, epics, playtests, art bible, entity inventory, MVP GDDs, the master architecture document, both ADR items, control manifest, the UX items (key screen specs, HUD document, `/ux-review`), and the Vertical Slice items (the slice, its playtest, and the Vertical Slice Validation block) — the two current-build checks below replace them
|
||||
**Quality checks at `minimal`:** every check that reads a dropped artifact drops with it — the sprint-plan, architecture, both ADR, GDD-coherence, UX and accessibility checks, and the Player Fantasy check (no GDD holds one). Two still apply, to the current build instead of a slice: **the core loop is fun** (ask the user, or read a playtest note if one exists) and **it runs end to end** — one complete start → challenge → resolution cycle. A "no" to either is FAIL, as a NO on a built slice is at the other tiers; a "not yet" to the fun question means nobody has played the build — NOT ASSESSED.
|
||||
|
||||
> **The Vertical Slice keeps its Section 2 status at every tier.** The
|
||||
> **The Vertical Slice keeps its Section 2 status at `full` and `standard`.** 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*.
|
||||
> `full` and `standard` alike. At `minimal` they drop — the minimal route never
|
||||
> builds a slice — and the two current-build checks replace them. The
|
||||
> genuinely-required floor item at this gate is the **sprint plan** at `standard`
|
||||
> and `full`, and the **brief's build order plus stories** at `minimal`. The one
|
||||
> hard rule that binds at every tier: if a Vertical Slice *was built* and any of
|
||||
> its validation items is NO (at `minimal`, if the current build fails either of
|
||||
> its two checks), the verdict is FAIL regardless of tier — tier reductions relax
|
||||
> what must *exist*, never what must *work*.
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
- [ ] 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/`)
|
||||
- [ ] All Must Have story test evidence is present (Logic/Integration: test files pass; UI: retained screenshots of each screen touched; Visual/Feel: retained screenshots plus lead sign-off — both in `production/qa/evidence/`, and no `qa.level` waives either)
|
||||
- [ ] 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)
|
||||
- [ ] Release checklist completed (`/release-checklist` run)
|
||||
- [ ] Store metadata prepared (if applicable)
|
||||
- [ ] Changelog / patch notes drafted
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
- [ ] 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
|
||||
- [ ] No known open S1 Critical, S2 High or S3 Medium bugs
|
||||
- [ ] No open CRITICAL or HIGH findings in the newest `production/security/security-audit-*.md` whose **Scope** is `full`, as updated by any later `quick` report (the re-run `/security-audit` prescribes after remediation). A later `network`, `save` or `input` report adds its open findings but never clears a category it did not scan — any open CRITICAL or HIGH finding means not ready (a blocker). No `full`-scope audit report means the check could not run: this item is NOT ASSESSED, never passed. A report whose release recommendation is itself NOT ASSESSED makes this item NOT ASSESSED too
|
||||
- [ ] Accessibility basics covered (remapping, text scaling if applicable)
|
||||
- [ ] Localization verified for all target languages
|
||||
- [ ] Localization verified for all target languages — every translated locale being shipped has a `/localize qa` verdict of PASS or PASS WITH CONDITIONS (`production/localization/loc-qa-[locale]-[date].md`). A FAIL blocks that locale; the others may still ship. A locale with no QA report, or whose QA reported NOT ASSESSED (nobody has played it), has not been verified: this item is NOT ASSESSED, never passed. The source locale (`en`, per `/localize`) is not a target language and needs no `/localize qa` report; a game that ships only its source locale marks this item N/A and says so
|
||||
- [ ] Legal requirements met (EULA, privacy policy, age ratings if applicable)
|
||||
- [ ] Build compiles and packages cleanly
|
||||
|
||||
@@ -36,6 +37,6 @@ 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**
|
||||
- **`full`** — all features + content complete + localization + QA sign-off + smoke (PASS) + no open S1–S3 bugs all required
|
||||
- **`standard`** — content-complete audit + QA sign-off + localization → recommended; **all features + smoke + no open S1 Critical bugs** required; open S2 High and S3 Medium bugs → recommended
|
||||
- **`minimal`** — only **smoke + no open S1 Critical bugs** required; everything else **drops**
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
**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)
|
||||
- [ ] `/review-all-gdds` verdict is not FAIL (cross-GDD consistency and design theory checks pass). A NOT ASSESSED verdict does not satisfy this: that review could not compare the GDDs, so this item is NOT ASSESSED for the gate
|
||||
- [ ] 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
|
||||
@@ -33,4 +33,6 @@ only thing that adds one.
|
||||
> 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.
|
||||
> applies on user confirmation. Do NOT flag absent GDDs as blockers. This is the
|
||||
> named exception to Section 2b's rule that a gate with no required artifacts left
|
||||
> may not PASS; the director panel does not run for it.
|
||||
|
||||
+115
-12
@@ -3,7 +3,7 @@ name: help
|
||||
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, Bash, Bash(bash "*/.claude/skills/help/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Bash(bash "*/.claude/skills/help/../../hooks/yaml-helper.sh" resolve_config *), Bash(bash "*/.claude/skills/help/../../scripts/story-status.sh"), Bash(bash .claude/scripts/story-status.sh*), Bash(bash .claude/scripts/artifact-check.sh *), Bash(bash ".claude/scripts/artifact-check.sh" *), Bash(bash ./.claude/scripts/artifact-check.sh *), Bash(git log *)
|
||||
model: haiku
|
||||
---
|
||||
|
||||
@@ -19,14 +19,12 @@ gap analysis, use `/project-stage-detect`.
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" 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:
|
||||
These 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.
|
||||
- **`workflow`** from the config block is the tier for Steps 2 and 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`.
|
||||
|
||||
@@ -65,7 +63,15 @@ skills in production/polish, etc.).
|
||||
|
||||
## Step 2: Determine Current Phase
|
||||
|
||||
Check in this order:
|
||||
**First, take `workflow` from the config block above.** If it is `minimal`, the
|
||||
project is on the minimal path, not the phase ladder: skip the rest of this step,
|
||||
read the session context (**Step 3**), then go to **Step 4m**. At that tier, do
|
||||
not map `project.stage` — nothing on the minimal path runs `/gate-check`, so
|
||||
the stage reads Concept however far the
|
||||
project has got, and walking the Concept phase would send a project that already
|
||||
has stories back to the concept doc, art bible and systems map.
|
||||
|
||||
Otherwise, check in this order:
|
||||
|
||||
1. **Take `project.stage` from the config block above** — it is already resolved. Map its value to a catalog phase key:
|
||||
- "Concept" → `concept`
|
||||
@@ -84,7 +90,7 @@ Check in this order:
|
||||
- `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
|
||||
3. **`workflow`** was taken at the top of this step (per
|
||||
`.claude/docs/workflow-modes.md`). It controls whether optional docs are
|
||||
surfaced as next steps (Step 5).
|
||||
|
||||
@@ -92,13 +98,20 @@ Check in this order:
|
||||
|
||||
## Step 3: Read Session Context
|
||||
|
||||
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:
|
||||
Read `production/session-state/active.md` if it exists — but only its STATUS
|
||||
and CHECKPOINT blocks (schema: `.claude/docs/templates/session-state.md`); the
|
||||
narrative below them can be long. Find the markers
|
||||
(`Grep pattern="<!-- /?(STATUS|CHECKPOINT) -->" path="production/session-state/active.md" output_mode="content" -n`)
|
||||
and `Read` from the first to the last. A file with no markers predates the schema: read its
|
||||
last `## Session Extract` block instead. Extract:
|
||||
- What was most recently worked on
|
||||
- Any in-progress tasks or open questions
|
||||
- Current epic/feature/task from STATUS block (if present)
|
||||
|
||||
This tells you what the user just finished or is stuck on — use it to personalize
|
||||
the output.
|
||||
the output. It runs at every tier: at `minimal` it is the only read of the
|
||||
checkpoint Step 4m relies on (a checkpoint saying "Next step: /story-done" means
|
||||
the work is written). From here, `minimal` goes to **Step 4m**, not Step 4.
|
||||
|
||||
---
|
||||
|
||||
@@ -114,6 +127,10 @@ For each step in the current phase (from the catalog):
|
||||
Bash: bash .claude/scripts/artifact-check.sh --phase [current-phase]
|
||||
```
|
||||
|
||||
Run it exactly as written, here and below: from the project root, with the
|
||||
relative path — no absolute path, no `cd`, no `2>&1`. This skill's permission
|
||||
grant matches that form; any other asks the user to approve it.
|
||||
|
||||
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:
|
||||
|
||||
@@ -157,6 +174,69 @@ Label these differently — show what's been detected, then note it may be ongoi
|
||||
|
||||
---
|
||||
|
||||
## Step 4m: The Minimal Path (`workflow: minimal` only)
|
||||
|
||||
At `minimal` the route is the catalog's `paths.minimal`, not a phase: engine →
|
||||
`design/game-brief.md` → stories → `/dev-story` ↔ `/story-done`. Resolve it in
|
||||
one call:
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/artifact-check.sh --path minimal
|
||||
```
|
||||
|
||||
Map the statuses exactly as in Step 4. `implement` and `story-done` are
|
||||
`NO_CHECK` by design — the story status lines below are their check. The next
|
||||
step is the first of these that applies:
|
||||
|
||||
1. `engine-setup` not PRESENT → `/setup-engine`
|
||||
2. `game-brief` not PRESENT → `/brainstorm` (at `minimal` it writes the one-page brief)
|
||||
3. `create-stories` not PRESENT → `/create-stories` with no argument (at
|
||||
`minimal` it builds the stories straight from the brief's MVP list)
|
||||
4. Stories exist → the list below was printed by `.claude/scripts/story-status.sh`
|
||||
before you read this skill: one line per unfinished story, **already in
|
||||
the route's order** — `IN_REVIEW`, then `IN_PROGRESS`, then `TODO` (a
|
||||
`Ready` or `Not Started` story) in build order — then `BLOCKED`, `OTHER`,
|
||||
`NO_STATUS` and the `COMPLETE` count:
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../scripts/story-status.sh"`
|
||||
|
||||
**Next up is the story on the first `IN_REVIEW`, `IN_PROGRESS` or `TODO`
|
||||
line.** The list is already current; do not run the script again, and do
|
||||
not re-read or re-rank the story files:
|
||||
an `In Review` story is closed before an `In Progress` one continues — its
|
||||
work is written, and `/story-done` is quick.
|
||||
- `IN_REVIEW` → its work is written and waiting to be closed:
|
||||
`/story-done [path]`
|
||||
- `IN_PROGRESS` → it is **not** done — whatever the code or commits
|
||||
suggest, only `/story-done` makes a story Complete. Recommend
|
||||
`/story-done [path]` only if the user, `active.md` or the git log says
|
||||
its implementation is written; otherwise `/dev-story [path]` to carry on
|
||||
- `TODO` → `/dev-story [path]`
|
||||
- a `BLOCKED` story → name it and its blocker; it is never Next up
|
||||
- **no `IN_REVIEW`, `IN_PROGRESS` or `TODO` line, but `BLOCKED`, `OTHER` or
|
||||
`NO_STATUS` lines remain** → nothing can be built next, and the build
|
||||
order is **not** done. Name each of those stories with its status as
|
||||
written, and a blocked story's blocker (read it from that story's file).
|
||||
Next up is clearing the first of them: resolve its blocker, or give an
|
||||
`OTHER` or `NO_STATUS` story a `Status:` line the route reads (`Ready`
|
||||
once it can be built)
|
||||
- **every story `Complete` (or `Done`)** → the brief's build order is done.
|
||||
Say so, and offer three ways on: play the build; add the next stories from
|
||||
the brief with `/create-stories`; or, if the game has outgrown a one-page
|
||||
brief, `/settings` to raise `modes.rigor`.
|
||||
|
||||
**At `minimal`, never present any of these as required or as a blocker:** the
|
||||
game concept doc, art bible, systems map, GDDs, `/create-epics`, a sprint plan,
|
||||
`/gate-check`, or sprint close-out (`/smoke-check`, `/team-qa`,
|
||||
`/retrospective`). The brief replaces the design docs and its build order
|
||||
replaces the sprint plan (`.claude/docs/workflow-modes.md` — `minimal` floor).
|
||||
Every one of them still runs if the user asks for it; mention one only when the
|
||||
user's argument asks about it.
|
||||
|
||||
Then skip Steps 5 and 8, and present with the `minimal` shape in Step 7.
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Find Position and Identify Next Steps
|
||||
|
||||
From the completion data, determine:
|
||||
@@ -168,8 +248,7 @@ From the completion data, determine:
|
||||
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
|
||||
gaps). At `minimal` this step does not run — Step 4m replaces it
|
||||
4. **Upcoming required steps** — required steps after the current blocker
|
||||
(show as "coming up" so user can plan ahead)
|
||||
|
||||
@@ -215,6 +294,27 @@ Command: `[/command]`
|
||||
Approaching **[next phase]** gate → run `/gate-check` when ready.
|
||||
```
|
||||
|
||||
**At `minimal`** use this shape instead — no phase label, no gate line. `N`
|
||||
counts only stories whose status line says `Complete` or `Done`, and only those
|
||||
go under ✓ Done. `N` and `M` are the two numbers on the `COMPLETE` line; it
|
||||
names no finished story, so ✓ Done gives their count, not their titles:
|
||||
|
||||
```
|
||||
## Where You Are: Minimal path — [N] of [M] stories complete
|
||||
|
||||
**In progress:** [from active.md, if any]
|
||||
|
||||
### ✓ Done
|
||||
- Engine: [engine] · Game brief · [N] stories
|
||||
|
||||
### → Next up
|
||||
**[Story NNN: title]** — [what it delivers]
|
||||
Command: `/story-done [story-path]` for an In Review story, or an In Progress one whose work is written; otherwise `/dev-story [story-path]`
|
||||
|
||||
### Coming up after that
|
||||
- [the next Ready stories in build order, at most 3]
|
||||
```
|
||||
|
||||
**Formatting rules:**
|
||||
- `✓` for confirmed complete
|
||||
- `→` for the current required next step (only one — the first blocker)
|
||||
@@ -229,6 +329,8 @@ Verdict: **COMPLETE** — next steps identified.
|
||||
|
||||
## Step 8: Gate Warning (if close)
|
||||
|
||||
Skip this step at `minimal` — the minimal path has no phase gates.
|
||||
|
||||
After the current phase's steps, check if the user is likely approaching a gate:
|
||||
- If all required steps in the current phase are complete (or nearly complete),
|
||||
add: "You're close to the **[Current] → [Next]** gate. Run `/gate-check` when ready."
|
||||
@@ -258,7 +360,8 @@ Only show this if the user's input suggested confusion (e.g. "I don't know", "st
|
||||
"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.
|
||||
project has outgrown its tier — not on every confused query. At `minimal`, leave
|
||||
out the `/gate-check` line: the minimal path has no phase gates (Step 4m).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -12,17 +12,17 @@ model: sonnet
|
||||
|
||||
## Phase 1: Assess Severity
|
||||
|
||||
Read the bug description or ID. Assess severity using these criteria:
|
||||
Read the bug description or ID. Assess severity on `/bug-triage`'s scale:
|
||||
|
||||
- **S1 (Critical)**: Game unplayable, data loss, security vulnerability
|
||||
- **S2 (Major)**: Significant feature broken, workaround exists
|
||||
- **S3 or lower**: Minor issue — normal bug fix workflow applies
|
||||
- **S1 (Critical)**: Crash, data loss, or complete feature failure — the game cannot proceed (rate a security issue by that impact)
|
||||
- **S2 (High)**: Major feature broken, but the game is still playable
|
||||
- **S3 or lower**: Feature degraded with a workaround, or cosmetic — normal bug fix workflow applies
|
||||
|
||||
Confirm with `AskUserQuestion`:
|
||||
- Prompt: "I've assessed this as **[assessed severity]** — [brief rationale]. Confirm severity to proceed:"
|
||||
- Options:
|
||||
- `[A] S1 (Critical) — game unplayable, data loss, or security issue`
|
||||
- `[B] S2 (Major) — significant feature broken, workaround exists`
|
||||
- `[A] S1 (Critical) — crash, data loss, or complete feature failure`
|
||||
- `[B] S2 (High) — major feature broken, game still playable`
|
||||
- `[C] S3 or lower — redirect to normal bug fix workflow`
|
||||
|
||||
If [C]: stop. Verdict: **REDIRECTED** — use the normal bug fix workflow for S3 and below.
|
||||
@@ -75,6 +75,12 @@ Check whether this is a git repository:
|
||||
|
||||
If this command fails or returns empty: note "Not a git repository — create the branch manually." and skip branch creation.
|
||||
|
||||
`[base-ref]` is the release the bug is in. Releases are tags on `main` (the
|
||||
trunk), so it is that release's tag (`git tag --list`; the newest is usually
|
||||
the live build) — or its `release/*` branch, if one was cut to stabilise that
|
||||
release (`git branch --list 'release/*'`). Never the head of `main`: it may carry
|
||||
work that has not shipped.
|
||||
|
||||
If the check passes, use `AskUserQuestion` before creating the branch:
|
||||
- Prompt: "Ready to create hotfix branch 'hotfix/[short-name]' from [base-ref]?"
|
||||
- Options:
|
||||
@@ -96,7 +102,7 @@ Present the root cause and proposed fix, then ask: "May I implement this fix?" D
|
||||
|
||||
## 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.
|
||||
Implement the approved minimal change. Validate the fix by running targeted tests for the affected system, with `commands.test` from `project.yaml` (narrowed to the affected suite where the runner allows) — never a runner line written from memory, which drops the flags the engine needs (gdUnit4 hangs without `--remote-debug tcp://127.0.0.1:0`). Check for regressions in adjacent systems. If `commands.test` is unset, or no test covers the affected system, say so and record `Tests: NOT RUN — [reason]` in the hotfix record's Testing section; the Phase 5b QA gate then carries the verification.
|
||||
|
||||
Update the hotfix record with root cause, fix details, and test results.
|
||||
|
||||
@@ -124,8 +130,13 @@ After approvals, determine the QA scope required before deploying the hotfix. Sp
|
||||
Ask qa-lead: **Is a full smoke check sufficient, or does this fix require a targeted team-qa pass?**
|
||||
|
||||
Apply the verdict:
|
||||
- **Smoke check sufficient** — run `/smoke-check` against the hotfix build. If PASS, proceed to Phase 6.
|
||||
- **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.
|
||||
- **Smoke check sufficient** — run `/smoke-check` against the hotfix build. If PASS or
|
||||
PASS WITH WARNINGS, proceed to Phase 6 (carry the warnings into the hotfix record).
|
||||
If **FAIL**, do not deploy: return to Phase 4 with the failing checks, get the
|
||||
revised fix approved there, implement it (Phase 4b), then re-run Phase 5's
|
||||
approvals — qa-tester's regression run among them — and this QA step. A hotfix
|
||||
that breaks the smoke suite is a second incident, not a fix.
|
||||
- **Targeted QA pass required** — run `/team-qa feature: [affected-system]` scoped to the changed system only. If QA returns APPROVED or APPROVED WITH CONDITIONS, proceed to Phase 6; if NOT APPROVED or BLOCKED, handle it as a smoke-check FAIL above.
|
||||
- **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,
|
||||
@@ -136,7 +147,8 @@ 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.
|
||||
gate that quietly cleared. Log that decision — who made it, and why — in the
|
||||
hotfix record's Testing section.
|
||||
|
||||
Do not skip this gate. A hotfix that breaks something else is worse than the original bug.
|
||||
|
||||
@@ -145,27 +157,38 @@ Do not skip this gate. A hotfix that breaks something else is worse than the ori
|
||||
## 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`:
|
||||
> hotfix and tagging the patch release 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
|
||||
> - Prompt: "Hotfix validated and approved. Merge to [targets], tag [patch tag]
|
||||
> and deploy?" — `[targets]` is `main`, plus the release's `release/*` branch
|
||||
> only if it has one
|
||||
> - Options: `[A] Yes — merge and deploy` / `[B] Merge to main 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.
|
||||
On `[A]`: merge the hotfix branch to `main`, and to the release's `release/*`
|
||||
branch if it has one; tag the patch release (the next patch version, e.g.
|
||||
`v1.2.0` → `v1.2.1`) on the fixed build — the `release/*` branch head if there
|
||||
is one, else the hotfix branch head — and deploy that tag, not the head of
|
||||
`main`. On `[B]`: merge to `main` only — no release-branch merge, no tag, no
|
||||
deploy. On `[C]`: stop — no merge, no tag, no deploy and no bug-file update; the
|
||||
hotfix record's Status stays IN PROGRESS, and say so.
|
||||
|
||||
Update the original bug file if one exists:
|
||||
> **Backport is not verified unless you verify it.** The frontmatter advertises
|
||||
> "backport verified". After merging, confirm the fix is present on `main` (the
|
||||
> trunk) — and on the release's `release/*` branch, if it has one — and state
|
||||
> the result. An unbackported hotfix means the bug returns in the next release
|
||||
> tagged from `main`, which is the single most common hotfix regression.
|
||||
|
||||
Update the original bug file if one exists — find it in `production/qa/bugs/`
|
||||
by its number, as `/bug-report verify` does. Ask first: "May I update
|
||||
`production/qa/bugs/[bug file]` with the fix record below and set its Status to
|
||||
`Fixed — Pending Verification`?"
|
||||
|
||||
```markdown
|
||||
## Fix Record
|
||||
@@ -176,10 +199,13 @@ Update the original bug file if one exists:
|
||||
|
||||
Set `**Status**: Fixed — Pending Verification` in the bug file header.
|
||||
|
||||
Output a deployment summary:
|
||||
Output a deployment summary. Its title follows the Phase 6 answer — `Hotfix
|
||||
Deployed: [short-name]` on `[A]`, `Hotfix Merged to main — release held:
|
||||
[short-name]` on `[B]` — and on `[B]` the closing line omits the Tag, since none
|
||||
was created:
|
||||
|
||||
```
|
||||
## Hotfix Ready to Deploy: [short-name]
|
||||
## Hotfix Deployed: [short-name]
|
||||
|
||||
**Severity**: [S1/S2]
|
||||
**Root cause**: [one line]
|
||||
@@ -187,18 +213,20 @@ Output a deployment summary:
|
||||
**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]
|
||||
**Backport**: [verified present on `main` (and the `release/*` branch, if the
|
||||
release has one) — or NOT VERIFIED, with what was not checked]
|
||||
**Rollback plan**: [from Phase 2 record]
|
||||
|
||||
Merge to: release branch AND development branch
|
||||
Merge to: [targets] · Tag: [patch tag]
|
||||
Next: /bug-report verify [BUG-ID] after deploy to confirm resolution
|
||||
```
|
||||
|
||||
### Rules
|
||||
- Hotfixes must be the MINIMUM change to fix the issue — no cleanup, no refactoring
|
||||
- Every hotfix must have a rollback plan documented before deployment
|
||||
- Hotfix branches merge to BOTH the release branch AND the development branch
|
||||
- A hotfix branch starts from the release it fixes — its tag, or its `release/*`
|
||||
branch if one exists — and merges to `main` (the trunk), and to that
|
||||
`release/*` branch only if it exists; the patch release is tagged
|
||||
- All hotfixes require a post-incident review within 48 hours
|
||||
- If the fix is complex enough to need more than 4 hours, escalate to `technical-director`
|
||||
|
||||
@@ -210,8 +238,12 @@ After deploying, run `/bug-report verify [BUG-ID]` to confirm the fix resolved t
|
||||
|
||||
If VERIFIED FIXED: run `/bug-report close [BUG-ID]` to formally close it.
|
||||
If STILL PRESENT: the hotfix failed — immediately re-open, assess rollback, and escalate.
|
||||
If CANNOT VERIFY: the fix is unconfirmed — do not close the bug; play its reproduction steps in the deployed build, then run `/bug-report verify [BUG-ID]` again and answer its manual-play question to settle it.
|
||||
|
||||
Schedule a post-incident review within 48 hours using `/retrospective hotfix`.
|
||||
Schedule a post-incident review within 48 hours. `/retrospective` reviews a
|
||||
sprint or milestone, not an incident: record the review with
|
||||
`.claude/docs/templates/incident-response.md`, and raise its lessons at the next
|
||||
`/retrospective`.
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "Hotfix complete. What's the next step?"
|
||||
|
||||
@@ -3,10 +3,10 @@ name: launch-checklist
|
||||
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, Bash(bash "*/.claude/skills/launch-checklist/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, AskUserQuestion, Bash(bash "*/.claude/skills/launch-checklist/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys rigor,project.stage,cert_tier,automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys rigor,workflow,project.stage,cert_tier,automation`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -26,12 +26,14 @@ trains the reader to skip the list, which defeats the gate:
|
||||
- **`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
|
||||
to emit every certification track. The answer, mapped onto the four values
|
||||
below, is the tier for this run. 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.
|
||||
and not on platform names. The full requirement table is the `## platform.cert_tier`
|
||||
section of `.claude/docs/effects-map.md` — read **only that section** (Grep its
|
||||
heading, then a bounded Read); the file as a whole is not a runtime input.
|
||||
- `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.
|
||||
@@ -60,7 +62,7 @@ ratings, of which ~140 are unassessable.
|
||||
|
||||
## Phase 1: Parse Arguments
|
||||
|
||||
Read the argument for the launch date or `dry-run` mode. Dry-run mode generates the checklist without creating sign-off entries or writing files.
|
||||
Read the argument for the launch date or `dry-run` mode. Dry-run mode generates the checklist without creating sign-off entries or writing files. With no argument the run is a normal one with the target date unset (`Target Launch: not set`) — dry-run only when the argument says `dry-run`.
|
||||
|
||||
---
|
||||
|
||||
@@ -82,15 +84,18 @@ Read the argument for the launch date or `dry-run` mode. Dry-run mode generates
|
||||
>
|
||||
> **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.
|
||||
> `NOT ASSESSED — [code root unresolved | no source files | no asset folder | directory empty]`.
|
||||
> Never a bare tick. The code root is `src/`, `Assets/` or `Source/` by engine
|
||||
> (resolve per `.claude/docs/code-root-resolution.md`); assets live in
|
||||
> `assets/`, `Assets/` or `Content/`.
|
||||
>
|
||||
> 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,
|
||||
> four bullets. All four search the code root 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.
|
||||
> warning, an empty or absent code root returns zero
|
||||
> hits three times and read as three clean results. With no `assets/` directory,
|
||||
> for example, the placeholder scan returns zero hits, and "All placeholder art
|
||||
> replaced" would be ticked green.
|
||||
|
||||
- Count `TODO`, `FIXME`, `HACK` comments and their locations
|
||||
- Check for any `console.log`, `print()`, or debug output left in production code
|
||||
@@ -179,8 +184,8 @@ Generated: [Date]
|
||||
### Testing
|
||||
- [ ] Full regression test suite passed
|
||||
- [ ] Zero S1 (Critical) bugs open
|
||||
- [ ] Zero S2 (Major) bugs open (or documented exceptions)
|
||||
- [ ] Soak test passed (8+ hours continuous play)
|
||||
- [ ] Zero S2 (High) bugs open (or documented exceptions) — at `workflow: full` instead: zero S2 (High) and S3 (Medium) bugs open, no exceptions
|
||||
- [ ] Soak test passed (the longest soak `/soak-test` runs, or longer by hand if a play session lasts longer)
|
||||
- [ ] Multiplayer stress test passed (if applicable)
|
||||
- [ ] All critical user paths tested on every platform
|
||||
- [ ] Edge cases tested (full storage, no network, suspend/resume)
|
||||
@@ -312,13 +317,27 @@ do not fall back to emitting all of them.
|
||||
|
||||
## Go / No-Go Decision
|
||||
|
||||
**Overall Status**: [READY / NOT READY / CONDITIONAL]
|
||||
**Overall Status**: [READY / CONDITIONAL / NOT ASSESSED / NOT READY]
|
||||
|
||||
First match wins: **NOT READY** if Blocking Items is not empty; else **NOT
|
||||
ASSESSED** if any item is `- [?]`, any section came out `NOT ASSESSED`, or any
|
||||
item is still unconfirmed — neither ticked on evidence or on a Phase 4b answer,
|
||||
nor marked N/A, nor listed below (name each; group by section when there are
|
||||
many); else **CONDITIONAL** if Conditional
|
||||
Items is not empty; else **READY**. NOT ASSESSED outranks CONDITIONAL and READY —
|
||||
an item nobody could check is not a passed one — and ranks below NOT READY, so a
|
||||
known blocker is never buried behind it.
|
||||
|
||||
### Blocking Items
|
||||
[List any items that must be resolved before launch]
|
||||
[Every FAIL or unresolved finding: a check that found a problem — FIXMEs, debug
|
||||
output, placeholder assets, hardcoded dev values, an open S1 bug, a failing
|
||||
build or test — with no documented workaround and no explicitly accepted risk]
|
||||
|
||||
### Conditional Items
|
||||
[List items that have documented workarounds or accepted risk]
|
||||
[Every shortfall with a documented workaround or an explicitly accepted risk —
|
||||
e.g. a HACK with its documented justification, an S2 with a documented
|
||||
exception (below `workflow: full`, which allows none). Name the workaround, or
|
||||
who accepted the risk]
|
||||
|
||||
### Sign-Offs Required
|
||||
- [ ] Creative Director — Content and experience quality
|
||||
@@ -330,17 +349,47 @@ do not fall back to emitting all of them.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4b: Confirm What Only a Person Can
|
||||
|
||||
Most items above cannot be settled from the repository — the on-call schedule,
|
||||
the EULA, press keys, pricing, a soak test someone ran. Left unasked, every one
|
||||
of them stays unconfirmed and the Overall Status can only be NOT ASSESSED, so ask.
|
||||
|
||||
For each of the seven sections, collect the items no scan or file settled (the
|
||||
Phase 3 counts and anything read in Phase 2 are not asked again) and ask **one
|
||||
`AskUserQuestion` per section**, listing those items numbered. Each item's
|
||||
answer is **yes / no / not yet / N/A**. Options: `Yes — all of them` /
|
||||
`Not yet — none of them` / `N/A — this section does not apply` /
|
||||
`Some differ — I'll answer per item` (the user then gives each numbered item its
|
||||
answer). Skip a section with nothing left to ask.
|
||||
|
||||
- **yes** → ticked `- [x]`, marked `(confirmed by the user)`
|
||||
- **no** or **not yet** → a failed item: under Blocking Items, or under
|
||||
Conditional Items when the user names a workaround or accepts the risk
|
||||
- **N/A** → written `- N/A — [item]` and left out of the Overall Status
|
||||
- an item left unanswered stays unconfirmed, and the status names it
|
||||
|
||||
These are questions of fact only the user can answer, so they are asked in
|
||||
`collaborative` and `guided` alike and never answered on the user's behalf. In
|
||||
`autonomous` mode and in `dry-run`, skip this phase and say so: the items it
|
||||
would have asked stay unconfirmed, and the Overall Status is NOT ASSESSED.
|
||||
|
||||
Then fill in the Go / No-Go section from the answers.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Save Checklist
|
||||
|
||||
Present the completed checklist and summary to the user (total items, blocking items count, conditional items count, departments with incomplete sections).
|
||||
Present the completed checklist and summary to the user (Overall Status, total items, blocking items count, conditional items count, not-assessed items count, departments with incomplete sections).
|
||||
|
||||
If not in dry-run mode, ask: "May I write this to `production/releases/launch-checklist-[date].md`?"
|
||||
|
||||
If yes, write the file, creating directories as needed.
|
||||
Create nothing before the answer — not even the `production/releases/` directory.
|
||||
If yes, write the file; the write creates the directory with it.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Next Steps
|
||||
|
||||
- Run `/gate-check` to get a formal PASS/CONCERNS/FAIL verdict before launch.
|
||||
- Coordinate sign-offs via `/team-release`.
|
||||
- If `project.stage` is not `Release` (`Polish`, an earlier stage, or unset), run `/gate-check release` first — it is the readiness gate before launch.
|
||||
- Coordinate sign-offs and the deployment via `/team-release`.
|
||||
|
||||
@@ -112,6 +112,7 @@ String freeze: [Active / Not yet called / Lifted]
|
||||
| Locale | Total | Translated | Missing | Stale | Coverage |
|
||||
|--------|-------|-----------|---------|-------|----------|
|
||||
| en (source) | [N] | [N] | [N] | [N] | [N]% |
|
||||
| [locale] | [N] | [N] | [N] | [N] | [X]% |
|
||||
|
||||
> **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
|
||||
@@ -120,7 +121,6 @@ String freeze: [Active / Not yet called / Lifted]
|
||||
> 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
|
||||
- [N] hardcoded strings found in source code (run /localize scan)
|
||||
@@ -348,7 +348,7 @@ Pre-Freeze Checklist
|
||||
```
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "Are all items above confirmed? Calling string freeze locks the source table."
|
||||
- Prompt: "Call string freeze now? This writes `production/localization/freeze-status.md` (Status: ACTIVE) and locks the source table."
|
||||
- Options: `[A] Yes — call string freeze now` / `[B] No — I still have strings to add`
|
||||
|
||||
If [A]: Write `production/localization/freeze-status.md`:
|
||||
@@ -367,11 +367,11 @@ If [A]: Write `production/localization/freeze-status.md`:
|
||||
|
||||
### freeze lift
|
||||
|
||||
If argument includes `lift`: update `freeze-status.md` Status to `LIFTED`, record the reason and date. Warn: "Lifting the freeze requires re-translation of all modified strings. Notify the translation team."
|
||||
If argument includes `lift`: ask "May I update `freeze-status.md` to LIFTED?", then set its Status to `LIFTED` and record the reason and date. Warn: "Lifting the freeze requires re-translation of all modified strings. Notify the translation team."
|
||||
|
||||
### freeze check (auto-integrated into extract)
|
||||
|
||||
When `extract` mode finds new or modified strings and `freeze-status.md` shows Status: ACTIVE — append the new keys to `## Post-Freeze Changes` and warn:
|
||||
When `extract` mode finds new or modified strings and `freeze-status.md` shows Status: ACTIVE — name `freeze-status.md` in extract's own "May I write" question, append the new keys to its `## Post-Freeze Changes` on approval, and warn:
|
||||
> "⚠️ String freeze is active. [N] new/modified strings have been added. These are freeze violations. Notify your localization vendor before proceeding."
|
||||
|
||||
---
|
||||
@@ -402,7 +402,7 @@ Output a QA verdict per locale:
|
||||
```
|
||||
## Localization QA Verdict — [Locale]
|
||||
|
||||
**Status**: PASS / PASS WITH CONDITIONS / FAIL
|
||||
**Status**: PASS / PASS WITH CONDITIONS / NOT ASSESSED / FAIL
|
||||
**Reviewed by**: localization-lead
|
||||
**Date**: [date]
|
||||
|
||||
@@ -420,9 +420,17 @@ Output a QA verdict per locale:
|
||||
[ ] Producer approves shipping [Locale]
|
||||
```
|
||||
|
||||
First match wins: **FAIL** if any BLOCKING finding is open; else **NOT ASSESSED**
|
||||
if a check could not run — the checks are playthrough-based, so a locale nobody
|
||||
has played in-game (or whose translations were not delivered) cannot pass on the
|
||||
string tables alone; name each check that did not run; else **PASS WITH
|
||||
CONDITIONS** if conditions remain; else **PASS**. NOT ASSESSED outranks both
|
||||
pass values — an unplayed locale has not passed — and ranks below FAIL, so an
|
||||
open BLOCKING finding is never buried behind it.
|
||||
|
||||
Ask: "May I write this localization QA report to `production/localization/loc-qa-[locale]-[date].md`?"
|
||||
|
||||
**Gate integration**: The Polish → Release gate requires a PASS or PASS WITH CONDITIONS verdict for every locale being shipped. A FAIL blocks release for that locale only — other locales may still proceed if their QA passes.
|
||||
**Gate integration**: At `workflow: full`, the Polish → Release gate requires a PASS or PASS WITH CONDITIONS verdict for every translated locale being shipped (recommended at `standard`; dropped at `minimal`). A FAIL blocks release for that locale only — other locales may still proceed if their QA passes. A NOT ASSESSED locale has not passed: its QA did not run.
|
||||
|
||||
---
|
||||
|
||||
@@ -453,4 +461,4 @@ Ask: "May I write this localization QA report to `production/localization/loc-qa
|
||||
/localize qa → full localization QA pass
|
||||
```
|
||||
|
||||
After `qa` returns PASS for all shipping locales, include the QA report path when running `/gate-check release`.
|
||||
After `qa` returns PASS or PASS WITH CONDITIONS for every translated locale you ship, include the QA report paths when running `/gate-check release`.
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, TaskCreate, TaskG
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow,docs.density`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow,docs.density,project.stage`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
|
||||
defaults in `.claude/docs/config-resolution.md`.
|
||||
@@ -30,12 +30,14 @@ See `.claude/docs/director-gates.md` for the full check pattern. Individual gate
|
||||
|
||||
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).
|
||||
`automation_always_ask` categories always prompt). In collaborative mode the
|
||||
system list, dependency, priority and write approvals are separate questions:
|
||||
each waits for its answer before the next step runs.
|
||||
|
||||
**`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);
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = one-line system descriptions;
|
||||
`balanced` = a brief paragraph per system + dependency notes (`rigor: standard`);
|
||||
`thorough` = full system-by-system rationale + relationship analysis. Apply it to
|
||||
every section you author.
|
||||
|
||||
@@ -202,9 +204,9 @@ dependencies I'm missing or that should be removed?"
|
||||
|
||||
**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.
|
||||
Pass: the dependency graph (each system → what it depends on), layer assignments, bottleneck systems, and any circular dependencies with their proposed resolutions.
|
||||
|
||||
Present the assessment. If REJECT, revise the system boundaries with the user before moving to priority assignment. If CONCERNS, note them inline in the systems index and continue.
|
||||
Present the assessment. If REJECT, revise the system boundaries with the user, show the revised dependency map, and only then move to priority assignment. If CONCERNS, note them inline in the systems index and continue. If NOT ASSESSED [missing input], it is not an APPROVE: name what was missing, then supply it and re-run the gate, or continue with `TD-SYSTEM-BOUNDARY: NOT ASSESSED — [input]` noted in the index draft.
|
||||
|
||||
---
|
||||
|
||||
@@ -258,15 +260,21 @@ both, and cites the pillar it serves:
|
||||
> 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.
|
||||
- `solo` → skip. Note: "PR-SCOPE skipped — Solo mode." Proceed to Step 4c.
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "PR-SCOPE skipped — Lean mode." Proceed to Step 4c.
|
||||
- `full` → spawn as normal.
|
||||
|
||||
**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.
|
||||
Pass the gate's fields from the index: the full vision scope (every system in the index), the MVP definition (the MVP tier's systems), the scope tiers (system count per milestone tier, with estimated implementation volume — system count × average complexity), the stated project timeline as the timeline estimate, and team size.
|
||||
|
||||
Present the assessment. If UNREALISTIC, offer to revise priority tier assignments before writing the index. If CONCERNS, note them and continue.
|
||||
Present the assessment. PR-SCOPE answers REALISTIC / OPTIMISTIC / UNREALISTIC.
|
||||
If UNREALISTIC, offer to revise priority tier assignments before writing the
|
||||
index. If OPTIMISTIC, show the producer's suggested adjustments and ask whether to
|
||||
apply them to the tiers before writing; if the user declines, note them and
|
||||
continue. If NOT ASSESSED [missing input] — often the team size or timeline — it
|
||||
is not a REALISTIC: name what was missing, then supply it and re-run the gate, or
|
||||
continue with `PR-SCOPE: NOT ASSESSED — [input]` noted in the index draft.
|
||||
|
||||
### Step 4c: Determine Design Order
|
||||
|
||||
@@ -305,30 +313,36 @@ Present a summary of the document:
|
||||
`design/gdd/systems-index.md`?" 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.
|
||||
**At `automation: guided`** — a **new** index gets the same "May I write …?"
|
||||
question, because `.claude/docs/automation-modes.md` has `guided` ask "May I
|
||||
write?" for new files. When the index already exists, present the summary above,
|
||||
name the destination (`design/gdd/systems-index.md`), and write the update without
|
||||
waiting for an explicit "yes". 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.
|
||||
> *"proceeds after a short summary, does not wait for explicit yes"* and asks
|
||||
> "May I write?" *"for new files only"*, 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.
|
||||
- `solo` → skip. Note: "CD-SYSTEMS skipped — Solo mode." Proceed to Step 5c.
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "CD-SYSTEMS skipped — Lean mode." Proceed to Step 5c.
|
||||
- `full` → spawn as normal.
|
||||
|
||||
**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.
|
||||
Pass: systems index path; game pillars and core fantasy — from `design/gdd/game-concept.md`, or at `minimal` the pitch and "what they feel" line of `design/game-brief.md`, which has no pillars; the priority tier assignments for every tier (MVP / Vertical Slice / Alpha / Full Vision); and the high-risk and bottleneck systems from the dependency map.
|
||||
|
||||
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**`
|
||||
Present the assessment. If REJECT, revise the system set with the user before GDD authoring begins. If CONCERNS, show them and use `AskUserQuestion`: `Revise the system set` / `Accept — record them in the index` / `Discuss further`. On *Revise*, rework the affected systems with the user and ask again before re-writing the index. On *Accept* — the option names the edit, so choosing it is the ask — 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.
|
||||
direct the writer to one. If NOT ASSESSED [missing input], it is not an APPROVE
|
||||
(`.claude/docs/director-gates.md`): name what was missing, then supply it and
|
||||
re-run the gate, or ask before recording `> **Creative Director Note**:
|
||||
CD-SYSTEMS NOT ASSESSED — [input]` in the same place.
|
||||
|
||||
### Step 5c: Update Session State
|
||||
|
||||
@@ -395,14 +409,15 @@ After the systems index is created (or after designing some systems), present ne
|
||||
|
||||
- "Systems index is written. What would you like to do next?"
|
||||
- [A] Start designing GDDs — run `/design-system [first-system-in-order]`
|
||||
- [B] Run `/gate-check systems-design` — triggers the CD-SYSTEMS and TD-SYSTEM-BOUNDARY gates automatically for a formal director sign-off on the system set
|
||||
- [C] Stop here for this session
|
||||
- [B] Run `/gate-check systems-design` — the Concept → Systems Design gate; offer this only while `project.stage` is still Concept
|
||||
- [C] Run `/gate-check technical-setup` — the Systems Design → Technical Setup gate, once the MVP systems have GDDs
|
||||
- [D] Stop here for this session
|
||||
|
||||
**The gate-check option ([B]) is worth highlighting**: running `/gate-check systems-design` triggers both the CD-SYSTEMS and TD-SYSTEM-BOUNDARY gates, catching scope issues, missing systems, and boundary problems before they're locked in across many documents. It is optional but recommended for new projects.
|
||||
**The gate-check option ([C]) is worth knowing about**: `/gate-check technical-setup` checks that the Systems Design phase's required artifacts exist and runs the phase-gate directors before you commit to architecture. CD-SYSTEMS and TD-SYSTEM-BOUNDARY are this skill's own gates — they run here, in `full` review mode, not in `/gate-check`.
|
||||
|
||||
After any individual GDD is completed:
|
||||
- "Run `/design-review design/gdd/[system].md` in a fresh session to validate quality"
|
||||
- "Run `/gate-check systems-design` when all MVP GDDs are complete"
|
||||
- "Run `/gate-check technical-setup` when all MVP GDDs are complete"
|
||||
|
||||
---
|
||||
|
||||
@@ -447,4 +462,4 @@ If context reaches or exceeds 70% at any point, append this notice:
|
||||
- Run `/design-system [first-system-in-order]` to author the first GDD (use design order from the index)
|
||||
- Run `/map-systems next` to always pick the highest-priority undesigned system automatically
|
||||
- Run `/design-review design/gdd/[system].md` in a fresh session after each GDD is authored
|
||||
- Run `/gate-check pre-production` when all MVP GDDs are authored and reviewed
|
||||
- Run `/gate-check technical-setup` when all MVP GDDs are authored and reviewed
|
||||
|
||||
@@ -7,7 +7,10 @@ allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion, Bash(bash "*/.cl
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
|
||||
@@ -91,11 +94,26 @@ 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.
|
||||
|
||||
**Blocked stories** — the Blocked table and the blocked story count passed to
|
||||
PR-MILESTONE — are not in the sprint reports' scanned sections. Read them where
|
||||
they are recorded: the `status: blocked` stories in `production/sprint-status.yaml`
|
||||
(with their `blocker` field) and, for stories outside that sprint, one grep:
|
||||
|
||||
```
|
||||
Grep pattern="^> \*\*Status\*\*: Blocked|BLOCKED:" glob="production/epics/**/story-*.md" output_mode="content"
|
||||
```
|
||||
|
||||
Each blocked story goes in the Blocked table under the feature its epic folder
|
||||
implements, with its blocker (the yaml `blocker` field or the story's `BLOCKED:`
|
||||
note). With no story files and no `sprint-status.yaml`, the Blocked table and the
|
||||
blocked story count are `NOT ASSESSED — NO DATA`, not zero.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Scan Codebase Health
|
||||
|
||||
- Scan for `TODO`, `FIXME`, `HACK` markers that indicate incomplete work
|
||||
- Count open bugs by severity for Quality Metrics from `production/qa/bugs/` (one grep of the `**Severity**` and `**Status**` lines, as `/bug-triage` does); with no bug files, the bug lines are `NOT ASSESSED — NO DATA`, not zero
|
||||
- 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)
|
||||
|
||||
---
|
||||
@@ -114,6 +132,8 @@ omits a sprint understates the work and the slippage both.
|
||||
## Feature Completeness
|
||||
|
||||
### Fully Complete
|
||||
Only a feature whose Status is `Complete` goes here or counts toward the completion percentage; a Deferred feature stays in its denominator, named with the milestone it moved to.
|
||||
|
||||
| Feature | Acceptance Criteria | Test Status |
|
||||
|---------|-------------------|-------------|
|
||||
|
||||
@@ -121,6 +141,14 @@ omits a sprint understates the work and the slippage both.
|
||||
| Feature | % Done | Remaining Work | Risk to Milestone |
|
||||
|---------|--------|---------------|------------------|
|
||||
|
||||
### Blocked
|
||||
A started feature whose stories are Blocked goes here, not under Partially
|
||||
Complete — name the blocker, so the review says why it stalled, not only that
|
||||
the count moved.
|
||||
|
||||
| Feature | Blocked Stories | Blocker | Next Action / Owner |
|
||||
|---------|----------------|---------|---------------------|
|
||||
|
||||
### Not Started
|
||||
| Feature | Priority | Can Cut? | Impact of Cutting |
|
||||
|---------|----------|----------|------------------|
|
||||
@@ -201,7 +229,9 @@ If AT RISK, use `AskUserQuestion`:
|
||||
- `[B] NO-GO — conditions cannot be met in time`
|
||||
- `[C] GO — I accept the risk and want to proceed`
|
||||
|
||||
Do not issue a GO against an OFF TRACK verdict unless the user explicitly selects [B] above.
|
||||
If NOT ASSESSED: name the missing input — it is not ON TRACK, and never recommend GO on it. Supply the input and re-run PR-MILESTONE, or recommend NOT ASSESSED — or CONDITIONAL GO / NO-GO where the review's own findings call for one (the rank in `.claude/docs/director-gates.md`).
|
||||
|
||||
Do not issue a GO against an OFF TRACK verdict; issue CONDITIONAL GO only if the user explicitly selects [B] above.
|
||||
|
||||
---
|
||||
|
||||
@@ -220,4 +250,4 @@ If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
## Phase 5: Next Steps
|
||||
|
||||
- Run `/gate-check` for a formal phase gate verdict if this milestone marks a development phase boundary.
|
||||
- Run `/sprint-plan` to adjust the next sprint based on the scope recommendations above.
|
||||
- Run `/sprint-plan` to adjust the next sprint based on the scope recommendations above (at `workflow: minimal`, which has no sprints, adjust the brief's build order instead).
|
||||
|
||||
@@ -51,15 +51,21 @@ Read CLAUDE.md for project overview and standards.
|
||||
|
||||
Read the relevant agent definition from `.claude/agents/` if a specific role is specified.
|
||||
|
||||
`CLAUDE.md` and `.claude/agents/` ship with the framework — no skill creates them. If either is missing, report it as missing from the install.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Scan Relevant Area
|
||||
|
||||
- For programmers: scan the code root (resolve per `.claude/docs/code-root-resolution.md`) for architecture, patterns, key files
|
||||
- For programmers: scan the code root (resolve per `.claude/docs/code-root-resolution.md`) for architecture, patterns, key files. An unresolved root means the scan did not run: the sections it feeds read `NOT ASSESSED — code root unresolved`, never a guess at `src/`
|
||||
- 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
|
||||
- For QA: scan `tests/` for existing test coverage (`/test-setup` creates it)
|
||||
- For production: scan `production/` for current sprint and milestone
|
||||
- **No role or area given**: a general orientation — list the top level of `design/`,
|
||||
`docs/architecture/`, `production/` and the code root, read
|
||||
`production/session-state/active.md` if it exists, and say that a role would
|
||||
focus the next pass (e.g. `/onboard programmer`)
|
||||
|
||||
Read recent changes (git log if available) to understand current momentum.
|
||||
|
||||
@@ -91,7 +97,9 @@ Read recent changes (git log if available) to understand current momentum.
|
||||
[Summary of conventions relevant to this role from CLAUDE.md and agent definition]
|
||||
|
||||
## Current State of Your Area
|
||||
[What has been built, what is in progress, what is planned next]
|
||||
[What has been built, what is in progress, what is planned next. Name what
|
||||
Phase 2 found by path — for a designer, each existing GDD and design doc — or
|
||||
say it found none]
|
||||
|
||||
## Current Sprint Context
|
||||
[What the team is working on now and what is expected of this role]
|
||||
|
||||
@@ -20,7 +20,9 @@ every file write follows `.claude/docs/automation-modes.md`
|
||||
**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`.
|
||||
1. Sample the recent log: `git log --oneline -20`. **If it is empty or git is
|
||||
unavailable, skip this check** — there is nothing to classify, and Phase 2's
|
||||
no-changelog-data branch is the right stop.
|
||||
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.
|
||||
@@ -32,7 +34,7 @@ before Phase 2 and stop if it fails.
|
||||
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.
|
||||
- **Zero Game commits** → stop, using the message below, and give the count (0 of how many) so the reader can see the filter ran.
|
||||
|
||||
> **Filter per commit; do not stop on a repo that merely contains maintenance
|
||||
> work.** Every project built on this framework accumulates commits touching
|
||||
@@ -45,15 +47,19 @@ before Phase 2 and stop if it fails.
|
||||
> 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
|
||||
that appear in `design/` and the code root (`src/`, `Assets/` or `Source/`). 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
|
||||
> "The git history in this repo does not appear to belong to [game]: 0 of the [N]
|
||||
> recent commits are Game commits. 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."
|
||||
|
||||
Verdict: **BLOCKED** — stop here without generating notes.
|
||||
|
||||
**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"*
|
||||
@@ -110,7 +116,12 @@ Verdict: **BLOCKED** — stop here without generating notes.
|
||||
1. Glob for `docs/patch-notes-template.md` and `.claude/docs/templates/patch-notes-template.md`.
|
||||
2. If found at either location, read it and use it as the output structure for Phase 4
|
||||
instead of the built-in style templates (Brief / Detailed / Full). Fill in the
|
||||
template's sections with the categorized data.
|
||||
template's sections with the categorized data, mapping each category to the
|
||||
template section that means the same (New Content → its new-features section,
|
||||
Bug Fixes → its fixes section); a category with no matching section goes under
|
||||
the closest one, never dropped. Keep the template's header and footer text
|
||||
as written. Say in the output which template was used — and, when `--style`
|
||||
was passed, that the template replaced it.
|
||||
3. If not found, use the built-in style templates as defined in Phase 4.
|
||||
|
||||
---
|
||||
@@ -225,17 +236,18 @@ Check the generated notes for:
|
||||
|
||||
Present the completed patch notes to the user along with: a count of changes by category, and any internal changes that were excluded (for review).
|
||||
|
||||
Ask: "May I write these patch notes to `docs/patch-notes/[version].md`?"
|
||||
Ask: "May I write these patch notes to `docs/patch-notes/[version].md`, and an
|
||||
archive copy to `production/releases/[version]/patch-notes.md`?"
|
||||
|
||||
If yes, write the file to `docs/patch-notes/[version].md`, creating the directory
|
||||
if needed. Also write to `production/releases/[version]/patch-notes.md` as the
|
||||
internal archive copy.
|
||||
If yes, write both files, creating the directories if needed.
|
||||
If no, write nothing.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Next Steps
|
||||
|
||||
Verdict: **COMPLETE** — patch notes generated and saved.
|
||||
Verdict: **COMPLETE** — patch notes generated and saved. (If the write was
|
||||
declined: Verdict: **COMPLETE** — patch notes generated and shown, not saved.)
|
||||
|
||||
- Run `/release-checklist` to verify all other release gates are met before publishing.
|
||||
- Share the patch notes draft with the community-manager for tone review before posting publicly.
|
||||
|
||||
@@ -3,7 +3,7 @@ name: perf-profile
|
||||
description: "Performance profiling — find bottlenecks, measure against budgets, produce ranked optimization recommendations."
|
||||
argument-hint: "[system-name or 'full']"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Bash, Bash(bash "*/.claude/skills/perf-profile/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash, Bash(bash "*/.claude/skills/perf-profile/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -171,10 +171,10 @@ Generated: [Date]
|
||||
### Performance Budgets
|
||||
| Metric | Budget | Estimated Current | Status |
|
||||
|--------|--------|-------------------|--------|
|
||||
| Frame time | [16.67ms] | [estimate] | [OK/WARNING/OVER] |
|
||||
| Memory | [target] | [estimate] | [OK/WARNING/OVER] |
|
||||
| Load time | [target] | [estimate] | [OK/WARNING/OVER] |
|
||||
| Draw calls | [target] | [estimate] | [OK/WARNING/OVER] |
|
||||
| Frame time | [16.67ms] | [estimate] | [OK/WARNING/OVER/NOT ASSESSED] |
|
||||
| Memory | [target] | [estimate] | [OK/WARNING/OVER/NOT ASSESSED] |
|
||||
| Load time | [target] | [estimate] | [OK/WARNING/OVER/NOT ASSESSED] |
|
||||
| Draw calls | [target] | [estimate] | [OK/WARNING/OVER/NOT ASSESSED] |
|
||||
|
||||
### Hotspots Identified
|
||||
| # | Location | Issue | Estimated Impact | Fix Effort |
|
||||
@@ -194,7 +194,9 @@ Generated: [Date]
|
||||
- [Area that needs actual runtime profiling to confirm impact]
|
||||
```
|
||||
|
||||
Output the report with a summary: top 3 hotspots, estimated headroom vs budget, and recommended next action.
|
||||
Output the report with a summary: top 3 hotspots, estimated headroom against
|
||||
each budget that is set — for a metric with none, `no budget set — headroom not
|
||||
assessed` — and recommended next action.
|
||||
|
||||
---
|
||||
|
||||
@@ -211,7 +213,14 @@ Present significant-effort items and ask the user to choose for each:
|
||||
|
||||
If multiple items are deferred to Polish (choice C), record them under `### Deferred to Polish`.
|
||||
|
||||
This skill is read-only — no files are written. Verdict: **COMPLETE** — performance profile generated.
|
||||
---
|
||||
|
||||
## Verdict
|
||||
|
||||
Close every run that produced a report — whether or not Phase 5 ran — with:
|
||||
Verdict: **COMPLETE** — performance profile generated (saved to
|
||||
`production/polish/[scope]-report-[date].md` if the write was approved). The only
|
||||
other outcome is the `NOT ASSESSED — NO DATA` path above.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ model: sonnet
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
|
||||
## Phase 1: Parse Arguments
|
||||
@@ -23,8 +26,11 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
Determine the mode:
|
||||
|
||||
- `new` → generate a blank playtest report template
|
||||
- `new` → generate a blank playtest report template. This mode ends after
|
||||
Phase 2A: a blank template has nothing to route, review or save.
|
||||
- `analyze [path]` → read raw notes and fill in the template with structured findings
|
||||
- No argument → ask via `AskUserQuestion`: `[A] New blank template` /
|
||||
`[B] Analyze notes — I'll give you the path`
|
||||
|
||||
---
|
||||
|
||||
@@ -94,12 +100,19 @@ Generate this template and output it to the user:
|
||||
3. [Third priority]
|
||||
```
|
||||
|
||||
In `new` mode, stop here with: Verdict: **COMPLETE** — blank template output; nothing saved.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2B: Analyze Mode
|
||||
|
||||
Read the raw notes at the provided path. Cross-reference with existing design documents. Fill in the template above with structured findings. Flag any playtest observations that conflict with design intent.
|
||||
|
||||
An observation that describes a defect — a crash, a framerate drop, a softlock,
|
||||
something that plainly breaks rather than plays badly — goes in the **Bugs
|
||||
Encountered** table, not under Gameplay Flow → Pain points, and is routed as a
|
||||
bug in Phase 3. Pain points are for how the game feels to play.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Action Routing
|
||||
@@ -132,12 +145,13 @@ After categorising findings, spawn `creative-director` via `Agent` using gate **
|
||||
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.
|
||||
`design/game-brief.md` replaces it — the brief has no pillars: pass its
|
||||
one-sentence pitch and its "Who it's for / what they feel" line instead, and say
|
||||
they stand in for pillars. If neither document 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.
|
||||
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. If NOT ASSESSED (the director lacked an input — `.claude/docs/director-gates.md`), add the same section naming what was missing; it is not an approval.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: project-stage-detect
|
||||
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, Bash(bash "*/.claude/skills/project-stage-detect/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash(bash "*/.claude/skills/project-stage-detect/../../hooks/yaml-helper.sh" resolve_config *), Bash(bash .claude/scripts/artifact-check.sh), Bash(bash ".claude/scripts/artifact-check.sh"), Bash(bash ./.claude/scripts/artifact-check.sh), Bash(bash .claude/scripts/artifact-check.sh *), Bash(bash ".claude/scripts/artifact-check.sh" *), Bash(bash ./.claude/scripts/artifact-check.sh *)
|
||||
model: haiku
|
||||
# Read-only diagnostic skill — no specialist agent delegation needed
|
||||
---
|
||||
@@ -55,6 +55,10 @@ catalogued artifact in one call:**
|
||||
Bash: bash .claude/scripts/artifact-check.sh
|
||||
```
|
||||
|
||||
Run it exactly as written — from the project root, relative path, no
|
||||
arguments, no `cd`, no `2>&1`. This skill's permission grant matches that form;
|
||||
any other asks the user to approve it.
|
||||
|
||||
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
|
||||
@@ -81,9 +85,15 @@ track, and the judgement calls.
|
||||
- Identify major systems (directories with 5+ files)
|
||||
- Check for core/, gameplay/, ai/, networking/, ui/ directories
|
||||
- Estimate lines of code (rough scale)
|
||||
- An unresolved root means none of these ran: report
|
||||
`NOT ASSESSED — code root unresolved`, never zero source files — zero files
|
||||
reads as a greenfield project, and the source-file rows of the stage table
|
||||
cannot be decided without the count
|
||||
|
||||
**Production Artifacts** (`production/`):
|
||||
- Check for active sprint plans
|
||||
- Check for active sprint plans. At `workflow: minimal` there are no sprints:
|
||||
read the story files' progress through the brief's build order instead, and
|
||||
never report a missing sprint plan, milestone or roadmap as a gap
|
||||
- Look for milestone definitions
|
||||
- Find roadmap documents
|
||||
|
||||
@@ -116,9 +126,15 @@ Based on scanned artifacts, determine stage. Check `project.stage` in `project.y
|
||||
>
|
||||
> 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.
|
||||
> detector that cannot contradict its input is the one thing it must never be —
|
||||
> it would report `Release` for a project whose artifacts match its own
|
||||
> Pre-Production row, four stages below, and say nothing.
|
||||
>
|
||||
> **A disagreement makes Stage Confidence CONCERNS** (step 4) — ambiguous
|
||||
> signals by definition — however complete the artifacts are. One exception: at
|
||||
> `workflow: minimal` nothing runs `/gate-check`, so the configured stage stays
|
||||
> where `/start` set it. There, report the observed stage and say the configured
|
||||
> one is not advanced at this tier; that lag is expected, not a disagreement.
|
||||
|
||||
| Stage | Indicators |
|
||||
|-------|-----------|
|
||||
@@ -138,14 +154,16 @@ Based on scanned artifacts, determine stage. Check `project.stage` in `project.y
|
||||
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.
|
||||
absent GDDs, art bible, UX specs, ADRs, epics or sprint plans as gaps: the brief's build
|
||||
order is the plan, and 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?"
|
||||
- "I see combat code (`<code root>/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?"
|
||||
- "No sprint plans in `production/`. Are you tracking work elsewhere (Jira, Trello, etc.)?"
|
||||
- (`standard`/`full` only) "I see [N] systems under `<code root>/` but no ADRs in `docs/architecture/`. Were those decisions recorded somewhere else, or should we write the critical ones with `/architecture-decision`?"
|
||||
- (`standard`/`full` only) "No sprint plans in `production/`. Are you tracking work elsewhere (Jira, Trello, etc.)?"
|
||||
- "I found a game concept but no systems index. Have you decomposed the concept into individual systems yet, or should we run `/map-systems`?"
|
||||
- "Prototypes directory has 3 projects with no READMEs. Were these experiments, or do they need documentation?"
|
||||
|
||||
@@ -159,13 +177,13 @@ Use template: `.claude/docs/templates/project-stage-report.md`
|
||||
|
||||
**Date**: [date]
|
||||
**Stage**: [Concept/Systems Design/Technical Setup/Pre-Production/Production/Polish/Release]
|
||||
**Stage Confidence**: [PASS — clearly detected / CONCERNS — ambiguous signals / FAIL — critical gaps block progress]
|
||||
**Stage Confidence**: [PASS — clearly detected / CONCERNS — ambiguous signals / NOT ASSESSED — a check the stage depends on did not run / FAIL — critical gaps block progress]
|
||||
|
||||
## Completeness Overview
|
||||
- Design: [X%] ([N] docs, [gaps])
|
||||
- Code: [X%] ([N] files, [systems])
|
||||
- Architecture: [X%] ([N] ADRs, [gaps])
|
||||
- Production: [X%] ([status])
|
||||
- Production: [X%] ([status] — at `minimal`: stories complete in the brief's build order, never "no sprint plan")
|
||||
- Tests: [X%] ([coverage estimate])
|
||||
|
||||
## Gaps Identified
|
||||
@@ -176,6 +194,16 @@ Use template: `.claude/docs/templates/project-stage-report.md`
|
||||
[Priority-ordered list based on stage and role]
|
||||
```
|
||||
|
||||
**Stage Confidence — first match wins:** **FAIL** if critical gaps block
|
||||
progress; else **CONCERNS** if the signals that were gathered are ambiguous —
|
||||
they fit more than one stage, or the configured and observed stages disagree
|
||||
(step 2); else **NOT ASSESSED** if a check the stage depends on did not run —
|
||||
name it (an unresolved code root, two candidate roots included, leaves the
|
||||
source-file count, and so the table's Production row, undecided); else
|
||||
**PASS**. NOT ASSESSED outranks PASS — a stage nobody could check is not a
|
||||
clearly detected one — and ranks below CONCERNS and FAIL, so a known problem is
|
||||
never buried behind it.
|
||||
|
||||
### 5. Role-Filtered Recommendations (Optional)
|
||||
|
||||
If user provided a role argument (e.g., `/project-stage-detect programmer`):
|
||||
@@ -243,10 +271,10 @@ 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]`
|
||||
- **Missing design docs?** → `/reverse-document design <code root>/[system]`
|
||||
- **Missing architecture docs?** → `/architecture-decision` or `/reverse-document architecture`
|
||||
- **Prototypes need documentation?** → `/reverse-document concept prototypes/[name]`
|
||||
- **No sprint plan?** → `/sprint-plan`
|
||||
- **No sprint plan?** → `/sprint-plan` (not at `rigor: minimal`, where the brief's build order is the plan)
|
||||
- **Approaching milestone?** → `/milestone-review`
|
||||
|
||||
---
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
---
|
||||
name: propagate-design-change
|
||||
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]"
|
||||
argument-hint: "[path/to/changed-gdd.md] [--review full|lean|solo]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/propagate-design-change/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,system_overrides`
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow,system_overrides`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
# Propagate Design Change
|
||||
|
||||
@@ -122,7 +123,12 @@ below still runs.
|
||||
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.
|
||||
that references the changed GDD. An ADR is critical when the `**Layer**` row of
|
||||
its `## Engine Compatibility` table says `Foundation`, or when it has no
|
||||
`**Layer**` row — when in doubt, treat it as critical
|
||||
(`.claude/docs/workflow-modes.md`). Read every row in one call:
|
||||
`Grep pattern="\*\*Layer\*\*" glob="docs/architecture/adr-*.md" output_mode="content"`,
|
||||
and count an ADR that Grep does not list as critical.
|
||||
- **`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.
|
||||
@@ -147,7 +153,7 @@ 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." |
|
||||
| **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 retrofit [adr]`." 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.
|
||||
|
||||
@@ -170,8 +176,8 @@ This read is unbounded only up to a point — check size 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.
|
||||
the only path forward is paging through the entire remainder — most of it
|
||||
content this analysis never uses.
|
||||
|
||||
For each ADR that references the changed GDD:
|
||||
|
||||
@@ -254,6 +260,7 @@ Apply the verdict:
|
||||
- **APPROVE** → proceed to Phase 7 resolution workflow
|
||||
- **CONCERNS** → surface the specific ADRs or recommendations flagged; use `AskUserQuestion` with options: `Revise the impact assessment` / `Accept with noted concerns` / `Discuss further`
|
||||
- **REJECT** → do not proceed to resolution; re-analyze the impact before continuing
|
||||
- **NOT ASSESSED** [missing input] → not an approval (`.claude/docs/director-gates.md`): name what was missing, then supply it and re-run the gate — or, if the user chooses to go on without it, proceed to Phase 7 and state `TD-CHANGE-IMPACT: NOT ASSESSED — [input]` in the change impact report and the final Verdict line
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
---
|
||||
name: prototype
|
||||
description: "Concept prototype before GDDs — throwaway HTML, Engine or Paper build, PROCEED/PIVOT/KILL. After /brainstorm and /setup-engine."
|
||||
description: "Concept prototype before GDDs — throwaway HTML, Engine or Paper build, PROCEED/PIVOT/KILL/NOT ASSESSED. 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, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/prototype/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
isolation: worktree
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,workflow`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +42,12 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
**Check for spike mode:** If `--spike` was passed, skip to the **Spike Mode** section
|
||||
at the bottom of this skill.
|
||||
|
||||
Otherwise, use `AskUserQuestion` to confirm intent before proceeding:
|
||||
**Check for a carry-forward note:** Glob `prototypes/*/PIVOT-NOTE.md`. If one
|
||||
exists for this concept (or an earlier version of it), read it and start from its
|
||||
revised hypothesis instead of forming one from scratch — say which note you used.
|
||||
|
||||
Then, unless `--spike` sent you to Spike Mode, use `AskUserQuestion` to confirm
|
||||
intent before proceeding — with or without a carry-forward note:
|
||||
|
||||
- **Prompt**: "How would you like to use this prototype session?"
|
||||
- **Options**:
|
||||
@@ -93,7 +100,8 @@ thing the prototype should test — not the easiest part, the riskiest.
|
||||
|
||||
## Phase 2: Load Concept Context
|
||||
|
||||
Read `design/gdd/game-concept.md` if it exists. Extract:
|
||||
Read `design/gdd/game-concept.md` — or `design/game-brief.md`, the one-page brief
|
||||
that replaces it at `rigor: minimal` — if either exists. Extract:
|
||||
- Core fantasy (what the player is supposed to feel)
|
||||
- Core loop (the moment-to-moment action being tested)
|
||||
|
||||
@@ -255,6 +263,8 @@ Define in 3–5 bullet points the minimum viable prototype:
|
||||
If scope covers more than one mechanic, cut it down. When in doubt, cut more.
|
||||
|
||||
Present this plan to the user before building. Get confirmation before proceeding.
|
||||
Name the checkpoint file in that confirmation: "May I record this plan in
|
||||
`production/session-state/active.md`?"
|
||||
|
||||
Once confirmed, write a session checkpoint to `production/session-state/active.md`
|
||||
(create `production/session-state/` if it does not exist). Include: concept name,
|
||||
@@ -272,11 +282,17 @@ and begin implementation?"
|
||||
If yes, create the directory. Every file must begin with:
|
||||
|
||||
```
|
||||
// PROTOTYPE - NOT FOR PRODUCTION
|
||||
// Question: [Core question being tested]
|
||||
// Date: [Current date]
|
||||
[comment] PROTOTYPE - NOT FOR PRODUCTION
|
||||
[comment] Question: [Core question being tested]
|
||||
[comment] Date: [Current date]
|
||||
```
|
||||
|
||||
Write `[comment]` in each file's own comment syntax — `#` in GDScript (`.gd`) and
|
||||
Python, `//` in C#, C++ and JavaScript, `--` in Lua, `<!-- … -->` in HTML and
|
||||
Markdown. A header in another language's syntax is a parse error, not a label.
|
||||
Files that cannot hold a comment (JSON, engine-generated scene and project
|
||||
files) are exempt.
|
||||
|
||||
Standards are intentionally relaxed:
|
||||
|
||||
- Hardcode values freely
|
||||
@@ -372,6 +388,11 @@ behavior. Now ask for the overall assessment:
|
||||
> nearby, try running the rules with them. Come back when you've seen at least one
|
||||
> full play cycle."
|
||||
|
||||
**If nobody can play it this session**, do not ask for a verdict and do not infer
|
||||
one from how the build looks: the recommendation is **NOT ASSESSED — built, not
|
||||
played**. Write the report with that verdict (Phase 7, asking first) and name the
|
||||
next step — play it, then re-run this debrief.
|
||||
|
||||
Once the user returns, ask these questions **one at a time** — wait for each answer
|
||||
before asking the next:
|
||||
|
||||
@@ -406,11 +427,12 @@ Read `.claude/docs/templates/prototype-report.md` to get the report structure.
|
||||
Fill in every section based on what was observed during this session. Replace all
|
||||
placeholder text with real observations — no generic filler.
|
||||
|
||||
Ask: "May I write this report to `prototypes/[concept-name]-concept/REPORT.md`?"
|
||||
Ask: "May I write this report to `prototypes/[concept-name]-concept/REPORT.md`
|
||||
and add its row to `prototypes/index.md`?"
|
||||
|
||||
If yes, write the file. Then update `prototypes/index.md` (create if it does not
|
||||
exist) — append one row to the concept prototype table: concept name, date, path
|
||||
used, verdict (PROCEED/PIVOT/KILL), and a link to the REPORT.md. If a PIVOT chain
|
||||
used, verdict (PROCEED/PIVOT/KILL, or NOT ASSESSED when nobody has played it), and a link to the REPORT.md. If a PIVOT chain
|
||||
exists (prior PIVOT-NOTE.md in a related concept folder), note the chain. This file
|
||||
is the project's complete history of what was tried and what was learned.
|
||||
|
||||
@@ -422,16 +444,35 @@ is the project's complete history of what was tried and what was learned.
|
||||
- `solo` → skip. Note: "CD-PLAYTEST skipped — Solo mode."
|
||||
- `lean` → skip. Note: "CD-PLAYTEST skipped — Lean mode."
|
||||
- `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."
|
||||
`design/gdd/game-concept.md` exists with game pillars defined, or
|
||||
`design/game-brief.md` exists (the `rigor: minimal` brief has no pillars — its
|
||||
pitch and "what they feel" line stand in). If neither is available, note:
|
||||
"CD-PLAYTEST skipped — game pillars not yet defined at concept prototype stage."
|
||||
|
||||
Pass: the full REPORT.md content, the original hypothesis, and game pillars /
|
||||
core fantasy from `design/gdd/game-concept.md`.
|
||||
core fantasy from `design/gdd/game-concept.md` (or the brief's pitch and "what
|
||||
they feel" line from `design/game-brief.md`).
|
||||
|
||||
The creative director evaluates the result against the game's creative vision and
|
||||
confirms, modifies, or overrides the recommendation. Their verdict is final. Update
|
||||
REPORT.md if the verdict differs.
|
||||
returns one of the gate's verdicts — APPROVE, CONCERNS or REJECT — or NOT
|
||||
ASSESSED when it could not judge. Apply it to the recommendation:
|
||||
|
||||
- **APPROVE** → the recommendation stands.
|
||||
- **CONCERNS** → show the concerns alongside the recommendation, then use
|
||||
`AskUserQuestion`: `Revise the recommendation` / `Accept with noted concerns` /
|
||||
`Discuss further`. The user decides; the director does not.
|
||||
- **REJECT** (the core fantasy is not present) → a PROCEED recommendation cannot
|
||||
stand. Use `AskUserQuestion` to ask the user to choose `PIVOT` or `KILL`, and run
|
||||
Phase 9 for that choice. A PIVOT or KILL recommendation stands.
|
||||
- **NOT ASSESSED** (the director lacked an input — `.claude/docs/director-gates.md`)
|
||||
→ not an approval. Name what was missing; supply it and re-run the gate, or
|
||||
record the review as NOT ASSESSED and let the user decide whether the
|
||||
recommendation stands unreviewed.
|
||||
|
||||
When the director returned CONCERNS, REJECT or NOT ASSESSED, ask "May I update
|
||||
`prototypes/[concept-name]-concept/REPORT.md` and its `prototypes/index.md`
|
||||
row?", then record the director's verdict and reason in REPORT.md, and the final
|
||||
recommendation in both if it changed.
|
||||
|
||||
---
|
||||
|
||||
@@ -444,7 +485,10 @@ Link to `prototypes/[concept-name]-concept/REPORT.md`.
|
||||
Your concept prototype validated the core idea. Now design it properly, informed by
|
||||
what you just learned.
|
||||
|
||||
Recommended path (in order):
|
||||
At `workflow: minimal`: `/create-stories` (from the brief), then `/dev-story`
|
||||
on the first story — the rest of this list is the `standard`/`full` path.
|
||||
|
||||
Recommended path (in order, `standard`/`full`):
|
||||
1. `/design-review design/gdd/game-concept.md` — validate the concept doc against what the prototype revealed
|
||||
2. `/gate-check` — confirm readiness to advance to Systems Design
|
||||
3. `/art-bible` — define visual identity (optional but worth doing before GDDs)
|
||||
@@ -467,9 +511,8 @@ two questions (plain text, one at a time):
|
||||
Ask: "May I write this to `prototypes/[concept-name]-concept/PIVOT-NOTE.md`?"
|
||||
|
||||
If yes, write the file with: original hypothesis, what to keep, what to change, and
|
||||
the revised hypothesis for the next prototype. When `/prototype` is next run, check
|
||||
`prototypes/` for any `PIVOT-NOTE.md` files — if found, read them and use the
|
||||
revised hypothesis as the starting point rather than forming one from scratch.
|
||||
the revised hypothesis for the next prototype. The next `/prototype` run picks it
|
||||
up at the start of Phase 1.
|
||||
|
||||
- Run `/prototype [revised-concept]` to test the adjusted direction
|
||||
- Or `/brainstorm [hint]` if the concept needs more fundamental rethinking
|
||||
@@ -502,6 +545,14 @@ This file exists so the same mistake doesn't get made twice on the next concept.
|
||||
- Run `/brainstorm open` or `/brainstorm [new-hint]` to explore a different concept
|
||||
- The prototype report is the deliverable — no further action needed
|
||||
|
||||
**If NOT ASSESSED (nobody has played it):**
|
||||
|
||||
There is no fun evidence yet, so PROCEED, PIVOT and KILL are all unreachable —
|
||||
report NOT ASSESSED and stop here rather than guess.
|
||||
|
||||
- Play it, then run `/prototype [same concept]` again
|
||||
- The report and the concept index row read NOT ASSESSED until a playtest happens
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
@@ -529,11 +580,11 @@ gate implications. Hard cap: ~4 hours.
|
||||
|
||||
3. **Scope** — maximum 2-3 bullet points. One mechanic, one technical question, nothing else.
|
||||
|
||||
4. **Build** — same relaxed standards as concept prototype. Hard cap: 4 hours. If not demonstrable in 4 hours, the question is too large. Split it.
|
||||
4. **Build** — first ask "May I create `prototypes/[concept-name]-spike-[date]/` and build the spike there?" Same relaxed standards and header as the concept prototype. Hard cap: 4 hours. If not demonstrable in 4 hours, the question is too large. Split it.
|
||||
|
||||
5. **Observe and decide** — no formal playtest debrief. Ask: "Did the spike answer the question? YES or NO, and why in one sentence."
|
||||
|
||||
6. **Write a spike note** (not a full report) to `prototypes/[concept-name]-spike-[date]/SPIKE-NOTE.md`:
|
||||
6. **Write a spike note** (not a full report) to `prototypes/[concept-name]-spike-[date]/SPIKE-NOTE.md` — first ask once for this step and the next, naming both files: "May I write `prototypes/[concept-name]-spike-[date]/SPIKE-NOTE.md` and clear the spike from `production/session-state/active.md`?" The note holds:
|
||||
- Question tested
|
||||
- Result (YES it works / NO it doesn't / PARTIAL — needs more investigation)
|
||||
- What to do next (add to current sprint / investigate further / abandon the idea)
|
||||
|
||||
@@ -42,6 +42,8 @@ the test plan is mined from — see Phase 2.
|
||||
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).
|
||||
No level drops the Visual/Feel and UI screenshot rows — tests are waived at
|
||||
`minimal`, the look is not (`.claude/docs/coding-standards.md`).
|
||||
|
||||
## Phase 1: Parse Scope
|
||||
|
||||
@@ -72,6 +74,8 @@ for one missing file.
|
||||
> 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`."
|
||||
> At `workflow: minimal` there are no sprints by design — route instead to
|
||||
> `/qa-plan feature: [epic-slug]` or `/qa-plan story: [path]`.
|
||||
> - 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.
|
||||
@@ -190,7 +194,7 @@ Assemble the full QA plan document. Use this structure:
|
||||
| [story title] | Logic | Unit test — `tests/unit/[system]/` | None |
|
||||
| [story title] | Integration | Integration test — `tests/integration/[system]/` | Smoke check |
|
||||
| [story title] | Visual/Feel | None (not automatable) | Screenshot + lead sign-off |
|
||||
| [story title] | UI | Interaction walkthrough | Manual step-through |
|
||||
| [story title] | UI | None (verified by its screenshots) | Retained screenshot of each screen touched |
|
||||
| [story title] | Config/Data | Data validation test | Spot-check in-game values |
|
||||
|
||||
---
|
||||
@@ -227,7 +231,7 @@ criteria directly. Review the GDD Formulas section before writing tests.*
|
||||
### [Story Title] — [Type]
|
||||
**Verification method**: [Screenshot + designer sign-off | Playtest session |
|
||||
Manual step-through | Comparison against reference footage]
|
||||
**Who must sign off**: [designer / lead-programmer / qa-lead / art-lead]
|
||||
**Who must sign off**: [designer / lead-programmer / qa-lead / art-director]
|
||||
**Evidence to capture**: [screenshot of X | video clip of Y | written playtest
|
||||
notes | side-by-side comparison]
|
||||
|
||||
@@ -275,13 +279,14 @@ this sprint.*
|
||||
## Definition of Done — This Sprint
|
||||
|
||||
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):
|
||||
the test-file and smoke rows below — tests are waived there; the screenshot and
|
||||
sign-off rows stay at every level, because the look is not):
|
||||
|
||||
- [ ] 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 *(qa.level standard/full)*
|
||||
- [ ] Manual evidence document exists for all Visual/Feel and UI stories *(qa.level standard/full)*
|
||||
- [ ] Retained screenshot of each screen touched, in `production/qa/evidence/`, for all Visual/Feel and UI stories *(every qa.level)*
|
||||
- [ ] Signed-off evidence doc at `production/qa/evidence/[story-slug]-evidence.md` for all Visual/Feel stories *(every qa.level)*
|
||||
- [ ] 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)
|
||||
@@ -327,6 +332,10 @@ Silently append to `production/session-state/active.md` (create the file if it d
|
||||
<!-- QA-PLAN: [date] | System: [system/sprint identifier] | Plan written: production/qa/qa-plan-[identifier]-[date].md -->
|
||||
```
|
||||
|
||||
Close with the verdict: **COMPLETE** — QA plan written (or **COMPLETE** — QA plan
|
||||
shown, not written, if the write was declined). The only other outcome is the
|
||||
`NOT ASSESSED — no stories in scope` path in Phase 1.
|
||||
|
||||
---
|
||||
|
||||
## Collaborative Protocol
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, Bash(bash "*/.cla
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow`
|
||||
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@ model: sonnet
|
||||
|
||||
This is the **lightweight design path** for changes that don't need a full GDD.
|
||||
Full GDD authoring via `/design-system` is the heavyweight path. Use this skill
|
||||
for work under approximately 4 hours of implementation — tuning adjustments,
|
||||
minor behavioral tweaks, small additions to existing systems, or standalone
|
||||
features too small to warrant a full document.
|
||||
for work under about one week of implementation — tuning adjustments, minor
|
||||
behavioral tweaks, small additions to existing systems, or standalone features too
|
||||
small to warrant a full document. Most tweaks are hours; the one-week ceiling is
|
||||
the limit for a New Small System (see the categories below).
|
||||
|
||||
**Output:** `design/quick-specs/[name]-[date].md`
|
||||
|
||||
@@ -50,7 +51,8 @@ First, read the argument and determine which category this change falls into:
|
||||
If the change does NOT fit these categories — it introduces a new system with
|
||||
significant cross-system dependencies, requires more than one week of
|
||||
implementation, or fundamentally alters an existing system's core rules — stop
|
||||
and redirect to `/design-system` instead.
|
||||
and redirect to `/design-system` instead. Verdict: **REDIRECTED** — use
|
||||
`/design-system` for this change.
|
||||
|
||||
If there is no argument, ask the user to describe the change (plain text prompt), then classify it using the criteria above.
|
||||
|
||||
@@ -74,7 +76,11 @@ Otherwise: proceed with the selected type.
|
||||
Before drafting anything, read the relevant context:
|
||||
|
||||
- Search `design/gdd/` for the GDD most relevant to this change. Read the
|
||||
sections that this change would affect.
|
||||
sections that this change would affect. If no GDD covers this system — usually
|
||||
the case at `workflow: minimal`, where `design/game-brief.md` and the stories are
|
||||
the design record — read the brief's lines for it and the story the change
|
||||
touches instead, report "No GDD for [system] — using the brief and [story
|
||||
path]", and give the brief as the spec's GDD Reference.
|
||||
- Check whether `design/gdd/systems-index.md` exists. If it does, read it to
|
||||
understand where this system sits in the dependency graph and what tier it
|
||||
belongs to. If it does not exist, note "No systems index found — skipping
|
||||
@@ -85,7 +91,9 @@ Before drafting anything, read the relevant context:
|
||||
holds the relevant values.
|
||||
|
||||
Report what was found: "Found GDD at [path]. Relevant section: [section name].
|
||||
No conflicting quick specs found." (or note any conflicts found.)
|
||||
Prior quick specs for this system: [each path, and whether it agrees or
|
||||
conflicts with this change — or "none"]." Name a prior spec even when it
|
||||
agrees — "no conflicts" alone reads the same as "no prior specs".
|
||||
|
||||
---
|
||||
|
||||
@@ -272,7 +280,7 @@ System: [system name]
|
||||
GDD update: [Required — pending approval / Applied / Not required]
|
||||
|
||||
Next step: This spec is ready for `/story-readiness` validation before
|
||||
implementation. Reference this spec in the story's GDD Reference field.
|
||||
implementation (at `workflow: minimal`, go straight to `/dev-story`). Reference this spec in the story's GDD Reference field.
|
||||
```
|
||||
|
||||
### Pipeline Notes
|
||||
@@ -298,6 +306,6 @@ using `/design-system` to author a full GDD for this."
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
- Run `/story-readiness [story-path]` to validate the story before implementation begins — reference this spec in the story's GDD Reference field
|
||||
- Run `/story-readiness [story-path]` to validate the story before implementation begins (skip at `rigor: minimal` — `/dev-story` directly) — reference this spec in the story's GDD Reference field
|
||||
- Run `/dev-story [story-path]` to implement once the story passes readiness checks
|
||||
- If the change is larger than expected, run `/design-system [system-name]` to author a full GDD instead
|
||||
|
||||
@@ -28,7 +28,7 @@ and known failure points. This skill maintains that list.
|
||||
|
||||
**When to run:**
|
||||
- After fixing a bug (confirm a regression test was written or identify gap)
|
||||
- Before a release gate (`/gate-check polish` requires regression suite exists)
|
||||
- Before a phase gate — at `qa.level: full`, `/gate-check` requires a regression suite
|
||||
- As part of sprint close to detect coverage drift
|
||||
|
||||
---
|
||||
@@ -55,7 +55,9 @@ 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`.
|
||||
`minimal` branch on account of `qa.level`. This stop's verdict is
|
||||
**NOT ASSESSED** (Section 7) — tests are not required at this level, and nothing
|
||||
was scanned.
|
||||
|
||||
**Modes:**
|
||||
- `/regression-suite update` — scan new bug fixes this sprint and check
|
||||
@@ -107,8 +109,9 @@ scope the scan by each system's workflow tier (resolved above):
|
||||
- **`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.
|
||||
acceptance criteria). If no smoke report exists, stop with Verdict: **NOT
|
||||
ASSESSED — no smoke report to take critical paths from** — there is no
|
||||
critical-path source at minimal without one; run `/smoke-check` first.
|
||||
|
||||
(Tier affects `audit` mode only; `update` and `report` modes are tier-independent.)
|
||||
|
||||
@@ -206,7 +209,7 @@ Check for drift indicators:
|
||||
### Bug Regression Coverage
|
||||
| Bug ID | System | Severity | Has Regression Test? |
|
||||
|--------|--------|----------|----------------------|
|
||||
| BUG-NNN | [system] | S[N] | YES / NO ⚠ |
|
||||
| BUG-NNNN | [system] | S[N] | YES / NO ⚠ |
|
||||
|
||||
**Bugs without regression tests**: [N]
|
||||
|
||||
@@ -216,7 +219,7 @@ Check for drift indicators:
|
||||
### Recommended New Regression Tests
|
||||
| Priority | System | Suggested Test File | Covers |
|
||||
|----------|--------|---------------------|--------|
|
||||
| HIGH | [system] | `tests/unit/[system]/[slug]_regression_test.[ext]` | BUG-NNN / AC-[N] |
|
||||
| HIGH | [system] | `tests/unit/[system]/[slug]_regression_test.[ext]` | BUG-NNNN / AC-[N] |
|
||||
| MEDIUM | [system] | `tests/unit/[system]/[slug]_test.[ext]` | [criterion] |
|
||||
```
|
||||
|
||||
@@ -260,7 +263,7 @@ of which tests should always pass before a release:
|
||||
|
||||
| Test File | Test Function (if known) | Covers | Added |
|
||||
|-----------|--------------------------|--------|-------|
|
||||
| `tests/unit/[system]/[file]_test.[ext]` | `test_[scenario]` | AC-N / BUG-NNN | [date] |
|
||||
| `tests/unit/[system]/[file]_test.[ext]` | `test_[scenario]` | AC-N / BUG-NNNN | [date] |
|
||||
|
||||
## Known Gaps
|
||||
|
||||
@@ -268,7 +271,7 @@ Tests that should exist but don't yet:
|
||||
|
||||
| Priority | System | Suggested Path | Covers | Reason Not Yet Written |
|
||||
|----------|--------|----------------|--------|------------------------|
|
||||
| HIGH | [system] | `tests/unit/[system]/[path]` | BUG-NNN | Bug fixed without test |
|
||||
| HIGH | [system] | `tests/unit/[system]/[path]` | BUG-NNNN | Bug fixed without test |
|
||||
|
||||
## Quarantined Tests
|
||||
|
||||
@@ -283,7 +286,7 @@ Tests that are flaky or disabled (do not run in CI):
|
||||
|
||||
## 7. Write Output
|
||||
|
||||
Ask: "May I write/update `tests/regression-suite.md` with the current
|
||||
In `update` or `audit` mode, ask: "May I write/update `tests/regression-suite.md` with the current
|
||||
regression suite manifest?"
|
||||
|
||||
For `update` mode: append new entries; never remove existing entries
|
||||
@@ -300,7 +303,18 @@ After writing (if approved):
|
||||
- If coverage drift detected: "Regression suite may be drifting. Consider
|
||||
running `/regression-suite audit` at the next sprint boundary."
|
||||
|
||||
Verdict: **COMPLETE** — regression suite updated. (If user declined write: Verdict: **BLOCKED**.)
|
||||
Verdict, first match wins:
|
||||
- **NOT ASSESSED** — the Section 1 stop at `qa.level: minimal`: "Regression
|
||||
suite not generated at qa.level minimal". Tests are not required at this
|
||||
level; nothing was scanned or written.
|
||||
- **NOT ASSESSED** — the `minimal` stop above: no smoke report to take critical
|
||||
paths from; name `/smoke-check` as the fix.
|
||||
- **NOT ASSESSED** — coverage came back `Coverage: NOT ASSESSED — [reason]` (no GDDs or
|
||||
no test files); name the reason. Never report COMPLETE over a coverage figure
|
||||
that was not computed.
|
||||
- **BLOCKED** — `update` or `audit` mode and the user declined the write.
|
||||
- **COMPLETE** — `update` / `audit`: regression suite updated; `report`: coverage
|
||||
report shown (report mode writes nothing).
|
||||
|
||||
---
|
||||
|
||||
@@ -314,7 +328,7 @@ describe what collaborative mode requires, not universal behavior.
|
||||
explicit user approval — removing a test that was deliberately written is a
|
||||
regression risk itself
|
||||
- **Gaps are advisory, not blocking** — surface them clearly but do not prevent
|
||||
other work from proceeding (except at release gate where regression suite is required)
|
||||
other work from proceeding (except at `qa.level: full`, where phase gates require the regression suite)
|
||||
- **Quarantine is not deletion** — tests with intermittent failures should be
|
||||
quarantined (noted in manifest) but not removed; they should be fixed by
|
||||
`/test-flakiness`
|
||||
|
||||
@@ -6,7 +6,7 @@ user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash(bash "*/.claude/skills/release-checklist/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys rigor,project.stage,cert_tier,automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys rigor,workflow,project.stage,cert_tier,automation`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -30,8 +30,9 @@ trains the reader to skip the list, which defeats the gate:
|
||||
**`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.
|
||||
and not on platform names. The full requirement table is the `## platform.cert_tier`
|
||||
section of `.claude/docs/effects-map.md` — read **only that section** (Grep its
|
||||
heading, then a bounded Read); the file as a whole is not a runtime input.
|
||||
- `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.
|
||||
@@ -78,6 +79,7 @@ certification track.
|
||||
|
||||
- Read `CLAUDE.md` for project context, version information, and platform targets.
|
||||
- Read the current milestone from `production/milestones/` to understand what features and content should be included in this release.
|
||||
- Read the open bugs from `production/qa/bugs/`: grep the `**Severity**` and `**Status**` lines of `production/qa/bugs/*.md`, as `/bug-triage` does. A bug is open unless its Status is `Closed` or `Verified Fixed`. The bug items use the thresholds `/gate-check release` applies for the resolved `workflow`: at `full` an open S1, S2 or S3 bug fails its item; at `standard` and `minimal` only an open S1 does, and an open S2 or S3 is listed in the Rationale as a risk. Each failing bug is named in the Rationale as a blocking item. **No bug files in `production/qa/bugs/`** → the bug items read `NOT ASSESSED — no bug records` — never zero and never ticked, since an absent record and a clean one must not produce the same checklist; bugs are filed with `/bug-report`.
|
||||
|
||||
---
|
||||
|
||||
@@ -86,9 +88,12 @@ certification track.
|
||||
> **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.
|
||||
> `scanned [N] source files: [M] TODO, [M] FIXME, [M] HACK` — or, when the code
|
||||
> root (`src/`, `Assets/` or `Source/`; resolve per
|
||||
> `.claude/docs/code-root-resolution.md`) is unresolved,
|
||||
> **`NOT ASSESSED — code root unresolved`**, and when it 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
|
||||
@@ -115,6 +120,7 @@ passing one must not produce the same release checklist.
|
||||
Generated: [Date]
|
||||
|
||||
### Codebase Health
|
||||
- Scanned: [N] source files (or `NOT ASSESSED — [reason]`, per Phase 3)
|
||||
- TODO count: [N] ([list top 5 if many])
|
||||
- FIXME count: [N] ([list all -- these are potential blockers])
|
||||
- HACK count: [N] ([list all -- these need review])
|
||||
@@ -128,8 +134,9 @@ Generated: [Date]
|
||||
- [ ] Build is reproducible from tagged commit
|
||||
|
||||
### Quality Gates
|
||||
- [ ] Zero S1 (Critical) bugs
|
||||
- [ ] Zero S2 (Major) bugs -- or documented exceptions with producer approval
|
||||
- Open bugs (`production/qa/bugs/`): [N] S1, [N] S2, [N] S3 -- or `NOT ASSESSED — no bug records`
|
||||
- [ ] Zero open S1 (Critical) bugs
|
||||
- [ ] Zero open S2 (High) and S3 (Medium) bugs, no exceptions -- this row at `workflow: full` only; at `standard`/`minimal` open S2/S3 bugs go in the Rationale as risks
|
||||
- [ ] All critical path features tested and signed off by QA
|
||||
- [ ] Performance within budgets:
|
||||
- [ ] Target FPS met on minimum spec hardware
|
||||
@@ -283,7 +290,12 @@ emitting every track; if it cannot be determined, emit
|
||||
- [ ] Support team briefed on known issues and FAQ
|
||||
- [ ] Rollback plan documented (if critical issues found post-launch)
|
||||
|
||||
### Go / No-Go: [READY / NOT READY]
|
||||
### Go / No-Go: [READY / NOT ASSESSED / NOT READY]
|
||||
|
||||
First match wins: **NOT READY** if any blocking item fails; else **NOT ASSESSED**
|
||||
if any section or item came out `NOT ASSESSED` (name each one); else **READY**. NOT
|
||||
ASSESSED outranks READY — an unassessed section is not a passed one — and ranks
|
||||
below NOT READY, so a known blocker is never buried behind it.
|
||||
|
||||
**Rationale:**
|
||||
[Summary of readiness assessment. List any blocking items that must be
|
||||
@@ -311,5 +323,6 @@ If yes, write the file, creating the directory if needed.
|
||||
|
||||
## Phase 6: Next Steps
|
||||
|
||||
- Run `/gate-check` for a formal phase gate verdict before proceeding to release.
|
||||
- Coordinate final sign-offs via `/team-release`.
|
||||
- Draft the changelog or patch notes (`/changelog`, `/patch-notes`) if not done — the release gate checks them.
|
||||
- Run `/gate-check release` — the Polish → Release gate reads this checklist.
|
||||
- After a PASS: `/launch-checklist`, then coordinate the release via `/team-release`.
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Bash, AskUserQuestion, Bash(bash "*/.cla
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,qa.level`
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ If a matching file is found, use `AskUserQuestion`:
|
||||
- `[B] Start fresh — generate a new retrospective (archive the old one)`
|
||||
|
||||
If [A]: read the existing file and carry its content forward, revising sections with new data.
|
||||
If [B]: continue to Phase 2 with a blank slate. Before writing the new file, rename the existing one with a `-archived-[date]` suffix.
|
||||
If [B]: continue to Phase 2 with a blank slate. Before writing the new file, rename the existing one with a `-archived-[date]` suffix. That rename is a write too: it happens in Phase 5, only once the ask there — which names it — is approved.
|
||||
|
||||
---
|
||||
|
||||
@@ -81,17 +81,28 @@ Read the sprint or milestone plan from the appropriate location:
|
||||
|
||||
**If the file does not exist or is empty**, output:
|
||||
|
||||
> "No sprint data found for [sprint/milestone]. Run `/sprint-status` to generate
|
||||
> sprint data first, or provide the sprint details manually."
|
||||
> "No sprint data found for [sprint/milestone]. Run `/sprint-plan new` to create a
|
||||
> sprint (`/sprint-status` only reads one), or provide the sprint details manually."
|
||||
|
||||
Then use `AskUserQuestion` to present two options:
|
||||
At `workflow: minimal` (resolved above) there are no sprints: offer to look back over the stories
|
||||
closed so far instead (`production/epics/*/story-*.md` with `Status: Complete`).
|
||||
At `qa.level: minimal` (resolved above) tests are waived, so a story closed
|
||||
without one is not a finding; a Visual/Feel or UI story closed without its
|
||||
retained screenshot still is.
|
||||
|
||||
Then use `AskUserQuestion` to present these options ([C] only at `workflow: minimal`):
|
||||
|
||||
- **[A] Provide data manually** — ask the user to paste or describe the sprint
|
||||
tasks, dates, and outcomes; use that as the source of truth for the retrospective.
|
||||
- **[B] Stop** — abort the skill. Verdict: **BLOCKED** — no sprint data available.
|
||||
- **[C] Look back over the closed stories** — use the stories with
|
||||
`Status: Complete` as the record of what was done.
|
||||
|
||||
If the user chooses [A], collect the data and continue to Phase 3 using what they provide.
|
||||
If the user chooses [B], stop here.
|
||||
If the user chooses [C], read those stories and continue to Phase 3. Sections that
|
||||
need sprint data (planned vs actual, velocity, carryover, estimation accuracy)
|
||||
are `NOT ASSESSED — NO DATA`.
|
||||
|
||||
Extract: planned tasks, estimated effort, owners, and goals.
|
||||
|
||||
@@ -115,6 +126,10 @@ Scan for completed and incomplete tasks by comparing the plan against actual del
|
||||
- Tasks added mid-sprint (unplanned work)
|
||||
- Tasks removed or descoped
|
||||
|
||||
Every story with `status: blocked` in `production/sprint-status.yaml` goes under
|
||||
Blockers Encountered, with its `blocker` field as the Blocker, and gets an action
|
||||
item in Action Items for Next Iteration.
|
||||
|
||||
Scan the codebase for TODO/FIXME trends:
|
||||
|
||||
- Count current TODO/FIXME/HACK comments
|
||||
@@ -127,6 +142,10 @@ Read previous retrospectives (if any) from `production/retrospectives/` to check
|
||||
- Are the same problems recurring?
|
||||
- How has velocity trended?
|
||||
|
||||
With no earlier sprint or retrospective, Velocity Trend keeps only the current
|
||||
sprint's row and reads `NOT ASSESSED — NO DATA`, and Previous Action Items
|
||||
Follow-Up is that one line — no invented earlier rows, no empty table.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Generate the Retrospective
|
||||
@@ -156,7 +175,7 @@ Generated: [Date]
|
||||
| [N-1] | [X] | [Y] | [Z%] |
|
||||
| [N] (current) | [X] | [Y] | [Z%] |
|
||||
|
||||
**Trend**: [Increasing / Stable / Decreasing]
|
||||
**Trend**: [Increasing / Stable / Decreasing — or `NOT ASSESSED — NO DATA` with no earlier sprint to compare]
|
||||
[One sentence explaining the trend]
|
||||
|
||||
### What Went Well
|
||||
@@ -231,6 +250,10 @@ Present the retrospective and top findings to the user (completion rate, velocit
|
||||
|
||||
Ask: "May I write this to `production/retrospectives/retro-sprint-[N]-[date].md`?" (or `production/retrospectives/retro-[milestone-name]-[date].md` for milestone retrospectives)
|
||||
|
||||
After Start fresh in Phase 1b, the same ask also names the rename: "…and rename
|
||||
`[old file]` to `[old file name]-archived-[date].md`?" On yes, rename first, then
|
||||
write; on no, neither happens.
|
||||
|
||||
If yes, write the file, creating the `production/retrospectives/` directory if needed. Verdict: **COMPLETE** — retrospective saved.
|
||||
|
||||
If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: reverse-document
|
||||
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')"
|
||||
argument-hint: "<type> <path> (e.g., 'design src/gameplay/combat' or 'architecture Assets/Scripts/Core')"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Bash(bash "*/.claude/skills/reverse-document/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash(bash "*/.claude/skills/reverse-document/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
# Read-only diagnostic skill — no specialist agent delegation needed
|
||||
---
|
||||
@@ -30,9 +30,11 @@ appropriate design or architecture documentation. Use this when:
|
||||
- `architecture` → Generate an Architecture Decision Record (ADR)
|
||||
- `concept` → Generate a concept document from prototype
|
||||
|
||||
**Path**: Directory or file to analyze
|
||||
- `src/gameplay/combat/` → All combat-related code
|
||||
- `src/core/event-system.cpp` → Specific file
|
||||
**Path**: Directory or file to analyze, under the code root — `src/` Godot,
|
||||
`Assets/` Unity, `Source/<Module>/` Unreal (`.claude/docs/code-root-resolution.md`)
|
||||
- `src/gameplay/combat/` → All combat-related code (Godot)
|
||||
- `Assets/Scripts/Core/EventSystem.cs` → Specific file (Unity)
|
||||
- `Source/MyGame/Private/AI/` → A module folder (Unreal)
|
||||
- `prototypes/stealth-mech/` → Prototype directory
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys workflow,system_overrides,automation`
|
||||
@@ -62,7 +64,7 @@ generated — see Phase 5. Semantics of each tier are in
|
||||
**Examples**:
|
||||
```bash
|
||||
/reverse-document design src/gameplay/magic-system
|
||||
/reverse-document architecture src/core/entity-component
|
||||
/reverse-document architecture Source/MyGame/Private/EntityComponent
|
||||
/reverse-document concept prototypes/vehicle-combat
|
||||
```
|
||||
|
||||
@@ -335,12 +337,12 @@ Would you like me to tackle any of these now?
|
||||
## Example Session: Reverse-Document a System
|
||||
|
||||
```
|
||||
User: /reverse-document design src/gameplay/[system]
|
||||
User: /reverse-document design <code root>/gameplay/[system]
|
||||
|
||||
Agent: I'll analyze your [system] implementation to create a design doc.
|
||||
[Reads code, discovers mechanics, formulas]
|
||||
|
||||
Agent: I've analyzed src/gameplay/[system]/. Here's what I found:
|
||||
Agent: I've analyzed <code root>/gameplay/[system]/. Here's what I found:
|
||||
[Shows mechanics, formulas, unclear areas]
|
||||
|
||||
Before drafting, could you clarify:
|
||||
|
||||
@@ -37,7 +37,7 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
**Argument modes:**
|
||||
|
||||
**Focus:** `$ARGUMENTS[0]` (blank = `full`)
|
||||
**Focus:** `$ARGUMENTS` (blank = `full`)
|
||||
|
||||
- **No argument / `full`**: Both consistency and design theory passes
|
||||
- **`consistency`**: Cross-GDD consistency checks only (faster)
|
||||
@@ -119,7 +119,9 @@ Run `/consistency-check` after this review to populate the registry."
|
||||
|
||||
Read whole (small, and every part is used):
|
||||
|
||||
1. `design/gdd/game-concept.md` — game vision, core loop, MVP definition
|
||||
1. `design/gdd/game-concept.md` — game vision, core loop, MVP definition (or
|
||||
`design/game-brief.md`, the one-page brief that replaces it at `rigor: minimal` —
|
||||
pitch, core loop, MVP list)
|
||||
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
|
||||
|
||||
@@ -150,7 +152,7 @@ never shrinks the *review set*.
|
||||
|
||||
Report: "Loaded [N] system GDDs covering [M] systems. Pillars: [list]. Anti-pillars: [list]."
|
||||
|
||||
If fewer than 2 system GDDs exist, stop:
|
||||
If fewer than 2 system GDDs exist (count the files present; an empty one is handled under NOT ASSESSED in Phase 5, not here), stop:
|
||||
> "Cross-GDD review requires at least 2 system GDDs. Write more GDDs first,
|
||||
> then re-run `/review-all-gdds`."
|
||||
|
||||
@@ -249,15 +251,24 @@ with the same name and behaviour:
|
||||
- If GDD-A references "the progression curve defined in [system].md", check that
|
||||
[system].md actually has that curve, not a different progression model
|
||||
- If GDD-A was written before GDD-B and assumed a mechanic that GDD-B later
|
||||
designed differently, flag GDD-A as containing a stale reference
|
||||
designed differently, flag GDD-A as containing a stale reference. Severity: a
|
||||
reference to a mechanic or formula that **does not exist** is **Blocking** — the
|
||||
architecture would inherit a rule nobody defined; one that exists but was
|
||||
designed differently is a **Warning**, unless the difference changes a rule the
|
||||
referencing GDD depends on (then Blocking)
|
||||
- If the **target GDD is not written yet** (no file in `design/gdd/`): when
|
||||
`systems-index.md` lists that system (e.g. `Status: Not Started`), it is a
|
||||
**Warning** — a dependency on planned work, to re-check when that GDD is
|
||||
written; when neither a GDD nor a systems-index entry exists for it, it is
|
||||
**Blocking** — nothing will ever define it
|
||||
|
||||
```
|
||||
⚠️ Stale Reference
|
||||
🔴 Stale Reference
|
||||
inventory.md (written first): "Item weight uses the encumbrance formula
|
||||
from movement.md"
|
||||
movement.md (written later): Defines no encumbrance formula — uses a flat
|
||||
carry limit instead
|
||||
→ inventory.md references a formula that doesn't exist
|
||||
→ inventory.md references a formula that doesn't exist — Blocking
|
||||
```
|
||||
|
||||
### 2d: Data and Tuning Knob Ownership Conflicts
|
||||
@@ -562,7 +573,8 @@ step where the issue occurs, and the nature of the failure mode.
|
||||
```
|
||||
## Cross-GDD Review Report
|
||||
Date: [date]
|
||||
GDDs Reviewed: [N]
|
||||
GDDs Reviewed: [N] of [M] present
|
||||
Not read: [each GDD that could not be read or is present but empty, by file name — or "none"]
|
||||
Systems Covered: [list]
|
||||
|
||||
---
|
||||
@@ -615,6 +627,7 @@ Scenarios walked: [N]
|
||||
| GDD | Reason | Type | Priority |
|
||||
|-----|--------|------|----------|
|
||||
| [system-a].md | Rule contradiction with [system-b].md | Consistency | Blocking |
|
||||
| [system-b].md | Rule contradiction with [system-a].md | Consistency | Blocking |
|
||||
| [system-c].md | Stale reference to nonexistent mechanic | Consistency | Blocking |
|
||||
| [system-d].md | No pillar alignment | Design Theory | Warning |
|
||||
|
||||
@@ -622,13 +635,13 @@ Scenarios walked: [N]
|
||||
|
||||
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
|
||||
PASS: No blocking issues. Warnings present but don't prevent architecture.
|
||||
PASS: No blocking issues and no warnings.
|
||||
NOT ASSESSED: One or more review phases could not run — named below.
|
||||
CONCERNS: Warnings present that should be resolved but are not blocking.
|
||||
CONCERNS: Warnings present that should be resolved, but nothing 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]
|
||||
[Name each phase that did not run and the input it needed, and each GDD that could not be read or is present but empty, by file name]
|
||||
|
||||
### If FAIL — required actions before re-running:
|
||||
[Specific list of what must change in which GDD]
|
||||
@@ -649,10 +662,16 @@ thorough while covering a fraction of the surface. Emit it when any of:
|
||||
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.
|
||||
- **A GDD is present but empty** (headings only, or all placeholders), **or
|
||||
could not be read**. 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`.
|
||||
Report the covered set explicitly either way: `GDDs reviewed: [N] of [M] present`
|
||||
(`[M]` counts the system GDDs present — the Phase 1c set, not `game-concept.md`,
|
||||
`game-pillars.md`, `systems-index.md` or an earlier `gdd-cross-review-*.md`),
|
||||
and the `Not read:` line naming every GDD that could not be read or is present but empty, whatever the
|
||||
verdict — a FAIL found in the GDDs that were read does not make the unread ones
|
||||
reviewed.
|
||||
A cross-review that silently skipped half the systems is indistinguishable from
|
||||
one that found them consistent.
|
||||
|
||||
@@ -719,7 +738,7 @@ Build the option list dynamically — only include options that apply:
|
||||
- `[_] Apply quick fix: [W-XX description] in [gdd-name].md — [effort estimate]` (one option per simple-edit warning; only for Warning-level, not Blocking)
|
||||
- `[_] Run /design-review [flagged-gdd-path] — address flagged warnings` (one per flagged GDD, if any)
|
||||
- `[_] Run /design-system [next-system] — next in design order` (always include, name the actual system)
|
||||
- `[_] Run /create-architecture — begin architecture (verdict is PASS/CONCERNS)` (include if verdict is not FAIL)
|
||||
- `[_] Run /create-architecture — begin architecture (verdict is PASS/CONCERNS)` (include only if the verdict is PASS or CONCERNS — never on FAIL or NOT ASSESSED)
|
||||
- `[_] Run /gate-check — validate Systems Design phase gate` (include if verdict is PASS)
|
||||
- `[_] Stop here`
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: scope-check
|
||||
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
|
||||
allowed-tools: Read, Glob, Grep, Bash(git log *)
|
||||
model: haiku
|
||||
---
|
||||
|
||||
@@ -14,7 +14,7 @@ This skill is read-only — it reports findings but writes no files.
|
||||
Compares original planned scope against current state to detect, quantify, and triage
|
||||
scope creep.
|
||||
|
||||
**Argument:** `$ARGUMENTS[0]` — feature name, sprint number, or milestone name.
|
||||
**Argument:** `$ARGUMENTS` — the whole string: a feature name (it may be several words), sprint number, or milestone name.
|
||||
|
||||
---
|
||||
|
||||
@@ -23,7 +23,7 @@ scope creep.
|
||||
Locate the baseline scope document for the given argument:
|
||||
|
||||
- **Feature name** → read `design/gdd/[feature].md` or matching file in `design/`
|
||||
- **Sprint number** (e.g., `sprint-3`) → read `production/sprints/sprint-03.md` or similar
|
||||
- **Sprint number** (e.g., `sprint-3`) → read `production/sprints/sprint-003.md` (the name `/sprint-plan` writes) or similar
|
||||
- **Milestone** → read `production/milestones/[name].md`
|
||||
|
||||
If the document is not found, report the missing file and stop. Do not proceed without
|
||||
@@ -58,7 +58,8 @@ Generated: [Date]
|
||||
|
||||
> **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
|
||||
> `[Baseline | Current state] unusable — see verdict` (whichever side could not
|
||||
> be read) 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.
|
||||
@@ -115,7 +116,8 @@ Assign a canonical verdict based on net scope change:
|
||||
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.
|
||||
unreadable present is not a 0% change, and not the −100% that zero current
|
||||
items computes — the table reads both as PASS.
|
||||
- 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.
|
||||
|
||||
@@ -145,9 +147,12 @@ After presenting the report, offer concrete follow-up:
|
||||
- **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.
|
||||
|
||||
Always end with:
|
||||
End every verdict except NOT ASSESSED with:
|
||||
> "Run `/scope-check [name]` again after cuts are made to verify the verdict improves."
|
||||
|
||||
(NOT ASSESSED ends with what would make it assessable, above — a re-run against
|
||||
the same inputs would repeat the non-answer.)
|
||||
|
||||
---
|
||||
|
||||
### Rules
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Bash, Write, Agent, Bash(bash "*/.claude/skills
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -15,6 +15,10 @@ 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).
|
||||
|
||||
**`workflow`** (resolved above) decides only what Phase 7 tells you about the
|
||||
release gate: at `standard` and `full` it requires this report; at `minimal` it
|
||||
does not. The audit itself runs the same at every tier.
|
||||
|
||||
# Security Audit
|
||||
|
||||
Security is not optional for any shipped game. Even single-player games have
|
||||
@@ -24,12 +28,14 @@ codebase for the most common game security failures and produces a prioritised
|
||||
remediation plan.
|
||||
|
||||
**Run this skill:**
|
||||
- Before any public release (required for the Polish → Release gate)
|
||||
- Before any public release (required for the Polish → Release gate at `workflow: standard` and `full`)
|
||||
- Before enabling any online/multiplayer feature
|
||||
- After implementing any system that reads from disk or network
|
||||
- When a security-related bug is reported
|
||||
|
||||
**Output:** `production/security/security-audit-[date].md`
|
||||
**Output:** `production/security/security-audit-[date]-[scope].md` — the scope
|
||||
in the name keeps a same-day `quick` or `save` run from overwriting the `full`
|
||||
report the release gate reads.
|
||||
|
||||
---
|
||||
|
||||
@@ -45,8 +51,8 @@ remediation plan.
|
||||
|
||||
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
|
||||
pattern set, and an engine with no sourced set for a category makes that
|
||||
category `NOT ASSESSED`.** 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)
|
||||
@@ -55,19 +61,21 @@ Read `project.yaml` to determine the following, falling back to `.claude/docs/te
|
||||
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.
|
||||
> this skill — and **no writer in the setup flow**: neither
|
||||
> `/setup-engine` nor `/start` emits a `platform:` block, and only `/settings`
|
||||
> sets them, when someone runs it, so on most CCGS projects both keys are
|
||||
> absent. Defaulting them to `false` would skip **Category 2 (Network and
|
||||
> Multiplayer Security) on every project, genuinely multiplayer ones
|
||||
> included** — 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.
|
||||
> `NOT ASSESSED — multiplayer scope unconfirmed (platform.multiplayer unset —
|
||||
> set it with /settings)`, which makes `CLEAR TO SHIP` unreachable per Phase 5.
|
||||
> While the scope is unconfirmed, rate severity as for a multiplayer game — an
|
||||
> open HIGH is then DO NOT SHIP — and say in the report that the rating assumed
|
||||
> multiplayer, as `security-engineer` does.
|
||||
> Over-scanning a single-player game costs a few minutes; under-scanning a
|
||||
> multiplayer one ships the category unrun.
|
||||
>
|
||||
@@ -79,10 +87,49 @@ Read `project.yaml` to determine the following, falling back to `.claude/docs/te
|
||||
|
||||
## Phase 2: Spawn Security Engineer
|
||||
|
||||
Spawn `security-engineer` via `Agent`. Pass:
|
||||
- The audit scope/mode
|
||||
- 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
|
||||
Spawn `security-engineer` via `Agent` — the audit is its job, so do not run the
|
||||
categories in this session instead. If it cannot be spawned, say why, run the
|
||||
scan here, and let the report's **Audited by** line say so.
|
||||
|
||||
**Send this fixed brief template.** Fill only the `{…}` slots, from
|
||||
`project.yaml` (else technical preferences), the code root resolved per
|
||||
`.claude/docs/code-root-resolution.md`, and the Phase 3 text copied as written.
|
||||
Add nothing else: no view on the game's type, no expected severity, no opinion
|
||||
on any finding — a sentence of your own is where a pre-rating gets in.
|
||||
|
||||
```text
|
||||
Run a security audit of this project for /security-audit.
|
||||
|
||||
Scope: {full | network | save | input | quick}
|
||||
Engine: {engine.name} {engine.version}, language {engine.language}
|
||||
platform.multiplayer: {true | false | unset} platform.online: {true | false | unset} Phase 1 answer: {multiplayer | single-player | not asked}
|
||||
Code root: {the resolved code root, or "unresolved"}
|
||||
Also scan: {assets/data/ and the config files that exist, or "none"}
|
||||
Categories to run, with their checks and grep patterns for this engine:
|
||||
{each Phase 3 category this scope runs, copied as written, with the table's row for this engine}
|
||||
NOT SOURCEABLE on this engine: {categories, or "none"} — report each NOT ASSESSED; never call it reviewed, verified safe or passed
|
||||
Skipped, with reason: {e.g. "Category 2 — platform.multiplayer and platform.online are false", or "none"}
|
||||
Report: production/security/security-audit-{date}-{scope}.md — return the report as text; /security-audit writes the file after asking
|
||||
|
||||
Severity (rate every finding yourself, against this table only):
|
||||
- CRITICAL: Remote code execution, data breach, or trivially-exploitable cheat that breaks multiplayer integrity
|
||||
- HIGH: Save tampering that bypasses progression, credential exposure, or server-side authority bypass
|
||||
- MEDIUM: Client-side cheat enablement, information disclosure, or input validation gap with limited impact
|
||||
- LOW: Defence-in-depth improvement — hardening that reduces attack surface but no direct exploit exists
|
||||
Nothing in this brief sets or suggests a severity. The game's type never lowers a rating: a single-player game is rated on the same table. The one adjustment is upward — when the game is multiplayer, or its scope is unconfirmed (unset and not answered), a HIGH counts as CRITICAL; say so where it applies.
|
||||
Report each finding as SEC-NNN with category, file:line, description, attack scenario, remediation and effort, grouped by severity.
|
||||
```
|
||||
|
||||
The template carries the rating rule, so there is nothing to restate: the
|
||||
table already rates save tampering that bypasses progression HIGH, the agent
|
||||
rates each finding against it, and Phase 5 applies the multiplayer rule to the
|
||||
recommendation.
|
||||
|
||||
If the code root is unresolved, do not pass a guessed one: every category that
|
||||
scans code is `NOT ASSESSED — code root unresolved`, and the report says so. An
|
||||
empty code root is the insufficient-implementation case in Phase 5, and each
|
||||
category that scans code reads `NOT ASSESSED — no source under <root>`, not zero
|
||||
findings. Neither is ever reported clean.
|
||||
|
||||
The security-engineer runs the audit across 6 categories (see Phase 3). Collect their full findings before proceeding.
|
||||
|
||||
@@ -90,7 +137,10 @@ The security-engineer runs the audit across 6 categories (see Phase 3). Collect
|
||||
|
||||
## Phase 3: Audit Categories
|
||||
|
||||
The security-engineer evaluates each of the following. Skip categories not applicable to the project scope.
|
||||
The security-engineer evaluates each of the following. Skip categories not
|
||||
applicable to the project scope, and name each skipped category and why in the
|
||||
Executive Summary (`Category 2 — skipped: platform.multiplayer and
|
||||
platform.online are false`).
|
||||
|
||||
### Engine pattern sets — read this before any Category below
|
||||
|
||||
@@ -121,8 +171,10 @@ this table omits — it is a floor, not a complete set.
|
||||
> 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.
|
||||
> for this engine — see Phase 5. To close it properly, add a save/serialization
|
||||
> module, sourced like the others, to `docs/engine-reference/<engine>/modules/`;
|
||||
> when one is there, take the category's pattern names from it, cite it in the
|
||||
> report, and the category runs.
|
||||
|
||||
|
||||
### Category 1: Save File and Serialization Security
|
||||
@@ -180,7 +232,10 @@ Grep for: `get_input`, `Input.get_`, `input_map`, user-facing text fields — ch
|
||||
- Does the game log sensitive player data to disk or console?
|
||||
- Are any internal file paths or system information exposed to players?
|
||||
|
||||
Grep for: `api_key`, `secret`, `password`, `token`, `private_key`, `DEBUG`, `print(` in release-facing code.
|
||||
Grep case-insensitively in release-facing code for: `api[_-]?key`, `secret`,
|
||||
`password`, `token`, `private[_-]?key`, `sk_live`, `BEGIN PRIVATE KEY`, `DEBUG`,
|
||||
and the engine's print call (`print(` on Godot, `Debug.Log` on Unity, `UE_LOG`
|
||||
on Unreal).
|
||||
|
||||
### Category 5: Cheat and Anti-Tamper Vectors
|
||||
- Are gameplay-critical values stored only in memory, not in easily-editable files?
|
||||
@@ -223,7 +278,7 @@ For each finding, assign:
|
||||
**Date**: [date]
|
||||
**Scope**: [full | network | save | input | quick]
|
||||
**Engine**: [engine + version]
|
||||
**Audited by**: security-engineer via /security-audit
|
||||
**Audited by**: [security-engineer via /security-audit | this session — security-engineer not spawned: reason]
|
||||
**Files scanned**: [N source files, N config files]
|
||||
|
||||
---
|
||||
@@ -237,19 +292,37 @@ For each finding, assign:
|
||||
| MEDIUM | [N] | Recommended |
|
||||
| LOW | [N] | Optional |
|
||||
|
||||
**Release recommendation**: [NOT ASSESSED — INSUFFICIENT IMPLEMENTATION / CLEAR TO SHIP / FIX CRITICALS FIRST / DO NOT SHIP]
|
||||
**Release recommendation**: [NOT ASSESSED — INSUFFICIENT IMPLEMENTATION / CLEAR TO SHIP / FIX BEFORE SHIPPING / DO NOT SHIP]
|
||||
|
||||
Choose it by the open findings, first match wins:
|
||||
- **DO NOT SHIP** — any open CRITICAL finding (in a multiplayer game, any open HIGH
|
||||
counts as CRITICAL)
|
||||
- **FIX BEFORE SHIPPING** — open HIGH findings and no CRITICAL; the Polish → Release
|
||||
gate needs zero open HIGH (at `standard` and `full`)
|
||||
- **NOT ASSESSED** — per the rule below, when the scan could not cover the surface.
|
||||
It ranks below both failure values — a known finding is more actionable than an
|
||||
unscanned category, and still has to be fixed — and above CLEAR TO SHIP
|
||||
- **CLEAR TO SHIP** — no open CRITICAL or HIGH (MEDIUM and LOW may remain)
|
||||
|
||||
> **`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
|
||||
> confirmed — **in place of CLEAR TO SHIP, never of a failure value.** An open
|
||||
> CRITICAL or HIGH still decides the recommendation (first match above): a run
|
||||
> with an unscanned category and an open HIGH is FIX BEFORE SHIPPING, and names
|
||||
> the unscanned category beside it. 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.
|
||||
> Executive Summary, and **`CLEAR TO SHIP` is unreachable for the run**. The
|
||||
> category reads `NOT ASSESSED — <category> has no sourced pattern set for
|
||||
> <engine>`; the release recommendation is still the first match above, so it is
|
||||
> NOT ASSESSED only where the run would otherwise have been CLEAR TO SHIP. Never
|
||||
> report the category as reviewed by other means: files it covers may still be
|
||||
> read for another category, and a finding that read turns up is reported, but
|
||||
> the category stays NOT ASSESSED — never "reviewed", "verified safe" or passed.
|
||||
> 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.
|
||||
|
||||
@@ -311,7 +384,7 @@ For each finding, assign:
|
||||
## Re-Audit Trigger
|
||||
|
||||
Run `/security-audit` again after remediating any CRITICAL or HIGH findings.
|
||||
The Polish → Release gate requires this report with no open CRITICAL or HIGH items.
|
||||
At `workflow: standard` and `full`, the Polish → Release gate requires this report with no open CRITICAL or HIGH items.
|
||||
```
|
||||
|
||||
---
|
||||
@@ -320,7 +393,7 @@ The Polish → Release gate requires this report with no open CRITICAL or HIGH i
|
||||
|
||||
Present the report summary (executive summary + CRITICAL/HIGH findings only) in conversation.
|
||||
|
||||
Ask: "May I write the full security audit report to `production/security/security-audit-[date].md`?"
|
||||
Ask: "May I write the full security audit report to `production/security/security-audit-[date]-[scope].md`?"
|
||||
|
||||
Write only after approval.
|
||||
|
||||
@@ -328,14 +401,34 @@ Write only after approval.
|
||||
|
||||
## Phase 7: Gate Integration
|
||||
|
||||
This report is a required artifact for the **Polish → Release gate**.
|
||||
This report is a required artifact for the **Polish → Release gate** at `workflow: standard` and `full`; the `minimal` gate drops it with everything but smoke and S1 bugs. Say which applies to this project, from the `workflow` resolved above.
|
||||
|
||||
After remediating findings, re-run: `/security-audit quick` to confirm CRITICAL/HIGH items are resolved before running `/gate-check release`.
|
||||
|
||||
If CRITICAL findings exist:
|
||||
Branch on the release recommendation, not on the finding counts alone:
|
||||
|
||||
If it is **DO NOT SHIP** (an open CRITICAL, or an open HIGH in a multiplayer game):
|
||||
> "⛔ CRITICAL security findings must be resolved before any public release. Do not proceed to `/launch-checklist` until these are addressed."
|
||||
|
||||
If no CRITICAL/HIGH findings:
|
||||
If it is **FIX BEFORE SHIPPING** (open HIGH findings, no CRITICAL, single-player):
|
||||
> At `workflow: standard`/`full`: "⚠️ [N] HIGH finding(s) are open. The Polish → Release gate's security audit item requires none — fix them and re-run `/security-audit quick` before `/gate-check release`."
|
||||
>
|
||||
> At `minimal`: "⚠️ [N] HIGH finding(s) are open — fix them and re-run `/security-audit quick` before you ship. The `minimal` release gate does not read this report; the open HIGH still makes the recommendation FIX BEFORE SHIPPING."
|
||||
|
||||
If it is **NOT ASSESSED**:
|
||||
> "Security audit NOT ASSESSED — [each category not assessed, and why]. The report is
|
||||
> written. [At `workflow: standard`/`full`:] `/gate-check release` will report its
|
||||
> security item NOT ASSESSED until [the missing input] is supplied and the audit
|
||||
> re-run. [At `minimal`:] The `minimal` release gate does not read this report,
|
||||
> but those categories stay unscanned until [the missing input] is supplied."
|
||||
>
|
||||
> Name the missing input for each category: `engine.name`, the code root, the
|
||||
> multiplayer scope (`/settings platform.multiplayer=…`), or — for a category the
|
||||
> Phase 3 table marks NOT SOURCEABLE on this engine, the usual cause on Unity and
|
||||
> Unreal — a save/serialization module in `docs/engine-reference/<engine>/modules/`
|
||||
> (Phase 3), naming that category.
|
||||
|
||||
If it is **CLEAR TO SHIP**:
|
||||
> "✅ No blocking security findings. Report written to `production/security/`. Include this path when running `/gate-check release`."
|
||||
|
||||
---
|
||||
|
||||
@@ -185,7 +185,7 @@ Schema validation: ok
|
||||
Effective config:
|
||||
|
||||
framework:
|
||||
version: 1.1.1 (project.yaml, locked)
|
||||
version: 1.1.2 (project.yaml, locked)
|
||||
|
||||
modes:
|
||||
review_mode: lean (project.yaml)
|
||||
|
||||
@@ -20,7 +20,7 @@ artifact this skill expects and the finish path it recommends in §12:
|
||||
- **`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`.
|
||||
If the block did not render (shell preprocessing disabled), assume `minimal` (the default).
|
||||
|
||||
## 1. Parse Arguments
|
||||
|
||||
@@ -155,9 +155,13 @@ 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 |
|
||||
| Godot | `godot --version`, else look for `godot`/`Godot_v*` on PATH or in the platform's usual install location (macOS: the binary inside the bundle, `Godot.app/Contents/MacOS/Godot`) |
|
||||
| Unity | The Hub's editor directory, then that editor's `-version` — `C:/Program Files/Unity/Hub/Editor/<version>/Editor/Unity.exe` on Windows, `/Applications/Unity/Hub/Editor/<version>/Unity.app/Contents/MacOS/Unity` on macOS, `/home/<user>/Unity/Hub/Editor/<version>/Editor/Unity` on Linux. Not bare `Unity`: on `PATH` it may be Unity's separate CLI, which rejects `-version` |
|
||||
| Unreal | The launcher's install directory (`UE_<version>` folders under `C:/Program Files/Epic Games/` on Windows); elsewhere, ask where the engine was built or installed. The editor is not on `PATH` by default |
|
||||
|
||||
Keep the executable the probe found (for Godot, whether bare `godot --version`
|
||||
ran — that is, `godot` is on `PATH`): Section 5.5.1 writes it into `commands.*`
|
||||
and `engine.path`.
|
||||
|
||||
Then:
|
||||
- **Match** — say so in one line and continue.
|
||||
@@ -190,6 +194,13 @@ If Godot was chosen, ask the user which language to use **before** showing the p
|
||||
|
||||
Record the choice. It determines the CLAUDE.md template, naming conventions, specialist routing, and which agent is spawned for code files throughout the project.
|
||||
|
||||
### Primary Language (Unreal)
|
||||
|
||||
If Unreal was chosen, ask via `AskUserQuestion`: "Will most gameplay logic live in
|
||||
C++ or in Blueprints?" — `[A] C++ (Blueprints for tuning and prototyping)` /
|
||||
`[B] Blueprint-primary (C++ only where needed)`. Default to C++ if the user has no
|
||||
preference. The answer sets `engine.language` (`"C++"` or `"Blueprint"`).
|
||||
|
||||
---
|
||||
|
||||
Read `CLAUDE.md` and show the user the proposed Technology Stack changes.
|
||||
@@ -212,10 +223,12 @@ Update the Technology Stack section, replacing the `[CHOOSE]` placeholders with
|
||||
**For Unreal:**
|
||||
```markdown
|
||||
- **Engine**: Unreal Engine [version]
|
||||
- **Language**: C++ (primary), Blueprint (gameplay prototyping)
|
||||
- **Language**: [C++ (primary), Blueprint (gameplay prototyping) | Blueprint (primary), C++ where needed]
|
||||
- **Build System**: Unreal Build Tool (UBT)
|
||||
- **Asset Pipeline**: Unreal Content Pipeline
|
||||
```
|
||||
The Language line follows the primary-language answer above: the first form for
|
||||
`[A]` (`engine.language: "C++"`), the second for `[B]` (`"Blueprint"`).
|
||||
|
||||
### Engine reference import
|
||||
|
||||
@@ -317,8 +330,8 @@ Example filled section:
|
||||
- If [A]: populate with the suggested defaults. If [B]: leave as placeholder.
|
||||
- **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
|
||||
> **Must match `commands.test` in Section 5.5.1, which writes gdUnit4's own
|
||||
> runner (`res://addons/gdUnit4/bin/GdUnitCmdTool.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.
|
||||
@@ -380,7 +393,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 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?"
|
||||
> "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 may I save them to `.claude/docs/technical-preferences.md`?"
|
||||
|
||||
For all other engines, present the defaults directly without referencing the appendix.
|
||||
|
||||
@@ -552,6 +565,14 @@ the language:
|
||||
> than an explicit question: it produces a `commands.build` that runs, succeeds,
|
||||
> and builds the wrong artifact.
|
||||
>
|
||||
> **`-buildTarget` alone builds nothing.** It switches the active platform and
|
||||
> exits 0 (verified on 6000.3.23f1). The row also needs a player-build flag,
|
||||
> `-build<PLATFORM>Player <output path>` — for Windows 64-bit,
|
||||
> `-buildWindows64Player Builds/Win64/<Game>.exe` (verified: exit 0 and an
|
||||
> `.exe`; exit 1 on a compile error or when no scene is in the build settings).
|
||||
> Ask which platform, and confirm any other platform's flag against Unity's
|
||||
> command-line documentation rather than recalling one.
|
||||
>
|
||||
> **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
|
||||
@@ -605,15 +626,44 @@ naming:
|
||||
|
||||
| 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` |
|
||||
| Godot | `godot --headless --export-debug '<PRESET>'` **(ASK — do not default)** | `godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode` | `godot --path . --windowed --resolution 1280x720` | `godot --headless --quit-after 5` |
|
||||
| Unity | `"<Unity editor>" -batchmode -quit -projectPath . -buildTarget <TARGET> -build<PLATFORM>Player Builds/<Target>/<Game>.exe` **(ASK — do not default)** | `"<Unity editor>" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/editmode.xml` | `Builds/<Target>/<Game>.exe -screen-width 1280 -screen-height 720 -screen-fullscreen 0` | `"<Unity editor>" -batchmode -quit -projectPath . -logFile -` |
|
||||
|
||||
> **What each exit code proves — every row verified on the pinned engines.**
|
||||
> Godot `test` exits 0 when all pass, 100 on a failure, 101 when all pass but
|
||||
> nodes leaked (a warning, not a failure), 105 when a test script does not
|
||||
> parse, and 103 / 104 when gdUnit4 cannot run at all (headless refused, Godot
|
||||
> older than 4.3). Keep `--remote-debug tcp://127.0.0.1:0`: without it a script
|
||||
> error opens Godot's interactive debugger and the run waits at a `debug>`
|
||||
> prompt forever instead of exiting. Run `godot --headless --path . --import`
|
||||
> before it on a fresh clone: with no `.godot/` class cache,
|
||||
> `GdUnitCmdTool.gd` did not load and the run exits 1 having run nothing. Unity `test`
|
||||
> exits 0 / 2, and a results file with `testcasecount="0"` means no test was
|
||||
> compiled — not a pass. It runs Edit Mode only: Play Mode tests under
|
||||
> `Assets/Tests/PlayMode/` need a second run into their own results file
|
||||
> (`-testPlatform PlayMode -testResults test-results/playmode.xml`), which
|
||||
> `/smoke-check` makes whenever that folder holds tests and CI runs as its own
|
||||
> step. Unity `smoke` exits 1 on a compile error, 0 when clean.
|
||||
> **Godot `smoke` exits 0 even on a parse error** — it is a boot check: read its
|
||||
> output for `SCRIPT ERROR`. It also needs `run/main_scene` set: without one it
|
||||
> prints `Can't run project: no main scene defined` and never exits, so run it
|
||||
> under a timeout. Unity `smoke` compiles only the editor-side assemblies; an
|
||||
> error that exists only in a player build (an `Editor/` script without its own
|
||||
> assembly) shows up in `build`, not here. The real Godot parse check is
|
||||
> `godot --headless --path . --import`, then
|
||||
> `godot --headless --path . -s res://.claude/scripts/godot-parse-check.gd -- res://<file>.gd …`
|
||||
> (exit 1 when a script does not load). `--check-only` is not one: it fails
|
||||
> valid code that names an autoload. `<Unity editor>` is the **editor**
|
||||
> executable's full path, quoted. Never write bare `Unity`: on `PATH` that name
|
||||
> may be Unity's separate CLI, which rejects `-batchmode` with exit 2 — the same
|
||||
> code as a failed test.
|
||||
|
||||
> **`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.
|
||||
> (`.claude/docs/run-and-observe.md`). `smoke` is Unity's parse check, `test`
|
||||
> feeds `/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**
|
||||
@@ -621,8 +671,9 @@ naming:
|
||||
> 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.
|
||||
> load-bearing: `/smoke-check` and `/dev-story` run these values, `/settings`
|
||||
> reads and writes them through this parser, and the same holds for every other
|
||||
> quoted value in `project.yaml`.
|
||||
> 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' ..."`
|
||||
@@ -634,22 +685,64 @@ naming:
|
||||
> 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
|
||||
answer for `<PRESET>` / `<TARGET>` / `<PLATFORM>`, and the editor's full path for
|
||||
`<Unity editor>`. 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"
|
||||
test: "godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode"
|
||||
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:
|
||||
**Write bare `godot` only when Section 3's `godot --version` ran** — that is,
|
||||
`godot` is on `PATH`. Otherwise (the usual case on Windows and macOS)
|
||||
substitute the executable the probe found or the user gave — a Windows
|
||||
`Godot_v<version>-stable_win64.exe`, macOS `/Applications/Godot.app/Contents/MacOS/Godot`
|
||||
— as its full path, in double quotes, for the leading `godot` in all four
|
||||
values, exactly as `<Unity editor>` is. The value then holds double quotes, so it
|
||||
takes a single-quoted scalar, and `build` quotes its preset with double quotes
|
||||
too, so no value holds both quote types. Godot not on PATH, installed under
|
||||
`C:/Program Files/Godot/`:
|
||||
|
||||
```yaml
|
||||
commands:
|
||||
build: '"C:/Program Files/Godot/Godot_v4.6.1-stable_win64.exe" --headless --export-debug "Windows Desktop"'
|
||||
test: '"C:/Program Files/Godot/Godot_v4.6.1-stable_win64.exe" --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode'
|
||||
run: '"C:/Program Files/Godot/Godot_v4.6.1-stable_win64.exe" --path . --windowed --resolution 1280x720'
|
||||
smoke: '"C:/Program Files/Godot/Godot_v4.6.1-stable_win64.exe" --headless --quit-after 5'
|
||||
```
|
||||
|
||||
If the probe found no executable and the user does not know where it is, keep
|
||||
bare `godot`, put `# TODO: godot is not on PATH here — set the editor's full
|
||||
path via /settings` above the block, and say so: those commands will not run
|
||||
until one of the two is fixed.
|
||||
|
||||
For Unity, probe the Hub install (`C:/Program Files/Unity/Hub/Editor/<version>/Editor/Unity.exe`
|
||||
on Windows, `/Applications/Unity/Hub/Editor/<version>/Unity.app/Contents/MacOS/Unity`
|
||||
on macOS, `/home/<user>/Unity/Hub/Editor/<version>/Editor/Unity` on Linux) or ask.
|
||||
Write the expanded absolute path — a `~` inside quotes is not expanded, and the
|
||||
command then exits 127. The
|
||||
quoted path puts double quotes in the command, so the value takes a
|
||||
single-quoted scalar:
|
||||
|
||||
```yaml
|
||||
commands:
|
||||
test: '"C:/Program Files/Unity/Hub/Editor/6000.3.23f1/Editor/Unity.exe" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/editmode.xml'
|
||||
smoke: '"C:/Program Files/Unity/Hub/Editor/6000.3.23f1/Editor/Unity.exe" -batchmode -quit -projectPath . -logFile -'
|
||||
```
|
||||
|
||||
> **Also write `engine.path` if the editor is not on `PATH`.** Agents and
|
||||
> `/smoke-check` read it to find the editor, but a command is run as written —
|
||||
> `engine.path` is never spliced into `commands.*` at run time, which is why the
|
||||
> full path goes into the commands above — and on Windows and macOS none of
|
||||
> the three engines installs onto `PATH` by default (on macOS the editor is inside an app
|
||||
> bundle, e.g. `/Applications/Godot.app/Contents/MacOS/Godot`). Ask for or probe the
|
||||
> install location and record it — the editor executable for Godot and Unity,
|
||||
> the engine folder (`<UE root>`) for Unreal:
|
||||
>
|
||||
> ```yaml
|
||||
> engine:
|
||||
@@ -663,25 +756,79 @@ commands:
|
||||
|
||||
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:
|
||||
Substitute the engine's install folder for `<UE root>` (the value you record as
|
||||
`engine.path`) — none of the editor binaries is on `PATH`. The commands embed
|
||||
double quotes, so they take single-quoted scalars. Write the block for the
|
||||
machine the project is developed on (`uname -s`: `Linux`, `Darwin` = macOS,
|
||||
anything else = Windows). The Windows block was run on UE 5.7; the Linux and
|
||||
macOS lines come from Epic's documentation, recorded with their sources in
|
||||
`docs/engine-reference/unreal/current-best-practices.md` ("Command Line").
|
||||
|
||||
Windows:
|
||||
|
||||
```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"'
|
||||
build: '"<UE root>/Engine/Binaries/DotNET/AutomationTool/AutomationTool.exe" BuildCookRun -project="$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -platform=Win64 -build -cook'
|
||||
test: '"<UE root>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -ExecCmds="Automation RunTests <project>.; Quit" -unattended -nullrhi -stdout -FullStdOutLogOutput'
|
||||
run: '"<UE root>/Engine/Binaries/Win64/UnrealEditor.exe" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -game -windowed -ResX=1280 -ResY=720'
|
||||
smoke: '"<UE root>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -game -nullrhi -unattended -stdout -ExecCmds="Quit"'
|
||||
```
|
||||
|
||||
**Two details are load-bearing.** `smoke` needs `-game`: without it
|
||||
Linux — the editor binary is `Engine/Binaries/Linux/UnrealEditor`, the build
|
||||
scripts are shell scripts:
|
||||
|
||||
```yaml
|
||||
commands:
|
||||
# TODO: confirm these for your UE version and project — adjust via /settings
|
||||
build: '"<UE root>/Engine/Build/BatchFiles/RunUAT.sh" BuildCookRun -project="$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -platform=Linux -build -cook'
|
||||
test: '"<UE root>/Engine/Binaries/Linux/UnrealEditor" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -ExecCmds="Automation RunTests <project>.; Quit" -unattended -nullrhi -stdout -FullStdOutLogOutput'
|
||||
run: '"<UE root>/Engine/Binaries/Linux/UnrealEditor" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -game -windowed -ResX=1280 -ResY=720'
|
||||
smoke: '"<UE root>/Engine/Binaries/Linux/UnrealEditor" "$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -game -nullrhi -unattended -stdout -ExecCmds="Quit"'
|
||||
```
|
||||
|
||||
macOS — only the build is sourced. Epic documents the `UnrealEditor.app`
|
||||
bundle but no command-line editor inside it, so write `build` and leave the
|
||||
other three as TODO lines rather than a guessed path; `/smoke-check` reports
|
||||
NOT ASSESSED for tests until the user sets `commands.test`:
|
||||
|
||||
```yaml
|
||||
commands:
|
||||
# TODO: confirm this for your UE version and project — adjust via /settings
|
||||
build: '"<UE root>/Engine/Build/BatchFiles/RunUAT.sh" BuildCookRun -project="$(pwd -W 2>/dev/null || pwd)/<project>.uproject" -platform=Mac -build -cook'
|
||||
# TODO: test, run and smoke — no documented command-line editor on macOS.
|
||||
# Set them via /settings to the editor command you run for this project.
|
||||
```
|
||||
|
||||
On Windows, `build` calls AutomationTool directly: from Git Bash, `RunUAT.bat` fails
|
||||
(`'C:\Program' is not recognized`) whenever the project path has a space.
|
||||
AutomationTool.exe runs on the machine's .NET 8 runtime; `RunUAT.bat` brings
|
||||
its own SDK, so with no space in the path and no .NET 8 installed, use it.
|
||||
`-build` builds the editor target too (verified on 5.7).
|
||||
|
||||
**Three details are load-bearing.** The project path is absolute: UE 5.7
|
||||
does not find a relative `<project>.uproject` and exits 1 (`Project file not
|
||||
found`) before anything runs. `$(pwd -W 2>/dev/null || pwd)` gives the `C:/…`
|
||||
form in Git Bash and the plain path elsewhere, run from the project root;
|
||||
`$PWD` alone fails when `MSYS_NO_PATHCONV` is set. `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.
|
||||
finish, and without it the run also never returns. Its filter runs every test
|
||||
whose full name *contains* `<project>.` — a substring match, not a prefix — so
|
||||
name tests `<project>.[System].[Scenario]` as `qa-tester` does. If the
|
||||
project's name is also an engine area — `Audio`, `Core`, `Input`, `Test`,
|
||||
`System`, `Engine`, `Editor`, `AI`, `Math` — `<project>.` also runs hundreds
|
||||
to thousands of the engine's own tests; give the tests a distinct root (say
|
||||
`<project>Game.`) and put the same root in the filter. This form exits 255 on
|
||||
a failing test AND on a filter that matches nothing (`No automation tests
|
||||
matched`, verified on 5.7), so `/smoke-check` reads the output, not the exit
|
||||
code. `smoke` carries `-stdout` for the same reason: without it a failed boot
|
||||
prints nothing. Do not swap in
|
||||
`-TestExit="Automation Test Queue Empty"`: that form exits **0** on a failing
|
||||
test unless its report JSON is parsed.
|
||||
|
||||
### 5.5.2 Write the blocks to `project.yaml`
|
||||
|
||||
@@ -703,7 +850,7 @@ Wait for confirmation, then apply based on the file's current state:
|
||||
schema_version: 1
|
||||
|
||||
framework:
|
||||
version: 1.1.1
|
||||
version: 1.1.2
|
||||
last_upgraded: <today's date>
|
||||
|
||||
engine:
|
||||
@@ -736,7 +883,7 @@ Wait for confirmation, then apply based on the file's current state:
|
||||
|
||||
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.
|
||||
the review mode regardless of the project's rigor.
|
||||
|
||||
- **`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
|
||||
@@ -747,6 +894,11 @@ Wait for confirmation, then apply based on the file's current state:
|
||||
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.
|
||||
|
||||
**Unreal on macOS is the exception in both cases:** `commands.test`, `run` and
|
||||
`smoke` are written as the TODO comment lines from the macOS block — never as
|
||||
`<...>` placeholders or a guessed path — and a re-run leaves them unset until the
|
||||
user sets them.
|
||||
|
||||
Preserve all other content in `project.yaml` (`schema_version`, `framework`,
|
||||
`modes`, `project`, etc.) — only the four blocks are touched.
|
||||
|
||||
@@ -763,11 +915,12 @@ user and stop — a split config corrupts skill and hook reads.
|
||||
|
||||
Check whether the engine version is likely beyond the LLM's training data.
|
||||
|
||||
**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
|
||||
**Known approximate coverage** — the same figures the shipped
|
||||
`docs/engine-reference/*/VERSION.md` files record:
|
||||
- LLM knowledge cutoff: **May 2025**
|
||||
- Godot: training data likely covers up to ~4.3
|
||||
- Unity: training data likely covers up to ~2022 LTS (2022.3)
|
||||
- Unreal: training data likely covers up to ~5.3
|
||||
|
||||
> **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
|
||||
@@ -777,9 +930,10 @@ Check whether the engine version is likely beyond the LLM's training data.
|
||||
> 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.
|
||||
> **If the model running this skill states an earlier training cutoff than the
|
||||
> one above, do not trust the table.** Say so, and treat the engine version as
|
||||
> `HIGH RISK` regardless of the comparison — a cutoff the model does not have is
|
||||
> not a cutoff that was met.
|
||||
|
||||
Compare the user's chosen version against these baselines:
|
||||
|
||||
@@ -806,11 +960,15 @@ 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
|
||||
- **Same version** → nothing to regenerate. Refresh `Last Docs Verified` only if you
|
||||
actually re-verified against the docs this run. Do not restamp a date you did
|
||||
not check.
|
||||
not check. The one row still written is `Installed at pin time`, from
|
||||
Section 3 — its probe result is recorded whatever the outcome, after asking
|
||||
"May I record `Installed at pin time: [result]` in
|
||||
`docs/engine-reference/<engine>/VERSION.md`?" (it is a tracked file).
|
||||
- **Directory pins an OLDER version than the one chosen** → **update, do not
|
||||
replace.** This is the common case.
|
||||
replace.** This is the common case. Show the changes below, then ask "May I
|
||||
update the `docs/engine-reference/<engine>/` files for [version]?" before editing.
|
||||
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.
|
||||
@@ -842,7 +1000,8 @@ produces work that looks verified and is not.
|
||||
|
||||
### If WITHIN training data (LOW RISK):
|
||||
|
||||
Create a minimal `docs/engine-reference/<engine>/VERSION.md`:
|
||||
Ask: "May I create `docs/engine-reference/<engine>/VERSION.md`?" Wait for
|
||||
confirmation, then create this minimal file:
|
||||
|
||||
```markdown
|
||||
# [Engine] — Version Reference
|
||||
@@ -851,7 +1010,8 @@ Create a minimal `docs/engine-reference/<engine>/VERSION.md`:
|
||||
|-------|-------|
|
||||
| **Engine Version** | [version] |
|
||||
| **Project Pinned** | [today's date] |
|
||||
| **LLM Knowledge Cutoff** | May 2025 |
|
||||
| **Installed at pin time** | [Section 3 result — the installed version, or NOT DETERMINED] |
|
||||
| **LLM Knowledge Cutoff** | [the cutoff from the Section 6 coverage table] |
|
||||
| **Risk Level** | LOW — version is within LLM training data |
|
||||
|
||||
## Note
|
||||
@@ -948,7 +1108,9 @@ 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
|
||||
(`godot --headless --path . --import`) and report the result — read the output
|
||||
for `ERROR`, because the import exits 0 even when something in the project
|
||||
fails to load. 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
|
||||
@@ -1189,7 +1351,7 @@ After setup is complete, output:
|
||||
Engine Setup Complete
|
||||
=====================
|
||||
Engine: [name] [version]
|
||||
Language: [GDScript | C# | GDScript + C# | C# | C++ + Blueprint]
|
||||
Language: [GDScript | C# | GDScript + C# | C# | C++ + Blueprint | Blueprint + C++]
|
||||
Knowledge Risk: [LOW/MEDIUM/HIGH]
|
||||
Reference Docs: [created/skipped]
|
||||
CLAUDE.md: [updated]
|
||||
|
||||
@@ -49,6 +49,10 @@ Static baseline: [N] failures, [M] warnings
|
||||
Failing: Check 4 (no ask-before-write), Check 5 (no handoff)
|
||||
```
|
||||
|
||||
If the static result is **NOT ASSESSED** (the skill file could not be read or
|
||||
parsed), stop and report it with its reason: there is no score to improve, and
|
||||
0 FAILs from a file nobody could read is not a clean result.
|
||||
|
||||
If baseline is 0 FAILs and 0 WARNs, note it and proceed to Phase 2b.
|
||||
|
||||
### Phase 2b: Category Baseline
|
||||
@@ -69,7 +73,12 @@ Display to the user:
|
||||
Category baseline: [N] failures, [M] warnings ([category] rubric)
|
||||
```
|
||||
|
||||
If BOTH static and category baselines are 0 FAILs and 0 WARNs, stop:
|
||||
A category result of **NOT ASSESSED** (a rubric section the skill-test could not
|
||||
find or apply) is reported with its reason and is not a zero: the category
|
||||
dimension is then excluded from "already passes" below.
|
||||
|
||||
If BOTH static and category baselines are 0 FAILs and 0 WARNs — and neither is
|
||||
NOT ASSESSED — stop:
|
||||
"This skill already passes all static and category checks. No improvements needed."
|
||||
|
||||
---
|
||||
@@ -90,8 +99,9 @@ For each failing or warning **static** check, identify the exact gap:
|
||||
|
||||
For each failing or warning **category** check (if category was assigned in Phase 2b),
|
||||
identify the exact gap in the skill's text. For example:
|
||||
- If G2 fails (gate mode, full directors not spawned): skill body never references all 4
|
||||
PHASE-GATE director prompts
|
||||
- If G2 fails (gate mode, director panel width): skill body does not size the
|
||||
PHASE-GATE panel from `modes.workflow` (PR at `minimal`, TD + PR at `standard`,
|
||||
all 4 at `full`)
|
||||
- If A2 fails (authoring, no per-section May-I-write): skill asks once at the end, not
|
||||
before each section write
|
||||
- If T3 fails (team, BLOCKED not surfaced): skill doesn't halt dependent work on blocked agent
|
||||
@@ -114,25 +124,32 @@ If the user says no, stop here.
|
||||
|
||||
## Phase 5: Write and Retest
|
||||
|
||||
Record the current content of the skill file (for revert if needed).
|
||||
Record the current content of the skill file — the exact text, kept in this
|
||||
conversation — so Phase 6 can restore it.
|
||||
|
||||
Write the improved skill to `.claude/skills/[name]/SKILL.md`.
|
||||
|
||||
Re-run `/skill-test static [name]` and record the new static score.
|
||||
Re-run `/skill-test static [name]` and record the new static score — measured by that run, never stated from the edit.
|
||||
If a category was assigned, also re-run `/skill-test category [name]` and record the new category score.
|
||||
|
||||
Display the comparison:
|
||||
```
|
||||
Static: Before [N] failures, [M] warnings → After [N'] failures, [M'] warnings
|
||||
Category: Before [N] failures, [M] warnings → After [N'] failures, [M'] warnings (if applicable)
|
||||
Combined change: improved / no change / worse
|
||||
Combined: [before] → [after] (improved / no change / worse)
|
||||
```
|
||||
|
||||
`[before]` and `[after]` are the Phase 6 combined counts — failures plus
|
||||
warnings, both dimensions — e.g. `Combined: 3 → 0 (improved)`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Verdict
|
||||
|
||||
Count the combined failure total: static FAILs + category FAILs + static WARNs + category WARNs.
|
||||
**A re-test that comes back NOT ASSESSED** (for example, the edit broke the
|
||||
frontmatter so the file no longer parses) is never an improvement, whatever its
|
||||
counts: take the "did not improve" branch below.
|
||||
|
||||
**If combined score improved (combined failure count is lower than baseline):**
|
||||
Report: "Score improved. Changes kept."
|
||||
@@ -141,8 +158,10 @@ Show a summary of what was fixed in each dimension.
|
||||
**If combined score is the same or worse:**
|
||||
Report: "Combined score did not improve."
|
||||
Show what changed and why it may not have helped.
|
||||
Ask: "May I revert `.claude/skills/[name]/SKILL.md` using git checkout?"
|
||||
If yes: run `git checkout -- .claude/skills/[name]/SKILL.md`
|
||||
Ask: "May I restore `.claude/skills/[name]/SKILL.md` to the content it had before this run?"
|
||||
If yes: write the content recorded in Phase 5 back to the file with Write; if no, leave the file as written. Never
|
||||
`git checkout` it — that returns the last *committed* version and discards any edits
|
||||
made before this run that were not yet committed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: skill-test
|
||||
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"
|
||||
argument-hint: "static [skill-name | all] | spec [skill-or-agent-name] | category [skill-or-agent-name | all] | audit"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash(bash "*/.claude/skills/skill-test/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
@@ -17,17 +17,17 @@ every file write follows `.claude/docs/automation-modes.md`
|
||||
|
||||
# Skill Test
|
||||
|
||||
Validates `.claude/skills/*/SKILL.md` files for structural compliance and
|
||||
behavioral correctness. No external dependencies — runs entirely within the
|
||||
existing skill/hook/template architecture.
|
||||
Validates skills (`.claude/skills/*/SKILL.md`) and agents (`.claude/agents/*.md`)
|
||||
for structural compliance and behavioral correctness. No external dependencies —
|
||||
runs entirely within the existing skill/hook/template architecture.
|
||||
|
||||
**Four modes:**
|
||||
|
||||
| Mode | Command | Purpose | Token Cost |
|
||||
|------|---------|---------|------------|
|
||||
| `static` | `/skill-test static [name\|all]` | Structural linter — 7 compliance checks per skill | Low (~1k/skill) |
|
||||
| `spec` | `/skill-test spec [name]` | Behavioral verifier — evaluates assertions in test spec | Medium (~5k/skill) |
|
||||
| `category` | `/skill-test category [name\|all]` | Category rubric — checks skill against its category-specific metrics | Low (~2k/skill) |
|
||||
| `static` | `/skill-test static [name\|all]` | Structural linter — 7 compliance checks per skill (skills only) | Low (~1k/skill) |
|
||||
| `spec` | `/skill-test spec [name]` | Behavioral verifier — evaluates assertions in a skill's or agent's test spec | Medium (~5k each) |
|
||||
| `category` | `/skill-test category [name\|all]` | Category rubric — checks a skill or agent against its category-specific metrics | Low (~2k each) |
|
||||
| `audit` | `/skill-test audit` | Coverage report — skills, agent specs, last test dates | Low (~3k total) |
|
||||
|
||||
---
|
||||
@@ -38,12 +38,25 @@ Determine mode from the first argument:
|
||||
|
||||
- `static [name]` → run 7 structural checks on one skill
|
||||
- `static all` → run 7 structural checks on all skills (Glob `.claude/skills/*/SKILL.md`)
|
||||
- `spec [name]` → read skill + test spec, evaluate assertions
|
||||
- `spec [name]` → read the skill or agent + its test spec, evaluate assertions
|
||||
- `category [name]` → run category-specific rubric from `CCGS Skill Testing Framework/quality-rubric.md`
|
||||
- `category all` → run category rubric for every skill that has a `category:` in catalog
|
||||
- `category all` → run category rubric for every skill and every agent that has a `category:` in catalog
|
||||
- `audit` (or no argument) → read catalog, list all skills and agents, show coverage
|
||||
|
||||
If argument is missing or unrecognized, output usage and stop.
|
||||
If the argument is unrecognized, output usage and stop.
|
||||
|
||||
**Resolve the name before `spec` or `category`.** Look it up in
|
||||
`CCGS Skill Testing Framework/catalog.yaml`: an entry under `skills:` is a skill
|
||||
(`.claude/skills/[name]/SKILL.md`); an entry under `agents:` is an agent
|
||||
(`.claude/agents/[name].md`). With no catalog entry, use whichever of those two
|
||||
files exists. Only when neither exists, report "'[name]' is neither a skill in
|
||||
`.claude/skills/` nor an agent in `.claude/agents/`." and stop. A name that is
|
||||
also an ordinary word is still a name: `/skill-test spec help` tests the `/help`
|
||||
skill, never a request for this skill's usage.
|
||||
|
||||
`static` checks SKILL.md structure, so it is skills-only. Given an agent name,
|
||||
say so and point to `/skill-test spec [name]` — do not report the agent as
|
||||
missing.
|
||||
|
||||
---
|
||||
|
||||
@@ -59,7 +72,9 @@ The file must contain all of these in the YAML frontmatter block:
|
||||
- `user-invocable:`
|
||||
- `allowed-tools:`
|
||||
|
||||
**FAIL** if any are absent.
|
||||
**FAIL** if any are absent. A file whose frontmatter does not parse fails Check 1
|
||||
too — malformed YAML is a structural defect this check exists to catch, not an
|
||||
unassessable file; see the per-skill result rule below.
|
||||
|
||||
### Check 2 — Multiple Phases
|
||||
The skill must have ≥2 numbered phase headings. Look for patterns like:
|
||||
@@ -88,11 +103,12 @@ 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.
|
||||
> A narrower list — gate verdicts only, hard FAIL on anything else — would wrongly
|
||||
> fail skills for reasons that are 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 produces false failures on legitimate patterns stops
|
||||
> being trusted.
|
||||
|
||||
### Check 4 — Collaborative Protocol Language
|
||||
The skill must contain ask-before-write language. Look for:
|
||||
@@ -145,6 +161,14 @@ Verdict: WARNINGS (1 warning, 0 failures)
|
||||
Recommended: Add a "Follow-Up Actions" section at the end of the skill.
|
||||
```
|
||||
|
||||
A WARN or FAIL line names its cause in parentheses, and any verdict other than
|
||||
COMPLIANT ends with a `Recommended:` line naming the fix.
|
||||
|
||||
The single-skill `Verdict:` is one of four values, the same as the `static all`
|
||||
Result column: **COMPLIANT** (no warnings, no failures), **WARNINGS** (warnings,
|
||||
no failures), **NON-COMPLIANT** (any FAIL), or **NOT ASSESSED** (the file could
|
||||
not be read or parsed, or its checks could not run — name the reason).
|
||||
|
||||
For `static all`, produce a summary table then list any non-compliant skills:
|
||||
```
|
||||
=== Skill Static Check: All 74 Skills ===
|
||||
@@ -161,43 +185,96 @@ 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**.
|
||||
whose file is missing or otherwise unreadable (permissions, not found), so no
|
||||
check could even start, 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**. A file that *was* read but
|
||||
whose frontmatter does not parse is a different case: Check 1 fails on it (see
|
||||
above), so it is reported **NON-COMPLIANT**, not NOT ASSESSED — the defect is in
|
||||
the skill, not in the linter's access to it.
|
||||
|
||||
**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.
|
||||
|
||||
No file writes in static mode.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2B: Spec Mode — Behavioral Verifier
|
||||
|
||||
### Step 1 — Locate Files
|
||||
|
||||
Find skill at `.claude/skills/[name]/SKILL.md`.
|
||||
Use the skill or agent file resolved in Phase 1.
|
||||
Look up the spec path from `CCGS Skill Testing Framework/catalog.yaml` — use the
|
||||
`spec:` field for the matching skill entry.
|
||||
`spec:` field on the matching `skills:` or `agents:` entry.
|
||||
|
||||
If either is missing:
|
||||
- Missing skill: "Skill '[name]' not found in `.claude/skills/`."
|
||||
- Missing skill or agent: the Phase 1 message.
|
||||
- Missing spec path in catalog: "No spec path set for '[name]' in catalog.yaml."
|
||||
- Spec file not found at path: "Spec file missing at [path]. Run `/skill-test audit`
|
||||
to see coverage gaps."
|
||||
|
||||
### Step 2 — Read Both Files
|
||||
|
||||
Read the skill file and test spec file completely.
|
||||
Read the skill or agent file and the test spec file completely.
|
||||
|
||||
### Step 3 — Evaluate Assertions
|
||||
|
||||
**Evaluate against what the model running it can see.** A skill runs in a
|
||||
session, and a spawned agent in its own context, and both have the project's
|
||||
`CLAUDE.md` loaded along with every file it imports on an `@path` line (a
|
||||
spawned agent quotes `coordination-rules.md` word for word without reading it).
|
||||
Read those files too. A rule stated there counts for every skill and agent —
|
||||
cite the file it came from. Where the skill's or agent's own file contradicts
|
||||
it, the own file wins: it is the more specific instruction.
|
||||
|
||||
**For an agent**, the spec's sections are evaluated against the agent file —
|
||||
and against every skill its frontmatter lists under `skills:`, which Claude
|
||||
Code loads into the agent at launch:
|
||||
|
||||
- **Static Assertions** — check each against the agent's frontmatter and body.
|
||||
An assertion that names a literal value (a `model:` alias, a frontmatter key,
|
||||
a tool name) is an exact comparison with the file: `model: inherit` does not
|
||||
satisfy "Model tier is `sonnet`", and a near match is FAIL, never PARTIAL.
|
||||
- **Test Cases** — evaluate each case's expected behavior against the agent's
|
||||
written instructions, the same way a skill's are evaluated below. A case
|
||||
that names a gate ID (`LP-FEASIBILITY`, `CD-PILLARS`, …) is that gate's
|
||||
invocation: the spawning skill has the agent read
|
||||
`.claude/docs/director-gates/[gate-id].md` first, so that file's Prompt and
|
||||
Verdicts are the agent's instructions for the case — read it too.
|
||||
- **Redirect and escalation cases** — the agent is asked for work another role
|
||||
owns, or meets a conflict it cannot settle. The case is met when the loaded
|
||||
`coordination-rules.md` covers the step — rule 2 (no binding decisions
|
||||
outside its domain), rule 3 (escalate a conflict to the shared parent) or
|
||||
rule 5 (no files outside its directories without delegation) — **and** the
|
||||
agent's own file names the owning role in its collaborator, delegation,
|
||||
escalation or "must not" lists. Cite both; do not require the agent to
|
||||
restate the redirect in its own words. It is a FAIL when the agent's file
|
||||
claims that work for itself, or when no loaded file names who owns it.
|
||||
- **Protocol Compliance** — use the spec's own `## Protocol Compliance` list in
|
||||
place of the four skill checks below.
|
||||
|
||||
**For a skill**, check each of the spec's **Static Assertions** against the
|
||||
`SKILL.md` frontmatter and body the same way; a literal value is an exact
|
||||
comparison. `/skill-test static` runs only its 7 fixed checks, so a spec's own
|
||||
static lines — a verdict keyword, a phase, "May I write" before a named file —
|
||||
are evaluated here or nowhere.
|
||||
|
||||
The rest of this step applies to skills and agents alike.
|
||||
|
||||
For each **Test Case** in the spec:
|
||||
|
||||
1. Read the **Fixture** description (assumed state of project files)
|
||||
2. Read the **Expected behavior** steps
|
||||
3. Read each **Assertion** checkbox
|
||||
|
||||
A case with no **Fixture** reads its **Input** as the fixture; a case with no
|
||||
**Assertions** list treats each **Expected behavior** bullet as an assertion —
|
||||
most agent specs are written this way, and a case verdict is not left undefined
|
||||
just because it has no separate checklist.
|
||||
|
||||
For each assertion, evaluate whether the skill's written instructions, if
|
||||
followed correctly given the fixture state, would satisfy it. This is a
|
||||
Claude-evaluated reasoning check, not code execution.
|
||||
@@ -208,14 +285,20 @@ Mark each assertion:
|
||||
- **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
|
||||
read can settle, or references a file or section that does not exist (a file
|
||||
that is merely silent on the behaviour is FAIL or PARTIAL, not this). 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):
|
||||
For a skill's **Protocol Compliance** section (always present), evaluate each line
|
||||
of the spec's own list against the `SKILL.md` exactly as you evaluate a case
|
||||
assertion — PASS, PARTIAL, FAIL or NOT ASSESSED. Specs put rules there that no
|
||||
case repeats ("covered by the protocol compliance assertions above"), so a
|
||||
list that is not evaluated is a set of rules nobody checks. These four checks are
|
||||
the floor, added when the list does not already cover them:
|
||||
- Check whether the skill requires "May I write" before file writes
|
||||
- Check whether the skill presents findings before requesting approval
|
||||
- Check whether the skill ends with a recommended next step
|
||||
@@ -228,6 +311,11 @@ For **Protocol Compliance** assertions (always present):
|
||||
Date: [date]
|
||||
Spec: CCGS Skill Testing Framework/skills/[category]/[name].md
|
||||
|
||||
Static Assertions:
|
||||
[PASS] [assertion text]
|
||||
[NOT ASSESSED] [assertion text]
|
||||
Reason: [why it could not be evaluated]
|
||||
|
||||
Case 1: [Happy Path — name]
|
||||
Fixture: [summary]
|
||||
Assertions:
|
||||
@@ -243,11 +331,21 @@ Case 2: [Edge Case — name]
|
||||
Protocol Compliance:
|
||||
[PASS] Uses "May I write" before file writes
|
||||
[PASS] Presents findings before asking approval
|
||||
[WARN] No explicit next-step handoff at end
|
||||
[PARTIAL] No explicit next-step handoff at end
|
||||
|
||||
Overall Verdict: FAIL (1 case failed, 1 warning)
|
||||
Overall Verdict: FAIL (1 case failed, 1 protocol line partial)
|
||||
```
|
||||
|
||||
A Case Verdict is the worst result among its assertions, and the Overall
|
||||
Verdict the worst across the static assertions, the cases and Protocol
|
||||
Compliance, in this order:
|
||||
FAIL, PARTIAL, NOT ASSESSED, PASS. An assertion nobody could evaluate keeps the
|
||||
overall result from reading PASS.
|
||||
|
||||
For an agent, the header is `=== Agent Spec Test: [name] ===`, `Spec:` is its
|
||||
path under `CCGS Skill Testing Framework/agents/`, and a `Static Assertions:`
|
||||
block comes before Case 1.
|
||||
|
||||
### Step 5 — Offer to Write Results
|
||||
|
||||
"May I write these results to `CCGS Skill Testing Framework/results/skill-test-spec-[name]-[date].md`
|
||||
@@ -255,9 +353,9 @@ and update `CCGS Skill Testing Framework/catalog.yaml`?"
|
||||
|
||||
If yes:
|
||||
- Write results file to `CCGS Skill Testing Framework/results/`
|
||||
- Update the skill's entry in `CCGS Skill Testing Framework/catalog.yaml`:
|
||||
- Update the skill's or agent's entry in `CCGS Skill Testing Framework/catalog.yaml`:
|
||||
- `last_spec: [date]`
|
||||
- `last_spec_result: PASS|PARTIAL|FAIL`
|
||||
- `last_spec_result: PASS|PARTIAL|FAIL|NOT ASSESSED` — the Overall Verdict
|
||||
|
||||
---
|
||||
|
||||
@@ -265,51 +363,72 @@ If yes:
|
||||
|
||||
### Step 1 — Locate Skill and Category
|
||||
|
||||
Find skill at `.claude/skills/[name]/SKILL.md`.
|
||||
Look up `category:` field in `CCGS Skill Testing Framework/catalog.yaml`.
|
||||
Use the skill or agent file resolved in Phase 1.
|
||||
Look up the `category:` field on its `skills:` or `agents:` entry in
|
||||
`CCGS Skill Testing Framework/catalog.yaml`.
|
||||
|
||||
If skill not found: "Skill '[name]' not found."
|
||||
If neither file exists: the Phase 1 message.
|
||||
If no `category:` field: "No category assigned for '[name]' in catalog.yaml.
|
||||
Add `category: [name]` to the skill entry first."
|
||||
Add `category: [name]` to its entry first."
|
||||
|
||||
For `category all`: collect all skills with a `category:` field and process each.
|
||||
For `category all`: collect every skill and every agent with a `category:` field
|
||||
and process each, reporting skills and agents in separate tables.
|
||||
`category: utility` skills are evaluated against U1 (static checks pass) and U2
|
||||
(gate mode correct if applicable) only — skip to the static mode for U1.
|
||||
Cross-check against `.claude/skills/*/SKILL.md` and `.claude/agents/*.md`
|
||||
(Audit mode's Step 2 glob): list any skill or agent missing from the catalog, or
|
||||
catalogued with no `category:`, by name as **NOT ASSESSED** — never silently
|
||||
excluded from the run.
|
||||
|
||||
### Step 2 — Read Rubric Section
|
||||
|
||||
Read `CCGS Skill Testing Framework/quality-rubric.md`.
|
||||
Extract the section matching the skill's category (e.g., `### gate`, `### team`).
|
||||
Extract the section matching the category (e.g., `### gate`, `### team`; an
|
||||
agent's category is under `## Agent Categories`, e.g. `### director`).
|
||||
If the rubric has no section for the category, the result is **NOT ASSESSED**:
|
||||
name the missing section, and never borrow another category's metrics.
|
||||
|
||||
### Step 3 — Read Skill
|
||||
|
||||
Read the skill's `SKILL.md` fully.
|
||||
Read the skill's `SKILL.md` or the agent's `.claude/agents/[name].md` fully,
|
||||
and the project context Phase 2B Step 3 describes — a metric met by a rule in
|
||||
`CLAUDE.md` or a file it imports is met, citing that file. Its rule for
|
||||
redirect and escalation cases decides the domain, deferral and escalation
|
||||
metrics too (D2, D3, L2, S1–S3, O2).
|
||||
|
||||
### Step 4 — Evaluate Rubric Metrics
|
||||
|
||||
For each metric in the category's rubric table:
|
||||
1. Check whether the skill's written instructions clearly satisfy the criterion
|
||||
2. Mark PASS, FAIL, or WARN
|
||||
3. For FAIL/WARN, identify the exact gap in the skill text (quote the relevant section
|
||||
or note its absence)
|
||||
1. Check whether the skill's or agent's written instructions clearly satisfy the criterion
|
||||
2. Mark PASS, FAIL, WARN, or NOT ASSESSED (the metric could not be evaluated — name why)
|
||||
3. For FAIL/WARN/NOT ASSESSED, identify the exact gap in the text (quote the
|
||||
relevant section, note its absence, or name what could not be evaluated)
|
||||
|
||||
### Step 5 — Output Report
|
||||
|
||||
For an agent, the header is `=== Agent Category Check: [name] ([category]) ===`.
|
||||
|
||||
```
|
||||
=== Skill Category Check: /[name] ([category]) ===
|
||||
|
||||
Metric G1 — Review mode read: PASS
|
||||
Metric G2 — Full mode directors: FAIL
|
||||
Gap: Phase 3 spawns only CD-PHASE-GATE; TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE absent
|
||||
Metric G2 — Director panel width: FAIL
|
||||
Gap: Phase 3 spawns only CD-PHASE-GATE at `workflow: full`; TD-PHASE-GATE, PR-PHASE-GATE, AD-PHASE-GATE absent
|
||||
Metric G3 — Lean mode: PHASE-GATE only: PASS
|
||||
Metric G4 — Solo mode: no directors: PASS
|
||||
Metric G5 — No auto-advance: PASS
|
||||
|
||||
Verdict: FAIL (1 failure, 0 warnings)
|
||||
Fix: Add TD-PHASE-GATE, PR-PHASE-GATE, and AD-PHASE-GATE to the full-mode director
|
||||
panel in Phase 3.
|
||||
Fix: Size the Phase 3 panel from `modes.workflow` — PR at `minimal`, TD + PR at
|
||||
`standard`, all four at `full` — and name any perspective a narrower panel leaves out.
|
||||
```
|
||||
|
||||
The category verdict, first match wins: **FAIL** when any metric fails; else
|
||||
**WARNINGS** when any metric warns; else **NOT ASSESSED** when any metric could
|
||||
not be evaluated (a rubric section missing, a file unreadable); else **PASS**
|
||||
when every metric passes — the same ranking as static and spec mode. It is
|
||||
`last_category_result` in the catalog.
|
||||
|
||||
### Step 6 — Offer to Update Catalog
|
||||
|
||||
"May I update `CCGS Skill Testing Framework/catalog.yaml` to record this category check
|
||||
@@ -329,8 +448,11 @@ yet (first-run state).
|
||||
Glob `.claude/skills/*/SKILL.md` to get the complete list of skills.
|
||||
Extract skill name from each path (directory name).
|
||||
|
||||
Also read the `agents:` section from `CCGS Skill Testing Framework/catalog.yaml` to get the
|
||||
complete list of agents.
|
||||
Glob `.claude/agents/*.md` for the complete list of agents — the repo itself,
|
||||
not the catalog, is the covered set (`.claude/rules/skill-authoring.md` §5:
|
||||
gates derive their covered set, they do not enumerate it). Compare both globs
|
||||
against the catalog's `skills:`/`agents:` entries and report any skill or agent
|
||||
missing from the catalog by name, so an uncatalogued one cannot drop out silently.
|
||||
|
||||
### Step 3 — Build Skill Coverage Table
|
||||
|
||||
@@ -345,7 +467,8 @@ For each skill:
|
||||
|
||||
For each agent in catalog's `agents:` section:
|
||||
- Check if a spec file exists (use the `spec:` path from catalog, or glob `CCGS Skill Testing Framework/agents/*/[name].md`)
|
||||
- Look up `last_spec`, `last_spec_result`, `category` from catalog
|
||||
- Look up `last_spec`, `last_spec_result`, `last_category`,
|
||||
`last_category_result`, `category` from catalog
|
||||
|
||||
### Step 4 — Output Report
|
||||
|
||||
@@ -354,7 +477,7 @@ For each agent in catalog's `agents:` section:
|
||||
Date: [date]
|
||||
|
||||
SKILLS (74 total)
|
||||
Specs written: 72 (97%) | Never static tested: 74 | Never category tested: 74
|
||||
Specs written: 73 (99%) | Never static tested: 74 | Never category tested: 74
|
||||
|
||||
Skill | Cat | Has Spec | Last Static | S.Result | Last Cat | C.Result | Priority
|
||||
-----------------------|----------|----------|-------------|----------|----------|----------|----------
|
||||
@@ -365,16 +488,16 @@ design-review | review | YES | never | — | never
|
||||
AGENTS (49 total)
|
||||
Agent specs written: 49 (100%)
|
||||
|
||||
Agent | Category | Has Spec | Last Spec | Result
|
||||
-----------------------|------------|----------|-------------|--------
|
||||
creative-director | director | YES | never | —
|
||||
technical-director | director | YES | never | —
|
||||
Agent | Category | Has Spec | Last Spec | Result | Last Cat | C.Result
|
||||
-----------------------|------------|----------|-------------|--------|----------|----------
|
||||
creative-director | director | YES | never | — | never | —
|
||||
technical-director | director | YES | never | — | never | —
|
||||
...
|
||||
|
||||
Top 5 Priority Gaps (skills with no spec, critical/high priority):
|
||||
(none if all specs are written)
|
||||
|
||||
Skill coverage: 72/72 specs (100%)
|
||||
Skill coverage: 73/74 specs (99%)
|
||||
Agent coverage: 49/49 specs (100%)
|
||||
```
|
||||
|
||||
@@ -397,6 +520,7 @@ After any mode completes, offer contextual follow-up:
|
||||
- After `spec [name]` PASS: "Update `CCGS Skill Testing Framework/catalog.yaml` to record this
|
||||
pass date. Consider running `/skill-test audit` to find the next spec gap."
|
||||
- After `spec [name]` FAIL: "Review the failing assertions and update the skill
|
||||
or the test spec to resolve the mismatch."
|
||||
or agent, or the test spec, to resolve the mismatch."
|
||||
- After `audit`: "Start with the critical-priority gaps. Use the spec template
|
||||
at `CCGS Skill Testing Framework/templates/skill-test-spec.md` to create new specs."
|
||||
at `CCGS Skill Testing Framework/templates/skill-test-spec.md` (agents:
|
||||
`agent-test-spec.md`) to create new specs."
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Bash, Write, AskUserQuestion, Bash(bash "*/.cla
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,qa.level,testing.strict`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,qa.level,testing.strict`
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
`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
|
||||
run, a FAIL is advisory and never blocks hand-off, and a project with no game
|
||||
tests is checked by its build, launch and critical paths alone (Phase 1 step 1); 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`.
|
||||
@@ -74,11 +75,25 @@ Before running anything, understand the environment:
|
||||
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.**
|
||||
that `tests/` does. Check the engine's **test root** (from step 3; the table
|
||||
is in `.claude/docs/directory-structure.md` — Godot `tests/unit/` and
|
||||
`tests/integration/`, Unity `Assets/Tests/`, Unreal
|
||||
`Source/*/Private/Tests/`) and `tests/smoke/` for actual test files. A
|
||||
**test file** is one the engine's test runner executes — a `*_test.gd` suite,
|
||||
a C# test class, an Unreal automation test source. Markdown checklists do not
|
||||
count: `/test-setup` always writes `tests/smoke/critical-paths.md`, and
|
||||
counting it would hide exactly the zero-test state this step exists to catch.
|
||||
If none are found **at `qa.level: minimal`**, tests are waived at this level:
|
||||
record the automated row as `WAIVED — qa.level: minimal, no game tests`, skip
|
||||
the test run in Phase 2 and all of Phase 3 (say so in one line each), run
|
||||
Phase 2's **build check**, and go on to Phase 4 — the build check and the
|
||||
launch and critical-path checks are the smoke check at this level, so
|
||||
a project with no tests can still reach PASS, but never without a run: a
|
||||
Batch 1 answer that the build was not launched this session leaves the
|
||||
verdict NOT ASSESSED.
|
||||
If none are found **at `standard` or `full`**, **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
|
||||
[the test root] or `tests/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.
|
||||
@@ -92,9 +107,8 @@ Before running anything, understand the environment:
|
||||
> **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**.
|
||||
> was ever written. Count actual test files instead; gated on the directory,
|
||||
> a project with no build and zero game tests passes this step.
|
||||
|
||||
2. **CI check**: check whether `.github/workflows/` contains a workflow file
|
||||
referencing tests. Note in the report whether CI is configured.
|
||||
@@ -105,6 +119,17 @@ Before running anything, understand the environment:
|
||||
(a `[TO BE CONFIGURED]` value means not configured). Store this for test
|
||||
command selection in Phase 2.
|
||||
|
||||
Then find the **editor executable** — none of the three engines installs
|
||||
onto `PATH` by default on Windows or macOS, so a bare `godot` that does not
|
||||
resolve says nothing about whether the engine is installed. Take the first
|
||||
that resolves (the file exists, or `command -v` finds it): the executable
|
||||
`commands.test` names (its quoted path or first word), else the editor
|
||||
`engine.path` records, else the engine's name on `PATH` (`godot`). Use it
|
||||
wherever Phase 2 writes `godot` or `"<Unity editor>"`, quoting a path with a
|
||||
space; on Unreal, `<UE root>` is `engine.path`. If none resolves, the test
|
||||
runner is not available (Phase 2) — on Godot,
|
||||
`NOT ASSESSED — Godot executable not found (commands.test, engine.path, PATH)`.
|
||||
|
||||
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
|
||||
Phase 4. If neither exists, smoke tests will be drawn from the current QA
|
||||
@@ -113,28 +138,57 @@ Before running anything, understand the environment:
|
||||
5. **QA plan check**: glob `production/qa/qa-plan-*.md` and take the most
|
||||
recently modified file. If found, note the path — it will be used in
|
||||
Phase 3 and Phase 4. If not found, note: "No QA plan found. Run
|
||||
`/qa-plan sprint` before smoke-checking for best results."
|
||||
`/qa-plan sprint` before smoke-checking for best results." (At `workflow: minimal`,
|
||||
which has no sprints, a QA plan is optional — say so rather than recommend one.)
|
||||
|
||||
Report findings before proceeding: "Environment: [engine]. Test directory:
|
||||
Report findings before proceeding: "Environment: [engine]. Editor: [the
|
||||
resolved executable / not found]. Test directory:
|
||||
[found / not found]. CI configured: [yes / no]. QA plan: [path / not found]."
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Run Automated Tests
|
||||
|
||||
Attempt to run the test suite via Bash. Select the command based on the engine
|
||||
detected in Phase 1:
|
||||
**Run `commands.test` from `project.yaml` when it is set** — it is the
|
||||
project's own test command, the one `/setup-engine` wrote and CI runs. Use the
|
||||
per-engine default below only when `commands.test` is absent, and say in the
|
||||
report which of the two you ran. Wrap it in a timeout (`timeout 900 …`): **a
|
||||
timeout (exit 124) is a gate FAILURE, never a pass** — the run never completed
|
||||
and nothing was verified. macOS has no `timeout`: use `gtimeout 900 …` from
|
||||
Homebrew's `coreutils` (same exit 124), or, with nothing installed,
|
||||
`perl -e 'alarm shift; exec @ARGV' 900 …`, which exits 142 when time runs out —
|
||||
a FAILURE the same way. Then read the result for the engine. On every engine
|
||||
one outcome looks like success and is not; each is named below.
|
||||
|
||||
**Godot 4:**
|
||||
**Godot 4** — first check that `addons/gdUnit4/bin/GdUnitCmdTool.gd` exists —
|
||||
the folder has a **capital U**. If it does not, report
|
||||
`NOT ASSESSED — gdUnit4 not installed at addons/gdUnit4/` instead of running
|
||||
anything. Then import, whether you run `commands.test` or the
|
||||
default. A fresh clone has no `.godot/` class cache, and without it gdUnit4's
|
||||
runner does not load; a cache that predates a new `class_name` fails valid
|
||||
code with 105. The import takes seconds when nothing changed (`godot` below is
|
||||
the executable Phase 1 step 3 resolved):
|
||||
```bash
|
||||
godot --headless --script tests/gdunit4_runner.gd 2>&1
|
||||
godot --headless --path . --import
|
||||
godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode 2>&1
|
||||
```
|
||||
If the GDUnit4 runner script does not exist at that path, try:
|
||||
```bash
|
||||
godot --headless -s addons/gdunit4/GdUnitRunner.gd 2>&1
|
||||
```
|
||||
If neither path exists, note: "GDUnit4 runner not found — confirm the runner
|
||||
path for your test framework."
|
||||
gdUnit4's exit code gives the verdict (6.1.3):
|
||||
- **0** — every test passed: PASS. **But exit 0 over zero tests is not a pass:**
|
||||
gdUnit4 aborts and still exits 0, so if the output says `No test cases found`,
|
||||
the verdict is `NOT ASSESSED — no tests found`.
|
||||
- **101** — every test passed but a test leaked nodes (orphans): PASS WITH
|
||||
WARNINGS, naming the orphan count from the output. Not a failure.
|
||||
- **100** — a test failed: FAIL. **105** — a test script does not parse: FAIL.
|
||||
- **103** — gdUnit4 refused to run headless (`--ignoreHeadlessMode` missing);
|
||||
**104** — Godot older than 4.3: `NOT ASSESSED`, with that reason.
|
||||
- **1** — Godot's own error: `GdUnitCmdTool.gd` did not load (`Failed to load
|
||||
script`), so no test ran. Usually the import above was skipped; after it,
|
||||
exit 1 is a FAIL.
|
||||
|
||||
Every run opens with two `ERROR:` lines about the remote port
|
||||
(`127.0.0.1:0`) — that is the `--remote-debug` flag working, not a failure.
|
||||
Never drop the flag: without it a script error opens Godot's interactive
|
||||
debugger and the run hangs at a `debug>` prompt until the timeout.
|
||||
|
||||
**Unity:**
|
||||
Unity **can** run tests headlessly via shell. Do not skip to reading artifacts.
|
||||
@@ -150,33 +204,106 @@ 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:
|
||||
If present, the default is (the **editor** executable — `Unity` on `PATH` may be
|
||||
Unity's separate CLI). Delete the old results file first, whether you run
|
||||
`commands.test` or this default:
|
||||
```bash
|
||||
timeout 900 "<Unity.exe>" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/results.xml
|
||||
rm -f test-results/editmode.xml
|
||||
timeout 900 "<Unity editor>" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/editmode.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.
|
||||
Exit 0 when every test passes, 2 on a failure. **Exit 1 or 3 is a FAIL**: 1
|
||||
means the project did not compile (the editor log has the `error CS…` lines),
|
||||
3 that the run itself failed; 4 (an unknown `-testPlatform`) or any other
|
||||
non-zero exit is a FAIL too. A compile error writes no results file — which
|
||||
is why the old one is deleted first: left in place, the last run's pass is read
|
||||
as this run's. After any exit, no results file is a FAIL. Parse the `<test-run>`
|
||||
element of the results file for `testcasecount`, `passed` and `failed`. **`testcasecount="0"`
|
||||
is NOT ASSESSED, never a pass**: tests outside `Assets/` are never compiled, and
|
||||
Unity then reports `result="Passed"` with exit 0 over zero tests.
|
||||
|
||||
**Unreal Engine:**
|
||||
**Play Mode is a second run.** `-testPlatform EditMode` — this default, and
|
||||
`commands.test` as `/setup-engine` writes it — never runs the integration tests
|
||||
`/test-setup` scaffolds under `Assets/Tests/PlayMode/`. When that folder holds a
|
||||
test file and the command you ran did not already pass `-testPlatform PlayMode`,
|
||||
run Play Mode the same way, into its own results file, and read it by the same
|
||||
rules:
|
||||
```bash
|
||||
# List most recent Unreal automation logs (bash) — on Windows PowerShell use the fallback below
|
||||
ls -t Saved/Logs/ 2>/dev/null | grep -i "test\|automation" | head -5 \
|
||||
|| powershell -Command "Get-ChildItem Saved/Logs/ -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'test|automation' } | Sort-Object LastWriteTime -Descending | Select-Object -First 5 -ExpandProperty Name"
|
||||
rm -f test-results/playmode.xml
|
||||
timeout 900 "<Unity editor>" -batchmode -runTests -projectPath . -testPlatform PlayMode -testResults test-results/playmode.xml
|
||||
```
|
||||
If no matching log found: "UE automation tests must be run via the Session
|
||||
Frontend or CI pipeline. Please confirm test status manually."
|
||||
Report each platform on its own line — `EditMode: PASS (12/12)`,
|
||||
`PlayMode: FAIL (1 failure)`. A Play Mode run that could not be made is
|
||||
reported by name, `PlayMode: NOT RUN — [reason]`: the Edit Mode result does not
|
||||
cover those tests, so it cannot make the automated-test row a PASS.
|
||||
|
||||
**Unreal Engine** — build the editor target first, whether you then run
|
||||
`commands.test` or the default. `Binaries/` is not committed, and without a
|
||||
built game module the editor stops with "The game module could not be found",
|
||||
exit 1, before running any test. The build is incremental — seconds when
|
||||
nothing changed; a failed build is a FAIL.
|
||||
|
||||
**Pick the commands for this machine** with `uname -s`: `Linux` → Linux,
|
||||
`Darwin` → macOS, anything else (`MINGW*`, `MSYS*`, `CYGWIN*`) → Windows. The
|
||||
Windows forms below were run on UE 5.7; the Linux and macOS forms come from
|
||||
Epic's documentation — `docs/engine-reference/unreal/current-best-practices.md`,
|
||||
"Command Line", has them with their sources. On Windows use
|
||||
`UnrealBuildTool.exe`, not `Build.bat`: run from bash, `Build.bat` fails on an
|
||||
engine path with spaces.
|
||||
```bash
|
||||
# Windows
|
||||
timeout 1800 "<UE root>/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe" <Project>Editor Win64 Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" 2>&1
|
||||
# Linux
|
||||
timeout 1800 "<UE root>/Engine/Build/BatchFiles/Linux/Build.sh" <Project>Editor Linux Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" 2>&1
|
||||
# macOS (timeout: see the macOS note above)
|
||||
gtimeout 1800 "<UE root>/Engine/Build/BatchFiles/Mac/Build.sh" <Project>Editor Mac Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" 2>&1
|
||||
```
|
||||
Then the default. Keep `-stdout -FullStdOutLogOutput`; when `commands.test`
|
||||
lacks them, add them to the command for this run only: without them the editor
|
||||
prints nothing, and the lines below are only in `Saved/Logs/<Project>.log`.
|
||||
Give the project as an **absolute** path — when `commands.test` passes a
|
||||
relative one, run it with the absolute path instead: UE 5.7
|
||||
does not find a relative `<Project>.uproject` and exits 1 (`Project file not
|
||||
found`). `$(pwd -W 2>/dev/null || pwd)` gives the `C:/…` form in Git Bash and
|
||||
the plain path elsewhere; `$PWD` alone fails when `MSYS_NO_PATHCONV` is set.
|
||||
Either way, say in the report what you changed and tell the user to fix
|
||||
`commands.test` in `project.yaml` — never edit `project.yaml` without asking.
|
||||
`<Project>.` in the filter is the root the tests are named under: the project
|
||||
name, or the distinct root `/setup-engine` chose when the project's name is
|
||||
also an engine area — read one test's name string under
|
||||
`Source/*/Private/Tests/` if unsure.
|
||||
```bash
|
||||
# Windows
|
||||
timeout 1800 "<UE root>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" -ExecCmds="Automation RunTests <Project>.; Quit" -unattended -nullrhi -stdout -FullStdOutLogOutput 2>&1
|
||||
# Linux
|
||||
timeout 1800 "<UE root>/Engine/Binaries/Linux/UnrealEditor" "$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" -ExecCmds="Automation RunTests <Project>.; Quit" -unattended -nullrhi -stdout -FullStdOutLogOutput 2>&1
|
||||
```
|
||||
**macOS has no sourced test command.** Epic documents only the
|
||||
`UnrealEditor.app` bundle, not a command-line editor inside it. Run a
|
||||
`commands.test` the user has set and confirmed; with none, report
|
||||
`NOT ASSESSED — Unreal test command on macOS not sourced; set commands.test to the editor command you use`
|
||||
instead of guessing a path.
|
||||
Read the output, not the exit code: a failing test and a run that matched nothing both exit 255.
|
||||
- `Result={Fail}` on any line → FAIL.
|
||||
- `No automation tests matched` → `NOT ASSESSED — no tests found` (tests
|
||||
outside `Source/<Module>/` are never built), not FAIL.
|
||||
- Exit 0 with `Result={Success}` lines → PASS.
|
||||
- Any other non-zero exit (`Project file not found`, `The game module … could
|
||||
not be found`) → FAIL: no test ran. The exception: the editor never started (exit 126 or 127, `command not found`) — that is the runner not being
|
||||
available, below, and `NOT ASSESSED`.
|
||||
|
||||
**Unknown engine / not configured:**
|
||||
"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:
|
||||
**If the test runner is not available in this environment** (no editor
|
||||
executable resolved in Phase 1 step 3, 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
|
||||
"Automated tests could not be executed — engine executable not found (checked
|
||||
`commands.test`, `engine.path` and `PATH`; set `engine.path`, or put the
|
||||
editor's full path in `commands.test`). Status will be recorded as NOT RUN.
|
||||
Confirm test results from your local IDE
|
||||
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."
|
||||
|
||||
@@ -193,6 +320,21 @@ Parse runner output and extract:
|
||||
- Names of any failing tests (up to 10; if more, note the count)
|
||||
- Any crash or error output from the runner itself
|
||||
|
||||
**Build check — the WAIVED path only** (`qa.level: minimal`, no game tests;
|
||||
Phase 1 step 1). With no suite to run, run the project's own boot check:
|
||||
`commands.smoke` when set, else `commands.build` when set, with the executable
|
||||
Phase 1 step 3 resolved, under the same timeout rules (`timeout 900`, or
|
||||
`timeout 1800` for `commands.build`; a timeout is a FAIL). On Godot, run the
|
||||
import line above first. Read the result as `/setup-engine` documents it:
|
||||
Godot `smoke` exits 0 even on a parse error, so a `SCRIPT ERROR` line in its
|
||||
output is a FAIL, and so is `Can't run project: no main scene defined` — the
|
||||
game cannot launch; Unity `smoke` exits 1 on a compile error; any other
|
||||
non-zero exit is a FAIL. Record `Build check: PASS — [command] exit 0`,
|
||||
`FAIL — [reason]`, or `NOT RUN — [commands.smoke and commands.build unset |
|
||||
executable not found]`. A build check that did not run is named in the report
|
||||
and leaves the launch in Batch 1 to carry the verdict; it never passes on its
|
||||
own.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Check Test Coverage
|
||||
@@ -233,7 +375,7 @@ fully close those stories.
|
||||
|
||||
## Phase 4: Run Manual Smoke Checks
|
||||
|
||||
Draw the smoke test checklist from, in priority order:
|
||||
Draw the smoke test checklist from, in priority order (and name the one you used in the report):
|
||||
1. The QA plan's "Smoke Test Scope" section (if QA plan was found in Phase 1)
|
||||
2. `production/qa/smoke-tests.md` (if it exists)
|
||||
3. `tests/smoke/` directory contents (if it exists)
|
||||
@@ -254,8 +396,15 @@ sprint's stories.
|
||||
|
||||
Use `AskUserQuestion` to batch-verify. Keep to at most 3 calls.
|
||||
|
||||
**Batch 1 — Core stability (always run):**
|
||||
**Batch 1 — Core stability (always run):** one call, two questions — an empty
|
||||
failure list means nothing unless somebody launched the build.
|
||||
```
|
||||
question: "Did you launch the current build this session?"
|
||||
multiSelect: false
|
||||
options:
|
||||
- "Yes — I launched it and checked the items below"
|
||||
- "No — I have not launched the current build this session"
|
||||
|
||||
question: "Core stability — select any items that FAILED (leave all unselected if everything passed):"
|
||||
multiSelect: true
|
||||
options:
|
||||
@@ -267,6 +416,12 @@ options:
|
||||
|
||||
For any selected item, ask the user to briefly describe what failed before generating the report.
|
||||
|
||||
If the build was **not launched**, the Batch 1 checks could not be executed:
|
||||
record them as `NOT RUN — build not launched this session`, skip Batches 2 and
|
||||
3 and any platform batch (say so — they need a running build), and ignore the
|
||||
unselected failure list. The verdict is then NOT ASSESSED unless something else
|
||||
FAILED.
|
||||
|
||||
**Batch 2 — Sprint changes and regression (always run):**
|
||||
```
|
||||
question: "Sprint changes and regression — select any items that FAILED (leave all unselected if everything passed):"
|
||||
@@ -354,8 +509,16 @@ Assemble the full smoke check report:
|
||||
|
||||
### Automated Tests
|
||||
|
||||
**Status**: [PASS ([N] tests, [N] passing) | FAIL ([N] failures) |
|
||||
NOT RUN ([reason])]
|
||||
**Status**: [PASS ([N] tests, [N] passing) | PASS WITH WARNINGS ([N] tests
|
||||
passing; [the runner's warning, e.g. [N] orphan nodes leaked]) | FAIL ([N]
|
||||
failures, or did not complete: [timeout | compile, parse or build error | no
|
||||
results file]) | NOT ASSESSED ([reason, e.g. zero tests executed, runner could
|
||||
not run]) | NOT RUN ([reason]) | WAIVED (qa.level: minimal — no game tests)]
|
||||
|
||||
[Unity: one Status line per test platform — `EditMode:` and `PlayMode:`.]
|
||||
|
||||
[WAIVED only:] **Build check**: [PASS — `[command]` exit 0 | FAIL — [reason] |
|
||||
NOT RUN — [commands.smoke and commands.build unset | executable not found]]
|
||||
|
||||
[If FAIL, list failing tests:]
|
||||
- `[test name]` — [brief failure description from runner output]
|
||||
@@ -381,6 +544,7 @@ will determine whether the automated test row contributes to a FAIL verdict."
|
||||
|
||||
### Manual Smoke Checks
|
||||
|
||||
- [x] Build launched this session — yes [or: `NOT RUN — build not launched this session`; the batches below were not asked]
|
||||
- [x] Game launches without crash — PASS
|
||||
- [x] New game starts — PASS
|
||||
- [x] [Core mechanic] — PASS
|
||||
@@ -422,13 +586,23 @@ Any platform with one or more FAIL checks contributes to the overall FAIL verdic
|
||||
|
||||
**FAIL** if ANY of:
|
||||
- Automated test suite ran and reported one or more test failures
|
||||
- The automated suite did not complete: a timeout, a compile, parse or build
|
||||
error, or no results file after the run (Phase 2 names each engine's form)
|
||||
- The build check (WAIVED path) failed: a non-zero exit, a timeout, or a Godot
|
||||
`SCRIPT ERROR` or no-main-scene line
|
||||
- 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
|
||||
- The runner could not run (gdUnit4 103 or 104, gdUnit4 or the Unity Test
|
||||
Framework not installed), or it ran and executed zero tests
|
||||
(`No test cases found`, `testcasecount="0"`, `No automation tests matched`)
|
||||
- Unity Play Mode tests exist and are `PlayMode: NOT RUN`, unconfirmed — the
|
||||
Edit Mode result does not cover them
|
||||
- A Batch 1 or Batch 2 check could not be executed (no build, engine not
|
||||
configured, platform unavailable) as opposed to executing and failing
|
||||
configured, platform unavailable) as opposed to executing and failing —
|
||||
including a Batch 1 answer that the build was not launched this session
|
||||
- **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
|
||||
@@ -438,13 +612,17 @@ Any platform with one or more FAIL checks contributes to the overall FAIL verdic
|
||||
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 **and the developer has confirmed the result
|
||||
from their local IDE or CI**
|
||||
- Automated tests PASS or PASS WITH WARNINGS, WAIVED at `qa.level: minimal`, 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
|
||||
- At least one warning: a Logic/Integration story with MISSING test evidence,
|
||||
a runner warning on a passing suite (gdUnit4 101 — orphan nodes leaked), or
|
||||
a NOT RUN suite the developer confirmed
|
||||
|
||||
**PASS** if ALL of:
|
||||
- Automated tests PASS
|
||||
- Automated tests PASS, or WAIVED (`qa.level: minimal` and no game tests exist —
|
||||
the build check, when `commands.smoke` or `commands.build` is set, and the
|
||||
launch and critical-path batches below then carry the verdict)
|
||||
- All smoke checks in all batches PASS or N/A
|
||||
- No MISSING test evidence entries
|
||||
````
|
||||
@@ -527,10 +705,13 @@ are fixed."
|
||||
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]
|
||||
`PlayMode: NOT RUN`, zero tests executed, runner not installed, engine
|
||||
executable not found, no build, build not launched this session, 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'.]
|
||||
result from your IDE or CI', 'run `/setup-engine`', 'set `engine.path`',
|
||||
'produce a build', 'launch the build and play the checks'.]
|
||||
|
||||
Re-run `/smoke-check` once any of those is resolved."
|
||||
|
||||
@@ -546,7 +727,8 @@ their behalf.
|
||||
"Smoke check passed with warnings. The build is ready for manual QA.
|
||||
|
||||
Advisory items to resolve before running `/story-done` on affected stories:
|
||||
[list MISSING test evidence entries]
|
||||
[list MISSING test evidence entries, and any runner warning — e.g. the orphan
|
||||
count]
|
||||
|
||||
QA hand-off: share `production/qa/qa-plan-[sprint].md` with the qa-tester
|
||||
agent to begin manual verification."
|
||||
|
||||
@@ -66,7 +66,9 @@ Read:
|
||||
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
|
||||
soak duration), core loop description (or `design/game-brief.md`, the one-page
|
||||
brief that replaces it at `rigor: minimal` — core loop, and session length only
|
||||
if its "Who it's for" line states one)
|
||||
- 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
|
||||
@@ -113,6 +115,13 @@ Engine-specific monitoring guidance.
|
||||
> and it would read as a plausible instruction throughout. Deltas need no such
|
||||
> claim, so the safest fix was to stop needing it.
|
||||
|
||||
> **NOT SOURCEABLE — the tool, panel and counter names below are not covered by
|
||||
> `docs/engine-reference/`**: Godot's Debugger → Monitors and its memory
|
||||
> counters, Unity's Memory Profiler and its fields, Unreal's `stat memory`. Mark
|
||||
> them so in the protocol: they are pointers for the tester to confirm in their
|
||||
> own editor at T+0, not verified paths. If no memory tool can be found, nothing
|
||||
> was measured, and the Verdict section's NOT ASSESSED applies.
|
||||
|
||||
**Godot 4:**
|
||||
- Open Debugger → Monitors tab; track `Memory → Static Memory` and
|
||||
`Object Count → Objects` across checkpoints
|
||||
@@ -181,6 +190,8 @@ Before starting the soak:
|
||||
- **Godot**: Debugger → Monitors tab → Memory section visible
|
||||
- **Unity**: Memory Profiler window open
|
||||
- **Unreal**: `stat memory` ready in console
|
||||
- Tool actually used, as named in this editor: [record it — the names above
|
||||
are NOT SOURCEABLE from `docs/engine-reference/`; none found → NOT ASSESSED]
|
||||
- [ ] Soak target confirmed: [session design intent from game concept]
|
||||
- [ ] Prior known issues to watch for: [from most recent playtest / qa-plan]
|
||||
|
||||
|
||||
@@ -34,35 +34,23 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
`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`.
|
||||
many stories to allocate per sprint, scaled by velocity: **2–4** at `coarse` (the default, via `rigor: minimal`),
|
||||
**6–10** at `balanced` (`rigor: standard`), **15–25** at `fine`. A Ready backlog
|
||||
smaller than the range is planned whole — never padded with invented stories.
|
||||
|
||||
**Review mode check** (before gates run):
|
||||
- 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: 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?"
|
||||
- Use the review mode from the resolved block above (`--review` overrides it
|
||||
for this run) — do not re-resolve it, and do not ask for it. With nothing
|
||||
configured it follows `modes.rigor`: `solo` at `minimal`, `lean` at `standard`.
|
||||
- **Never write a review mode** — not to `project.yaml`, not to
|
||||
`production/review-mode.txt`. `modes.review_mode` is one of the knobs
|
||||
`modes.rigor` fronts: pinning it in `project.yaml` shadows the rigor
|
||||
expansion, and the legacy file sits *above* that expansion, so either write
|
||||
would freeze director-review depth for good. `--review` covers a one-off. If
|
||||
the user wants a different depth to persist, point them to changing
|
||||
`modes.rigor` (`/settings modes.rigor=<minimal|standard|full>`), or to pinning
|
||||
it on purpose with `/settings --local modes.review_mode=<full|lean|solo>` (a
|
||||
personal override in `project.local.yaml`).
|
||||
|
||||
---
|
||||
|
||||
@@ -76,7 +64,14 @@ many stories to allocate per sprint, scaled by velocity: **2–4** at `coarse`,
|
||||
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.
|
||||
understand velocity and carryover. In `new` mode:
|
||||
- The new sprint's number `[N]` is the highest `sprint-NNN.md` in the
|
||||
Existing Sprints listing plus one (`001` when there is none). It is the
|
||||
`[N]` in the plan's title, its QA plan path and the write ask.
|
||||
- Every story of the previous sprint that is not `Complete` — by its status
|
||||
in `production/sprint-status.yaml`, else its story file's Status line —
|
||||
goes in the Carryover table with a Reason and a New Estimate. It appears
|
||||
only there, never again as new Must Have / Should Have / Nice to Have work.
|
||||
|
||||
3. **Find the stories to plan** — this is the actual backlog, and it is the one
|
||||
input this phase cannot do without:
|
||||
@@ -92,7 +87,7 @@ many stories to allocate per sprint, scaled by velocity: **2–4** at `coarse`,
|
||||
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.
|
||||
which do not exist cannot be implemented. Verdict: **BLOCKED** — no stories to plan.
|
||||
|
||||
4. **Scan design documents** in `design/gdd/` for additional context on the
|
||||
features those stories implement. At `workflow: minimal` there are no
|
||||
@@ -153,7 +148,7 @@ For `new`:
|
||||
## Definition of Done for this Sprint
|
||||
- [ ] All Must Have tasks completed
|
||||
- [ ] All tasks pass acceptance criteria
|
||||
- [ ] QA plan exists (`production/qa/qa-plan-sprint-[N].md`)
|
||||
- [ ] QA plan exists (`production/qa/qa-plan-[sprint-slug]-[date].md`, from `/qa-plan sprint`)
|
||||
- [ ] All Logic/Integration stories have passing unit/integration tests
|
||||
- [ ] Smoke check passed (`/smoke-check sprint`)
|
||||
- [ ] QA sign-off report: APPROVED or APPROVED WITH CONDITIONS (`/team-qa sprint`)
|
||||
@@ -255,6 +250,7 @@ Initialize each story from the sprint plan's task tables:
|
||||
- Must Have tasks → `priority: must-have`, `status: ready-for-dev`
|
||||
- Should Have tasks → `priority: should-have`, `status: backlog`
|
||||
- Nice to Have tasks → `priority: nice-to-have`, `status: backlog`
|
||||
- Carryover rows → the story's previous `priority`, and the `status` it has now
|
||||
|
||||
For `update`: read the existing `sprint-status.yaml`, carry over statuses for
|
||||
stories that haven't changed, add new stories, remove dropped ones.
|
||||
@@ -274,7 +270,9 @@ Pass: proposed story list (titles, estimates, dependencies), total team capacity
|
||||
|
||||
Present the producer's assessment.
|
||||
|
||||
If UNREALISTIC: revise the story selection (defer stories to Should Have or Nice to Have) and re-present the updated plan before asking for write approval.
|
||||
If UNREALISTIC: revise the story selection (defer stories to Should Have or Nice to Have) and re-present the updated plan, then continue to Phase 5.
|
||||
|
||||
If NOT ASSESSED: name the missing input — it is not REALISTIC. Supply it and re-run PR-SPRINT, or record `NOT ASSESSED — [missing input]` for PR-SPRINT in the plan's header (`.claude/docs/director-gates.md`) and continue to Phase 5, repeating it at the write ask.
|
||||
|
||||
If CONCERNS, use `AskUserQuestion`:
|
||||
- Prompt: "Producer flagged concerns with this sprint plan. How do you want to proceed?"
|
||||
@@ -283,15 +281,12 @@ If CONCERNS, use `AskUserQuestion`:
|
||||
- `[B] Adjust scope — defer some Should Have stories`
|
||||
- `[C] Extend the sprint timeline`
|
||||
|
||||
If [A]: proceed to write approval.
|
||||
If [B]: revise the story list, re-present the updated plan, then proceed to write approval.
|
||||
If [C]: adjust sprint dates and capacity, re-present the updated plan, then proceed to write approval.
|
||||
If [A]: continue to Phase 5.
|
||||
If [B]: revise the story list, re-present the updated plan, then continue to Phase 5.
|
||||
If [C]: adjust sprint dates and capacity, re-present the updated plan, then continue to Phase 5.
|
||||
|
||||
After handling the producer's verdict, ask: "May I write the sprint plan to `production/sprints/sprint-[N].md` and `production/sprint-status.yaml`?" If yes, write both files (creating directories as needed). Verdict: **COMPLETE** — sprint plan and status file created. If no: Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
After writing, add:
|
||||
|
||||
> **Scope check:** If this sprint includes stories added beyond the original epic scope, run `/scope-check [epic]` to detect scope creep before implementation begins.
|
||||
After handling the producer's verdict, continue to Phase 5. The write comes at
|
||||
its end, so the file you approve already holds everything Phase 5 adds.
|
||||
|
||||
---
|
||||
|
||||
@@ -299,7 +294,7 @@ After writing, add:
|
||||
|
||||
Before closing the sprint plan, check whether a QA plan exists for this sprint.
|
||||
|
||||
Use `Glob` to look for `production/qa/qa-plan-sprint-[N].md` or any file in `production/qa/` referencing this sprint number.
|
||||
Use `Glob` for `production/qa/qa-plan-*.md` — `/qa-plan` writes `qa-plan-[sprint-slug]-[date].md` — and keep a file whose name or content references this sprint number.
|
||||
|
||||
**If a QA plan is found**: note it in the sprint plan output — "QA Plan: `[path]`" — and proceed.
|
||||
|
||||
@@ -315,7 +310,9 @@ Use `AskUserQuestion`:
|
||||
- `[A] Run /qa-plan sprint now — I'll do that before starting implementation (Recommended)`
|
||||
- `[B] Skip for now — I understand QA sign-off will be blocked at the Production → Polish gate`
|
||||
|
||||
If [A]: close with "Sprint plan written. Run `/qa-plan sprint` next — then begin implementation."
|
||||
Wait for this answer before the write ask below — the two are separate questions.
|
||||
|
||||
If [A]: note in the plan "QA plan: run `/qa-plan sprint` before implementation begins."
|
||||
If [B]: add a warning block to the sprint plan document:
|
||||
|
||||
```markdown
|
||||
@@ -324,6 +321,19 @@ If [B]: add a warning block to the sprint plan document:
|
||||
> sign-off report, which requires a QA plan.
|
||||
```
|
||||
|
||||
### Write the plan
|
||||
|
||||
Ask: "May I write the sprint plan to `production/sprints/sprint-NNN.md` (`[N]` zero-padded to three digits) and
|
||||
`production/sprint-status.yaml`?" If yes, write both files (creating directories as
|
||||
needed). Verdict: **COMPLETE** — sprint plan and status file created. If no:
|
||||
Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
After writing, add:
|
||||
|
||||
> **Scope check:** If this sprint includes stories added beyond the original epic scope, run `/scope-check [epic]` to detect scope creep before implementation begins.
|
||||
|
||||
If the user chose `Run /qa-plan sprint now` in Phase 5, close with "Sprint plan written. Run `/qa-plan sprint` next — then begin implementation."
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Next Steps
|
||||
@@ -336,8 +346,8 @@ 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, 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)
|
||||
**Review mode configuration:** All director gates (producer feasibility, QA review, code review) respect the project review mode, resolved in the block at the top of this skill (`--review` flag → `project.local.yaml` → `modes.review_mode` in `project.yaml` → `production/review-mode.txt` → the `modes.rigor` expansion, which yields `lean` at standard rigor and `solo` at minimal). This skill never asks for it or writes it; Phase 0 says where to point a user who wants a different depth. The mode is one of:
|
||||
- `lean` — skip non-phase-gate director gates (the `rigor: standard` value)
|
||||
- `full` — run all director gates as spawned sub-agents
|
||||
- `solo` — skip all gate spawning unconditionally (single developer, no review)
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ name: sprint-status
|
||||
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, Bash(bash "*/.claude/skills/sprint-status/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Bash(bash "*/.claude/skills/sprint-status/../../hooks/yaml-helper.sh" resolve_config *), Bash(bash "*/.claude/skills/sprint-status/../../scripts/story-status.sh"), Bash(bash .claude/scripts/story-status.sh*)
|
||||
model: haiku
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys story_granularity`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys story_granularity,workflow`
|
||||
|
||||
|
||||
|
||||
@@ -22,22 +22,58 @@ concise snapshot in under 30 lines. For detailed sprint management, use
|
||||
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`.
|
||||
grain of the burn-down read: **feature-sized** chunks at `coarse` (the default, via `rigor: minimal`), **task-sized**
|
||||
at `balanced` (`rigor: standard`), **AC-sized** at `fine`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Find the Sprint
|
||||
|
||||
**Argument:** `$ARGUMENTS[0]` (blank = use current sprint)
|
||||
**Argument:** `$ARGUMENTS` (blank = use current sprint)
|
||||
|
||||
- If an argument is given (e.g., `/sprint-status 3`), search
|
||||
`production/sprints/` for a file matching `sprint-03.md`, `sprint-3.md`,
|
||||
or similar. Report which file was found.
|
||||
`production/sprints/` for a file matching `sprint-003.md`, `sprint-03.md`, `sprint-3.md`,
|
||||
or similar (`/sprint-plan` writes three digits). Report which file was found.
|
||||
- If no argument is given, find the most recently modified file in
|
||||
`production/sprints/` and treat it as the current sprint.
|
||||
- If `production/sprints/` does not exist or is empty, report: "No sprint
|
||||
files found. Start a sprint with `/sprint-plan new`." Then stop.
|
||||
- If `production/sprints/` does not exist or is empty:
|
||||
- **At `workflow: minimal` there are no sprints by design** — the brief's
|
||||
build order is the plan and the story files carry it. Report progress
|
||||
through it instead, then stop:
|
||||
1. The list below was printed by `.claude/scripts/story-status.sh`
|
||||
before you read this skill: one line per unfinished story, already in
|
||||
the route's order (`IN_REVIEW`, `IN_PROGRESS`, then `TODO` — a `Ready`
|
||||
or `Not Started` story — in build order), then `BLOCKED`, `OTHER`,
|
||||
`NO_STATUS` and the `COMPLETE` count:
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../scripts/story-status.sh"`
|
||||
|
||||
2. Print, in under 15 lines: `Build order: [N] of [M] stories complete`
|
||||
from the `COMPLETE` line (count only `Complete` and `Done` stories —
|
||||
`In Review` is not complete), then **Next**: the story on the first
|
||||
`IN_REVIEW`, `IN_PROGRESS` or `TODO` line. The list is already
|
||||
current; do not run the script again, and do not re-rank the story files — an `In Review` story is closed before an
|
||||
`In Progress` one continues: its work is written. Recommend
|
||||
`/story-done [path]` for `IN_REVIEW`, `/dev-story [path]` for
|
||||
`IN_PROGRESS` or `TODO`. Name any `BLOCKED` story with its blocker; it is
|
||||
never Next.
|
||||
3. Every story `Complete` (or `Done`) → "Build order done: [M] of [M]
|
||||
stories complete." Offer three ways on: play the build; add the next
|
||||
stories from the brief with `/create-stories`; or `/settings` to raise
|
||||
`modes.rigor` if the game has outgrown a one-page brief.
|
||||
4. `STORIES none` — no story files at all → "No stories yet. Run
|
||||
`/create-stories` to turn the brief's build order into stories."
|
||||
5. No `IN_REVIEW`, `IN_PROGRESS` or `TODO` line, yet the `COMPLETE` line
|
||||
is short of the total — every unfinished story is `BLOCKED`, `OTHER`
|
||||
(such as `Draft`) or `NO_STATUS`. There is **no Next**, and the build
|
||||
order is **not** done: never say it is. Print the `Build order` line,
|
||||
then name each `BLOCKED` story with its blocker — read from its story
|
||||
file, usually a `BLOCKED:` note — and each other story with its status
|
||||
as written. Recommend one step: what the first blocker needs, or else
|
||||
finishing the first `Draft` or unstatused story and setting its Status
|
||||
to `Ready`.
|
||||
- **At `standard` or `full`**, report: "No sprint files found. Start a sprint
|
||||
with `/sprint-plan new`." Then stop.
|
||||
|
||||
Read the sprint file in full. Extract:
|
||||
- Sprint number and goal
|
||||
@@ -65,7 +101,7 @@ found — burndown assessment skipped."
|
||||
**First: check for `production/sprint-status.yaml`.**
|
||||
|
||||
If it exists, read it directly — it is the authoritative source of truth.
|
||||
Extract status for each story from the `status` field. No markdown scanning needed.
|
||||
Extract each story's `status`, and its `priority`, `owner` and `blocker` when set — they fill the status table's columns. No markdown scanning needed.
|
||||
Use its `sprint`, `goal`, `start`, `end` fields instead of re-parsing the sprint plan.
|
||||
|
||||
**If `sprint-status.yaml` does not exist** (legacy sprint or first-time setup),
|
||||
@@ -116,8 +152,9 @@ section (see Phase 5 output format).
|
||||
|
||||
**Stale story escalation**: If any IN PROGRESS story is flagged STALE (no progress in 4+ days), the burndown verdict
|
||||
is upgraded to at least **At Risk** — even if the completion percentage is within the normal
|
||||
On Track window. Record this escalation reason: "At Risk — [N] story(ies) with no progress in
|
||||
[N] days."
|
||||
On Track window. Record this escalation reason: "At Risk — [S] stale story(ies): [title]
|
||||
([D] days)[, …]" — [S] is how many stories are STALE, and each is named with its own [D],
|
||||
the days since its own Last Updated date (not the oldest age, not an average).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -51,6 +51,13 @@ Check:
|
||||
- **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/`.
|
||||
- **Still wired to the template repo?** Read `.git/config` if it is a file. If its
|
||||
`[remote "origin"]` url contains `donchitos/claude-code-game-studios`, compared
|
||||
case-insensitively, the user cloned the template and `origin` still points at
|
||||
it — so `git push` and `gh pr create` target the CCGS repo, not their game. A
|
||||
fork (the same repo name under another owner) is the user's own and does not
|
||||
count. Note it: it is reported on every path, the returning user's included.
|
||||
Read only; never run git.
|
||||
|
||||
Store these findings internally to validate the user's self-assessment and tailor recommendations.
|
||||
|
||||
@@ -58,7 +65,7 @@ Store these findings internally to validate the user's self-assessment and tailo
|
||||
|
||||
## Phase 2: Ask Where the User Is
|
||||
|
||||
This is the first thing the user sees. Use `AskUserQuestion` with these exact options so the user can click rather than type:
|
||||
This is the first thing the user sees — unless Phase 1 found a returning user (engine configured, and a concept or brief present): then ask nothing here and answer as the **User is returning** edge case below. Otherwise, use `AskUserQuestion` with these exact options so the user can click rather than type:
|
||||
|
||||
- **Prompt**: "Welcome to Claude Code Game Studios! Before I suggest anything, I'd like to understand where you're starting from. Where are you at with your game idea right now?"
|
||||
- **Options**:
|
||||
@@ -111,8 +118,8 @@ The user needs creative exploration before anything else.
|
||||
2. Acknowledge the concept, then use `AskUserQuestion` to offer two paths:
|
||||
- **Prompt**: "How would you like to proceed?"
|
||||
- **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
|
||||
- `Formalize it first` — Run `/brainstorm [concept]` to write it down: a one-page brief at `rigor: minimal` (the default), a full concept document above it
|
||||
- `Jump straight in` — Go to `/setup-engine` now and write the design down afterward
|
||||
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
|
||||
@@ -134,19 +141,23 @@ The user needs creative exploration before anything else.
|
||||
1. `/project-stage-detect` — understand what phase and what's missing entirely
|
||||
2. `/adopt` — audit whether existing artifacts are in the right internal format
|
||||
|
||||
3. Show the recommended path for D2:
|
||||
- `/project-stage-detect` — phase detection + existence gaps
|
||||
- `/adopt` — format compliance audit + migration plan
|
||||
- `/setup-engine` — if engine not configured
|
||||
- `/design-system retrofit [path]` — fill missing GDD sections
|
||||
- `/architecture-decision retrofit [path]` — add missing ADR sections
|
||||
- `/architecture-review` — bootstrap the TR requirement registry
|
||||
- `/gate-check` — validate readiness for next phase
|
||||
3. For D2, name the **immediate next step only** — `/project-stage-detect`.
|
||||
The rest of the D2 path depends on rigor, which Phase 3d has not asked yet,
|
||||
so Phase 4 prints it. Say: "I'll lay out the full path once I know how much
|
||||
process you want — two quick questions away."
|
||||
|
||||
---
|
||||
|
||||
## Phase 3c: Write Initial Stage
|
||||
|
||||
**Ask before the `project.yaml` write:** "May I write `project.stage: [stage]`
|
||||
to `project.yaml` (and the legacy mirror `production/stage.txt`)?" Take `[stage]` from the Stage mapping below; say the file
|
||||
will be created when there is none, and that the Phase 3d and 3e answers will go
|
||||
there too when those questions are still to be asked. That one approval covers
|
||||
this write and the Phase 3d and 3e writes. If the user declines, write neither
|
||||
file, keep the stage and those answers for this run only, and say they were not
|
||||
saved.
|
||||
|
||||
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]`.
|
||||
@@ -163,7 +174,7 @@ In `project.yaml`, ensure a `project:` block exists with `stage: [value]`.
|
||||
schema_version: 1
|
||||
|
||||
framework:
|
||||
version: 1.1.1
|
||||
version: 1.1.2
|
||||
last_upgraded: <YYYY-MM-DD>
|
||||
|
||||
project:
|
||||
@@ -174,7 +185,10 @@ In `project.yaml`, ensure a `project:` block exists with `stage: [value]`.
|
||||
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.
|
||||
question. The other knobs `modes.rigor`
|
||||
fronts — `modes.workflow`, `docs.density`, `qa.level`,
|
||||
`modes.story_granularity`, `team.size` — are never written by `/start`
|
||||
either, here or in Phase 3d: each would pin its value over the rigor expansion.
|
||||
|
||||
Then also write the same single-line stage name to `production/stage.txt` (no trailing newline) so legacy tooling still works.
|
||||
|
||||
@@ -184,7 +198,8 @@ 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 these stage anchors.
|
||||
`production/stage.txt` is covered by the same ask: it is a one-line legacy mirror
|
||||
of the stage approved for `project.yaml`, kept for hooks that have not migrated.
|
||||
|
||||
Say: "I've set `project.stage` to `[stage]` (and updated `production/stage.txt`) — this anchors your status line and stage detection."
|
||||
|
||||
@@ -213,8 +228,9 @@ archetype presets in `.claude/docs/settings-guidance.md § 2–3`:
|
||||
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).
|
||||
- If nothing in the description points either way, recommend `minimal`, the
|
||||
documented default, and add: "`/settings` raises it once the game shows it
|
||||
needs more."
|
||||
|
||||
Then use `AskUserQuestion`. Order the options so the **recommended** archetype is
|
||||
first and append ` (Recommended)` to its label (per the AskUserQuestion
|
||||
@@ -223,7 +239,7 @@ 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.
|
||||
- `Jam / prototype / first game` — Short docs, coarse stories, tests optional — the screenshot of what you built is not. **~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.
|
||||
|
||||
@@ -235,6 +251,8 @@ 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.
|
||||
If the Phase 3c `project.yaml` write was declined, do not write this one either —
|
||||
carry the answer forward and say it was not saved.
|
||||
|
||||
Then say: "Set `modes.rigor` to `[choice]`. That drives six settings —
|
||||
`modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`,
|
||||
@@ -271,7 +289,8 @@ Value mapping: `Collaborative` → `collaborative`, `Guided (recommended)` →
|
||||
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.
|
||||
legacy mirror file** for this setting. If the Phase 3c `project.yaml` write was
|
||||
declined, do not write this one either — say it was not saved.
|
||||
|
||||
Then say: "Set `modes.automation` to `[choice]`. See
|
||||
`.claude/docs/automation-modes.md` for exactly what each mode asks vs. proceeds
|
||||
@@ -283,8 +302,8 @@ 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).
|
||||
already set, so seeding it would suppress its own question (the same collision
|
||||
Phase 3c's rigor note describes for the other knobs).
|
||||
|
||||
---
|
||||
|
||||
@@ -293,9 +312,9 @@ and Y.6 guard for the other knobs).
|
||||
**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.)
|
||||
`minimal` (its documented default) rather than skipping the path. (Paths A/B/C;
|
||||
a D2 user gets the retrofit path below instead, and a D1 user was given their
|
||||
steps 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
|
||||
@@ -304,13 +323,13 @@ it — nothing is locked, it simply is not demanded up front. And if one system
|
||||
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:**
|
||||
**If `minimal` (default) — 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:**
|
||||
**If `standard` — 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`
|
||||
@@ -320,6 +339,19 @@ deserves more care, raise just that one with
|
||||
- Everything in `standard`, plus `/vertical-slice` and `/playtest-report` (×1+)
|
||||
in Pre-Production, and `/design-review` after each GDD.
|
||||
|
||||
**For a Path D2 user, print this retrofit path in place of the three above.**
|
||||
At `minimal` it stops after `/adopt` and `/setup-engine`: the minimal path needs
|
||||
only `design/game-brief.md` (`/brainstorm`) and stories (`/create-stories`), so
|
||||
do not send the user through the GDD, ADR and registry retrofit below. At
|
||||
`standard` and `full`:
|
||||
- `/project-stage-detect` — phase detection + existence gaps
|
||||
- `/adopt` — format compliance audit + migration plan
|
||||
- `/setup-engine` — if engine not configured
|
||||
- `/design-system retrofit [path]` — fill missing GDD sections
|
||||
- `/architecture-decision retrofit [path]` — add missing ADR sections
|
||||
- `/architecture-review` — bootstrap the TR requirement registry
|
||||
- `/gate-check` — validate readiness for next phase
|
||||
|
||||
> **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
|
||||
@@ -333,6 +365,14 @@ multi-year commercial project, or `full` for a weekend jam — apply the "mismat
|
||||
trigger in `.claude/docs/settings-guidance.md § 4`: say so once, in one sentence,
|
||||
and offer `/settings` to change it. Do not re-ask.
|
||||
|
||||
If Phase 1 found `origin` pointing at the template repo, add once, after the path:
|
||||
"Your clone's `origin` still points at the Claude Code Game Studios repo, so a push
|
||||
or pull request would go there, not to your game. When you're ready:
|
||||
`git remote rename origin template` (the name `UPGRADING.md` uses to pull updates),
|
||||
then `git remote add origin <your repo URL>`. After the rename, `template` already
|
||||
exists, so skip `UPGRADING.md`'s own one-time `git remote add template` step —
|
||||
it would fail with `remote template already exists`." Suggest it; do not run it.
|
||||
|
||||
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]?"
|
||||
@@ -354,7 +394,7 @@ Verdict: **COMPLETE** — user oriented and handed off to next step.
|
||||
|
||||
- **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 `[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 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 `/help` — it reads your tier and progress and names the next step — or just tell me what you'd like to work on." If Phase 1 found `origin` pointing at the template repo, add the Phase 4 note about renaming `origin` here too.
|
||||
- **User doesn't fit any option**: Let them describe their situation in their own words and adapt.
|
||||
|
||||
---
|
||||
|
||||
@@ -8,12 +8,19 @@ Closes the implementation loop for a single story by verifying every acceptance
|
||||
### 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 |
|
||||
| `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 closes a story it verified — `/dev-story`'s dependency option `[C]` also sets `Complete`, on a dependency the user says is done, after an ask), `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 |
|
||||
| `production/session-state/active.md` | Active story path (used when no argument given) | No — `<!-- CHECKPOINT -->` block overwritten |
|
||||
|
||||
> **Tier.** The TR registry, GDD-section and ADR rows are `standard`/`full` inputs.
|
||||
> At `workflow: minimal` the story traces to the brief, and Phase 4 runs the
|
||||
> acceptance-criteria check only (no GDD/ADR traceability); the manifest,
|
||||
> hardcoded-value and scope checks still run. At `qa.level: minimal` no test
|
||||
> evidence is required (SKILL.md Phase 3) — but the Visual/UI run-and-observe
|
||||
> screenshot is not waived.
|
||||
|
||||
### Test Evidence Files (presence checked, not pre-required to exist — absence triggers gate)
|
||||
| Story Type | Expected Location |
|
||||
@@ -21,14 +28,14 @@ Closes the implementation loop for a single story by verifying every acceptance
|
||||
| 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 |
|
||||
| UI | A retained screenshot of each screen touched, under `production/qa/evidence/` — no evidence doc or sign-off required |
|
||||
| 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
|
||||
- For Visual/Feel and UI stories, a retained screenshot must exist under `production/qa/evidence/` before a COMPLETE verdict is possible, and for Visual/Feel an evidence doc with every sign-off `[x] Approved` too (UI needs the screenshot only, as `coding-standards.md` says) — 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
|
||||
@@ -48,17 +55,17 @@ verdict set at all, so a reader had nothing to branch on.
|
||||
| `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) |
|
||||
| `production/session-state/active.md` | `<!-- CHECKPOINT -->` block: current task (story path and verdict), next step (the next story), blocker, tech debt count | block overwritten, never appended (file created from `.claude/docs/templates/session-state.md` if absent) |
|
||||
|
||||
### Output Guarantees
|
||||
- `Status: Complete` is written only when verdict is COMPLETE or COMPLETE WITH NOTES and the user explicitly approves
|
||||
- `Status: Complete` is written only after the user explicitly approves: on a COMPLETE or COMPLETE WITH NOTES verdict, or — on a BLOCKED or NOT ASSESSED verdict — only when the user explicitly asks to close anyway (the Phase 7 override, which always prompts as a `scope_changes` decision), with the override risk recorded in `## Completion Notes`
|
||||
- `## 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
|
||||
- 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 under the code root — `src/`, `Assets/` or `Source/` by engine (Grep only) — and test files under the engine's test root (existence checked with Glob; never run or edited)
|
||||
- MODIFIES: the story `.md` file (status + completion notes), `production/sprint-status.yaml` (if exists), `production/session-state/active.md` (the `<!-- CHECKPOINT -->` block, overwritten), `docs/tech-debt-register.md` (append a row, and update its `Last updated:` and `Total items:` lines, only with user approval)
|
||||
- Does NOT write to the code root or the test root under any circumstances
|
||||
|
||||
## Hard Constraints (Never Violate)
|
||||
- Never sets `Status: Complete` without explicit user approval ("May I update the story file?")
|
||||
@@ -66,7 +73,7 @@ verdict set at all, so a reader had nothing to branch on.
|
||||
- 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 proceeds to Phase 7 (file update) on its own when the verdict is BLOCKED or NOT ASSESSED — list blockers and offer help resolving them; Phase 7 is reached only on the user's explicit request to close anyway, and then always prompts (`scope_changes`), even in autonomous mode
|
||||
- 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
|
||||
@@ -75,7 +82,7 @@ verdict set at all, so a reader had nothing to branch on.
|
||||
- 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 assumes: Visual/Feel and UI stories that are Complete have a retained screenshot in `production/qa/evidence/`, and Visual/Feel ones a signed-off evidence doc as well — 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
|
||||
|
||||
@@ -52,9 +52,11 @@ does not change any completion check.
|
||||
`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
|
||||
At `minimal`, no *test* evidence is required → skip the Logic, Integration and
|
||||
Config/Data evidence checks (Phase 3), the >50%-untested traceability escalation,
|
||||
and the Phase 4b QA gate; the acceptance-criteria verification still runs, and so
|
||||
do the Visual/Feel and UI screenshot gate and the `Run result:` check for other
|
||||
story types — the look is never waived. 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
|
||||
@@ -117,7 +119,10 @@ three methods:
|
||||
### Automatic verification (run without asking)
|
||||
|
||||
- **File existence check**: `Glob` for files the story said would be created.
|
||||
- **Test pass check**: if a test file path is mentioned, run it via `Bash`.
|
||||
- **Test file check**: if a test file path is mentioned, confirm the file exists
|
||||
with `Glob`. Do not run it — this skill establishes existence only (see the
|
||||
note under Test Evidence Requirement), so report "test file present", never
|
||||
"test passes".
|
||||
- **No hardcoded values check**: `Grep` for numeric literals in gameplay code
|
||||
paths that should be in config files.
|
||||
- **No hardcoded strings check**: `Grep` for player-facing strings in the **code root** (resolve per `.claude/docs/code-root-resolution.md`). **If the code root is unresolved, report `NOT ASSESSED — code root unresolved` rather than zero hits.**
|
||||
@@ -128,6 +133,8 @@ three methods:
|
||||
|
||||
- Criteria about subjective qualities ("feels responsive", "animations play correctly")
|
||||
- Criteria about gameplay behaviour ("player takes damage when...", "enemy responds to...")
|
||||
— these are asked, never marked verified from reading the code: the code says
|
||||
what should happen, not what the build does
|
||||
- Performance criteria ("completes within Xms") — ask if profiled or accept as assumed
|
||||
|
||||
Batch up to 4 manual verification questions into a single `AskUserQuestion` call:
|
||||
@@ -137,6 +144,12 @@ question: "Does [criterion]?"
|
||||
options: "Yes — passes", "No — fails", "Not tested yet"
|
||||
```
|
||||
|
||||
Map each answer: `Yes — passes` → confirmed; `No — fails` → FAILS;
|
||||
`Not tested yet` → not evaluated — UNTESTED in the traceability table below, and
|
||||
the verdict is NOT ASSESSED (Phase 6) until someone checks it. If the criterion
|
||||
genuinely needs a full-build playtest, mark it `DEFERRED — requires playtest
|
||||
session` instead.
|
||||
|
||||
### Unverifiable (flag without blocking)
|
||||
|
||||
- Criteria that require a full game build to test (end-to-end gameplay scenarios)
|
||||
@@ -161,7 +174,10 @@ For each acceptance criterion in the story:
|
||||
`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.
|
||||
reads as >50% untested and false-escalates. "Shows it" means you opened
|
||||
the image with `Read` and saw it; a checkpoint's `Run result: OBSERVED —
|
||||
<text>` is `/dev-story`'s description, to quote as such, not yours.
|
||||
**Never describe an image you have not opened.**
|
||||
|
||||
2. Produce a traceability table:
|
||||
|
||||
@@ -190,11 +206,12 @@ For each acceptance criterion in the story:
|
||||
|
||||
### Test Evidence Requirement
|
||||
|
||||
**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.
|
||||
**First apply `qa.level` (resolved in Phase 1).** At `minimal`, no *test*
|
||||
evidence is required — skip the Logic, Integration and Config/Data checks below.
|
||||
But still run the Visual/Feel and UI check and the `Run result:` check: the look
|
||||
is not waived at minimal, only the tests are. At `standard`, require evidence
|
||||
for the story's own type. At `full`, require evidence for every story type. The
|
||||
`testing.strict` resolution below applies to every check that runs.
|
||||
|
||||
Based on the Story Type extracted in Phase 2, check for required evidence.
|
||||
|
||||
@@ -277,13 +294,23 @@ required path. Use `Glob` to check that exact path first, then search
|
||||
playtest record referencing this story.
|
||||
If none found: flag at the resolved gate level (same rule as Logic).
|
||||
|
||||
**For Visual/Feel and UI stories**: glob `production/qa/evidence/` for 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."
|
||||
**For Visual/Feel and UI stories**: glob `production/qa/evidence/` for a
|
||||
retained screenshot for this story (`*.png`, `*.jpg`, `*.gif`) and for an
|
||||
evidence doc referencing it. What closes the story follows the evidence table
|
||||
in `.claude/docs/coding-standards.md`, the same at every `qa.level`:
|
||||
- A **UI** story is satisfied by the retained screenshot of each screen it
|
||||
touched. No evidence doc or sign-off is required; note one if it exists.
|
||||
- A **Visual/Feel** story also needs the sign-off: the evidence doc
|
||||
(`production/qa/evidence/[story-slug]-evidence.md`, from the test-evidence
|
||||
template) with every sign-off row `[x] Approved`.
|
||||
|
||||
Flag at the resolved gate level:
|
||||
- No screenshot: "No visual evidence found. Capture a screenshot of each screen or effect this story touched and save it under `production/qa/evidence/` before final closure." For Visual/Feel add: "then record sign-off in `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template."
|
||||
- An evidence doc but no screenshot retained beside it: "Evidence doc found at `[path]` but no screenshot is retained. A described check is an assertion, not evidence — capture the screen and save the image under `production/qa/evidence/` before final closure."
|
||||
- Visual/Feel with a screenshot but no evidence doc: "Screenshot found but no sign-off is recorded. Create `production/qa/evidence/[story-slug]-evidence.md` using the test-evidence template and obtain sign-off before final closure."
|
||||
- Visual/Feel sign-off rows still unchecked — grep the doc for `| .* | .* | .* | \[ \] Approved`: "Evidence file found at `[path]` but [N] sign-off(s) are still pending (shown as `[ ] Approved` in the sign-off table). Obtain required sign-offs before final closure. Note: for solo developers, all roles may be signed off by the same person."
|
||||
|
||||
Otherwise note "Retained screenshot found[, sign-offs complete] — gate satisfied."
|
||||
|
||||
The retained image **is** the `Run result: OBSERVED` from `/dev-story` Phase 6
|
||||
step 4 (`.claude/docs/run-and-observe.md`); its absence means the run was
|
||||
@@ -291,14 +318,20 @@ step 4 (`.claude/docs/run-and-observe.md`); its absence means the run was
|
||||
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
|
||||
`/dev-story` checkpoint in `production/session-state/active.md` — only when its
|
||||
**Current task** names this story; a later `/dev-story` overwrites it — or from
|
||||
the story's `## Completion Notes`. `OBSERVED` with a retained path: note
|
||||
it. `N/A — <reason>`: accept only if the reason names why nothing is
|
||||
observable — "it's a Logic story" is not a reason. `NOT VERIFIED — <reason>`
|
||||
on a story whose acceptance criteria name anything on screen: flag at the
|
||||
resolved gate level for the story's type. No `Run result:` line at all: flag
|
||||
as ADVISORY — "the implementation summary carries no run result; confirm the
|
||||
build was launched and looked at before closure."
|
||||
build was launched and looked at before closure." The exception: when the
|
||||
acceptance criteria name something on screen and no retained image for this
|
||||
story is under `production/qa/evidence/`, nothing observed the story — a user's
|
||||
`Yes — passes` to such a criterion is an assertion, not the retained observation
|
||||
`.claude/docs/run-and-observe.md` requires — so flag it at the resolved gate
|
||||
level for the story's type, as for `NOT VERIFIED`.
|
||||
|
||||
**For Config/Data stories**: check for any `production/qa/smoke-*.md` file.
|
||||
If none: flag at the resolved gate level — "No smoke check report found. Run `/smoke-check`."
|
||||
@@ -386,6 +419,10 @@ Pass:
|
||||
- Test file paths found during Phase 3 (exact paths, or "none found")
|
||||
- The story's `## QA Test Cases` section (the pre-written test specs from story creation)
|
||||
- The story's `## Acceptance Criteria` list
|
||||
- The GDD acceptance criteria and Edge Cases for the story's system, from the GDD
|
||||
section read in Phase 2 — or "no GDD for this system" when there is none (at
|
||||
`workflow: minimal` the story's own criteria are the spec); an absent GDD is
|
||||
information for the gate, not a missing input
|
||||
|
||||
The qa-lead reviews whether the tests actually cover what was specified — not just whether files exist.
|
||||
|
||||
@@ -393,6 +430,7 @@ Apply the verdict:
|
||||
- **ADEQUATE** → proceed to Phase 5
|
||||
- **GAPS** → flag as **ADVISORY**: "QA lead identified coverage gaps: [list]. Story can complete but gaps should be addressed in a follow-up story."
|
||||
- **INADEQUATE** → flag as **BLOCKING**: "QA lead: critical logic is untested. Verdict cannot be COMPLETE until coverage improves. Specific gaps: [list]."
|
||||
- **NOT ASSESSED [missing input]** → no judgement was made; never read it as ADEQUATE. Name the missing input — supply it and re-run the gate, or carry it to Phase 6, where it keeps the verdict at best NOT ASSESSED.
|
||||
|
||||
Skip this phase for Config/Data stories (no code tests required).
|
||||
|
||||
@@ -418,6 +456,7 @@ Pass: implementation file paths, story file path, relevant GDD section, governin
|
||||
Present the verdict to the user. If CONCERNS, surface them via `AskUserQuestion`:
|
||||
- Options: `Revise flagged issues` / `Accept and proceed` / `Discuss further`
|
||||
If REJECT, do not proceed to Phase 6 verdict until the issues are resolved.
|
||||
If NOT ASSESSED, name the input the gate said was missing and never treat it as APPROVE: supply it and re-run the gate, or carry it to Phase 6, where it keeps the verdict at best NOT ASSESSED.
|
||||
|
||||
If the story has no implementation files yet (verdict is being run before coding is done), skip this phase and note: "LP-CODE-REVIEW skipped — no implementation files found. Run after implementation is complete."
|
||||
|
||||
@@ -433,7 +472,7 @@ Before updating any files, present the full report:
|
||||
**Date**: [today]
|
||||
|
||||
### Acceptance Criteria: [X/Y passing]
|
||||
- [x] [Criterion 1] — auto-verified (test passes)
|
||||
- [x] [Criterion 1] — auto-verified (test file present)
|
||||
- [x] [Criterion 2] — confirmed
|
||||
- [ ] [Criterion 3] — FAILS: [reason]
|
||||
- [?] [Criterion 4] — DEFERRED: requires playtest
|
||||
@@ -447,7 +486,7 @@ Before updating any files, present the full report:
|
||||
|
||||
### Test Evidence
|
||||
**Story Type**: [Logic | Integration | Visual/Feel | UI | Config/Data | Not declared]
|
||||
**Required evidence**: [unit test file | integration test or playtest | screenshot + sign-off | walkthrough doc | smoke check pass]
|
||||
**Required evidence**: [unit test file | integration test or playtest | screenshot + sign-off | screenshot of each screen touched | smoke check pass]
|
||||
**Evidence found**: [YES — `[path]` | NO — BLOCKING | NO — ADVISORY]
|
||||
|
||||
### Deviations
|
||||
@@ -464,7 +503,9 @@ Before updating any files, present the full report:
|
||||
|
||||
**Verdict definitions:**
|
||||
- **COMPLETE**: all criteria pass, no blocking deviations
|
||||
- **COMPLETE WITH NOTES**: all criteria pass, advisory deviations documented
|
||||
- **COMPLETE WITH NOTES**: every criterion passes or is `DEFERRED` (Phase 3 —
|
||||
evaluable, awaiting a playtest), with advisory deviations or deferred criteria
|
||||
documented — list each DEFERRED criterion so it is not lost
|
||||
- **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
|
||||
@@ -492,6 +533,11 @@ Emit it when any of:
|
||||
> 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.
|
||||
- A criterion the user answered **`Not tested yet`** (Phase 3) — it could be
|
||||
checked, but nobody has. Name it and what would settle it: launch the build,
|
||||
check it, then re-run `/story-done`.
|
||||
- QL-TEST-COVERAGE or LP-CODE-REVIEW returned **NOT ASSESSED** and the input it
|
||||
named was not supplied.
|
||||
- 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
|
||||
@@ -570,11 +616,11 @@ If "Fix first": stop here and list what the user flagged. Do not write any files
|
||||
**Code Review**: [Pending / Complete / Skipped]
|
||||
```
|
||||
|
||||
4. If the user chose "Close and log tech debt": append each advisory deviation to `docs/tech-debt-register.md` in this format:
|
||||
4. If the user chose "Close and log tech debt": append each advisory deviation to `docs/tech-debt-register.md` as one row of `/tech-debt`'s register table — the format under "Debt Register Format" in `.claude/skills/tech-debt/SKILL.md` — so `/tech-debt report` can date it from its `Added` column:
|
||||
```
|
||||
- **[date]** ([story title]): [deviation description] — tracked from [story file path]
|
||||
| TD-[next free NNN] | [category] | [deviation description] — from [story file path] | [files] | [S/M/L/XL] | [Low/Med/High/Critical] | — | Open | [YYYY-MM-DD] | Backlog |
|
||||
```
|
||||
Create the file with a `# Tech Debt Register` heading if it does not exist.
|
||||
Category is one of `/tech-debt`'s six (Architecture, Code Quality, Test, Documentation, Dependency, Performance); Effort and Impact are your estimate from the deviation; Priority stays `—` until `/tech-debt prioritize` scores it; `Added` is today. If the file does not exist, create it with that format's heading, `Last updated:` and `Total items:` lines and table header; if it exists, update those two lines (and add the table header first if the file has none yet).
|
||||
|
||||
5. **Update `production/sprint-status.yaml`** (if it exists):
|
||||
- Find the entry matching this story's file path or ID
|
||||
@@ -586,7 +632,7 @@ If "Fix first": stop here and list what the user flagged. Do not write any files
|
||||
|
||||
```
|
||||
Suggested commit:
|
||||
git add [code-root and tests/ files changed during implementation] [story-file-path]
|
||||
git add [code-root and test-root files changed during implementation] [story-file-path]
|
||||
git commit -m "feat: [story title] ([TR-ID])"
|
||||
```
|
||||
|
||||
@@ -594,23 +640,86 @@ The `validate-commit.sh` hook will verify design doc references and check for ha
|
||||
|
||||
### Session State Update
|
||||
|
||||
After updating the story file, silently append to
|
||||
`production/session-state/active.md`:
|
||||
After updating the story file, silently update the checkpoint in
|
||||
`production/session-state/active.md` — **overwrite the `<!-- CHECKPOINT -->` …
|
||||
`<!-- /CHECKPOINT -->` block, never append** (schema:
|
||||
`.claude/docs/templates/session-state.md`). `session-start.sh` shows exactly
|
||||
that block when the next session opens. Fill **Next step** from Phase 8, so it
|
||||
names the same next story the user is shown:
|
||||
|
||||
## Session Extract — /story-done [date]
|
||||
- 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"]
|
||||
<!-- CHECKPOINT -->
|
||||
**Updated:** [date]
|
||||
**Branch:** `[current git branch]`
|
||||
**Current task:** /story-done — [story file path] closed: [COMPLETE / COMPLETE WITH NOTES / NOT ASSESSED / BLOCKED]
|
||||
**Next step:** [/story-done [next story path] for an In Review story, else /dev-story [next story path] — or "build order done: play the build" — or the blocker to clear when every unfinished story is blocked — or the sprint's next step]
|
||||
**Blocked on:** [nothing, or what blocked this verdict]
|
||||
**Files in progress:** none
|
||||
**Open questions:** [tech debt logged: N items, or none]
|
||||
<!-- /CHECKPOINT -->
|
||||
|
||||
If `active.md` does not exist, create it with this block as the initial content.
|
||||
If `active.md` does not exist, create it from the template. If it exists with no
|
||||
markers (a file from before the schema), insert the template's STATUS and
|
||||
CHECKPOINT blocks at the top and leave the rest untouched.
|
||||
Confirm in conversation: "Session state updated."
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Surface the Next Story
|
||||
|
||||
After completion, help the developer keep momentum:
|
||||
After completion, help the developer keep momentum. Which branch applies depends
|
||||
on whether there is a sprint at all.
|
||||
|
||||
### No sprint plan — the minimal path
|
||||
|
||||
**At `workflow: minimal`, or whenever `production/sprints/` holds no sprint
|
||||
plan, there is no sprint to close out.** The brief's build order is the plan and
|
||||
the story files carry it:
|
||||
|
||||
1. Run `bash .claude/scripts/story-status.sh`, from the project root — after
|
||||
Phase 7's story-file write, so this story's new status is in it. It prints
|
||||
every unfinished story under `production/epics/`, whatever Status form its
|
||||
file uses, **already in the route's order** — `IN_REVIEW`, then `IN_PROGRESS`, then `TODO` (a `Ready` or
|
||||
`Not Started` story) in build (file-name) order — then `BLOCKED`, `OTHER`,
|
||||
`NO_STATUS` and the `COMPLETE` count. It is the list `/help` and
|
||||
`/sprint-status` read, so the three name the same next story; do not re-read
|
||||
or re-rank the story files.
|
||||
2. The first `In Review` story is next (recommend `/story-done [path]` for it —
|
||||
its work is written, and closing it first keeps finished work from piling
|
||||
up); else the first `In Progress` one; else the first `Ready` or
|
||||
`Not Started` one — the story on the script's first `IN_REVIEW`,
|
||||
`IN_PROGRESS` or `TODO` line. Name any `Blocked` story with its blocker and pass
|
||||
over it.
|
||||
|
||||
```
|
||||
### Next Up
|
||||
**[Story NNN: title]** — [1-line description]
|
||||
Run `/story-done [path]` to close it (In Review) — else `/dev-story [path]` to implement it.
|
||||
```
|
||||
|
||||
At `minimal` recommend `/dev-story` directly (or `/story-done` for an In Review
|
||||
story) — `/story-readiness` is not on
|
||||
the minimal path (engine → brief → stories → code), and it checks fields the
|
||||
minimal story template does not carry. With no sprint plan at a higher tier,
|
||||
add the `/story-readiness [path]` line from the sprint branch below.
|
||||
3. **No unfinished story — only `COMPLETE N of N`** → every story is built —
|
||||
at `minimal`, the brief's build order is done. Say so, and offer three ways on:
|
||||
- play the build and note what feels wrong
|
||||
- add the next stories from the brief with `/create-stories`
|
||||
- if the game has outgrown a one-page brief, `/settings` to raise `modes.rigor`
|
||||
4. **No `IN_REVIEW`, `IN_PROGRESS` or `TODO` line, but `BLOCKED`, `OTHER` or
|
||||
`NO_STATUS` lines remain** — every unfinished story is `Blocked`, `Draft`, or
|
||||
has no status line. There is no Next Up, and the
|
||||
build order is **not** done — never say it is. Name each such story with its
|
||||
blocker (or `Draft` / `no status`), and suggest clearing the blocker first. For
|
||||
a Draft or unstatused story: at `minimal`, finish it and set its Status to
|
||||
`Ready`; at a higher tier, `/story-readiness [path]` shows what it still needs.
|
||||
|
||||
**Never print the Sprint Close-Out Sequence on this branch** (`/smoke-check
|
||||
sprint`, `/team-qa sprint`, `/retrospective`, `/gate-check`, `/sprint-plan new`)
|
||||
— it closes a sprint, and there is none. Each of those still runs if the user
|
||||
asks for it; do not present them as required.
|
||||
|
||||
### With a sprint plan
|
||||
|
||||
1. Read the current sprint plan from `production/sprints/`.
|
||||
2. Find stories that are:
|
||||
@@ -678,6 +787,7 @@ behavior. The BLOCKED-override close (Phase 7) always prompts regardless of mode
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
- Run `/story-readiness [next-story-path]` to validate the next story before starting implementation
|
||||
- If all Must Have stories are complete: run `/smoke-check sprint` → `/team-qa sprint` → `/gate-check`
|
||||
- At `minimal`: run `/dev-story [next-story-path]` (`/story-done` for an In Review one); when every story is Complete, play the build, then `/create-stories` for more or `/settings` to raise `modes.rigor`
|
||||
- With a sprint plan: run `/story-readiness [next-story-path]` to validate the next story before starting implementation
|
||||
- If a sprint plan exists and all its Must Have stories are complete: run `/smoke-check sprint` → `/team-qa sprint` → `/gate-check`
|
||||
- If tech debt was logged: track it via `/tech-debt` to keep the register current
|
||||
|
||||
@@ -16,6 +16,14 @@ implementation and produces a READY / NEEDS WORK / BLOCKED / NOT ASSESSED verdic
|
||||
| `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 |
|
||||
|
||||
> **Tier.** The manifest, TR registry, ADR and systems-index rows are
|
||||
> `standard`/`full` inputs. At `workflow: minimal` the skill is not on the path
|
||||
> (`/dev-story` follows `/create-stories` directly); run anyway, it checks
|
||||
> acceptance criteria and scope only and treats Architecture Completeness as N/A
|
||||
> except the referenced-ADR rule: an ADR the story references that is missing,
|
||||
> `Proposed`, `Deprecated` or `Superseded` BLOCKS at every tier (SKILL.md, the tier note above Design
|
||||
> Completeness).
|
||||
|
||||
### 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
|
||||
@@ -30,7 +38,7 @@ None. This skill is strictly read-only and produces no file modifications under
|
||||
- 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
|
||||
- For `sprint` scope: a sprint-level escalation warning is prepended if any Must Have story is not READY (NEEDS WORK, BLOCKED or NOT ASSESSED)
|
||||
- The skill offers to draft missing sections in conversation but never uses Write or Edit tools
|
||||
|
||||
## Immutability Rules
|
||||
@@ -40,7 +48,7 @@ None. This skill is strictly read-only and produces no file modifications under
|
||||
## 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 its governing ADR has `Status: Proposed`, `Deprecated` or `Superseded`, at any tier
|
||||
- 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
|
||||
@@ -51,7 +59,7 @@ None. This skill is strictly read-only and produces no file modifications under
|
||||
|
||||
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
|
||||
- If verdict is NEEDS WORK, BLOCKED or NOT ASSESSED: `/dev-story` must not be run until the story is corrected (or, for NOT ASSESSED, made readable) and re-validated — a story nobody could evaluate has not been shown ready
|
||||
- `/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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: story-readiness
|
||||
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']"
|
||||
argument-hint: "[story-file-path or 'all' or 'sprint'] [--review full|lean|solo]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, AskUserQuestion, Agent, Bash(bash "*/.claude/skills/story-readiness/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
@@ -25,12 +25,14 @@ and asks whether the user wants help filling gaps.
|
||||
**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.
|
||||
> finding about the story — a Proposed ADR, an ADR file it names that does not
|
||||
> exist, 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, a referenced ADR exists but has no readable
|
||||
> `## Status` (malformed), or a referenced 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
|
||||
> blocker instead of the unreadable file.
|
||||
> `READY` must never be reachable for a story that was not actually evaluated.
|
||||
>
|
||||
> **Precedence — first matching rule wins**, in this order: **BLOCKED**, then
|
||||
@@ -68,13 +70,16 @@ sets which checklist sections block — see the note in Section 3.
|
||||
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`.
|
||||
coverage target. Distinct axis from `workflow`. **UI and Visual/Feel stories are
|
||||
the exception at `minimal`:** their retained screenshot is required at every
|
||||
`qa.level`, so for them the item is still validated — the tests are waived, the
|
||||
look is not.
|
||||
|
||||
---
|
||||
|
||||
## 1. Parse Arguments
|
||||
|
||||
**Scope:** `$ARGUMENTS[0]` (blank = ask user via AskUserQuestion)
|
||||
**Scope:** `$ARGUMENTS` with any `--review <mode>` pair removed (blank = ask user via AskUserQuestion). What remains is one value — a path may contain spaces.
|
||||
|
||||
- **Specific path** (e.g., `/story-readiness production/epics/combat/story-001-basic-attack.md`):
|
||||
validate that single story file.
|
||||
@@ -107,7 +112,7 @@ Report the scope before proceeding: "Validating [N] story files."
|
||||
>
|
||||
> 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;
|
||||
> unreadable or unparseable file, an ADR with no readable Status). 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.
|
||||
>
|
||||
@@ -141,7 +146,7 @@ Before checking any stories, load reference documents once (not per-story):
|
||||
```
|
||||
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`"
|
||||
"no Accepted ADRs"** — report "run `/architecture-decision retrofit [file]`"
|
||||
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 /
|
||||
@@ -159,20 +164,24 @@ items pass or are explicitly marked N/A with a stated reason.
|
||||
> - **`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.
|
||||
> In **Architecture Completeness**, an ADR the story references that is missing,
|
||||
> `Proposed`, `Deprecated` or `Superseded` BLOCKS at every tier (see that section's note). Beyond that, only
|
||||
> a **critical (Foundation-layer) ADR** that is missing or `Proposed` BLOCKS; 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.
|
||||
> Completeness and Scope Clarity. Treat the rest of **Architecture
|
||||
> Completeness** as N/A — except that a referenced ADR that is missing,
|
||||
> `Proposed`, `Deprecated` or `Superseded` still BLOCKS. Do not flag a missing ADR, TR-ID or manifest reference.
|
||||
|
||||
### Design Completeness
|
||||
|
||||
- [ ] **GDD requirement referenced**: The story includes a `design/gdd/` path
|
||||
and quotes or links a specific requirement, acceptance criterion, or rule from
|
||||
that GDD — not just the GDD filename. A link to the document without tracing
|
||||
to a specific requirement does not pass.
|
||||
to a specific requirement does not pass. At `minimal`,
|
||||
`design/game-brief.md` — the MVP feature and the Player goal & fail state the
|
||||
story traces to — stands in for the GDD.
|
||||
- [ ] **Requirement is self-contained**: The acceptance criteria in the story
|
||||
are understandable without opening the GDD. A developer should not need to
|
||||
read a separate document to understand what DONE means.
|
||||
@@ -191,9 +200,22 @@ 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.
|
||||
> The `BLOCKED` / fail outcomes in this section are the `full` baseline, with one
|
||||
> rule that holds at every tier: **an ADR the story references that is missing,
|
||||
> `Proposed`, `Deprecated` or `Superseded` BLOCKS**. `/dev-story` stops on it at `full`, `standard` and
|
||||
> `minimal` alike, so a READY here would send the story straight into a stop.
|
||||
> Beyond that, apply the tier note above: at `standard` the other items are
|
||||
> advisory unless they concern a **critical** ADR; at `minimal` the rest of this
|
||||
> section is N/A.
|
||||
>
|
||||
> At `standard`, an advisory item — a stale manifest version, missing engine notes
|
||||
> or manifest rules for a non-critical ADR — is written up like a NEEDS WORK item,
|
||||
> under Gaps with its `Fix:` line, but it never BLOCKS and does not by itself
|
||||
> downgrade READY. An ADR is critical
|
||||
> when the `**Layer**` row of its `## Engine Compatibility` table says
|
||||
> Foundation, or when that row is missing — when in doubt, treat it as critical
|
||||
> (`.claude/docs/workflow-modes.md`). Read the rows once, alongside the Section 2
|
||||
> status scan: `Grep pattern="\*\*Layer\*\*" glob="docs/architecture/adr-*.md" output_mode="content"`.
|
||||
|
||||
- [ ] **ADR referenced or N/A stated**: The story references at least one ADR,
|
||||
OR explicitly states "No ADR applies" with a brief reason.
|
||||
@@ -205,6 +227,12 @@ items pass or are explicitly marked N/A with a stated reason.
|
||||
and the story's implementation guidance could be wrong.
|
||||
Fix: `BLOCKED: ADR-NNNN is Proposed — wait for acceptance before implementing.`
|
||||
- If the ADR file does not exist → **BLOCKED**: referenced ADR is missing.
|
||||
- If `Status:` is `Deprecated` or `Superseded by ADR-XXXX` → **BLOCKED**: the
|
||||
decision no longer stands.
|
||||
Fix: `BLOCKED: ADR-NNNN is [status] — point the story at [successor] (edit its ADR field — /create-stories never rewrites an existing story).`
|
||||
- If the ADR file exists but has no readable `## Status` (the Section 2 scan
|
||||
found none in it) → **NOT ASSESSED** for this check: its status is unknown,
|
||||
not failed. Name the file and route to `/architecture-decision retrofit [file]`.
|
||||
- Auto-pass if story has an explicit "No ADR applies" N/A note.
|
||||
- [ ] **TR-ID is valid and active**: If the story contains a `TR-[system]-NNN`
|
||||
reference, look it up in the TR registry loaded in Section 2.
|
||||
@@ -284,10 +312,14 @@ 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** *(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).
|
||||
- [ ] **Test evidence requirement is clear** *(auto-pass at `qa.level: minimal` for
|
||||
Logic, Integration and Config/Data stories — no test evidence is required for
|
||||
them; never for UI or Visual/Feel, whose retained screenshot is required at every
|
||||
`qa.level`)*: 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; for UI, where the retained screenshot of each screen touched
|
||||
goes under `production/qa/evidence/`; for Visual/Feel, that plus the sign-off doc
|
||||
`production/qa/evidence/[story-slug]-evidence.md`).
|
||||
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`,
|
||||
@@ -308,21 +340,30 @@ items pass or are explicitly marked N/A with a stated reason.
|
||||
|
||||
## 4. Verdict Assignment
|
||||
|
||||
Assign one of three verdicts per story:
|
||||
Assign one of four verdicts per story, first match wins in the order BLOCKED,
|
||||
NEEDS WORK, NOT ASSESSED, READY (the precedence stated at the top):
|
||||
|
||||
**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.
|
||||
`testing.strict`, or one the Section 3 workflow tier note makes advisory).
|
||||
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
|
||||
exist and are not DRAFT. The story can be fixed before assignment.
|
||||
|
||||
**BLOCKED** — One or more dependency stories are missing or in DRAFT state,
|
||||
OR a governing ADR is `Proposed`, `Deprecated` or `Superseded`, or its file is missing (Section 3's ADR check),
|
||||
OR a critical design question (flagged UNRESOLVED in a criterion or rule) has
|
||||
no owner. The story cannot be assigned until the blocker is resolved. Note:
|
||||
a story that is BLOCKED may also have NEEDS WORK items — list both.
|
||||
|
||||
**NOT ASSESSED** — the story could not be evaluated at all (unreadable or
|
||||
unparseable file, a referenced ADR with no readable `## Status`, or a referenced
|
||||
design document that cannot be located, so the checks cannot run — a referenced
|
||||
ADR file that does not exist is BLOCKED instead). Name what could not be read.
|
||||
Never READY.
|
||||
|
||||
---
|
||||
|
||||
## 5. Output Format
|
||||
@@ -332,10 +373,15 @@ a story that is BLOCKED may also have NEEDS WORK items — list both.
|
||||
```
|
||||
## Story Readiness: [story title]
|
||||
File: [path]
|
||||
Verdict: [READY / NEEDS WORK / BLOCKED]
|
||||
Verdict: [READY / NEEDS WORK / BLOCKED / NOT ASSESSED]
|
||||
|
||||
### Passing Checks (N/[total])
|
||||
[list passing items briefly]
|
||||
Design Completeness: [passing items, briefly]
|
||||
Architecture Completeness: [passing items — or "N/A — [reason]", e.g. "N/A at `minimal` (referenced-ADR check applied)"]
|
||||
Scope Clarity: [passing items]
|
||||
Open Questions: [passing items]
|
||||
Asset References: [passing items — or "no asset references"]
|
||||
Definition of Done: [passing items]
|
||||
|
||||
### Gaps
|
||||
- [Checklist item]: [exact description of what is missing or wrong]
|
||||
@@ -345,14 +391,19 @@ Verdict: [READY / NEEDS WORK / BLOCKED]
|
||||
- [What is blocking]: [story ID or design question that must resolve first]
|
||||
```
|
||||
|
||||
Name all six check groups under Passing Checks every time. A group with nothing
|
||||
passing says so ("none — see Gaps"), so a reader can see that each group was
|
||||
evaluated rather than skipped.
|
||||
|
||||
### Multiple story aggregate output
|
||||
|
||||
```
|
||||
## Story Readiness Summary — [scope] — [date]
|
||||
|
||||
Ready: [N] stories
|
||||
Needs Work: [N] stories
|
||||
Blocked: [N] stories
|
||||
Ready: [N] stories
|
||||
Needs Work: [N] stories
|
||||
Blocked: [N] stories
|
||||
Not Assessed: [N] stories
|
||||
|
||||
### Ready Stories
|
||||
- [story title] ([path])
|
||||
@@ -370,8 +421,8 @@ Blocked: [N] stories
|
||||
|
||||
### Sprint escalation
|
||||
|
||||
If the scope is `sprint` and any Must Have stories are NEEDS WORK or BLOCKED,
|
||||
add a prominent warning at the top of the output:
|
||||
If the scope is `sprint` and any Must Have stories are NEEDS WORK, BLOCKED or
|
||||
NOT ASSESSED, add a prominent warning at the top of the output:
|
||||
|
||||
```
|
||||
WARNING: [N] Must Have stories are not implementation-ready.
|
||||
@@ -398,7 +449,7 @@ in conversation. Do not use Write or Edit tools — the user (or
|
||||
- If a story file does not exist at all: "This story file is missing entirely.
|
||||
Run `/create-epics [layer]` then `/create-stories [epic-slug]` to generate stories from the GDD and ADR."
|
||||
- If a story has no GDD reference and the work appears small: "This story has
|
||||
no GDD reference. If the change is small (under ~4 hours), run
|
||||
no GDD reference. If the change is small (under about one week of implementation), run
|
||||
`/quick-design [description]` to create a Quick Design Spec, then reference
|
||||
that spec in the story."
|
||||
- If a story's scope has grown beyond its original sizing: "This story appears
|
||||
@@ -443,17 +494,20 @@ Apply the review mode resolved in Phase 0 before spawning QL-STORY-READY:
|
||||
|
||||
Spawn `qa-lead` via `Agent` using gate **QL-STORY-READY** (`.claude/docs/director-gates/ql-story-ready.md`).
|
||||
|
||||
Pass the following context:
|
||||
- Story title
|
||||
- Acceptance criteria list (all items from the story's acceptance criteria section)
|
||||
Pass the context that gate lists, plus this skill's findings:
|
||||
- Story file path
|
||||
- Story type (Logic / Integration / Visual/Feel / UI / Config/Data) — the gate's prompt branches on it
|
||||
- Acceptance criteria list (verbatim, all items)
|
||||
- The GDD requirement the story covers (TR-ID and text)
|
||||
- Dependency status (all dependencies listed and their current state: exist / DRAFT / missing)
|
||||
- Overall verdict (READY / NEEDS WORK / BLOCKED) from Phase 4
|
||||
- Overall verdict (READY / NEEDS WORK / BLOCKED / NOT ASSESSED) from Phase 4
|
||||
|
||||
Handle the verdict per standard rules in `director-gates.md`:
|
||||
- **ADEQUATE** → story is cleared. Proceed to close.
|
||||
- **GAPS [list]** → surface the specific gaps to the user via `AskUserQuestion`:
|
||||
options: `Update story with suggested gaps` / `Accept and proceed anyway` / `Discuss further`.
|
||||
- **INADEQUATE** → surface the specific gaps; ask user whether to update the story or proceed anyway.
|
||||
- **INADEQUATE** → the gate says the story must be revised before sprint inclusion, so it is not READY: the verdict becomes at least NEEDS WORK (a BLOCKED one stays BLOCKED). List the gaps and restate the final verdict line, then ask whether to update the story or proceed anyway. If the user proceeds anyway, the verdict stays NEEDS WORK (BLOCKED if it was BLOCKED) and the output states the override — "proceeding despite QL-STORY-READY: INADEQUATE (user override)" — never a silent READY.
|
||||
- **NOT ASSESSED [missing input]** → the gate made no judgement; never read it as ADEQUATE. Name the missing input and offer to supply it and re-run the gate; otherwise a READY verdict becomes NOT ASSESSED (BLOCKED and NEEDS WORK stand).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ model: sonnet
|
||||
---
|
||||
|
||||
If no argument is provided, output usage guidance and exit without spawning any agents:
|
||||
> Usage: `/team-audio [feature or area]` — specify the feature or area to design audio for (e.g., `combat`, `main menu`, `forest biome`, `boss encounter`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
> Usage: `/team-audio [feature or area to design audio for] [--review full|lean|solo]` — specify the feature or area to design audio for (e.g., `combat`, `main menu`, `forest biome`, `boss encounter`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
|
||||
When this skill is invoked with an argument, orchestrate the audio team through a structured pipeline.
|
||||
|
||||
@@ -29,19 +29,19 @@ in `autonomous` mode it runs end to end, recording each step outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
- **`small`**: + `audio-director` + `technical-artist` + `gameplay-programmer`.
|
||||
- **`studio`**: + `accessibility-specialist` + the primary engine specialist (the full pipeline as documented).
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -56,10 +56,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -73,7 +73,14 @@ enforced.**
|
||||
|
||||
2. **Gather context**:
|
||||
- Read relevant design docs in `design/gdd/` for the feature
|
||||
- Read the sound bible at `design/gdd/sound-bible.md` if it exists
|
||||
- Read the sound bible at `design/audio/sound-bible.md` if it exists. If only
|
||||
`design/gdd/sound-bible.md` exists (where earlier versions put it), read that
|
||||
and recommend moving it to `design/audio/` — in `design/gdd/` the GDD checks
|
||||
count every file as a system GDD. If neither exists,
|
||||
say so in one line — "No sound bible at `design/audio/sound-bible.md`; audio
|
||||
direction starts from the GDDs alone" — so the gap is visible in the output.
|
||||
Carry the gap forward: say so in the audio-director's Step 1 brief, and
|
||||
recommend creating a sound bible in Next Steps.
|
||||
- Read existing audio asset lists in `assets/audio/`
|
||||
- Read any existing sound design docs for this area
|
||||
|
||||
@@ -82,13 +89,31 @@ enforced.**
|
||||
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: accessibility-specialist` — Visual fallbacks and subtitles for critical audio, auditory sensitivity
|
||||
- `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
|
||||
|
||||
**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.
|
||||
**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. **Implementation files are the exception:** an agent writing code or assets first returns the files it will create or change, and its return contract names them only after you have asked once for the set and the user said yes (File Write Protocol) — that answer, not the bounded exception, authorises those writes.
|
||||
|
||||
**Substitute a real path for `[path]`.** Working artifacts go under
|
||||
`production/audio/[feature]/`, where `[feature]` is the argument as a slug —
|
||||
lowercase, spaces → hyphens (`boss encounter` → `boss-encounter`), the same slug
|
||||
the "Save to" step uses. One file per agent, so parallel steps never share one:
|
||||
|
||||
| Step / agent | Writes to |
|
||||
|---|---|
|
||||
| 1 audio-director | `production/audio/[feature]/direction.md` |
|
||||
| 2 sound-designer | `production/audio/[feature]/sfx-spec.md` |
|
||||
| 2 accessibility-specialist | `production/audio/[feature]/accessibility.md` |
|
||||
| 3 technical-artist | `production/audio/[feature]/integration-plan.md` |
|
||||
| 3 engine specialist | `production/audio/[feature]/engine-notes.md` |
|
||||
| 4 gameplay-programmer | the code root and the engine's test root — the files the one implementation ask lists (File Write Protocol), outside the bounded exception |
|
||||
|
||||
These are working drafts; the durable record is the audio design document you
|
||||
compile from them.
|
||||
|
||||
> **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.
|
||||
|
||||
@@ -117,6 +142,12 @@ Spawn the `accessibility-specialist` agent in parallel to:
|
||||
- Review the audio event list for any that could cause issues for players with auditory sensitivities (high-frequency alerts, sudden loud events)
|
||||
- Output: audio accessibility requirements list integrated into the audio event spec
|
||||
|
||||
A gameplay-critical audio event with no visual cue or subtitle is labelled
|
||||
**BLOCKING** in the report, not advisory. Step 3 does not start until the user
|
||||
resolves it or explicitly accepts it at the Step 2 decision point, which offers
|
||||
the fix (a visual cue, subtitle or haptic fallback) and a stop; an accepted gap
|
||||
is listed among the open questions in the summary.
|
||||
|
||||
### Step 3: Technical Implementation (parallel)
|
||||
Spawn the `technical-artist` agent to:
|
||||
- Design the audio middleware integration (Wwise/FMOD/native)
|
||||
@@ -131,7 +162,7 @@ Spawn the **primary engine specialist** in parallel (`<engine>-specialist` deriv
|
||||
- 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. **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.
|
||||
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:
|
||||
@@ -154,32 +185,46 @@ Spawn the `gameplay-programmer` agent to:
|
||||
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).
|
||||
Note: If `design/audio/` does not exist, writing the file creates it.
|
||||
|
||||
6. **Output a summary** with: audio event count, estimated asset count,
|
||||
implementation tasks, and any open questions between team members.
|
||||
|
||||
Verdict: **COMPLETE** — audio design document produced and team pipeline finished.
|
||||
|
||||
If the engine validation was skipped (no engine configured), the verdict says
|
||||
so — never a plain COMPLETE:
|
||||
|
||||
Verdict: **COMPLETE — engine validation NOT ASSESSED ([reason])** — audio design document produced; the engine specialist never reviewed the integration plan.
|
||||
|
||||
If the pipeline stops because a dependency is unresolved (e.g., critical accessibility gap or missing GDD not resolved by the user):
|
||||
|
||||
Verdict: **BLOCKED** — [reason]
|
||||
|
||||
## File Write Protocol
|
||||
|
||||
All file writes (audio design docs, SFX specs, implementation files) are 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.
|
||||
Per-agent artifacts (SFX specs, integration plans) 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. **Implementation files** — gameplay-programmer's audio
|
||||
integration code, anything under the code root or `assets/` — are outside those
|
||||
bounds: the agent returns the files it will create or change, you ask once for the
|
||||
set, and it writes after a yes. The **one exception is the final compiled audio design
|
||||
document**: the orchestrator already holds every input, so it compiles and writes
|
||||
`design/audio/audio-[feature].md` itself after its own "May I write …?" prompt
|
||||
(the "Save to" step above).
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Review the audio design doc with the audio-director before implementation begins.
|
||||
- Use `/dev-story` to implement the audio manager and event system once the design is approved.
|
||||
- Run `/asset-audit` after audio assets are created to verify naming and format compliance.
|
||||
- If there was no sound bible, create one before the next audio pass: ask the
|
||||
`audio-director` agent to draft `design/audio/sound-bible.md` from
|
||||
`.claude/docs/templates/sound-bible.md`, starting from this run's Step 1
|
||||
direction (it asks before writing under `design/`).
|
||||
|
||||
## Error Recovery Protocol
|
||||
|
||||
@@ -193,10 +238,10 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, Task
|
||||
model: sonnet
|
||||
---
|
||||
**Argument check:** If no combat feature description is provided, output:
|
||||
> "Usage: `/team-combat [combat feature description]` — Provide a description of the combat feature to design and implement (e.g., `melee parry system`, `ranged weapon spread`)."
|
||||
> "Usage: `/team-combat [combat feature description] [--review full|lean|solo]` — Provide a description of the combat feature to design and implement (e.g., `melee parry system`, `ranged weapon spread`)."
|
||||
Then stop immediately without spawning any subagents or reading any files.
|
||||
|
||||
When this skill is invoked with a valid argument, orchestrate the combat team through a structured pipeline.
|
||||
@@ -24,24 +24,31 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
|
||||
## Phase 0: Resolve Config
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size,workflow`
|
||||
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
|
||||
`workflow` sizes the Phase 1 design document the way `/design-system` does:
|
||||
`## Summary` plus all 8 sections at `full`; at `standard`, Overview, Detailed
|
||||
Design, Edge Cases, Dependencies and Acceptance Criteria, plus Formulas whenever
|
||||
the mechanic defines numeric rules (a combat mechanic almost always does); at
|
||||
`minimal` the game brief is the design record and the GDD is optional — draft
|
||||
those five sections and tell the user it is optional at this workflow level.
|
||||
|
||||
**`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.
|
||||
- **`studio`**: full pipeline + engine sub-specialists + an adversarial review pass. *Engine sub-specialists*: the primary engine specialist's prompt says it may hand parts of its review to the sub-specialists its `tools:` grant names (for example `ue-gas-specialist` for abilities); below `studio` it answers alone. *Adversarial review pass*: Phase 5's qa-tester is told "your job is not to confirm this works — find how it breaks", and the report says the pass ran.
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -56,10 +63,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -90,18 +97,20 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
|
||||
**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.
|
||||
**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. **Implementation files are the exception:** an agent writing code or assets first returns the files it will create or change, and its return contract names them only after you have asked once for the set and the user said yes (File Write Protocol) — that answer, not the bounded exception, authorises those writes.
|
||||
|
||||
**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 |
|
||||
| 1 game-designer (draft) | `production/combat/[feature]-gdd-draft.md` | this skill — you write the final `design/gdd/[feature].md` (Phase 1) |
|
||||
| 2 gameplay-programmer | `docs/architecture/[feature]-sketch.md` | see note below |
|
||||
| 2 engine specialist | `docs/architecture/[feature]-engine-notes.md` | see note below |
|
||||
| 3 gameplay-programmer, ai-programmer, technical-artist | the code root and `assets/` — the files the Phase 3 approval lists | outside the bounded exception: asked once for the set (File Write Protocol) |
|
||||
| 3 sound-designer | `production/combat/[feature]-audio-events.md` | this skill |
|
||||
| 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 |
|
||||
| 5 qa-tester (bugs) | `production/qa/bugs/BUG-[NNNN].md` | `/team-qa` Phase 5 |
|
||||
|
||||
Phase 6 is a spoken status report, not an artifact — no path, and none needed.
|
||||
|
||||
@@ -123,8 +132,15 @@ Launch independent agents in parallel where the pipeline allows it (e.g., Phase
|
||||
|
||||
### Phase 1: Design
|
||||
Delegate to **game-designer**:
|
||||
- Create or update the design document in `design/gdd/` covering: mechanic overview, player fantasy, detailed rules, formulas with variable definitions, edge cases, dependencies, tuning knobs with safe ranges, and acceptance criteria
|
||||
- Output: completed design document
|
||||
- Create or update the design document for `design/gdd/[feature].md` from `.claude/docs/templates/game-design-document.md`, with `## Summary` and the sections `workflow` requires (Phase 0) — at `full`: mechanic overview, player fantasy, detailed rules, formulas with variable definitions, edge cases, dependencies, tuning knobs with safe ranges, and acceptance criteria
|
||||
- Output: completed design document, drafted to `production/combat/[feature]-gdd-draft.md`
|
||||
|
||||
`design/` is outside the bounded write exception above, so the game-designer
|
||||
drafts and **you** write the GDD — the pattern `/team-level` and
|
||||
`/team-narrative` use. At the Phase 1 decision point, present the draft and ask
|
||||
via `AskUserQuestion`: "May I write the design document to
|
||||
`design/gdd/[feature].md`?" Write it on approval; nothing is written under
|
||||
`design/` before that answer.
|
||||
|
||||
### Phase 2: Architecture
|
||||
Delegate to **gameplay-programmer** (with **ai-programmer** if AI is involved):
|
||||
@@ -139,6 +155,8 @@ Then spawn the **primary engine specialist** to validate the proposed architectu
|
||||
- Any proposed APIs that are deprecated or changed in the pinned engine version?
|
||||
- Output: engine architecture notes — incorporate into the architecture before Phase 3 begins
|
||||
|
||||
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.
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "Architecture sketch complete. Approve to proceed with parallel implementation."
|
||||
- Options:
|
||||
@@ -157,13 +175,19 @@ Delegate in parallel:
|
||||
- **gameplay-programmer**: Implement core combat mechanic code
|
||||
- **ai-programmer**: Implement AI behaviors (if the feature involves NPC reactions)
|
||||
- **technical-artist**: Create VFX and shader effects
|
||||
- **sound-designer**: Define audio event list and mixing notes
|
||||
- **sound-designer**: Define audio event list and mixing notes, drafted to `production/combat/[feature]-audio-events.md`
|
||||
|
||||
The code, VFX and shader work is outside the bounded write exception: each of
|
||||
those agents first returns the files it will create or change, you ask once for
|
||||
the whole set, and they write only after a yes (File Write Protocol).
|
||||
|
||||
### Phase 4: Integration
|
||||
- Wire together gameplay code, AI, VFX, and audio
|
||||
- Ensure all tuning knobs are exposed and data-driven
|
||||
- Verify the feature works with existing combat systems
|
||||
|
||||
**Gate**: Use `AskUserQuestion` to present the integration result and confirm before proceeding to Phase 5.
|
||||
|
||||
### Phase 5: Validation
|
||||
Delegate to **qa-tester**:
|
||||
- Write test cases from the acceptance criteria
|
||||
@@ -188,30 +212,50 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
## File Write Protocol
|
||||
|
||||
All file writes (design documents, implementation files, test cases) are
|
||||
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.
|
||||
All file writes (design drafts, implementation files, test cases) are
|
||||
delegated to sub-agents spawned via `Agent`, under two rules:
|
||||
|
||||
- **Drafts, sketches and QA artifacts** — the path table's destinations under
|
||||
`production/`, `docs/` or `tests/` — 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, and the phase is gated by an
|
||||
`AskUserQuestion`. The sub-agent writes them without a per-write prompt.
|
||||
- **Implementation files** — Phase 3's code, VFX and shader files, and any
|
||||
Phase 4 integration edits, under the code root and `assets/` — are outside
|
||||
that exception, as the agents' own files say. Each implementing agent first
|
||||
returns the files it will create or change with a one-line summary each; ask
|
||||
once for the whole set ("May I have [agents] write these [N] files?") and have
|
||||
them write only after a yes. An edit to an existing file is always on that
|
||||
list, never implied by the pre-Phase 3 gate.
|
||||
|
||||
The **one exception is the design document**: the orchestrator writes
|
||||
`design/gdd/[feature].md` itself, from the game-designer's draft, after its own
|
||||
"May I write …?" prompt (Phase 1). It writes no other file.
|
||||
|
||||
## Output
|
||||
|
||||
A summary report covering: design completion status, implementation status per team member, test results, and any open issues.
|
||||
|
||||
Verdict: **COMPLETE** — combat feature designed, implemented, and validated.
|
||||
Verdict: **BLOCKED** — one or more phases could not complete; partial report produced with unresolved items listed.
|
||||
|
||||
If the engine validation was skipped (Phase 2, no engine configured), the verdict
|
||||
says so — never a plain COMPLETE:
|
||||
|
||||
Verdict: **COMPLETE — engine validation NOT ASSESSED ([reason])** — combat feature designed, implemented, and validated; the engine specialist never reviewed the architecture.
|
||||
|
||||
Verdict: **NEEDS WORK** — every phase ran, but Phase 5 validation left failures or open bugs unresolved; the report lists each with its owner.
|
||||
|
||||
Verdict: **BLOCKED** — one or more phases could not complete, or an agent was skipped (`.claude/docs/error-recovery-protocol.md` step 5); partial report produced with unresolved items listed.
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, Task
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
If no argument is provided, output usage guidance and exit without spawning any agents or reading any design files:
|
||||
> Usage: `/team-level [level name or area to design] [--review full|lean|solo]` — specify the level or area to design (e.g., `forest temple`, `tutorial village`, `final boss arena`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
|
||||
When this skill is invoked:
|
||||
|
||||
**Decision Points:** At each step transition, use `AskUserQuestion` to present
|
||||
@@ -26,19 +29,19 @@ in `autonomous` mode it runs end to end, recording each step outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
- **`individual`** (default): `level-designer` only. Other agents consulted via the level-designer, not spawned separately.
|
||||
- **`small`**: + `systems-designer` + `art-director` + `qa-tester`.
|
||||
- **`studio`**: + `narrative-director` + `world-builder` + `accessibility-specialist` (the full pipeline as documented).
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -53,10 +56,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -69,7 +72,8 @@ enforced.**
|
||||
`forest dungeon`, `hub town`, `final boss arena`).
|
||||
|
||||
2. **Gather context**:
|
||||
- Read the game concept at `design/gdd/game-concept.md`
|
||||
- Read the game concept at `design/gdd/game-concept.md` — or `design/game-brief.md`,
|
||||
the one-page brief that replaces it at `rigor: minimal` — if either exists
|
||||
- Read game pillars at `design/gdd/game-pillars.md`
|
||||
- Read existing level docs in `design/levels/`
|
||||
- Read relevant narrative docs in `design/narrative/`
|
||||
@@ -90,6 +94,24 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
|
||||
**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]`.** Working artifacts go under
|
||||
`production/levels/[level-name]/`, slugged as in the "Save to" step below. One
|
||||
file per agent, so the parallel steps never share one:
|
||||
|
||||
| Step / agent | Writes to |
|
||||
|---|---|
|
||||
| 1 narrative-director | `production/levels/[level-name]/narrative.md` |
|
||||
| 1 world-builder | `production/levels/[level-name]/lore.md` |
|
||||
| 1 art-director | `production/levels/[level-name]/visual-direction.md` |
|
||||
| 2 level-designer | `production/levels/[level-name]/layout.md` |
|
||||
| 3 systems-designer | `production/levels/[level-name]/systems.md` |
|
||||
| 4 art-director | `production/levels/[level-name]/production-concepts.md` |
|
||||
| 4 accessibility-specialist | `production/levels/[level-name]/accessibility.md` |
|
||||
| 5 qa-tester | `production/qa/test-cases/[level-name]-cases.md` — test cases, edge cases, playtest checklist, acceptance criteria |
|
||||
|
||||
These are working drafts; the durable record is the level design document you
|
||||
compile from them (`design/levels/[level-name].md`).
|
||||
|
||||
> **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:
|
||||
@@ -199,6 +221,9 @@ into the level-design template format, ask the user directly via
|
||||
`design/levels/[level-name].md`?" On approval, write it.
|
||||
|
||||
5. **Save to** `design/levels/[level-name].md` after that approval.
|
||||
`[level-name]` is the argument as a slug — lowercase, spaces → hyphens
|
||||
(`forest dungeon` → `forest-dungeon.md`) — and `[area-name]` in the adjacent
|
||||
area check is slugged the same way.
|
||||
|
||||
6. **Output a summary** with: area overview, encounter count, estimated asset
|
||||
list, narrative beats, any cross-team dependencies or open questions, open
|
||||
@@ -219,7 +244,7 @@ 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.
|
||||
Verdict: **BLOCKED** — one or more agents blocked, or an agent was skipped (`.claude/docs/error-recovery-protocol.md` step 5); partial report produced with unresolved items listed.
|
||||
|
||||
## Next Steps
|
||||
|
||||
@@ -239,10 +264,10 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, Task
|
||||
model: sonnet
|
||||
---
|
||||
**Argument check:** If no season name or event description is provided, output:
|
||||
> "Usage: `/team-live-ops [season name or event description]` — Provide the name or description of the season or live event to plan."
|
||||
> "Usage: `/team-live-ops [season name or event description] [--review full|lean|solo]` — Provide the name or description of the season or live event to plan."
|
||||
Then stop immediately without spawning any subagents or reading any files.
|
||||
|
||||
When this skill is invoked with a valid argument, orchestrate the live-ops team through a structured planning pipeline.
|
||||
@@ -29,19 +29,19 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
- **`small`**: + `analytics-engineer` + `community-manager`.
|
||||
- **`studio`**: + `writer` + `narrative-director` (the full pipeline as documented).
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -56,10 +56,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -70,7 +70,7 @@ enforced.**
|
||||
|
||||
## Team Composition
|
||||
- **live-ops-designer** — Season structure, event cadence, retention mechanics, battle pass
|
||||
- **economy-designer** — Live economy balance, store rotation, currency pricing, pity timers
|
||||
- **economy-designer** — Live economy balance, store rotation contents and prices (live-ops-designer sets its cadence), currency pricing, pity timers
|
||||
- **analytics-engineer** — Success metrics, A/B test design, event tracking, dashboard specs
|
||||
- **community-manager** — Player-facing announcements, event descriptions, seasonal messaging
|
||||
- **narrative-director** — Seasonal narrative theme, story arc, world event framing
|
||||
@@ -90,6 +90,24 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
|
||||
**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]`.** Working artifacts go under
|
||||
`production/live-ops/[season-slug]/`, where `[season-slug]` is the argument as a
|
||||
slug — lowercase, spaces → hyphens. One file per agent, so the parallel phases
|
||||
never share one:
|
||||
|
||||
| Phase / agent | Writes to |
|
||||
|---|---|
|
||||
| 1 live-ops-designer | `production/live-ops/[season-slug]/brief.md` |
|
||||
| 2 narrative-director | `production/live-ops/[season-slug]/narrative.md` |
|
||||
| 3 economy-designer | `production/live-ops/[season-slug]/economy.md` |
|
||||
| 4 analytics-engineer | `production/live-ops/[season-slug]/analytics.md` |
|
||||
| 5 narrative-director | `production/live-ops/[season-slug]/narrative-text.md` |
|
||||
| 5 writer | `production/live-ops/[season-slug]/copy.md` |
|
||||
| 6 community-manager | `production/live-ops/[season-slug]/comms.md` |
|
||||
|
||||
These are working drafts; the final documents under `design/live-ops/seasons/`
|
||||
are compiled from them (Output Documents).
|
||||
|
||||
> **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).
|
||||
@@ -112,11 +130,11 @@ Delegate to **narrative-director**:
|
||||
- Identify which existing lore threads this season can advance
|
||||
- Output: narrative framing document (theme, story hook, lore connections)
|
||||
|
||||
### Phase 3: Economy Design (parallel with Phase 2 if theme is clear)
|
||||
### Phase 3: Economy Design (parallel with Phase 4)
|
||||
Delegate to **economy-designer**:
|
||||
- Read the season brief and existing economy rules from `design/live-ops/economy-rules.md`
|
||||
- Design the reward track: free tier progression, premium tier value proposition
|
||||
- Plan the in-season economy: seasonal currency, store rotation, pricing
|
||||
- Plan the in-season economy: seasonal currency, store rotation contents, pricing
|
||||
- Define pity timer mechanics and bad-luck protection for any random elements
|
||||
- Verify no pay-to-win items in premium track
|
||||
- Output: economy design doc with reward tables, pricing, and currency flow
|
||||
@@ -130,7 +148,7 @@ Delegate to **analytics-engineer**:
|
||||
- Output: analytics plan with success criteria and instrumentation requirements
|
||||
|
||||
### Phase 5: Content Writing (parallel)
|
||||
Delegate in parallel:
|
||||
Start only after both Phase 3 and Phase 4 results are collected. Delegate in parallel:
|
||||
- **narrative-director** (if needed): Write any in-game narrative text (cutscene scripts, NPC dialogue, world event descriptions) for the season
|
||||
- **writer**: Write all player-facing text — event names, reward item descriptions, challenge objective text, seasonal flavor text
|
||||
- Both should read the narrative framing doc from Phase 2
|
||||
@@ -191,19 +209,20 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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 `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.
|
||||
Sub-agents write their working artifacts under `production/`, following 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 **final documents under `design/live-ops/`** — season design, analytics
|
||||
plan, communication calendar — are the exception: the orchestrator compiles and
|
||||
writes them itself after its own "May I write …?" prompt (Output Documents above).
|
||||
|
||||
## Output
|
||||
|
||||
@@ -216,3 +235,6 @@ Verdict: **COMPLETE** — season plan produced and handed off for production.
|
||||
- Run `/design-review` on the season design document for consistency validation.
|
||||
- Run `/sprint-plan` to schedule content creation work for the season.
|
||||
- Run `/team-release` when the season content is ready to deploy.
|
||||
- If the run ended **BLOCKED** on an ethics flag: revise the economy design against
|
||||
`design/live-ops/ethics-policy.md` and re-run `/team-live-ops`; the three steps
|
||||
above wait for a COMPLETE plan.
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, TaskCreate
|
||||
model: sonnet
|
||||
---
|
||||
If no argument is provided, output usage guidance and exit without spawning any agents:
|
||||
> Usage: `/team-narrative [narrative content description]` — describe the story content, scene, or narrative area to work on (e.g., `boss encounter cutscene`, `faction intro dialogue`, `tutorial narrative`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
> Usage: `/team-narrative [narrative content description] [--review full|lean|solo]` — describe the story content, scene, or narrative area to work on (e.g., `boss encounter cutscene`, `faction intro dialogue`, `tutorial narrative`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
|
||||
When this skill is invoked with an argument, orchestrate the narrative team through a structured pipeline.
|
||||
|
||||
@@ -28,19 +28,23 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
Phase 4's ND-CONSISTENCY is the exception in every mode: it is this pipeline's own
|
||||
review, not an optional director gate, so `review_mode` never skips it (`team.size`
|
||||
still decides who runs it — see Phase 4).
|
||||
|
||||
`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.
|
||||
- **`small`**: `narrative-director` + `writer`, plus `localization-lead` and `world-builder` when `review_mode` is `full` (at `lean` and `solo` they are consulted through the writer).
|
||||
- **`studio`**: all six Team Composition agents, whatever the `review_mode` (the full pipeline as documented).
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -55,10 +59,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -85,21 +89,27 @@ Use the `Agent` 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
|
||||
|
||||
**Read the canon first.** Before Phase 1, read the shared inputs that exist — the narrative bible or tone guide, the character and faction files under `design/narrative/`, and the world rules. Never tell an agent to invent canon: if none exists, say so and ask the user before any drafting.
|
||||
|
||||
**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:
|
||||
**Substitute a real path for `[path]`.** Agents write drafts under
|
||||
`production/narrative/[content-slug]/` — inside the bounded exception below. The
|
||||
finished documents belong in `design/narrative/`, which the exception does **not**
|
||||
cover, so **you** write those after one approval (see "Write the finals"):
|
||||
|
||||
| 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` |
|
||||
| Agent | Drafts to (`[path]`) | Final document (you write it) |
|
||||
|---|---|---|
|
||||
| narrative-director | `production/narrative/[content-slug]/brief.md` | `design/narrative/[content-slug]-brief.md` |
|
||||
| world-builder | `production/narrative/[content-slug]/lore-[topic].md` | `design/narrative/lore/[topic].md` |
|
||||
| writer | `production/narrative/[content-slug]/dialogue-[scene-slug].md` | `design/narrative/dialogue/[scene-slug].md` |
|
||||
| art-director | `production/narrative/[content-slug]/visual-direction.md` | `design/narrative/[content-slug]-visual-direction.md` |
|
||||
| level-designer | `production/narrative/[content-slug]/level-integration.md` | `design/narrative/[content-slug]-level-integration.md` |
|
||||
| localization-lead | `production/narrative/[content-slug]/i18n-review.md` | stays in `production/` — a review, not a design document |
|
||||
|
||||
> **The destination is not a free choice.** `design/narrative/` is read by
|
||||
> **The final 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.
|
||||
@@ -143,18 +153,41 @@ Delegate to **level-designer**:
|
||||
- Ensure pacing serves both gameplay and story
|
||||
|
||||
### Phase 4: Review and Consistency
|
||||
Delegate to **narrative-director**:
|
||||
- Review all dialogue against character voice profiles
|
||||
- Verify lore consistency across new and existing entries
|
||||
Spawn `narrative-director` via `Agent` using gate **ND-CONSISTENCY**
|
||||
(`.claude/docs/director-gates/nd-consistency.md`). This phase runs in every review
|
||||
mode — it is this pipeline's own review, not an optional director gate. Pass the
|
||||
context that gate lists (the Phase 2–3 draft paths, the narrative bible or tone
|
||||
guide, the world rules, the affected character and faction profiles) — named
|
||||
here, so do not read the gate file in this session — and add:
|
||||
- Confirm narrative pacing aligns with level design
|
||||
- Check that all mysteries have documented "true answers"
|
||||
|
||||
Act on the verdict: **APPROVE** → Phase 5. **CONCERNS** → show the listed
|
||||
inconsistencies and ask via `AskUserQuestion` whether to revise them (re-spawn the
|
||||
agent that owns each) or accept them. **REJECT** → do not start Phase 5; the
|
||||
contradictions are fixed first. **NOT ASSESSED [missing input]** → name the
|
||||
missing input, then supply it and re-run the gate, or carry
|
||||
`ND-CONSISTENCY: NOT ASSESSED — [input]` into the report's consistency review
|
||||
results; it is never read as APPROVE (`.claude/docs/director-gates.md`).
|
||||
|
||||
**At `team.size: individual`** narrative-director is not in the active set, so the
|
||||
gate is not spawned. The writer checks the drafts against the same criteria, and
|
||||
the output says so by name: "ND-CONSISTENCY not run — narrative-director is not
|
||||
active at `team.size: individual`; consistency self-checked by writer." A
|
||||
self-check is not the gate's verdict, and the report must not present it as one.
|
||||
|
||||
### Phase 5: Polish (parallel)
|
||||
Delegate in parallel:
|
||||
Delegate in parallel — issue every `Agent` call before waiting for any result:
|
||||
- **writer**: Final self-review — verify no line exceeds dialogue box constraints, all text uses string keys (not raw strings), placeholder variable names are consistent
|
||||
- **localization-lead**: Validate i18n compliance — check string key naming conventions, flag any strings with hardcoded formatting that won't survive translation, verify character limit headroom for languages that expand (German/Finnish typically +30%), confirm no cultural assumptions in text that would need locale-specific variants
|
||||
- **world-builder**: Finalize canon levels for all new lore entries
|
||||
|
||||
### Write the finals
|
||||
You hold every draft. List the final documents from the table above, then ask once
|
||||
via `AskUserQuestion` — "May I write these [N] narrative documents to
|
||||
`design/narrative/`?" — and write them on approval. The drafts under
|
||||
`production/narrative/[content-slug]/` stay as the working record.
|
||||
|
||||
## Error Recovery Protocol
|
||||
|
||||
**First, verify the artifact.** If the return contract named a path, check the
|
||||
@@ -167,30 +200,36 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
## File Write Protocol
|
||||
|
||||
All file writes (narrative docs, dialogue files, lore entries) are 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.
|
||||
Sub-agents write their drafts to the `production/narrative/[content-slug]/` paths
|
||||
you name, 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 documents under
|
||||
`design/narrative/`**: you hold every draft, so you write those yourself after
|
||||
the single "May I write …?" in "Write the finals".
|
||||
|
||||
## Output
|
||||
|
||||
A summary report covering: narrative brief status, lore entries created/updated, dialogue lines written, level narrative integration points, consistency review results, and any unresolved contradictions.
|
||||
A summary report covering: narrative brief status, lore entries created/updated, dialogue lines written, level narrative integration points, consistency review results, and any unresolved contradictions — including any localization issue the user chose to leave unfixed, by string key.
|
||||
|
||||
Verdict: **COMPLETE** — narrative content delivered.
|
||||
|
||||
If ND-CONSISTENCY answered NOT ASSESSED and that was carried into the report
|
||||
(Phase 4), the verdict says so — never a plain COMPLETE:
|
||||
|
||||
Verdict: **COMPLETE — consistency NOT ASSESSED ([input])** — narrative content delivered; the consistency review could not run for want of [input].
|
||||
|
||||
If the pipeline stops because a dependency is unresolved (e.g., lore contradiction or missing prerequisite not resolved by the user):
|
||||
|
||||
Verdict: **BLOCKED** — [reason]
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, Task
|
||||
model: sonnet
|
||||
---
|
||||
If no argument is provided, output usage guidance and exit without spawning any agents:
|
||||
> Usage: `/team-polish [feature or area]` — specify the feature or area to polish (e.g., `combat`, `main menu`, `inventory system`, `level-1`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
> Usage: `/team-polish [feature or area to polish] [--review full|lean|solo]` — specify the feature or area to polish (e.g., `combat`, `main menu`, `inventory system`, `level-1`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
|
||||
When this skill is invoked with an argument, orchestrate the polish team through a structured pipeline.
|
||||
|
||||
@@ -28,19 +28,19 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
- **`individual`** (default): `performance-analyst` + `technical-artist`. Other agents consulted via these two, not spawned separately. No programmer is active, so the optimisation list's programmer items are not implemented in this run — the report names the list as handed to `/dev-story` (Phase 2).
|
||||
- **`small`**: + `sound-designer` + `qa-tester` + `engine-programmer`, and `tools-programmer` when Phase 1 traces a cause to a content authoring tool (the full pipeline as documented).
|
||||
- **`studio`**: the `small` set, `engine-programmer` included, + an adversarial review pass: Phase 5's qa-tester is told "your job is not to confirm this holds — find how it breaks", and the report says the pass ran. This pipeline has no engine specialist to widen; engine-level work stays with `engine-programmer`.
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -55,10 +55,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -70,26 +70,26 @@ 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.
|
||||
|
||||
## Team Composition
|
||||
- **performance-analyst** — Profiling, optimization, memory analysis, frame budget
|
||||
- **engine-programmer** — Engine-level bottlenecks: rendering pipeline, memory, resource loading (invoke when performance-analyst identifies low-level root causes)
|
||||
- **performance-analyst** — Profiling, memory analysis, frame budget, and the optimisation list — it writes no game code
|
||||
- **engine-programmer** — Implements the optimisation list's engine-level items: rendering pipeline, memory, resource loading, hot paths (invoke when performance-analyst identifies low-level root causes)
|
||||
- **technical-artist** — VFX polish, shader optimization, visual quality
|
||||
- **sound-designer** — Audio polish, mixing, ambient layers, feedback sounds
|
||||
- **tools-programmer** — Content pipeline tool verification, editor tool stability, automation fixes (invoke when content authoring tools are involved in the polished area)
|
||||
- **tools-programmer** — Content pipeline tool verification, editor tool stability, automation fixes (Phase 2, when Phase 1 traces a cause to a content authoring tool)
|
||||
- **qa-tester** — Edge case testing, regression testing, soak testing
|
||||
|
||||
## How to Delegate
|
||||
|
||||
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: performance-analyst` — Profiling, memory analysis, the optimisation list
|
||||
- `subagent_type: engine-programmer` — Engine-level fixes from the optimisation list: rendering, memory, resource loading
|
||||
- `subagent_type: technical-artist` — VFX polish, shader optimization, visual quality
|
||||
- `subagent_type: sound-designer` — Audio polish, mixing, ambient layers
|
||||
- `subagent_type: tools-programmer` — Content pipeline and editor tool verification
|
||||
- `subagent_type: tools-programmer` — Content pipeline and editor tool fixes from the optimisation list
|
||||
- `subagent_type: qa-tester` — Edge case testing, regression testing, soak testing
|
||||
|
||||
**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.
|
||||
**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. **Implementation files are the exception:** an agent writing code or assets first returns the files it will create or change, and its return contract names them only after you have asked once for the set and the user said yes (File Write Protocol) — that answer, not the bounded exception, authorises those writes.
|
||||
|
||||
**Substitute a real path for `[path]` — this skill's destination is
|
||||
`production/polish/`.** Name it per agent, one file each:
|
||||
@@ -99,6 +99,7 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
| 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` |
|
||||
| tools-programmer | `production/polish/[area]-tool-fixes-[date].md` |
|
||||
| sound-designer | `production/polish/[area]-audio-notes-[date].md` |
|
||||
| qa-tester | `production/polish/[area]-verification-[date].md` |
|
||||
|
||||
@@ -126,20 +127,26 @@ Delegate to **performance-analyst**:
|
||||
- Identify performance bottlenecks and frame budget violations
|
||||
- Measure memory usage and check for leaks
|
||||
- Benchmark against target hardware specs
|
||||
- Output: performance report with prioritized optimization list
|
||||
- Output: performance report with the prioritized **optimisation list** — for each item, the change, its expected gain against the budget, and its owner (technical-artist for rendering-side changes, engine-programmer for engine systems and hot paths, tools-programmer for a content authoring tool, otherwise the programmer who owns the system)
|
||||
|
||||
### Phase 2: Optimization
|
||||
Delegate to **performance-analyst** (with relevant programmers as needed):
|
||||
- Fix performance hotspots identified in Phase 1
|
||||
- Optimize draw calls, reduce overdraw
|
||||
- Fix memory leaks and reduce allocation pressure
|
||||
- Verify optimizations don't change gameplay behavior
|
||||
- Output: optimized code with before/after metrics
|
||||
performance-analyst writes no game code ("recommend and assign", its agent file),
|
||||
so Phase 2 implements its Phase 1 list through the owners in the active set:
|
||||
- **engine-programmer** — spawned only when Phase 1 identified engine-level root causes (rendering pipeline, resource loading, memory allocator, hot paths in core loops): implement those items, fix allocation pressure, verify gameplay behavior is unchanged. Output: engine-level fixes with before/after metrics and profiler validation
|
||||
- **tools-programmer** — only when Phase 1 traced a cause to a content authoring tool: fix the tool. Output: tool fixes with before/after metrics
|
||||
- **technical-artist** — rendering-side items (draw calls, overdraw, particles, shaders, LOD) join its Phase 3 brief
|
||||
|
||||
If Phase 1 identified engine-level root causes (rendering pipeline, resource loading, memory allocator), delegate those fixes to **engine-programmer** in parallel:
|
||||
- Optimize hot paths in engine systems
|
||||
- Fix allocation pressure in core loops
|
||||
- Output: engine-level fixes with profiler validation
|
||||
Every implementing agent in Phases 2–4 first returns the files it will create or
|
||||
change, and you ask once for the whole Phase 2–4 set before any is edited (File
|
||||
Write Protocol).
|
||||
|
||||
**An item whose owner is not in the active set is not implemented in this run.**
|
||||
At `team.size: individual` that is every programmer item, since no programmer is
|
||||
active; at any size it includes an item owned by a programmer this pipeline does
|
||||
not name (e.g. gameplay-programmer for a gameplay-script hot spot). The report
|
||||
lists those items with their owners under
|
||||
"Optimisation list handed to `/dev-story`: `production/polish/[area]-report-[date].md`".
|
||||
A metric they target that is over budget stays a known problem at Phase 6.
|
||||
|
||||
### Phase 3: Visual Polish (parallel with Phase 2)
|
||||
Delegate to **technical-artist**:
|
||||
@@ -162,15 +169,29 @@ Delegate to **qa-tester**:
|
||||
- Test all edge cases: boundary conditions, rapid inputs, unusual sequences
|
||||
- Soak test: run the feature for extended periods checking for degradation
|
||||
- Stress test: maximum entities, worst-case scenarios
|
||||
- Regression test: verify polish changes haven't broken existing functionality
|
||||
- Regression test: verify polish changes haven't broken existing functionality — each Phase 2–4 change by name, engine-level fixes included
|
||||
- Test on minimum spec hardware (if available)
|
||||
- Output: test results with any remaining issues
|
||||
|
||||
### Phase 6: Sign-off
|
||||
- Collect results from all team members
|
||||
- Compare performance metrics against budgets
|
||||
- Report: READY FOR RELEASE / NEEDS MORE WORK
|
||||
- List any remaining issues with severity and recommendations
|
||||
- Report: READY FOR RELEASE / NOT ASSESSED / NEEDS MORE WORK
|
||||
- List every remaining issue with its severity (S1–S4), the measured gap where there is one (e.g. "9 ms against a 6 ms budget — 3 ms over"), and a recommendation; a regression also names the broken behavior and the polish change that caused it
|
||||
|
||||
**NOT ASSESSED ranks above READY FOR RELEASE and below NEEDS MORE WORK.** A known
|
||||
problem — a metric over budget, an unresolved regression — makes it NEEDS MORE
|
||||
WORK whatever else went unchecked. Otherwise, if any part of the scope could not
|
||||
be checked, the result is NOT ASSESSED, never READY FOR RELEASE, and the report
|
||||
names each gap:
|
||||
- A metric with no committed budget. `performance.target_framerate`,
|
||||
`performance.frame_budget_ms`, `performance.draw_call_limit` and
|
||||
`performance.memory_ceiling_mb` have no default, and `/perf-profile` reports an
|
||||
unset one as NOT ASSESSED — nothing was compared, so no budget was met.
|
||||
- A phase that did not run: BLOCKED, skipped, or its agent outside the active set.
|
||||
At `team.size: individual`, sound-designer's audio polish and qa-tester's
|
||||
hardening are only consulted through the active agents, not run, and Phase 2's
|
||||
programmer items are handed to `/dev-story` rather than implemented.
|
||||
|
||||
## Error Recovery Protocol
|
||||
|
||||
@@ -184,11 +205,11 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
@@ -199,15 +220,21 @@ 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.
|
||||
prompt per write inside those bounds; outside them it must ask. The optimization
|
||||
and polish changes of Phases 2–4 edit existing code, shaders, audio or assets, so
|
||||
they are outside those bounds: each implementing agent returns the files it will
|
||||
create or change, you ask once for the whole Phase 2–4 set ("May I have [agents]
|
||||
change these [N] files?"), and each edits only after a yes — one ask for the set,
|
||||
not one per phase. This orchestrator does not write files directly.
|
||||
|
||||
## Output
|
||||
|
||||
A summary report covering: performance before/after metrics, visual polish changes, audio polish changes, test results, and release readiness assessment.
|
||||
A summary report covering: performance before/after metrics, visual polish changes, audio polish changes, test results, any optimisation list handed to `/dev-story`, and release readiness assessment.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- If READY FOR RELEASE: run `/release-checklist` for the final pre-release validation.
|
||||
- If NEEDS MORE WORK: schedule remaining issues in `/sprint-plan update` and re-run `/team-polish` after fixes.
|
||||
- If NOT ASSESSED: supply what was missing — commit the unset `performance.*` budgets in `project.yaml` (`/settings`), or run the phases that did not run (raise `team.size`) — then re-run `/team-polish`. Do not treat the area as release-ready.
|
||||
- If the report handed an optimisation list to `/dev-story`: implement those items there, then re-run `/team-polish` to measure the gain.
|
||||
- Run `/gate-check` for a formal phase gate verdict before handing off to release.
|
||||
|
||||
@@ -21,15 +21,21 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
|
||||
## Phase 0: Resolve Config
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size,qa.level`
|
||||
|
||||
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
|
||||
`qa.level` decides what a Logic, Integration or Config/Data story's evidence is:
|
||||
its automated test at `standard` and `full`; at `minimal`, where tests are waived
|
||||
(`.claude/docs/coding-standards.md`), the acceptance-criteria walk in Phase 5 —
|
||||
a story without a test is then WAIVED, not missing its evidence. The UI and
|
||||
Visual/Feel screenshots are required at every level.
|
||||
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
@@ -38,7 +44,7 @@ defaults in `.claude/docs/config-resolution.md`.
|
||||
- **`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.
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode**: in `guided` or `autonomous`, where that question is skipped or logged, the phase is still a gate. Not every phase is one. Apply the test literally: if the phase below lists 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
|
||||
@@ -51,12 +57,15 @@ spawn, and which the pipeline below names but will **not** spawn at the resolved
|
||||
|
||||
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.
|
||||
An agent the resolved size spawns only at phase gates (`qa-lead` at
|
||||
`individual`) goes in the active set with that qualifier — it is spawned, not
|
||||
consulted through another agent.
|
||||
|
||||
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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -80,9 +89,9 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
|
||||
**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.
|
||||
> **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 a phase gate as defined above — one the pipeline lists as ending in an `AskUserQuestion` before it advances, whatever the automation mode. 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).
|
||||
At `team.size: studio`, Phase 4 spawns one qa-tester per story, in parallel; below that, one spawn covers the whole group.
|
||||
|
||||
## Pipeline
|
||||
|
||||
@@ -91,32 +100,36 @@ Launch independent qa-tester tasks in parallel where possible (e.g., multiple st
|
||||
Before doing anything else, gather the full scope:
|
||||
|
||||
1. Detect the current sprint or feature scope from the argument:
|
||||
- If argument is a sprint identifier (e.g., `sprint-03`): Glob `production/sprints/` for files matching `*[sprint-identifier]*.md`. Read the matched file. If multiple match, use the most recently modified.
|
||||
- If argument is a sprint identifier (e.g., `sprint-03`): Glob `production/sprints/sprint-*.md` and match by sprint number — `sprint-3`, `sprint-03` and `sprint-003` all name sprint 3 (`/sprint-plan` writes `sprint-NNN.md`). Read the matched file. If multiple match, use the most recently modified.
|
||||
- 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
|
||||
- If no argument: read `production/session-state/active.md` and `production/sprint-status.yaml` (if present) to infer the active sprint. If there is no sprint — at `rigor: minimal` there are none — ask which epic to cover and use `feature: [epic-slug]`; do not invent a sprint
|
||||
|
||||
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?"
|
||||
3. **Read the open bugs in scope** — the bugs already on file, before QA finds new ones: grep the `**Severity**`, `**Status**` and `**System**` lines of `production/qa/bugs/*.md`, as `/bug-triage` does. A bug is open unless its Status is `Closed` or `Verified Fixed`; it is in scope when its System is one the in-scope stories belong to, or it names an in-scope story — when unsure, list it. These go into the Phase 2 and Phase 6 briefs as **Open bugs in scope**: an open S1 or S2 here already makes the sign-off NOT APPROVED (Phase 6), whatever QA finds. No bug files → "Open bugs in scope: none on file".
|
||||
|
||||
4. Count stories found and report to the user:
|
||||
> "QA cycle starting for [sprint/feature]. Found [N] stories. Open bugs in scope: [N — S1: n, S2: n, or none on file]. Current stage: [stage]. Ready to begin QA strategy?"
|
||||
|
||||
### Phase 2: QA Strategy (qa-lead)
|
||||
|
||||
Spawn `qa-lead` via `Agent` to review all in-scope stories and produce a QA strategy.
|
||||
|
||||
Prompt the qa-lead to:
|
||||
Pass the qa-lead the **Open bugs in scope** from Phase 1 (ID, severity, story or system), then prompt it to:
|
||||
- Read each story file
|
||||
- Classify each story by type: **Logic** / **Integration** / **Visual/Feel** / **UI** / **Config/Data**
|
||||
- Identify which stories require automated test evidence vs. manual QA
|
||||
- Identify which stories require automated test evidence vs. manual QA — at `qa.level: minimal` none requires a test: a Logic, Integration or Config/Data story without one reads `WAIVED` under Automated Required and gets its acceptance criteria walked in manual QA
|
||||
- Flag any stories with missing acceptance criteria or missing test evidence that would block QA
|
||||
- Estimate manual QA effort (number of test sessions needed)
|
||||
- **Before assessing smoke status, check for an existing smoke check report**: Glob `production/qa/smoke-*.md` and read the most recently modified file (if found). If a report exists, use its verdict and findings directly — do not re-interview the user. If no report exists, note: "No prior smoke check report found — run `/smoke-check sprint` before proceeding." and set smoke check status to UNKNOWN (treat as PASS WITH WARNINGS for the purpose of continuing). Produce a smoke check verdict: **PASS** / **PASS WITH WARNINGS [list]** / **FAIL [list of failures]** / **UNKNOWN (no report found)**
|
||||
- **Before assessing smoke status, check for an existing smoke check report**: Glob `production/qa/smoke-*.md` and read the most recently modified file (if found). If a report exists, use its verdict and findings directly — do not re-interview the user. If no report exists, note: "No prior smoke check report found — run `/smoke-check sprint` before proceeding." and set smoke check status to UNKNOWN (treat as PASS WITH WARNINGS for the purpose of continuing). Produce a smoke check verdict: **PASS** / **PASS WITH WARNINGS [list]** / **NOT ASSESSED [what did not run]** / **FAIL [list of failures]** / **UNKNOWN (no report found)**
|
||||
- Produce a strategy summary table and smoke check result:
|
||||
|
||||
| Story | Type | Automated Required | Manual Required | Blocker? |
|
||||
|-------|------|--------------------|-----------------|----------|
|
||||
|
||||
**Smoke Check**: [PASS / PASS WITH WARNINGS / FAIL / UNKNOWN] — [source: `production/qa/smoke-[date].md` or "no report found"] — [details if not PASS]
|
||||
**Smoke Check**: [PASS / PASS WITH WARNINGS / NOT ASSESSED / FAIL / UNKNOWN] — [source: `production/qa/smoke-[date].md` or "no report found"] — [details if not PASS]
|
||||
|
||||
**Open bugs in scope**: [BUG-ID — S[n] — story or system, one per line; or "none on file"] — an open S1 or S2 is named here as a known failure
|
||||
|
||||
If the smoke check result is **FAIL**, the qa-lead must list the failures prominently. QA cannot proceed past the strategy phase with a failed smoke check.
|
||||
|
||||
@@ -134,6 +147,7 @@ options:
|
||||
|
||||
If smoke check **FAIL**: do not proceed to Phase 3. Surface the failures from the smoke check report and stop. The user must fix them, re-run `/smoke-check sprint`, and then re-run `/team-qa`.
|
||||
If smoke check **UNKNOWN**: surface a warning — "No smoke check report found. Recommend running `/smoke-check sprint` before QA. Proceeding with caution."
|
||||
If smoke check **NOT ASSESSED**: surface what the report says did not run — "The last smoke check could not assess [what did not run]. Recommend re-running `/smoke-check sprint` once it can. Proceeding with caution." — and continue as for UNKNOWN; the sign-off cannot be APPROVED on it (Phase 6).
|
||||
If smoke check **PASS WITH WARNINGS**: note the warnings for the sign-off report and continue.
|
||||
If blockers are present: list them explicitly. The user may choose to skip blocked stories or cancel the cycle.
|
||||
|
||||
@@ -144,10 +158,10 @@ Using the strategy from Phase 2, produce a structured test plan document.
|
||||
The test plan should cover:
|
||||
- **Scope**: sprint/feature name, story count, dates
|
||||
- **Story Classification Table**: from Phase 2 strategy
|
||||
- **Automated Test Requirements**: which stories need test files, expected paths in `tests/`
|
||||
- **Automated Test Requirements**: which stories need test files, expected paths in `tests/` (none at `qa.level: minimal`: list the waived stories under Manual QA Scope instead)
|
||||
- **Manual QA Scope**: which stories need manual walkthrough and what to validate
|
||||
- **Out of Scope**: what is explicitly not being tested this cycle and why
|
||||
- **Entry Criteria**: what must be true before QA can begin. Always include: (1) Smoke check PASS or PASS WITH WARNINGS report exists at `production/qa/smoke-*.md`, (2) build is stable (no crashes on launch), (3) all Must Have stories have Status: in-progress or done in `production/sprint-status.yaml`. Add any sprint-specific criteria beyond these.
|
||||
- **Entry Criteria**: what must be true before QA can begin. Always include: (1) Smoke check PASS or PASS WITH WARNINGS report exists at `production/qa/smoke-*.md`, (2) build is stable (no crashes on launch), (3) at sprint scope, all Must Have stories are `in-progress`, `review` or `done` in `production/sprint-status.yaml`; at `feature:` scope, every in-scope story file's Status is In Progress, In Review or Complete. Add any sprint-specific criteria beyond these.
|
||||
- **Exit Criteria**: what constitutes a completed QA cycle (all stories PASS or FAIL with bugs filed)
|
||||
|
||||
Ask: "May I write the QA plan to `production/qa/qa-plan-[sprint]-[date].md`?"
|
||||
@@ -156,11 +170,11 @@ Write only after receiving approval.
|
||||
|
||||
### Phase 4: Test Case Writing (qa-tester)
|
||||
|
||||
> **Smoke check** is performed as part of Phase 2 (QA Strategy). If the smoke check returned FAIL in Phase 2, the cycle was stopped there. This phase only runs when the Phase 2 smoke check was PASS, PASS WITH WARNINGS, or UNKNOWN.
|
||||
> **Smoke check** is performed as part of Phase 2 (QA Strategy). If the smoke check returned FAIL in Phase 2, the cycle was stopped there. This phase only runs when the Phase 2 smoke check was PASS, PASS WITH WARNINGS, NOT ASSESSED, or UNKNOWN.
|
||||
|
||||
For each story requiring manual QA (Visual/Feel, UI, Integration without automated tests):
|
||||
For each story requiring manual QA (Visual/Feel, UI, Integration without automated tests — and, at `qa.level: minimal`, where tests are waived, every Logic, Integration and Config/Data story without a test: its cases walk its acceptance criteria):
|
||||
|
||||
Spawn `qa-tester` via `Agent` for each story (run in parallel where possible), providing:
|
||||
Spawn `qa-tester` via `Agent` — one per story, in parallel, at `team.size: studio`; one spawn covering the whole group at `small` and `individual` — providing, for each story:
|
||||
- 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)
|
||||
@@ -198,7 +212,10 @@ options:
|
||||
|
||||
Walk through each story in the approved manual QA list.
|
||||
|
||||
Batch stories into groups of 3-4 and use `AskUserQuestion` for each:
|
||||
Batch stories into groups of 3-4 and use `AskUserQuestion` for each. **Wait for
|
||||
the tester's answer** and record only what they said: a result the tester did not
|
||||
give is never filled in for them. A story nobody answered for stays unexecuted,
|
||||
which makes the sign-off NOT ASSESSED — it is not BLOCKED unless they say so.
|
||||
|
||||
```
|
||||
question: "Manual QA — [Story Title]\n[brief description of what to test]"
|
||||
@@ -209,14 +226,21 @@ options:
|
||||
- "BLOCKED — cannot test yet (reason)"
|
||||
```
|
||||
|
||||
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 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/`, in `/bug-report`'s format — its Severity and Priority labels exactly as that template lists them (`S2-High`, `P1-Fix this sprint`, …), because `/bug-triage` parses them.
|
||||
|
||||
**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.
|
||||
**After each PASS or PASS WITH NOTES on a Visual/Feel or UI story, record its
|
||||
evidence in `production/qa/evidence/`.** The retained screenshot is the
|
||||
evidence: ask the tester to save one of each screen or effect the story touched
|
||||
under `production/qa/evidence/[story-slug]/`, and confirm it is on disk —
|
||||
`/story-done` checks for a retained image, not just the write-up. A UI story is
|
||||
closed by those screenshots; a Visual/Feel story also needs the lead sign-off.
|
||||
Then ask "May I write the evidence for [story titles] to
|
||||
`production/qa/evidence/`?", once per story group, and write the evidence
|
||||
artifact `production/qa/evidence/[story-slug]-evidence.md` from
|
||||
`.claude/docs/templates/test-evidence.md`, carrying the sign-off table intact and
|
||||
referencing the screenshots. If no screenshot was saved, name that story in the
|
||||
Phase 5 summary as missing its retained evidence rather than writing a doc that
|
||||
implies one.
|
||||
|
||||
> **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
|
||||
@@ -232,7 +256,9 @@ write-up.
|
||||
> 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).
|
||||
Bug report naming: `BUG-[NNNN].md`, numbered the way `/bug-report` numbers them — the
|
||||
highest ID in `production/qa/bugs/` plus one, zero-padded to four digits — so
|
||||
`/bug-report verify` and `close` can find it by its ID.
|
||||
|
||||
After collecting all results, summarize:
|
||||
- Stories PASS: [count]
|
||||
@@ -242,7 +268,9 @@ After collecting all results, summarize:
|
||||
|
||||
### Phase 6: QA Sign-Off Report
|
||||
|
||||
Spawn `qa-lead` via `Agent` to produce the sign-off report using all results from Phases 4–6.
|
||||
Spawn `qa-lead` via `Agent` to draft the sign-off report using all results from Phases 2–5. **Here the return contract is the report text in its reply, not a file:** the orchestrator writes the sign-off after the ask at the end of this phase, so the qa-lead writes nothing.
|
||||
|
||||
**Brief the qa-lead with the evidence and the verdict rules below — never a verdict.** Pass the strategy table, the smoke check verdict and its source, each story's result, the bugs filed in Phase 5 and the **Open bugs in scope** from Phase 1, and the verdict rules below, verbatim. Do not name a verdict, pre-fill the `### Verdict:` line, or say which fact decides it: the qa-lead applies the rules to the evidence. Then check its verdict against the same rules before asking to write; if they disagree, show both and ask — never silently substitute your own.
|
||||
|
||||
The sign-off report format:
|
||||
|
||||
@@ -254,12 +282,16 @@ The sign-off report format:
|
||||
| Story | Type | Auto Test | Manual QA | Result |
|
||||
|-------|------|-----------|-----------|--------|
|
||||
| [title] | Logic | PASS | — | PASS |
|
||||
| [title] | Logic | WAIVED (qa.level: minimal) | PASS — criteria walked | PASS |
|
||||
| [title] | Visual | — | PASS | PASS |
|
||||
| [title] | Integration | — | BLOCKED | BLOCKED — [reason]; no executed evidence |
|
||||
|
||||
### Bugs Found
|
||||
| ID | Story | Severity | Status |
|
||||
|----|-------|----------|--------|
|
||||
| BUG-001 | [story] | S2 | Open |
|
||||
| BUG-0001 | [story] | S2 | Open |
|
||||
|
||||
[every open bug in scope — those Phase 1 found on file and those filed in Phase 5]
|
||||
|
||||
### Verdict: NOT ASSESSED / APPROVED / APPROVED WITH CONDITIONS / NOT APPROVED
|
||||
|
||||
@@ -269,18 +301,30 @@ The sign-off report format:
|
||||
[guidance based on verdict]
|
||||
```
|
||||
|
||||
**Every story in scope gets a Test Coverage Summary row** — BLOCKED and
|
||||
unexecuted stories included, with the reason in Result — so a story that never
|
||||
ran cannot drop out of the report.
|
||||
|
||||
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.
|
||||
**Order.** Check **NOT APPROVED first**: any open S1/S2 bug in scope — one already on file (Phase 1) as much as one filed in Phase 5 — or a story that
|
||||
FAILs without a documented workaround, makes the verdict NOT APPROVED whatever
|
||||
else went unexecuted — a known failure outranks an unknown, and demoting it to
|
||||
NOT ASSESSED would bury it (`.claude/rules/skill-authoring.md`, obligation 1).
|
||||
|
||||
**Then the precondition.** 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. At `qa.level: minimal` a Logic, Integration or
|
||||
Config/Data story's acceptance-criteria walk is its executed evidence: its tests
|
||||
are WAIVED, not missing. If any story is BLOCKED, unexecuted, or has no
|
||||
evidence, the verdict is **NOT ASSESSED**, not either kind of APPROVED. A smoke
|
||||
check that was UNKNOWN (no report found) or NOT ASSESSED in Phase 2 also makes it
|
||||
NOT ASSESSED: the build's health was never checked.
|
||||
|
||||
- **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.
|
||||
evidence (BLOCKED, tests not written at `qa.level` standard/full, cases not
|
||||
walked, or smoke check FAIL / UNKNOWN / NOT ASSESSED). 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
|
||||
@@ -296,7 +340,7 @@ not evaluated.
|
||||
> 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."
|
||||
- NOT ASSESSED: "QA did not run to completion. Produce the missing evidence — write the Logic tests (at `qa.level` standard/full) or walk the waived stories' acceptance criteria (at `minimal`), 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."
|
||||
@@ -321,13 +365,13 @@ 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
## Output
|
||||
|
||||
A summary covering: stories in scope, smoke check result, manual QA results, bugs filed (with IDs and severities), and the final APPROVED / APPROVED WITH CONDITIONS / NOT APPROVED verdict.
|
||||
A summary covering: stories in scope, smoke check result, manual QA results, bugs filed (with IDs and severities), and the final APPROVED / APPROVED WITH CONDITIONS / NOT APPROVED / NOT ASSESSED verdict.
|
||||
|
||||
Verdict: **COMPLETE** — QA cycle finished.
|
||||
Verdict: **BLOCKED** — smoke check failed or critical blocker prevented cycle completion; partial report produced.
|
||||
@@ -337,5 +381,5 @@ Verdict: **BLOCKED** — smoke check failed or critical blocker prevented cycle
|
||||
After the final phase completes (sign-off report written or BLOCKED verdict reached), silently append to `production/session-state/active.md`:
|
||||
|
||||
```
|
||||
<!-- QA RUN: [date] | Sprint: [sprint identifier or "ad-hoc"] | Verdict: [PASS/FAIL/CONCERNS] | Report: production/qa/qa-[date].md -->
|
||||
<!-- QA RUN: [date] | Sprint: [sprint identifier or "ad-hoc"] | Verdict: [APPROVED/APPROVED WITH CONDITIONS/NOT APPROVED/NOT ASSESSED/BLOCKED] | Report: production/qa/qa-signoff-[sprint]-[date].md -->
|
||||
```
|
||||
|
||||
@@ -25,24 +25,42 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
|
||||
## Phase 0: Resolve Config
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation,team.size,workflow,project.stage`
|
||||
|
||||
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
|
||||
**Stage check — before anything is spawned.** This skill ships a release, and
|
||||
`/gate-check release` is the readiness gate that must pass first; only its PASS
|
||||
sets `project.stage` to `Release`. If the resolved `project.stage` is anything
|
||||
else — `Polish`, an earlier stage, or not set — stop before Phase 1 and spawn
|
||||
nothing:
|
||||
|
||||
> "The release readiness gate has not passed (project.stage: [stage]) — run
|
||||
> `/gate-check release` first."
|
||||
|
||||
Then ask with `AskUserQuestion`, in every `automation` mode — an override is never
|
||||
taken on the user's behalf: `[A] Stop — I'll run /gate-check release (recommended)`
|
||||
/ `[B] Proceed anyway — override the stage check`. On `[A]`, end the run: Verdict
|
||||
**BLOCKED** — release gate not passed. On `[B]`, ask (plain text) why, then record
|
||||
the override as `Stage override: project.stage was [stage] — release gate not
|
||||
passed; the user chose to proceed: [reason]` in the Phase 1 brief, in the go/no-go
|
||||
record (`go-no-go-[version].md`) and in the final report. An override never
|
||||
changes the stage itself.
|
||||
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
- **`small`**: + `producer` + `devops-engineer` + `qa-lead` + `community-manager`.
|
||||
- **`studio`**: + `security-engineer` + `analytics-engineer` + `localization-lead` + `performance-analyst`, and `network-programmer` when the game is multiplayer (the full pipeline as documented).
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, the stage check, or the Phase 6 deploy question — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -57,10 +75,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -70,49 +88,61 @@ indistinguishable, to the person reading the output, from one that was never
|
||||
enforced.**
|
||||
|
||||
## Team Composition
|
||||
- **release-manager** — Release branch, versioning, changelog, deployment
|
||||
- **release-manager** — Release tag, versioning, changelog, patch notes, deployment
|
||||
- **qa-lead** — Test sign-off, regression suite, release quality gate
|
||||
- **devops-engineer** — Build pipeline, artifacts, deployment automation
|
||||
- **security-engineer** — Pre-release security audit (invoke if game has online/multiplayer features or player data)
|
||||
- **network-programmer** — Netcode stability sign-off (invoke if game has multiplayer)
|
||||
- **analytics-engineer** — Verify telemetry events fire correctly and dashboards are live
|
||||
- **community-manager** — Patch notes, launch announcement, player-facing messaging
|
||||
- **localization-lead** — Verify every shipped string is translated
|
||||
- **performance-analyst** — Benchmark the release build against its performance targets
|
||||
- **community-manager** — Launch announcement and player-facing messaging, written from the patch notes
|
||||
- **producer** — Go/no-go decision, stakeholder communication, scheduling
|
||||
|
||||
## How to Delegate
|
||||
|
||||
Use the `Agent` tool to spawn each team member as a subagent:
|
||||
- `subagent_type: release-manager` — Release branch, versioning, changelog, deployment
|
||||
- `subagent_type: release-manager` — Release tag, versioning, changelog, patch notes, deployment
|
||||
- `subagent_type: qa-lead` — Test sign-off, regression suite, release quality gate
|
||||
- `subagent_type: devops-engineer` — Build pipeline, artifacts, deployment automation
|
||||
- `subagent_type: security-engineer` — Security audit for online/multiplayer/data features
|
||||
- `subagent_type: analytics-engineer` — Telemetry event verification and dashboard readiness
|
||||
- `subagent_type: community-manager` — Patch notes and launch communication
|
||||
- `subagent_type: community-manager` — Launch communication, written from the patch notes
|
||||
- `subagent_type: producer` — Go/no-go decision, stakeholder communication
|
||||
- `subagent_type: network-programmer` — Netcode stability sign-off (invoke if game has multiplayer)
|
||||
- `subagent_type: localization-lead` — Translation completeness sign-off (Phase 4)
|
||||
- `subagent_type: performance-analyst` — Performance benchmarks against targets (Phase 4)
|
||||
|
||||
**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:
|
||||
**Substitute a real path for `[path]`.** One file per agent under
|
||||
`production/releases/`, except the two whose homes are fixed elsewhere. An active
|
||||
agent standing in for one outside the active set writes that agent's file:
|
||||
|
||||
| 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 |
|
||||
| 3 devops-engineer | `production/releases/build-[version].md` | this skill |
|
||||
| 3 security-engineer | `production/releases/security-signoff-[version].md` | this skill |
|
||||
| 3 network-programmer | `production/releases/netcode-signoff-[version].md` | this skill |
|
||||
| 4 localization-lead | `production/releases/localization-signoff-[version].md` | this skill |
|
||||
| 4 performance-analyst | `production/releases/performance-signoff-[version].md` | this skill |
|
||||
| 4 analytics-engineer | `production/releases/analytics-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` |
|
||||
| 6 release-manager | `docs/patch-notes/[version].md` | `/patch-notes` |
|
||||
| 6 community-manager | `production/releases/announcement-[version].md` | this skill |
|
||||
| 7 release-manager | `production/releases/release-report-[version].md` | this skill |
|
||||
|
||||
> **Every one of those seven outputs needs a stated destination.**
|
||||
> **Every one of those thirteen 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
|
||||
> **A separate file per agent, 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.
|
||||
|
||||
@@ -131,29 +161,40 @@ Delegate to **producer**:
|
||||
|
||||
### Phase 2: Release Candidate
|
||||
Delegate to **release-manager**:
|
||||
- Cut release branch from the agreed commit
|
||||
- Bump version numbers in all relevant files
|
||||
- Generate the release checklist using `/release-checklist`
|
||||
- Freeze the branch — no feature changes, bug fixes only
|
||||
- Output: release branch name and checklist
|
||||
- Bump version numbers in all relevant files on `main`; the commit carrying the bump is the release candidate. Development is trunk-based — a release is a tag on `main` (applied in Phase 6), not a branch
|
||||
- Confirm the release checklist from Polish (`/release-checklist`, run before `/gate-check release`) is complete for this candidate; run it now only if none exists
|
||||
- Cut a `release/[version]` branch from the candidate only if this release needs stabilising (a freeze, platform certification) — bug fixes only there, and every fix lands on `main` as well
|
||||
- Output: release candidate commit (plus the `release/*` branch, if one was cut) and checklist
|
||||
|
||||
### Phase 3: Quality Gate (parallel)
|
||||
Delegate in parallel:
|
||||
- **qa-lead**: Execute full regression test suite. Test all critical paths. Verify no S1/S2 bugs. Sign off on quality.
|
||||
- **qa-lead**: Execute full regression test suite. Test all critical paths. Verify no open bugs at the severities `/gate-check release` blocks for this `workflow`: S1 at every tier, S2 and S3 too at `full`. Sign off on quality.
|
||||
- **devops-engineer**: Build release artifacts for all target platforms. Verify builds are clean and reproducible. Run automated tests in CI.
|
||||
- **security-engineer** *(if game has online features, multiplayer, or player data)*: Conduct pre-release security audit. Review authentication, anti-cheat, data privacy compliance. Sign off on security posture.
|
||||
- **network-programmer** *(if game has multiplayer)*: Sign off on netcode stability. Verify lag compensation, reconnect handling, and bandwidth usage under load.
|
||||
|
||||
When either agent is in the active set, decide its condition from `platform.online` and `platform.multiplayer` in `project.yaml`, plus whether the game stores player data. A key that is absent is not a `false`: ask the user rather than assume an offline game. An agent skipped on these grounds says so by name in the Phase 3 output — e.g. `security-engineer: not spawned — platform.online: false, platform.multiplayer: false, no player data`.
|
||||
|
||||
### Phase 4: Localization, Performance, and Analytics
|
||||
Delegate (can run in parallel with Phase 3 if resources available):
|
||||
- Verify all strings are translated (delegate to **localization-lead** if available)
|
||||
- Run performance benchmarks against targets (delegate to **performance-analyst** if available)
|
||||
- **analytics-engineer**: Verify all telemetry events fire correctly on release build. Confirm dashboards are receiving data. Check that critical funnels (onboarding, progression, monetization if applicable) are instrumented.
|
||||
- Output: localization, performance, and analytics sign-off
|
||||
- Output: localization, performance, and analytics sign-off — one file per agent (table above)
|
||||
|
||||
### Phase 5: Go/No-Go
|
||||
Delegate to **producer**:
|
||||
- Collect sign-off from: qa-lead, release-manager, devops-engineer, security-engineer (if spawned in Phase 3), network-programmer (if spawned in Phase 3), and technical-director
|
||||
Before delegating, get the **technical-director** release sign-off. The producer
|
||||
cannot spawn agents, so the orchestrator does: spawn `technical-director` at
|
||||
`review_mode: full` only — this is a director review, not a PHASE-GATE, so `lean`
|
||||
and `solo` skip it. Ask for GO, CONCERNS or NO-GO on the release candidate's
|
||||
technical state, or NOT ASSESSED naming what it could not read. When it is not
|
||||
spawned, the go/no-go record says `technical-director sign-off: not run
|
||||
(review_mode: <mode>)` instead of listing it as given; a NOT ASSESSED answer is
|
||||
recorded as such and never counted as a sign-off.
|
||||
|
||||
Delegate to **producer**, passing every sign-off collected so far:
|
||||
- Collect sign-off from: qa-lead, release-manager, devops-engineer, security-engineer (if spawned in Phase 3), network-programmer (if spawned in Phase 3), and technical-director (if spawned above)
|
||||
- Carry a stage-check override, if there was one, into the go/no-go record as its `Stage override:` line
|
||||
- Evaluate any open issues — are they blocking or can they ship?
|
||||
- Make the go/no-go call
|
||||
- Output: release decision with rationale
|
||||
@@ -187,13 +228,15 @@ Before tagging or deploying, use `AskUserQuestion`:
|
||||
|
||||
Only after explicit approval, delegate to **release-manager** + **devops-engineer**:
|
||||
- Tag the release in version control
|
||||
- Generate changelog using `/changelog`
|
||||
- Finalize the changelog drafted in Polish (`/changelog`), adding what changed since the gate
|
||||
- Deploy to staging for final smoke test
|
||||
- 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):
|
||||
- Finalize patch notes using `/patch-notes [version]`
|
||||
In parallel with deployment, delegate to **release-manager**:
|
||||
- Finalize the patch notes drafted in Polish using `/patch-notes [version]` — release-manager carries that skill and the Bash access its `git log` step needs; `community-manager` has neither
|
||||
|
||||
Then hand those patch notes to **community-manager**:
|
||||
- Prepare launch announcement (store page updates, social media, community post)
|
||||
- Draft known issues post if any S3+ issues shipped
|
||||
- Output: all player-facing release communication, ready to publish on deploy confirmation
|
||||
@@ -204,6 +247,7 @@ Delegate to **community-manager** (in parallel with deployment):
|
||||
- **qa-lead**: Monitor incoming bug reports for regressions
|
||||
- **community-manager**: Publish all player-facing communication, monitor community sentiment
|
||||
- **analytics-engineer**: Confirm live dashboards are healthy; alert if any critical events are missing
|
||||
- Keep the 48-hour monitoring window from Phase 6: bugs, dashboards and community sentiment are watched for 48 hours after release (release-manager's own watch runs to its 72h report)
|
||||
- Schedule post-release retrospective if issues occurred
|
||||
|
||||
## Error Recovery Protocol
|
||||
@@ -222,7 +266,7 @@ 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
|
||||
- ADR status is Proposed → do not implement; accept it with `/architecture-decision accept ADR-NNNN` once decided
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
@@ -249,10 +293,10 @@ require explicit confirmation regardless of which rule above applies.
|
||||
A summary report covering: release version, scope, quality gate results, go/no-go decision, deployment status, and monitoring plan.
|
||||
|
||||
Verdict: **COMPLETE** — release executed and deployed.
|
||||
Verdict: **BLOCKED** — release halted; go/no-go was NO or a hard blocker is unresolved.
|
||||
Verdict: **BLOCKED** — release halted; the stage check stopped it, go/no-go was NO, or a hard blocker is unresolved.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Monitor post-release dashboards for 48 hours.
|
||||
- Run `/retrospective` if significant issues occurred during the release.
|
||||
- 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`.
|
||||
- `project.stage` reads `Release` unless the stage check was overridden: `/gate-check release` is the Polish → Release readiness gate, run before this skill. After an override the stage still reads what it did. Only `/gate-check` changes `project.stage` (on a PASS, or a CONCERNS whose risks the user accepted), so this skill never writes it or `production/stage.txt`. `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`.
|
||||
|
||||
@@ -6,6 +6,9 @@ user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate, Bash(bash "*/.claude/skills/team-ui/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
If no argument is provided, output usage guidance and exit without spawning any agents or reading any design files:
|
||||
> Usage: `/team-ui [UI feature description] [--review full|lean|solo]` — describe the screen or UI feature to build (e.g., `inventory screen`, `main menu`, `combat HUD`). Do not use `AskUserQuestion` here; output the guidance directly.
|
||||
|
||||
When this skill is invoked, orchestrate the UI team through a structured pipeline.
|
||||
|
||||
**Decision Points:** At each phase transition, use `AskUserQuestion` to present
|
||||
@@ -25,10 +28,10 @@ in `autonomous` mode it runs end to end, recording each phase outcome via
|
||||
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
|
||||
`review_mode` sets director-gate depth, and this pipeline has no director gate:
|
||||
no phase below spawns CD-, TD-, PR- or AD-PHASE-GATE, at any `review_mode`. Its
|
||||
phase gates are the pipeline's own decision points (defined under `team.size`
|
||||
below), and the agents that work at them are team members, not director gates.
|
||||
|
||||
`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.
|
||||
@@ -36,8 +39,8 @@ defaults in `.claude/docs/config-resolution.md`.
|
||||
**`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.
|
||||
- **`studio`**: + engine UI specialist + an adversarial review pass: Phase 4's reviewers are told "your job is not to confirm this matches the spec — find where it fails it", and the report says the pass ran.
|
||||
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 this pipeline itself lists** — a transition under Decision Points above, or a **Gate** step written into the pipeline below — **whatever the `automation` mode.** `guided` and `autonomous` change how a gate is passed (it auto-advances, or is recorded with `log_decision`), not whether it is one, so bounded-exception condition (3) below holds at it in every mode. An agent restricted to "phase gates only" is spawned at those points and no others. 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
|
||||
@@ -52,10 +55,10 @@ 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`
|
||||
is one or two agents — `team-release` names ten 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
|
||||
`team.size` is rigor-fronted and the narrow default is the token lever.
|
||||
Without saying so, a reader cannot
|
||||
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.
|
||||
@@ -95,7 +98,21 @@ Use the `Agent` tool to spawn each team member as a subagent:
|
||||
|
||||
**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.
|
||||
**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. **Implementation files are the exception:** an agent writing code or assets first returns the files it will create or change, and its return contract names them only after you have asked once for the set and the user said yes (File Write Protocol) — that answer, not the bounded exception, authorises those writes.
|
||||
|
||||
**Substitute a real path for `[path]`.** Working artifacts go under
|
||||
`production/ui/[feature-name]/`, the slug Phase 1b's `design/ux/[feature-name].md`
|
||||
uses. One file per agent, so the parallel Phase 4 reviews never share one:
|
||||
|
||||
| Phase / agent | Writes to |
|
||||
|---|---|
|
||||
| 2 art-director | `production/ui/[feature-name]/visual-design.md` |
|
||||
| 3 engine UI specialist | `production/ui/[feature-name]/engine-notes.md` |
|
||||
| 3 ui-programmer | the code root — the files the one implementation ask lists (File Write Protocol), outside the bounded exception |
|
||||
| 4 ux-designer, art-director, accessibility-specialist | `production/ui/[feature-name]/review-[agent].md`, one each |
|
||||
|
||||
The UX spec itself (Phase 1b) and any pattern-library update are under `design/`,
|
||||
outside the bounded exception: `/ux-design` or the agent asks before writing them.
|
||||
|
||||
> **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.
|
||||
|
||||
@@ -106,11 +123,13 @@ Launch independent agents in parallel where the pipeline allows it (e.g., Phase
|
||||
### Phase 1a: Context Gathering
|
||||
|
||||
Before designing anything, read and synthesize:
|
||||
- `design/gdd/game-concept.md` — platform targets and intended audience
|
||||
- `design/gdd/game-concept.md` — platform targets and intended audience (or
|
||||
`design/game-brief.md`, the one-page brief that replaces it at `rigor: minimal` —
|
||||
its "Who it's for" line gives the audience; it names no platform)
|
||||
- `design/player-journey.md` — player's state and context when they reach this screen
|
||||
- All GDD UI Requirements sections relevant to this feature
|
||||
- `design/ux/interaction-patterns.md` — existing patterns to reuse (not reinvent)
|
||||
- `design/accessibility-requirements.md` — committed accessibility tier (e.g., Basic, Enhanced, Full)
|
||||
- `design/accessibility-requirements.md` — committed accessibility tier (Basic, Standard, Comprehensive or Exemplary)
|
||||
|
||||
**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
|
||||
@@ -131,8 +150,9 @@ is absent:
|
||||
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
|
||||
Absence of a concept doc (neither `design/gdd/game-concept.md` nor
|
||||
`design/game-brief.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.
|
||||
|
||||
@@ -163,7 +183,11 @@ Output: `design/ux/[feature-name].md` with all required spec sections filled.
|
||||
|
||||
After the spec is complete, invoke `/ux-review design/ux/[feature-name].md`.
|
||||
|
||||
**Gate**: Do not proceed to Phase 2 until the verdict is APPROVED. If the verdict is NEEDS REVISION, the ux-designer must address the flagged issues and re-run the review. The user may explicitly accept a NEEDS REVISION risk and proceed, but this must be a conscious decision — present the specific concerns via `AskUserQuestion` before asking whether to proceed.
|
||||
**Gate**: Do not proceed to Phase 2 until the verdict is APPROVED. If the verdict is NEEDS REVISION, the ux-designer must address the flagged issues in the same spec — it is kept and revised, never discarded — and re-run the review. The user may explicitly accept a NEEDS REVISION risk and proceed, but this must be a conscious decision — present the specific concerns via `AskUserQuestion` before asking whether to proceed.
|
||||
|
||||
A **NOT ASSESSED** verdict blocks the same way, and the user may override it the same way. Its fix is an input, not a revision: present the dimensions `/ux-review` could not assess and the missing input for each (e.g. `/ux-design accessibility` for an uncommitted tier). Re-running the review without that input returns the same verdict, so offer to produce the input first.
|
||||
|
||||
When the user proceeds past NEEDS REVISION or NOT ASSESSED, the final report records the override: the verdict, the concerns or unassessed dimensions left open, and that the user chose to proceed.
|
||||
|
||||
### Phase 2: Visual Design
|
||||
|
||||
@@ -183,7 +207,7 @@ Before implementation begins, spawn the **engine UI specialist** (`specialists.u
|
||||
- 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. **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.
|
||||
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
|
||||
@@ -233,11 +257,11 @@ usually still there.
|
||||
|
||||
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`.
|
||||
partial report.** A skipped agent's section stays a named gap — never fill it with content of your own. 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
|
||||
- ADR status is Proposed → do not implement; once it is decided, accept it with `/architecture-decision accept ADR-NNNN`
|
||||
- Scope too large → split into two stories via `/create-stories`
|
||||
- Conflicting instructions between ADR and story → surface the conflict, do not guess
|
||||
|
||||
@@ -251,6 +275,9 @@ delegated to sub-agents and sub-skills. The two follow **different** rules:
|
||||
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.
|
||||
**Implementation files** (ui-programmer's code under the code root) are outside
|
||||
those bounds: ui-programmer returns the files it will create or change, you ask
|
||||
once for the set, and it writes after a yes.
|
||||
- **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.
|
||||
|
||||
@@ -261,6 +288,12 @@ This orchestrator does not write files directly.
|
||||
A summary report covering: UX spec status, UX review verdict, visual design status, implementation status, accessibility compliance, input method support, interaction pattern library update status, and any outstanding issues.
|
||||
|
||||
Verdict: **COMPLETE** — UI feature delivered through full pipeline (UX spec → visual → implementation → review → polish).
|
||||
|
||||
If the accessibility gate (no committed tier) or the engine validation (no engine
|
||||
configured) was NOT ASSESSED, the verdict names each one — never a plain COMPLETE:
|
||||
|
||||
Verdict: **COMPLETE — [accessibility | engine validation] NOT ASSESSED ([reason])** — UI feature delivered; the named check could not run.
|
||||
|
||||
Verdict: **BLOCKED** — pipeline halted; surface the blocker and its phase before stopping.
|
||||
|
||||
## Next Steps
|
||||
|
||||
@@ -3,7 +3,7 @@ name: tech-debt
|
||||
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, Bash(bash "*/.claude/skills/tech-debt/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, AskUserQuestion, Bash(bash "*/.claude/skills/tech-debt/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
@@ -30,7 +30,8 @@ If no subcommand is provided, output usage and stop. Verdict: **FAIL** — missi
|
||||
|
||||
## Phase 2A: Scan Mode
|
||||
|
||||
Search the codebase for debt indicators:
|
||||
Search the **code root** (resolve per `.claude/docs/code-root-resolution.md`:
|
||||
`src/`, `Assets/` or `Source/` by engine) for debt indicators:
|
||||
|
||||
- `TODO` comments (count and categorize)
|
||||
- `FIXME` comments (these are bugs disguised as debt)
|
||||
@@ -50,10 +51,11 @@ Categorize each finding:
|
||||
- **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:
|
||||
Count the source files the scan actually covered. If the code root is
|
||||
unresolved, report `NOT ASSESSED — code root unresolved` and stop as below. If
|
||||
that count is **zero** — the code root is absent, or holds no source files — report:
|
||||
|
||||
> **NOT ASSESSED — no source files to scan.** `src/` contains no code, so
|
||||
> **NOT ASSESSED — no source files to scan.** The code root 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.
|
||||
|
||||
@@ -69,7 +71,11 @@ Present the findings to the user.
|
||||
|
||||
Ask: "May I write these findings to `docs/tech-debt-register.md`?"
|
||||
|
||||
If yes, update the register (append new entries, do not overwrite existing ones). Verdict: **COMPLETE** — scan findings written to register.
|
||||
If yes, update the register, never overwriting it. **Match before appending:** a
|
||||
finding with the same file and the same kind of debt as an existing `Open` entry
|
||||
updates that entry instead of adding a duplicate. An existing `Open` entry whose
|
||||
pattern is no longer in its file is proposed as `Resolved [date]` — list those and
|
||||
include them in the same approval. Verdict: **COMPLETE** — scan findings written to register.
|
||||
|
||||
If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
@@ -77,7 +83,7 @@ If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
## Phase 2B: Add Mode
|
||||
|
||||
Ask the user for the description, affected files, and impact if left unfixed (plain text prompts).
|
||||
Ask the user for the description and affected files (plain text prompts).
|
||||
|
||||
Then use `AskUserQuestion` to collect the **category**:
|
||||
- Prompt: "What category does this tech debt belong to?"
|
||||
@@ -97,11 +103,21 @@ Then use `AskUserQuestion` to collect the **estimated fix effort**:
|
||||
- `[C] L — Large (3–7 days)`
|
||||
- `[D] XL — Extra Large (over 1 week)`
|
||||
|
||||
Then use `AskUserQuestion` to collect the **impact if left unfixed** — the
|
||||
register's Impact column, which `/tech-debt prioritize` scores:
|
||||
- Prompt: "What does this cost if it is never fixed?"
|
||||
- Options: `[A] Low` / `[B] Med` / `[C] High` / `[D] Critical`
|
||||
|
||||
Present the complete new entry to the user.
|
||||
|
||||
Ask: "May I append this entry to `docs/tech-debt-register.md`?"
|
||||
**Match before appending:** if an existing `Open` entry already has the same
|
||||
file and the same category, show it to the user and ask whether to update that
|
||||
entry instead of adding a duplicate.
|
||||
|
||||
If yes, append the entry. Verdict: **COMPLETE** — entry added to register.
|
||||
Ask: "May I append this entry to `docs/tech-debt-register.md`?" (or, on a match,
|
||||
"May I update the existing entry instead?")
|
||||
|
||||
If yes, append the entry (or update the matched one). Verdict: **COMPLETE** — entry added to register.
|
||||
|
||||
If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
@@ -109,9 +125,15 @@ If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
## Phase 2C: Prioritize Mode
|
||||
|
||||
Read the debt register at `docs/tech-debt-register.md`.
|
||||
Read the debt register at `docs/tech-debt-register.md`. If it does not exist:
|
||||
Verdict: **NOT ASSESSED** — no register at `docs/tech-debt-register.md`; run
|
||||
`/tech-debt scan` first. Stop.
|
||||
|
||||
Score each item by: `(impact_if_unfixed × frequency_of_encounter) / fix_effort`
|
||||
Score each item from its own columns: `impact ÷ effort`, with Impact `Low` 1,
|
||||
`Med` 2, `High` 3, `Critical` 4 and Effort `S` 1, `M` 2, `L` 3, `XL` 4, rounded to
|
||||
one decimal and written to Priority. Higher scores first; ties go to the older
|
||||
`Added` date. An item whose Impact or Effort is `—` gets no score: list it after
|
||||
the scored items as "not scored — [column] not judged" rather than guessing one.
|
||||
|
||||
Re-sort the register by priority score and recommend which items to include in the next sprint.
|
||||
|
||||
@@ -127,12 +149,15 @@ If no, stop here. Verdict: **BLOCKED** — user declined write.
|
||||
|
||||
## Phase 2D: Report Mode
|
||||
|
||||
Read the debt register. Generate summary statistics:
|
||||
Read the debt register. If it does not exist: Verdict: **NOT ASSESSED** — no
|
||||
register to report on; run `/tech-debt scan` first. Stop.
|
||||
|
||||
- Total items by category
|
||||
- Total estimated fix effort
|
||||
- Items added vs resolved since last report
|
||||
- Trending direction (growing / stable / shrinking)
|
||||
Generate summary statistics:
|
||||
|
||||
- Open items by category, and total estimated fix effort for them
|
||||
- Items added and items resolved during the current sprint, from each entry's
|
||||
`Added` date and its `Resolved [date]` status
|
||||
- Trending direction (growing / stable / shrinking) — added vs resolved in that window
|
||||
|
||||
Flag any items that have been in the register for more than 3 sprints.
|
||||
|
||||
@@ -152,11 +177,32 @@ Output the report to the user. This mode is read-only — no files are written.
|
||||
Last updated: [Date]
|
||||
Total items: [N] | Estimated total effort: [T-shirt sizes summed]
|
||||
|
||||
| ID | Category | Description | Files | Effort | Impact | Priority | Added | Sprint |
|
||||
|----|----------|-------------|-------|--------|--------|----------|-------|--------|
|
||||
| TD-001 | [Cat] | [Description] | [files] | [S/M/L/XL] | [Low/Med/High/Critical] | [Score] | [Date] | [Sprint to fix or "Backlog"] |
|
||||
| ID | Category | Description | Files | Effort | Impact | Priority | Status | Added | Sprint |
|
||||
|----|----------|-------------|-------|--------|--------|----------|--------|-------|--------|
|
||||
| TD-001 | [Cat] | [Description] | [files] | [S/M/L/XL] | [Low/Med/High/Critical] | [Score] | [Open / Resolved YYYY-MM-DD / Accepted — reason] | [YYYY-MM-DD] | [Sprint to fix or "Backlog"] |
|
||||
```
|
||||
|
||||
Every skill that adds a row — this one, and `/story-done` when it logs
|
||||
deviations as debt — writes all ten columns in this order, and a skill that
|
||||
creates the file writes the header and table head above first:
|
||||
|
||||
- **ID** — `TD-` and three digits, one above the highest ID already in the
|
||||
register (`TD-001` in a new one). IDs are never reused.
|
||||
- **Category** — one of the six categories under Scan Mode, written without
|
||||
"Debt": `Architecture`, `Code Quality`, `Test`, `Documentation`, `Dependency`,
|
||||
`Performance` — the spelling `/story-done` writes, so Report Mode groups them once.
|
||||
- **Description** — what the debt is and why it was taken on.
|
||||
- **Files** — the affected paths, comma-separated; `—` when the debt has no single file.
|
||||
- **Effort** — `S`, `M`, `L` or `XL`, as in Add Mode; `—` if not yet estimated.
|
||||
- **Impact** — `Low`, `Med`, `High` or `Critical`: the cost if left unfixed; `—`
|
||||
if not yet judged.
|
||||
- **Priority** — the score `/tech-debt prioritize` writes; `—` until it runs.
|
||||
- **Status** — `Open` when added. `Resolved YYYY-MM-DD` records the day the debt
|
||||
was fixed; `Accepted — reason` records a conscious decision to keep it.
|
||||
- **Added** — the day the row was written, `YYYY-MM-DD`. Report Mode counts items
|
||||
added and resolved from this date and the `Resolved` date.
|
||||
- **Sprint** — the sprint scheduled to fix it, or `Backlog`.
|
||||
|
||||
### Rules
|
||||
- Tech debt is not inherently bad — it is a tool. The register tracks conscious decisions.
|
||||
- Every debt entry must explain WHY it was accepted (deadline, prototype, missing info)
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Bash(bash "*/.claude/skills/test-evidenc
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,qa.level,testing.strict`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -15,6 +15,22 @@ 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).
|
||||
|
||||
**`qa.level` and `testing.strict`** (resolved above) decide what this review may
|
||||
call a blocker — the same rules `/story-done` closes stories by, so a BLOCKING
|
||||
item here is one that would stop `/story-done`:
|
||||
- **`qa.level: minimal`** waives tests. A Logic, Integration or Config/Data story
|
||||
with no test evidence (for Config/Data, no smoke report) is
|
||||
`WAIVED (qa.level: minimal)` — not MISSING — and raises no BLOCKING item; a
|
||||
test that does exist is still reviewed, but its gaps are ADVISORY. Visual/Feel and UI evidence (the retained screenshots, and the
|
||||
Visual/Feel sign-off) is never waived.
|
||||
- **Gate level per story type**: take `testing.strict.<type>` from the resolved
|
||||
block (Logic→`logic`, Integration→`integration`, Visual/Feel→`visual`,
|
||||
UI→`ui`, Config/Data→`config`): `true` → BLOCKING, `false` → ADVISORY, `unset`
|
||||
→ a plain-boolean `testing.strict: true|false` (legacy form) applies to every
|
||||
type; else the Default Gate Level in `.claude/docs/coding-standards.md`
|
||||
(BLOCKING for Logic, Integration, Visual/Feel and UI; ADVISORY for
|
||||
Config/Data). Every "BLOCKING" below means that story type's gate level.
|
||||
|
||||
# Test Evidence Review
|
||||
|
||||
`/smoke-check` verifies that test files **exist** and **pass**. This skill
|
||||
@@ -55,7 +71,8 @@ the list of story file paths from the sprint plan.
|
||||
|
||||
> **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
|
||||
> path was empty, and route: no sprint file → `/sprint-plan new` (at `workflow: minimal`,
|
||||
> which has no sprints, `/test-evidence-review [epic-slug]` instead); 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.
|
||||
>
|
||||
@@ -92,16 +109,23 @@ Full-read a story only when its Test Evidence section is missing or ambiguous.
|
||||
|
||||
## 3. Locate Evidence Files
|
||||
|
||||
For each story, find the evidence:
|
||||
For each story, find the evidence. **Check the story's stated evidence path first**
|
||||
— the one Section 2 captured from its `## Test Evidence` section. If it exists, use
|
||||
it. Fall back to searching only when no path is stated or it is not found:
|
||||
|
||||
**Logic stories**: Glob `tests/unit/[system]/[story-slug]_test.*`
|
||||
- If not found, also try: Grep in `tests/unit/[system]/` for files
|
||||
containing the story slug
|
||||
**Logic stories**: search the engine's unit-test root — `tests/unit/[system]/`
|
||||
(Godot), `Assets/Tests/EditMode/` (Unity), `Source/<Module>/Private/Tests/`
|
||||
(Unreal); see `.claude/docs/directory-structure.md` — for a file whose name
|
||||
contains the story slug or its system. Test files are named per
|
||||
`.claude/rules/test-standards.md`, not necessarily `[story-slug]_test.*`.
|
||||
|
||||
**Integration stories**: Glob `tests/integration/[system]/[story-slug]_test.*`
|
||||
**Integration stories**: the same, under the integration root (`tests/integration/[system]/`,
|
||||
`Assets/Tests/PlayMode/`, or Unreal's test root)
|
||||
- Also check `production/session-logs/` for playtest records mentioning the story
|
||||
|
||||
**Visual/Feel and UI stories**: Glob `production/qa/evidence/[story-slug]-evidence.*`
|
||||
**Visual/Feel and UI stories**: Glob `production/qa/evidence/` for a retained image
|
||||
(`*.png`, `*.jpg`, `*.gif`) belonging to this story, and for
|
||||
`[story-slug]-evidence.*`
|
||||
|
||||
**Config/Data stories**: Glob `production/qa/smoke-*.md` (any smoke check report)
|
||||
|
||||
@@ -123,8 +147,9 @@ not cover the range of expected behaviour.
|
||||
Thresholds:
|
||||
- **3+ assertions per test function** → normal
|
||||
- **1-2 assertions per test function** → note as potentially thin
|
||||
- **0 assertions** (test exists but no asserts) → flag as BLOCKING — the
|
||||
test passes vacuously and proves nothing
|
||||
- **0 assertions** (test exists but no asserts) → flag as BLOCKING (the story
|
||||
type's gate level; ADVISORY at `qa.level: minimal`) — the test passes
|
||||
vacuously and proves nothing
|
||||
|
||||
### Edge case coverage
|
||||
|
||||
@@ -141,7 +166,9 @@ Heuristics:
|
||||
### Naming quality
|
||||
|
||||
Test function names should describe: the scenario + the expected result.
|
||||
Pattern: `test_[scenario]_[expected_outcome]`
|
||||
Pattern per engine (`.claude/rules/test-standards.md`): Godot
|
||||
`test_[scenario]_[expected]`, Unity `[Scenario]_[Expected]`, Unreal
|
||||
`<Project>.[System].[Scenario]`.
|
||||
|
||||
Flag functions named generically (`test_1`, `test_run`, `testBasic`) as
|
||||
**naming issues** — they make failures harder to diagnose.
|
||||
@@ -157,7 +184,14 @@ it by name is harder to maintain when the formula changes.
|
||||
|
||||
## 5. Review Manual Evidence Quality (Visual/Feel / UI)
|
||||
|
||||
For each evidence document found, read it and evaluate:
|
||||
For each evidence document found, read it and evaluate the checks below.
|
||||
|
||||
**A UI story needs no evidence document.** When it has none, its retained
|
||||
screenshots are the evidence: apply only Screenshot / artefact completeness (an
|
||||
image of each screen the story changes — a screen a criterion only navigates to,
|
||||
such as the title screen after Quit, needs none of its own) and Date coverage (the images'
|
||||
dates). A UI story is ADEQUATE on those two — never INCOMPLETE for lacking a doc,
|
||||
its criterion linkage or a sign-off.
|
||||
|
||||
### Criterion linkage
|
||||
|
||||
@@ -167,13 +201,13 @@ Missing criteria mean a criterion was never verified.
|
||||
|
||||
### Sign-off completeness
|
||||
|
||||
Check for three sign-off lines (or equivalent fields):
|
||||
- Developer sign-off
|
||||
- Designer / art-lead sign-off (for Visual/Feel)
|
||||
- QA lead sign-off
|
||||
|
||||
If any are missing or blank: flag as INCOMPLETE — the story cannot be fully
|
||||
closed without all required sign-offs.
|
||||
What closes the story follows the evidence table in
|
||||
`.claude/docs/coding-standards.md` — the same rule `/story-done` applies, at every
|
||||
`qa.level`:
|
||||
- **Visual/Feel**: the evidence doc (from the test-evidence template) must have
|
||||
every sign-off row `[x] Approved`. A blank or missing row is INCOMPLETE.
|
||||
- **UI**: no sign-off is required — the retained screenshots close it. Note a
|
||||
sign-off if one exists; never mark a UI story INCOMPLETE for lacking one.
|
||||
|
||||
### Screenshot / artefact completeness
|
||||
|
||||
@@ -182,8 +216,8 @@ For Visual/Feel stories: Glob `production/qa/evidence/` for a retained image
|
||||
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: require the same retained screenshot of each screen touched,
|
||||
plus a walkthrough sequence (step-by-step interaction log).
|
||||
For UI stories: require the same retained screenshot of each screen touched.
|
||||
A walkthrough log is welcome but not required.
|
||||
|
||||
### Date coverage
|
||||
|
||||
@@ -202,8 +236,9 @@ 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 |
|
||||
| **MISSING** | No test or evidence found for a story type that requires it at this `qa.level` |
|
||||
| **NOT ASSESSED** | The review could not be performed for this story — see below |
|
||||
| **WAIVED (qa.level: minimal)** | A Logic, Integration or Config/Data story with no test evidence at `qa.level: minimal` — tests are not required, so nothing is missing; name it as waived |
|
||||
|
||||
> **`NOT ASSESSED` is required, and it is not a softer `MISSING`.**
|
||||
> The other three verdicts all presume the review actually ran. `MISSING` means
|
||||
@@ -226,7 +261,9 @@ 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.
|
||||
and demoting a real failure behind an access problem would bury it. `WAIVED`
|
||||
ranks below `ADEQUATE`: the overall verdict reads WAIVED only when every story
|
||||
in scope was waived, and the report names each waived story either way.
|
||||
|
||||
> Why this needed saying: evidence review **gates story completion**, and
|
||||
> `coding-standards.md` makes Logic, Integration, Visual/Feel and UI evidence BLOCKING. A verdict
|
||||
@@ -240,13 +277,14 @@ and demoting a real failure behind an access problem would bury it.
|
||||
> **Date**: [date]
|
||||
> **Scope**: [single story path | Sprint [N] | [system name]]
|
||||
> **Stories reviewed**: [N]
|
||||
> **Overall verdict**: ADEQUATE / INCOMPLETE / MISSING / NOT ASSESSED
|
||||
> **Overall verdict**: ADEQUATE / INCOMPLETE / MISSING / NOT ASSESSED / WAIVED
|
||||
> **qa.level**: [minimal | standard | full] — **testing.strict**: [the resolved per-type values, or "unset — coding-standards.md defaults"]
|
||||
|
||||
---
|
||||
|
||||
### Story-by-Story Results
|
||||
|
||||
#### [Story Title] — [Type] — [ADEQUATE/INCOMPLETE/MISSING/NOT ASSESSED]
|
||||
#### [Story Title] — [Type] — [ADEQUATE/INCOMPLETE/MISSING/NOT ASSESSED/WAIVED]
|
||||
|
||||
**Test/evidence path**: `[path]` (found) / (not found)
|
||||
|
||||
@@ -258,7 +296,7 @@ and demoting a real failure behind an access problem would bury it.
|
||||
|
||||
**Manual evidence quality** *(Visual/Feel/UI only)*:
|
||||
- Criterion linkage: [N/M criteria referenced]
|
||||
- Sign-offs: [Developer ✓ | Designer ✗ | QA Lead ✗]
|
||||
- Lead sign-off: [✓ approved | ✗ missing | deferred — reason] *(Visual/Feel only; a UI story needs none)*
|
||||
- Artefacts: [screenshots present / missing / N/A]
|
||||
- Freshness: [dated [date] — current / potentially stale]
|
||||
|
||||
@@ -274,8 +312,9 @@ and demoting a real failure behind an access problem would bury it.
|
||||
|-------|------|---------|--------|
|
||||
| [title] | Logic | ADEQUATE | None |
|
||||
| [title] | Integration | INCOMPLETE | Thin assertions (avg 1.2/function) |
|
||||
| [title] | Visual/Feel | INCOMPLETE | QA lead sign-off missing |
|
||||
| [title] | Visual/Feel | INCOMPLETE | Lead sign-off missing |
|
||||
| [title] | Logic | MISSING | No test file found |
|
||||
| [title] | Logic | WAIVED | No test — waived at `qa.level: minimal` |
|
||||
|
||||
**BLOCKING items** (must resolve before story can be closed): [N]
|
||||
**ADVISORY items** (should address before release): [N]
|
||||
|
||||
@@ -55,14 +55,17 @@ ls -t .github/ 2>/dev/null
|
||||
ls -t test-results/ 2>/dev/null
|
||||
```
|
||||
|
||||
For Godot projects: GdUnit4 outputs XML results compatible with JUnit format.
|
||||
Check `test-results/` for `.xml` files.
|
||||
For Godot projects: GdUnit4 outputs XML results compatible with JUnit format,
|
||||
under `reports/` (its default report folder, `res://reports/`). Check `reports/`,
|
||||
and any `test-results/` you saved runs into, for `.xml` files.
|
||||
|
||||
For Unity projects: game-ci test runner outputs NUnit XML to `test-results/`
|
||||
by default.
|
||||
|
||||
For Unreal projects: automation logs go to `Saved/Logs/`. Grep for
|
||||
`Result: Success` and `Result: Fail` patterns.
|
||||
`Result={Success}` and `Result={Fail}` — each test prints
|
||||
`Test Completed. Result={<status>}`
|
||||
(`docs/engine-reference/unreal/current-best-practices.md`, "Command Line").
|
||||
|
||||
### Option B — Local log files
|
||||
|
||||
@@ -86,15 +89,22 @@ Stop and ask the user which option to pursue.
|
||||
|
||||
For each CI log or result file found, parse:
|
||||
|
||||
**JUnit XML format** (GdUnit4 / Unity):
|
||||
**JUnit XML format** (GdUnit4):
|
||||
- Grep for `<testcase name=` to get test names
|
||||
- Grep for `<failure` or `<error` to identify failures
|
||||
- Parse `classname` and `name` attributes for full test identifiers
|
||||
|
||||
**NUnit XML format** (Unity — the file whose `<test-run>` element `/smoke-check`
|
||||
reads):
|
||||
- Each test is a `<test-case` element; its `fullname` attribute is the identifier
|
||||
- Its `result` attribute is `Passed`, `Failed`, `Inconclusive` or `Skipped`
|
||||
(`docs/engine-reference/unity/current-best-practices.md`, "Command Line");
|
||||
only `Passed` and `Failed` enter the history
|
||||
|
||||
**Plain text logs**:
|
||||
- Grep for pass/fail patterns:
|
||||
- Godot: `PASSED` / `FAILED` adjacent to test names
|
||||
- Unreal: `Result: Success` / `Result: Fail`
|
||||
- Unreal: `Result={Success}` / `Result={Fail}`
|
||||
- Unity: `Test passed` / `Test failed`
|
||||
|
||||
Build a table: `test_id → [run1_result, run2_result, run3_result, ...]`
|
||||
@@ -112,6 +122,11 @@ Flakiness thresholds:
|
||||
- **Low/suspected flakiness**: Fails in 1–5% of runs — monitor; may be
|
||||
genuinely rare failure
|
||||
|
||||
**With fewer than 3 runs, every finding is *suspected*, whatever its fail rate.**
|
||||
One failure in two runs reads as 50%, but it is one data point: do not
|
||||
quarantine it, label it suspected, and ask whether more run data is available.
|
||||
The tiers above, and quarantine, apply from 3 runs up.
|
||||
|
||||
For each flaky test, classify the likely cause:
|
||||
|
||||
### Cause classification
|
||||
@@ -136,10 +151,24 @@ or equality comparisons on floats to narrow down the cause.
|
||||
For each flaky test:
|
||||
|
||||
**Quarantine (High flakiness):**
|
||||
> "Quarantine this test immediately. Disable it in CI by adding
|
||||
> `@pytest.mark.skip` / `[Ignore]` / `GdUnitSkip` annotation. Log it in
|
||||
> `tests/regression-suite.md` quarantine section. The test is now opt-in only.
|
||||
> Fix the root cause before removing quarantine."
|
||||
> "Quarantine this test immediately. Skip it with the engine's own mechanism,
|
||||
> log it in the `tests/regression-suite.md` quarantine section, and fix the root
|
||||
> cause before removing quarantine."
|
||||
|
||||
Skip mechanisms, by engine — name only the one for the project's engine:
|
||||
- **Godot (gdUnit4), GDScript**: a skip parameter on the test function —
|
||||
`func test_x(_do_skip := true, _skip_reason := "flaky: [cause]")`. gdUnit4 reads
|
||||
the argument names `do_skip` and `skip_reason` (a leading `_` is allowed) in
|
||||
`addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd`, as of gdUnit4 6.1.3;
|
||||
confirm them there for the installed version.
|
||||
- **Godot (gdUnit4), C#**: **NOT SOURCEABLE** — gdUnit4's C# test attributes are
|
||||
not in the `addons/gdUnit4/` source, and `docs/engine-reference/godot/` does not
|
||||
cover them. Log it in the quarantine section and ask the user how their C#
|
||||
tests are skipped; do not invent an attribute.
|
||||
- **Unity (NUnit)**: `[Ignore("flaky: [cause]")]` — NUnit 3 requires the reason
|
||||
- **Unreal**: **NOT SOURCEABLE** — `docs/engine-reference/unreal/` documents no way
|
||||
to skip an automation test. Log it in the quarantine section and ask the user
|
||||
how their CI excludes a test; do not invent a flag.
|
||||
|
||||
**Investigate and fix soon (Moderate):**
|
||||
> "This test is intermittently unreliable. Root cause appears to be [cause].
|
||||
@@ -164,11 +193,11 @@ For each flaky test:
|
||||
|
||||
### Flaky Tests Found
|
||||
|
||||
| Test | System | Fail Rate | Likely Cause | Recommendation |
|
||||
|------|--------|-----------|--------------|----------------|
|
||||
| [test_name] | [system] | [N]% | Timing | Quarantine + fix async |
|
||||
| [test_name] | [system] | [N]% | Float comparison | Fix: use epsilon compare |
|
||||
| [test_name] | [system] | [N]% | Order dependency | Investigate teardown |
|
||||
| Test | System | Fail Rate | Confidence | Likely Cause | Recommendation |
|
||||
|------|--------|-----------|------------|--------------|----------------|
|
||||
| [test_name] | [system] | [N]% | confirmed | Timing | Quarantine + fix async |
|
||||
| [test_name] | [system] | [N]% | confirmed | Float comparison | Fix: use epsilon compare |
|
||||
| [test_name] | [system] | [N]% | suspected (fewer than 3 runs) | Order dependency | Collect more runs before acting |
|
||||
|
||||
### Clean Tests (no flakiness detected)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: test-helpers
|
||||
description: "Generate engine-specific test helper libraries — assertion utilities, factory functions, mocks in tests/helpers/. Reduces boilerplate."
|
||||
description: "Generate engine-specific test helper libraries — assertion utilities, factory functions, mocks in the engine's test folder. Reduces boilerplate."
|
||||
argument-hint: "[system-name | all | scaffold]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Bash(bash "*/.claude/skills/test-helpers/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
@@ -22,7 +22,16 @@ and assertion patterns are abstracted into helpers. This skill generates a
|
||||
`tests/helpers/` library tailored to the project's actual engine, language,
|
||||
and systems — so every developer writes less boilerplate and more assertions.
|
||||
|
||||
**Output:** `tests/helpers/` directory with engine-specific helper files
|
||||
**Output:** engine-specific helper files in the engine's **helper root** —
|
||||
the only place its test runner compiles them (`.claude/docs/directory-structure.md`):
|
||||
|
||||
| Engine | Helper root |
|
||||
|---|---|
|
||||
| Godot | `tests/helpers/` |
|
||||
| Unity | `Assets/Tests/EditMode/Helpers/` — inside the `EditModeTests` assembly `/test-setup` creates. If PlayMode tests need the same helpers, ask before creating `Assets/Tests/Helpers/TestHelpers.asmdef` and referencing it from both test assemblies. |
|
||||
| Unreal | `Source/<Module>/Private/Tests/Helpers/` |
|
||||
|
||||
`tests/helpers/` below means the helper root for the project's engine.
|
||||
|
||||
**When to run:**
|
||||
- After `/test-setup` scaffolds the framework (first time)
|
||||
@@ -86,10 +95,13 @@ If the engine is not configured in either source: "Engine not configured. Run `/
|
||||
|
||||
## 3. Load Existing Test Patterns
|
||||
|
||||
Scan the test directory for patterns already in use:
|
||||
Scan the engine's test root for patterns already in use (Godot `tests/`, Unity
|
||||
`Assets/Tests/`, Unreal `Source/<Module>/Private/Tests/`):
|
||||
|
||||
```
|
||||
Glob pattern="tests/**/*_test.*" (all test files)
|
||||
Glob pattern="tests/**/*_test.*" (Godot)
|
||||
Glob pattern="Assets/Tests/**/*Tests.cs" (Unity)
|
||||
Glob pattern="Source/*/Private/Tests/**/*.cpp" (Unreal)
|
||||
```
|
||||
|
||||
For a representative sample (up to 5 files), read the test files and extract:
|
||||
@@ -163,11 +175,14 @@ static func assert_signal_emitted(
|
||||
signal_name: String,
|
||||
action: Callable
|
||||
) -> void:
|
||||
var emitted := false
|
||||
obj.connect(signal_name, func(_args): emitted = true)
|
||||
# A lambda captures a local by value: `emitted = true` inside it would set
|
||||
# the lambda's own copy. Mutate a Dictionary it shares instead. `...args`
|
||||
# (4.5+) accepts a signal with any number of arguments.
|
||||
var state := {"emitted": false}
|
||||
obj.connect(signal_name, func(...args): state.emitted = true)
|
||||
action.call()
|
||||
# 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)
|
||||
FAIL_IF(not state.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(
|
||||
@@ -175,11 +190,11 @@ static func assert_signal_not_emitted(
|
||||
signal_name: String,
|
||||
action: Callable
|
||||
) -> void:
|
||||
var emitted := false
|
||||
obj.connect(signal_name, func(_args): emitted = true)
|
||||
var state := {"emitted": false} # a Dictionary, as above
|
||||
obj.connect(signal_name, func(...args): state.emitted = true)
|
||||
action.call()
|
||||
# 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)
|
||||
FAIL_IF(state.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:
|
||||
@@ -213,17 +228,19 @@ static func make_player(health: int = 100) -> Node:
|
||||
**Scene helper** (`tests/helpers/scene_runner_helper.gd`):
|
||||
|
||||
```gdscript
|
||||
## Utilities for scene-based integration tests.
|
||||
## Wraps GdUnitSceneRunner for common patterns.
|
||||
## Utilities for scene-based integration tests. For input simulation and frame
|
||||
## stepping, use gdUnit4's own `scene_runner()` from inside the suite.
|
||||
|
||||
class_name SceneRunnerHelper
|
||||
extends GdUnitTestSuite
|
||||
extends RefCounted
|
||||
|
||||
## Load a scene and wait one frame for _ready() to complete.
|
||||
func load_scene_and_wait(scene_path: String) -> Node:
|
||||
var scene = load(scene_path).instantiate()
|
||||
add_child(scene)
|
||||
await get_tree().process_frame
|
||||
## Load a scene under `host` — the calling test suite, which passes `self` —
|
||||
## and wait one frame for _ready() to complete. A plain class, so the runner
|
||||
## never discovers this file as a suite with zero tests.
|
||||
static func load_scene_and_wait(host: Node, scene_path: String) -> Node:
|
||||
var scene: Node = load(scene_path).instantiate()
|
||||
host.add_child(scene)
|
||||
await host.get_tree().process_frame
|
||||
return scene
|
||||
```
|
||||
|
||||
@@ -231,7 +248,7 @@ func load_scene_and_wait(scene_path: String) -> Node:
|
||||
|
||||
### Unity (NUnit / C#)
|
||||
|
||||
**Base helper** (`tests/helpers/GameAssertions.cs`):
|
||||
**Base helper** (`Assets/Tests/EditMode/Helpers/GameAssertions.cs`):
|
||||
|
||||
```csharp
|
||||
using NUnit.Framework;
|
||||
@@ -271,7 +288,7 @@ public static class GameAssertions
|
||||
}
|
||||
```
|
||||
|
||||
**Factory helper** (`tests/helpers/GameFactory.cs`):
|
||||
**Factory helper** (`Assets/Tests/EditMode/Helpers/GameFactory.cs`):
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
@@ -303,7 +320,7 @@ public static class GameFactory
|
||||
|
||||
### Unreal Engine (C++)
|
||||
|
||||
**Base helper** (`tests/helpers/GameTestHelpers.h`):
|
||||
**Base helper** (`Source/<Module>/Private/Tests/Helpers/GameTestHelpers.h`):
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
@@ -362,7 +379,7 @@ namespace GameTestHelpers
|
||||
|
||||
For `[system-name]` or `all` modes, generate a helper per system:
|
||||
|
||||
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:
|
||||
Read only the GDD sections this needs — `Grep pattern="^## ([0-9]+\. )?(Formulas|Edge Cases|Detailed Rules|Detailed Design)" path="design/gdd/[system].md" output_mode="content" -A 30` (the optional number matches a reverse-documented GDD's `## 4. Formulas`) — 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
|
||||
@@ -412,16 +429,16 @@ Present a summary of what will be created:
|
||||
```
|
||||
## Test Helpers to Create
|
||||
|
||||
Base helpers (engine: [engine]):
|
||||
- tests/helpers/game_assertions.[ext]
|
||||
- tests/helpers/game_factory.[ext]
|
||||
Base helpers (engine: [engine], helper root: [helper root]):
|
||||
- [helper root]/game_assertions.[ext]
|
||||
- [helper root]/game_factory.[ext]
|
||||
[engine-specific extras]
|
||||
|
||||
System helpers ([mode]):
|
||||
- tests/helpers/[system]_factory.[ext] ← from [system] GDD
|
||||
- [helper root]/[system]_factory.[ext] ← from [system] GDD
|
||||
```
|
||||
|
||||
Ask: "May I write these helper files to `tests/helpers/`?"
|
||||
Ask: "May I write these helper files to `[helper root]`?"
|
||||
|
||||
**Never overwrite existing files.** If a file already exists, report:
|
||||
"Skipping `[path]` — already exists. Remove the file manually if you want it
|
||||
@@ -432,7 +449,7 @@ After writing: Verdict: **COMPLETE** — helper files created.
|
||||
"Helper files created. To use them in a test:
|
||||
- Godot: `class_name` is auto-imported — no explicit import needed
|
||||
- Unity: Add `using` directive or reference the test assembly
|
||||
- Unreal: `#include \"tests/helpers/GameTestHelpers.h\"`"
|
||||
- Unreal: `#include \"Tests/Helpers/GameTestHelpers.h\"` (from inside the module)"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Bash, Write, Bash(bash "*/.claude/skills/test-s
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow,qa.level`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -45,8 +45,11 @@ A test framework installed at sprint four costs 3 sprints.
|
||||
- Glob `tests/` — does the directory exist?
|
||||
- Glob `tests/unit/` and `tests/integration/` — do subdirectories exist?
|
||||
- Glob `.github/workflows/` — does a CI workflow file exist?
|
||||
- Glob `tests/gdunit4_runner.gd` (Godot) or `tests/EditMode/` (Unity) or
|
||||
`Source/Tests/` (Unreal) for engine-specific artifacts.
|
||||
- Glob `addons/gdUnit4/bin/GdUnitCmdTool.gd` (Godot — note the capital U) or
|
||||
`Assets/Tests/EditMode/` (Unity) or `Source/*/Private/Tests/` (Unreal) for
|
||||
engine-specific artifacts. These are the **test roots** in
|
||||
`.claude/docs/directory-structure.md`; tests anywhere else are never compiled
|
||||
on Unity or Unreal.
|
||||
|
||||
3. **Report findings**:
|
||||
- "Engine: [engine]. Test directory: [found / not found]. CI workflow: [found / not found]."
|
||||
@@ -70,11 +73,15 @@ Based on the engine detected and the existing state, present a plan:
|
||||
I will create the following (skipping any that already exist):
|
||||
|
||||
tests/
|
||||
unit/ — Isolated unit tests for formulas, state, and logic
|
||||
integration/ — Cross-system tests and save/load round-trips
|
||||
unit/ — Isolated unit tests for formulas, state, and logic (Godot only)
|
||||
integration/ — Cross-system tests and save/load round-trips (Godot only)
|
||||
smoke/ — Critical path test list (15-minute manual gate)
|
||||
README.md — Test framework documentation
|
||||
|
||||
[Unity/Unreal: unit and integration tests go under the engine's test root
|
||||
instead — Unity Assets/Tests/EditMode|PlayMode/, Unreal
|
||||
Source/<Module>/Private/Tests/ — because neither compiles code in tests/]
|
||||
|
||||
production/qa/
|
||||
evidence/ — Screenshot and manual test sign-off records
|
||||
|
||||
@@ -102,7 +109,7 @@ After approval, create the following files:
|
||||
|
||||
### `tests/README.md`
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
# Test Infrastructure
|
||||
|
||||
**Engine**: [engine name + version]
|
||||
@@ -119,17 +126,18 @@ tests/
|
||||
smoke/ # Critical path test list for /smoke-check gate
|
||||
```
|
||||
|
||||
[Unity/Unreal — replace the unit/integration lines: unit and integration tests
|
||||
live under the engine's test root, `Assets/Tests/EditMode|PlayMode/[System]/`
|
||||
or `Source/<Module>/Private/Tests/[System]/`; `tests/` keeps this README and
|
||||
`smoke/`. Every `tests/unit/` path below means that test root.]
|
||||
|
||||
```
|
||||
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.
|
||||
> **Manual evidence lives under `production/qa/evidence/`, not `tests/`** — that
|
||||
> is where every consumer reads it.
|
||||
|
||||
## Running Tests
|
||||
|
||||
@@ -137,9 +145,15 @@ production/qa/
|
||||
|
||||
## Test Naming
|
||||
|
||||
- **Files**: `[system]_[feature]_test.[ext]`
|
||||
- **Functions**: `test_[scenario]_[expected]`
|
||||
- **Example**: `combat_damage_test.gd` → `test_base_attack_returns_expected_damage()`
|
||||
Names follow the engine's language (`.claude/rules/test-standards.md`):
|
||||
- **Godot**: file `[system]_[feature]_test.gd`, function `test_[scenario]_[expected]`
|
||||
— `combat_damage_test.gd` → `test_base_attack_returns_expected_damage()`
|
||||
- **Unity**: class `[System]Tests` in `[System]Tests.cs`, method `[Scenario]_[Expected]`
|
||||
— `CombatTests.cs` → `BaseAttack_ReturnsExpectedDamage()`
|
||||
- **Unreal**: class `F[System][Scenario]Test`, test name `<Project>.[System].[Scenario]`
|
||||
— `FCombatBaseAttackTest` → `<Project>.Combat.BaseAttack`
|
||||
[`<Project>` is the root the filter in `commands.test` uses — write it out:
|
||||
the project name, or the distinct root `/setup-engine` chose]
|
||||
|
||||
## Story Type → Test Evidence
|
||||
|
||||
@@ -148,38 +162,57 @@ production/qa/
|
||||
| Logic | Automated unit test — must pass | `tests/unit/[system]/` |
|
||||
| Integration | Integration test OR playtest doc | `tests/integration/[system]/` |
|
||||
| Visual/Feel | Screenshot + lead sign-off | `production/qa/evidence/` |
|
||||
| UI | Manual walkthrough OR interaction test | `production/qa/evidence/` |
|
||||
| UI | Retained screenshot of each screen touched | `production/qa/evidence/` |
|
||||
| Config/Data | Smoke check pass | `production/qa/smoke-*.md` |
|
||||
|
||||
## CI
|
||||
|
||||
Tests run automatically on every push to `main` and on every pull request.
|
||||
A failed test suite blocks merging.
|
||||
```
|
||||
```
|
||||
````
|
||||
|
||||
The README and this skill's completion summary name the same evidence path —
|
||||
`production/qa/evidence/` is where `/smoke-check`, `/test-evidence-review`,
|
||||
`/qa-plan` and the evidence table in `.claude/docs/coding-standards.md` read,
|
||||
so a `tests/evidence/` would be a directory nothing reads.
|
||||
|
||||
### `production/qa/evidence/.gitkeep`
|
||||
|
||||
Create it empty. Git does not keep an empty directory, and this is where
|
||||
`/story-done`, `/smoke-check` and `/test-evidence-review` look for screenshots and
|
||||
sign-off records — the completion summary lists it, so it must exist.
|
||||
|
||||
### Engine-specific files
|
||||
|
||||
#### Godot 4 (`Engine: Godot`)
|
||||
|
||||
Create `tests/gdunit4_runner.gd`:
|
||||
**Do not write a runner script.** gdUnit4 ships its own command-line runner,
|
||||
`res://addons/gdUnit4/bin/GdUnitCmdTool.gd`. The command CI, `/smoke-check`
|
||||
and `commands.test` use is:
|
||||
|
||||
```gdscript
|
||||
# GdUnit4 test runner — invoked by CI and /smoke-check
|
||||
# Usage: godot --headless --script tests/gdunit4_runner.gd
|
||||
extends SceneTree
|
||||
|
||||
func _init() -> void:
|
||||
var runner := load("res://addons/gdunit4/GdUnitRunner.gd")
|
||||
if runner == null:
|
||||
push_error("GdUnit4 not found. Install via AssetLib or addons/.")
|
||||
quit(1)
|
||||
return
|
||||
var instance = runner.new()
|
||||
instance.run_tests()
|
||||
quit(0)
|
||||
```bash
|
||||
godot --headless --path . --import
|
||||
godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode
|
||||
```
|
||||
|
||||
Run the import first. A fresh clone has no `.godot/` class cache, and a run
|
||||
without one exits **1** — `GdUnitCmdTool.gd` did not load (`Failed to load
|
||||
script`), so no test ran. A cache older than a new `class_name` fails valid
|
||||
code with 105. The CI action imports on its own.
|
||||
|
||||
Exit code **0** when every test passes and **100** when any fails — verified
|
||||
on Godot 4.6.1 with gdUnit4 6.1.3. **101** means every test passed but a test
|
||||
leaked nodes: a warning, not a failure. 103 and 104 mean gdUnit4 could not run
|
||||
(headless refused, Godot older than 4.3); 105 means a test script does not parse. `-a res://tests` runs every suite
|
||||
under `tests/`; `--ignoreHeadlessMode` is required because gdUnit4 otherwise
|
||||
refuses to run headless. `--remote-debug tcp://127.0.0.1:0` is required too —
|
||||
it is what gdUnit4's own `runtest` script passes. Without it a script error
|
||||
opens Godot's interactive debugger, and the run waits at a `debug>` prompt
|
||||
forever instead of exiting 105. The flag makes every run print two `ERROR:`
|
||||
lines about the remote port (`127.0.0.1:0`); they are expected, not a failure.
|
||||
A run that finds no tests prints `No test cases found` and exits 0 — that is
|
||||
not a pass. The folder is `addons/gdUnit4/` with a **capital U**.
|
||||
|
||||
Create `tests/unit/.gdignore_placeholder` with content:
|
||||
`# Unit tests go here — one subdirectory per system (e.g., tests/unit/combat/)`
|
||||
|
||||
@@ -191,44 +224,116 @@ Note in the README: **Installing GdUnit4**
|
||||
1. Open Godot → AssetLib → search "GdUnit4" → Download & Install
|
||||
2. Enable the plugin: Project → Project Settings → Plugins → GdUnit4 ✓
|
||||
3. Restart the editor
|
||||
4. Verify: res://addons/gdunit4/ exists
|
||||
4. Verify: res://addons/gdUnit4/bin/GdUnitCmdTool.gd exists (capital U)
|
||||
```
|
||||
|
||||
#### Unity (`Engine: Unity`)
|
||||
|
||||
Create `tests/EditMode/` placeholder file `tests/EditMode/README.md`:
|
||||
```markdown
|
||||
# Edit Mode Tests
|
||||
Unit tests that run without entering Play Mode.
|
||||
Use for pure logic: formulas, state machines, data validation.
|
||||
Assembly definition required: `tests/EditMode/EditModeTests.asmdef`
|
||||
Tests live under **`Assets/Tests/`** — Unity compiles only `Assets/` and
|
||||
`Packages/`. A test under `tests/` is never compiled, and the run then reports
|
||||
**0 tests, `Passed`, exit 0** (verified on 6000.3.23f1): a false pass.
|
||||
|
||||
First check the Test Framework package:
|
||||
`grep -q 'com.unity.test-framework' Packages/manifest.json`. Without it
|
||||
`-runTests` does not fail — it hangs. If absent, ask to add
|
||||
`"com.unity.test-framework"` to `dependencies` at the version your editor
|
||||
bundles. Unity 6 releases bundle different ones — 1.6.0 in 6000.3.23f1, 1.5.1 in
|
||||
6000.1.0f1 — so read it rather than copy a number: on Windows it is the
|
||||
`version` in `Data/Resources/PackageManager/BuiltInPackages/com.unity.test-framework/package.json`
|
||||
under the folder that holds `Unity.exe`.
|
||||
|
||||
Create `Assets/Tests/EditMode/EditModeTests.asmdef` — unit tests, no Play Mode:
|
||||
```json
|
||||
{
|
||||
"name": "EditModeTests",
|
||||
"references": ["UnityEngine.TestRunner", "UnityEditor.TestRunner"],
|
||||
"includePlatforms": ["Editor"],
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": ["nunit.framework.dll"],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": ["UNITY_INCLUDE_TESTS"]
|
||||
}
|
||||
```
|
||||
|
||||
Create `tests/PlayMode/README.md`:
|
||||
```markdown
|
||||
# Play Mode Tests
|
||||
Integration tests that run in a real game scene.
|
||||
Use for cross-system interactions, physics, and coroutines.
|
||||
Assembly definition required: `tests/PlayMode/PlayModeTests.asmdef`
|
||||
```
|
||||
Create `Assets/Tests/PlayMode/PlayModeTests.asmdef` — integration tests in a
|
||||
running scene: the same JSON with `"name": "PlayModeTests"` and
|
||||
`"includePlatforms": []`.
|
||||
|
||||
Note in the README: **Enabling Unity Test Framework**
|
||||
> **A test assembly cannot see code in the default `Assembly-CSharp`.** An
|
||||
> `.asmdef` can reference only other `.asmdef`s. If the game's scripts have no
|
||||
> `.asmdef` of their own, ask before creating one (e.g. `Assets/Scripts/Game.asmdef`)
|
||||
> and add `"Game"` to both test assemblies' `references`. Without it the first
|
||||
> test that names a game class fails to compile. Moving scripts into an
|
||||
> `.asmdef` changes what they can see, so before creating it:
|
||||
>
|
||||
> - **List the packages the scripts use.** `Assembly-CSharp` references every
|
||||
> package on its own; an `.asmdef` references only what it names. Read the
|
||||
> scripts' `using` lines and add the matching assemblies — commonly
|
||||
> `"Unity.InputSystem"`, `"Unity.TextMeshPro"`, `"UnityEngine.UI"`:
|
||||
> `{ "name": "Game", "references": ["Unity.InputSystem", "Unity.TextMeshPro"] }`.
|
||||
> Name only packages the project has installed.
|
||||
> - **Give each `Editor/` folder under it its own `.asmdef`** with
|
||||
> `"includePlatforms": ["Editor"]` and `"references": ["Game"]`. Otherwise
|
||||
> editor scripts join the runtime assembly, and `using UnityEditor;` breaks the
|
||||
> player build.
|
||||
|
||||
Note in the README: **Running Unity tests** (use the editor executable —
|
||||
`Unity` on `PATH` may be Unity's separate CLI, not the editor)
|
||||
```
|
||||
Window → General → Test Runner
|
||||
(Unity Test Framework is included by default in Unity 2019+)
|
||||
"<Unity editor>" -batchmode -runTests -projectPath . -testPlatform EditMode -testResults test-results/editmode.xml
|
||||
"<Unity editor>" -batchmode -runTests -projectPath . -testPlatform PlayMode -testResults test-results/playmode.xml
|
||||
```
|
||||
Exit **0** when every test passes, **2** when any fails. Exit 1 or 3 is a FAIL
|
||||
too: 1 is a compile error, which writes no results file, and 3 a failed run.
|
||||
So is 4 (an unknown `-testPlatform`), and any other non-zero exit.
|
||||
Delete `test-results/editmode.xml` before each run so an old file is never read
|
||||
as a new result. Read the `<test-run>`
|
||||
element of the results file: `testcasecount="0"` means nothing was compiled or
|
||||
found — report it as not assessed, never as a pass. Do not add `-quit`;
|
||||
`-runTests` exits by itself. Play Mode is the second line: a separate run with
|
||||
its own results file, read the same way, and deleted before each run the same
|
||||
way. An Edit Mode run never runs the tests in `Assets/Tests/PlayMode/`, so
|
||||
`/smoke-check` runs both whenever that folder holds tests.
|
||||
|
||||
#### Unreal Engine (`Engine: Unreal` or `Engine: UE5`)
|
||||
|
||||
Create `Source/Tests/README.md`:
|
||||
Tests live **inside the game module**: `Source/<Module>/Private/Tests/`, where
|
||||
`<Module>` is the primary game module (for a C++ project, the `.uproject` name).
|
||||
UnrealBuildTool compiles only module folders — a tests folder directly under
|
||||
`Source/` is not a module, so a test there is silently never built and every
|
||||
run reports `No automation tests matched`.
|
||||
|
||||
Create `Source/<Module>/Private/Tests/README.md`. `<Project>.` in it — and
|
||||
`[ProjectName].` in the CI filter below — is the test root the filter in
|
||||
`commands.test` uses: the project name, or the distinct root `/setup-engine`
|
||||
chose when the project's name is also an engine area. Write that root:
|
||||
```markdown
|
||||
# Unreal Automation Tests
|
||||
Tests use the UE Automation Testing Framework.
|
||||
Run via: Session Frontend → Automation → select "MyGame." tests
|
||||
Or headlessly: UnrealEditor -nullrhi -ExecCmds="Automation RunTests MyGame.; Quit"
|
||||
Tests use the UE Automation Testing Framework and compile with this module.
|
||||
Wrap each test file in `#if WITH_DEV_AUTOMATION_TESTS` … `#endif`.
|
||||
Flags: `EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter`
|
||||
(there is no `GameFilter` flag).
|
||||
|
||||
Test class naming: F[SystemName]Test
|
||||
Test category naming: "MyGame.[System].[Feature]"
|
||||
Run via: Session Frontend → Automation → select "<Project>." tests
|
||||
Or headlessly from the project root, after building the editor target — on a
|
||||
fresh checkout the editor exits before any test runs:
|
||||
"<UE root>/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe" <Project>Editor Win64 Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject"
|
||||
"<UE root>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "$(pwd -W 2>/dev/null || pwd)/<Project>.uproject" -ExecCmds="Automation RunTests <Project>.; Quit" -unattended -nullrhi -stdout -FullStdOutLogOutput
|
||||
The project path must be absolute: UE does not find a relative one (exit 1,
|
||||
"Project file not found"). Those two lines are Windows'. On Linux build with
|
||||
`Engine/Build/BatchFiles/Linux/Build.sh <Project>Editor Linux Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject"` and run
|
||||
the tests with `Engine/Binaries/Linux/UnrealEditor` and the same arguments; on
|
||||
macOS build with `Engine/Build/BatchFiles/Mac/Build.sh <Project>Editor Mac Development -Project="$(pwd -W 2>/dev/null || pwd)/<Project>.uproject"`
|
||||
— Epic documents no command-line editor inside `UnrealEditor.app` for the test
|
||||
run (see `docs/engine-reference/unreal/current-best-practices.md`, "Command Line").
|
||||
|
||||
Read the output, not the exit code: a failing test and a run that matched nothing both exit 255.
|
||||
`Result={Fail}` is a failure; `No automation tests matched` means no test was
|
||||
built or named `<Project>.…`.
|
||||
|
||||
Test class naming: F[System][Scenario]Test — one class per test; a second
|
||||
test reusing a class name fails to link
|
||||
Test name: "<Project>.[System].[Scenario]"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -252,6 +357,14 @@ jobs:
|
||||
test:
|
||||
name: Run GdUnit4 Tests
|
||||
runs-on: ubuntu-latest
|
||||
# The action publishes its results as a check run. A new repository's
|
||||
# token is read-only, and without checks: write the job fails even when
|
||||
# every test passes. If you protect main, require the `Run GdUnit4 Tests` job
|
||||
# check, not `test-results`: that check run concludes success even when a
|
||||
# test fails.
|
||||
permissions:
|
||||
contents: read
|
||||
checks: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -259,10 +372,15 @@ jobs:
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
# godot-version must be a full release such as 4.6.1 (`godot --version`
|
||||
# shows it); VERSION.md's "4.6" is not one. version: installed runs the
|
||||
# gdUnit4 committed in addons/ -- without it the action deletes that
|
||||
# copy and installs the latest release, which may not match your tests.
|
||||
- name: Run GdUnit4 Tests
|
||||
uses: MikeSchulze/gdUnit4-action@v1
|
||||
uses: godot-gdunit-labs/gdUnit4-action@v1
|
||||
with:
|
||||
godot-version: '[VERSION FROM docs/engine-reference/godot/VERSION.md]'
|
||||
godot-version: '[FULL GODOT VERSION, e.g. 4.6.1]'
|
||||
version: 'installed'
|
||||
paths: |
|
||||
tests/unit
|
||||
tests/integration
|
||||
@@ -343,21 +461,36 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
name: Run UE Automation Tests
|
||||
runs-on: self-hosted # UE requires a local runner with the editor installed
|
||||
runs-on: [self-hosted, windows] # UE requires a local runner with the editor installed
|
||||
|
||||
# The quoted "{0}" in each `shell:` below: the Windows runner passes bash
|
||||
# its script path unquoted, so with plain `shell: bash` every step fails
|
||||
# ("No such file or directory") when the runner's folder has a space.
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
# Binaries/ is gitignored, so a fresh checkout has no compiled game
|
||||
# module: without this step the editor stops with "The game module could
|
||||
# not be found" before running any test. UnrealBuildTool.exe, not
|
||||
# Build.bat -- from bash, Build.bat fails on an engine path with spaces.
|
||||
- name: Build Editor Target
|
||||
run: |
|
||||
"$UE_ROOT/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.exe" [ProjectName]Editor Win64 Development \
|
||||
-Project="${{ github.workspace }}/[ProjectName].uproject"
|
||||
shell: bash --noprofile --norc -eo pipefail "{0}"
|
||||
|
||||
# -stdout -FullStdOutLogOutput: without them the editor prints nothing
|
||||
# here, and the results are only in Saved/Logs/.
|
||||
- name: Run Automation Tests
|
||||
run: |
|
||||
"$UE_EDITOR_PATH" "${{ github.workspace }}/[ProjectName].uproject" \
|
||||
"$UE_ROOT/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "${{ github.workspace }}/[ProjectName].uproject" \
|
||||
-nullrhi -nosound \
|
||||
-ExecCmds="Automation RunTests MyGame.; Quit" \
|
||||
-log -unattended
|
||||
shell: bash
|
||||
-ExecCmds="Automation RunTests [ProjectName].; Quit" \
|
||||
-unattended -stdout -FullStdOutLogOutput
|
||||
shell: bash --noprofile --norc -eo pipefail "{0}"
|
||||
|
||||
- name: Upload Logs
|
||||
if: always()
|
||||
@@ -367,8 +500,11 @@ jobs:
|
||||
path: Saved/Logs/
|
||||
```
|
||||
|
||||
Note: UE CI requires a self-hosted runner with Unreal Editor installed.
|
||||
Set the `UE_EDITOR_PATH` environment variable on the runner.
|
||||
Note: UE CI requires a self-hosted Windows runner with Unreal Editor installed.
|
||||
The `windows` label keeps the job off any Linux self-hosted runner the
|
||||
repository also has. Set the `UE_ROOT` environment variable on the runner to the engine folder
|
||||
(e.g. `C:/Program Files/Epic Games/UE_5.7`). `[ProjectName]Editor` is the
|
||||
editor target in `Source/[ProjectName]Editor.Target.cs`.
|
||||
|
||||
---
|
||||
|
||||
@@ -417,25 +553,34 @@ Test infrastructure created for [engine].
|
||||
|
||||
Files created:
|
||||
- tests/README.md
|
||||
- tests/unit/ (directory)
|
||||
- tests/integration/ (directory)
|
||||
- tests/unit/ and tests/integration/ (Godot) — or the engine's test root:
|
||||
Unity Assets/Tests/EditMode/ and PlayMode/, Unreal Source/<Module>/Private/Tests/
|
||||
- tests/smoke/critical-paths.md
|
||||
- production/qa/evidence/ (directory)
|
||||
- production/qa/evidence/.gitkeep
|
||||
[engine-specific files]
|
||||
- .github/workflows/tests.yml
|
||||
|
||||
Next steps:
|
||||
1. [Engine-specific install step, e.g., "Install GdUnit4 via AssetLib"]
|
||||
2. Write your first test: create tests/unit/[first-system]/[system]_test.[ext]
|
||||
2. Write your first test in the engine's test root:
|
||||
tests/unit/[system]/[system]_[feature]_test.gd (Godot),
|
||||
Assets/Tests/EditMode/[System]Tests.cs (Unity), or
|
||||
Source/<Module>/Private/Tests/[System]Test.cpp (Unreal)
|
||||
3. Run `/qa-plan sprint` before your first sprint to classify stories and set
|
||||
test evidence requirements
|
||||
test evidence requirements. At `workflow: minimal` — the default — skip
|
||||
this: there are no sprints. At `qa.level: minimal`, also the default, tests
|
||||
are waived, so `/dev-story` writes none. Raise `qa.level` with `/settings`
|
||||
to have it write them
|
||||
4. `/smoke-check` before every QA hand-off
|
||||
|
||||
Gate note: /gate-check Technical Setup → Pre-Production now requires:
|
||||
- tests/ directory with unit/ and integration/ subdirectories
|
||||
- the engine's test root: tests/unit/ and tests/integration/ (Godot),
|
||||
Assets/Tests/EditMode/ and Assets/Tests/PlayMode/ (Unity), or
|
||||
Source/<Module>/Private/Tests/ (Unreal)
|
||||
- .github/workflows/tests.yml
|
||||
- At least one example test file
|
||||
Run /test-setup and write one example test before advancing.
|
||||
(At `workflow: minimal` that gate requires only the engine.)
|
||||
|
||||
Verdict: **COMPLETE** — test framework scaffolded and CI/CD wired up.
|
||||
```
|
||||
|
||||
@@ -40,9 +40,9 @@ pointers in the templates name the exact section to read.
|
||||
|
||||
**`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 +
|
||||
`docs.density` explicitly to vary depth alone: `terse` (the default, via `rigor: minimal`) = wireframe descriptions +
|
||||
interaction bullets; `balanced` = wireframes + paragraph descriptions of flows
|
||||
(default); `thorough` = full prose including user-research summaries and
|
||||
(`rigor: standard`); `thorough` = full prose including user-research summaries and
|
||||
alternative flow considerations. Apply it to every section you author.
|
||||
|
||||
## 1. Parse Arguments & Determine Mode
|
||||
@@ -81,7 +81,8 @@ comes from arriving informed.
|
||||
|
||||
### 2a: Required Reads
|
||||
|
||||
- **Game concept**: Read `design/gdd/game-concept.md` — if missing, warn:
|
||||
- **Game concept**: Read `design/gdd/game-concept.md` — or `design/game-brief.md`,
|
||||
the one-page brief that replaces it at `rigor: minimal` — if neither exists, warn:
|
||||
> "No game concept found. Run `/brainstorm` first to establish the game's
|
||||
> foundation before designing UX."
|
||||
> Continue anyway if the user asks.
|
||||
@@ -123,7 +124,11 @@ Grep pattern="^#+ .*UI Requirements" glob="design/gdd/*.md" output_mode="content
|
||||
```
|
||||
|
||||
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
|
||||
the match count against it. Count system GDDs only: `game-concept.md`,
|
||||
`systems-index.md`, `game-pillars.md`, `gameplay-tags.md`, `entity-registry.md`,
|
||||
`fixture-swap-ledger.md`, `sound-bible.md` and any `gdd-cross-review-*.md` live
|
||||
there too, but they are not systems and have no UI to aggregate.
|
||||
**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
|
||||
@@ -200,7 +205,8 @@ Then ask: "Anything else I should read before we start, or shall we proceed?"
|
||||
|
||||
Before creating a skeleton, check if the target output file already exists.
|
||||
|
||||
Glob `design/ux/[filename].md` (where `[filename]` is the resolved output path from Phase 1).
|
||||
Glob the resolved output path from Phase 1 — `design/ux/[filename].md`, or
|
||||
`design/accessibility-requirements.md` in `accessibility` mode.
|
||||
|
||||
**If the file exists — retrofit mode:**
|
||||
- Read the file in full
|
||||
@@ -211,15 +217,25 @@ Glob `design/ux/[filename].md` (where `[filename]` is the resolved output path f
|
||||
>
|
||||
> | Section | Status |
|
||||
> |---------|--------|
|
||||
> | Overview & Context | [Complete / Empty / Placeholder] |
|
||||
> | Player Journey Integration | ... |
|
||||
> | Screen Layout & Information Architecture | ... |
|
||||
> | Interaction Model | ... |
|
||||
> | Feedback & State Communication | ... |
|
||||
> | Purpose & Player Need | [Complete / Empty / Placeholder] |
|
||||
> | Player Context on Arrival | ... |
|
||||
> | Navigation Position | ... |
|
||||
> | Entry & Exit Points | ... |
|
||||
> | Layout Specification | ... |
|
||||
> | States & Variants | ... |
|
||||
> | Interaction Map | ... |
|
||||
> | Data Requirements | ... |
|
||||
> | Events Fired | ... |
|
||||
> | Transitions & Animations | ... |
|
||||
> | Input Method Completeness Checklist | ... |
|
||||
> | Accessibility | ... |
|
||||
> | Edge Cases & Error States | ... |
|
||||
> | Localization Considerations | ... |
|
||||
> | Acceptance Criteria | ... |
|
||||
> | Open Questions | ... |
|
||||
>
|
||||
> (Rows are the skeleton's own `##` headings for the active mode — the list above is
|
||||
> UX spec mode; HUD and accessibility modes list their skeleton's headings.)
|
||||
>
|
||||
> I'll work on the [N] incomplete sections only — existing content will not be overwritten."
|
||||
|
||||
- Skip Section 3 (skeleton creation) — the file already exists
|
||||
@@ -251,6 +267,7 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
> **Author**: [user + ux-designer]
|
||||
> **Last Updated**: [today's date]
|
||||
> **Journey Phase(s)**: [from context]
|
||||
> **Platform Target**: [target platforms and input methods from 2h]
|
||||
> **Template**: UX Spec
|
||||
|
||||
---
|
||||
@@ -281,7 +298,7 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
## Layout Specification
|
||||
|
||||
### Information Hierarchy
|
||||
### ASCII Wireframe
|
||||
|
||||
[To be designed]
|
||||
|
||||
@@ -293,7 +310,7 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
[To be designed]
|
||||
|
||||
### ASCII Wireframe
|
||||
### Information Hierarchy
|
||||
|
||||
[To be designed]
|
||||
|
||||
@@ -311,6 +328,12 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
---
|
||||
|
||||
## Data Requirements
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Events Fired
|
||||
|
||||
[To be designed]
|
||||
@@ -323,7 +346,7 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
---
|
||||
|
||||
## Data Requirements
|
||||
## Input Method Completeness Checklist
|
||||
|
||||
[To be designed]
|
||||
|
||||
@@ -362,6 +385,7 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
> **Status**: In Design
|
||||
> **Author**: [user + ux-designer]
|
||||
> **Last Updated**: [today's date]
|
||||
> **Platform Targets**: [target platforms and input methods from 2h]
|
||||
> **Template**: HUD Design
|
||||
|
||||
---
|
||||
@@ -390,19 +414,37 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
---
|
||||
|
||||
## HUD Elements
|
||||
## HUD Element Specifications
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Dynamic Behaviors
|
||||
## HUD States by Gameplay Context
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Platform & Input Variants
|
||||
## Information Hierarchy
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Visual Budget
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Feedback & Notification Systems
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Platform Adaptation
|
||||
|
||||
[To be designed]
|
||||
|
||||
@@ -414,6 +456,18 @@ Ask: "May I create the skeleton file at `design/ux/[filename].md`?" — except i
|
||||
|
||||
---
|
||||
|
||||
## Tuning Knobs
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
[To be designed]
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
[To be designed]
|
||||
@@ -667,8 +721,9 @@ Update `production/session-state/active.md` with:
|
||||
Before presenting options, state clearly:
|
||||
|
||||
> "This spec should be validated with `/ux-review` before it enters the
|
||||
> implementation pipeline. The Pre-Production gate requires all key screen specs
|
||||
> to have a review verdict."
|
||||
> implementation pipeline. The Production gate (`/gate-check production`)
|
||||
> requires all key screen specs to have passed `/ux-review` at `workflow: full`
|
||||
> (recommended at `standard`)."
|
||||
|
||||
Then use `AskUserQuestion`:
|
||||
- "Run `/ux-review [filename]` now, or do something else first?"
|
||||
@@ -679,7 +734,7 @@ Then use `AskUserQuestion`:
|
||||
- "Stop here for this session"
|
||||
|
||||
If the user picks "Design another screen first", add a note: "Reminder: run
|
||||
`/ux-review` on all completed specs before running `/gate-check pre-production`."
|
||||
`/ux-review` on all completed specs before running `/gate-check production`."
|
||||
|
||||
### 6c: Cross-Link Related Specs
|
||||
|
||||
@@ -714,7 +769,7 @@ specific sub-topics, additional context or coordination may be needed:
|
||||
| Implementation feasibility (engine constraints) | `ui-programmer` — before finalizing component inventory |
|
||||
| Gameplay data requirements | `game-designer` — when data ownership is unclear |
|
||||
| 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 |
|
||||
| Accessibility tier decisions | Recorded by this session (`/ux-design accessibility`; the user picks the tier) against the criteria `accessibility-specialist` defines and audits — consult it when a requirement's criterion is unclear |
|
||||
|
||||
When delegating to another agent via the `Agent` tool:
|
||||
- Provide: screen name, game concept summary, the specific question needing expert input
|
||||
@@ -764,4 +819,4 @@ Verdict: **COMPLETE** — UX spec written and approved section by section.
|
||||
|
||||
- Run `/ux-review [filename]` to validate this spec before it enters the implementation pipeline
|
||||
- Run `/ux-design [next-screen]` to continue designing remaining screens or flows
|
||||
- Run `/gate-check pre-production` once all key screens have approved UX specs
|
||||
- Run `/gate-check production` once all key screens have approved UX specs
|
||||
|
||||
@@ -68,7 +68,7 @@ categorization from Section B.
|
||||
|
||||
---
|
||||
|
||||
#### Section D: HUD Elements
|
||||
#### Section D: HUD Element Specifications
|
||||
|
||||
For each element in the layout, specify:
|
||||
- Element name and category (Must Show / Contextual / On Demand)
|
||||
@@ -83,14 +83,16 @@ exist for status displays, resource bars, or cooldown indicators.
|
||||
|
||||
---
|
||||
|
||||
#### Sections E, F, G: Dynamic Behaviors, Platform Variants, Accessibility
|
||||
#### Sections E–L: HUD States, Information Hierarchy, Visual Budget, Feedback & Notification, Platform Adaptation, Accessibility, Tuning Knobs, Acceptance Criteria
|
||||
|
||||
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:
|
||||
**HUD States by Gameplay Context (states over time).** Cover at least
|
||||
exploration, combat, dialogue/cutscene and paused — `/ux-review` checks for all
|
||||
four. Beyond the happy path, capture what changes the HUD mid-gameplay and present
|
||||
it as a table for approval:
|
||||
|
||||
| State / Variant | Trigger | What Changes |
|
||||
|-----------------|---------|--------------|
|
||||
@@ -102,7 +104,22 @@ changes the HUD mid-gameplay and present it as a table for approval:
|
||||
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
|
||||
**Information Hierarchy.** Give every element in HUD Element Specifications a
|
||||
priority tier — MUST KEEP, SHOULD KEEP, CAN HIDE or ALWAYS HIDE — with the reason,
|
||||
and what carries its information when it is hidden (a sound, a diegetic cue, or
|
||||
nothing). This is the order the Visual Budget below drops elements in.
|
||||
|
||||
**Visual Budget.** State the maximum number of simultaneous HUD elements and
|
||||
the maximum share of the screen the HUD may cover, and which elements are dropped
|
||||
first when a state would exceed it.
|
||||
|
||||
**Feedback & Notification Systems.** One row per transient notification type
|
||||
(pickup, XP gain, objective update, achievement) — trigger system, screen position,
|
||||
duration, max simultaneous, priority and **queue behavior**: what happens when two
|
||||
arrive at once, which are held during combat, and which are never queued.
|
||||
`/ux-review` checks that every notification has queue/priority behavior defined.
|
||||
|
||||
**Platform Adaptation.** 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.
|
||||
|
||||
@@ -118,3 +135,14 @@ exists, then walk this checklist for the HUD:
|
||||
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.
|
||||
|
||||
**Tuning Knobs.** List every player-adjustable HUD setting — overall scale,
|
||||
opacity, per-element show/hide, subtitle size — with its range and default.
|
||||
|
||||
**Acceptance Criteria.** At least 5 checkbox criteria a QA tester can verify
|
||||
without reading another document — `/story-done` closes HUD stories against
|
||||
them. Cover at least: safe-zone margins on every target platform, the correct
|
||||
elements in each gameplay context above, the visual budget (screen share in
|
||||
exploration and in combat), one accessibility criterion for the committed tier,
|
||||
and notification queueing. Section 12 of `.claude/docs/templates/hud-design.md`
|
||||
has worked examples.
|
||||
|
||||
@@ -199,6 +199,19 @@ Present the data requirements as a table:
|
||||
|
||||
---
|
||||
|
||||
#### Section F2: Input Method Completeness Checklist
|
||||
|
||||
One checklist block per input method in the spec's **Platform Target** line —
|
||||
keyboard, gamepad, mouse, touch; drop the blocks for methods this game does not
|
||||
support and say so. Take the items from section 11 of
|
||||
`.claude/docs/templates/ux-spec.md` (reachability, tab/d-pad order, visible
|
||||
focus, focus trap for modals, Esc/back behavior, hit-target sizes, controller
|
||||
disconnect). Tick an item only when the Interaction Map above already specifies
|
||||
it; an unticked item is an open implementation question — list it under Open
|
||||
Questions rather than ticking it.
|
||||
|
||||
---
|
||||
|
||||
#### Section G: Accessibility
|
||||
|
||||
Cross-reference `design/accessibility-requirements.md` if it exists.
|
||||
|
||||
@@ -3,10 +3,15 @@ name: ux-review
|
||||
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
|
||||
allowed-tools: Read, Glob, Grep, Bash(bash "*/.claude/skills/ux-review/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys workflow`
|
||||
|
||||
Resolved above — use as-is. No block → defaults in
|
||||
`.claude/docs/config-resolution.md`.
|
||||
|
||||
## Overview
|
||||
|
||||
Validates UX design documents before they enter the implementation pipeline.
|
||||
@@ -49,6 +54,12 @@ when the accessibility tier is uncommitted (below).
|
||||
For `all`, output a summary table first (file | verdict | primary issue) then
|
||||
full detail for each.
|
||||
|
||||
**Which checklist a file gets** (a file path, or each file under `all`): its
|
||||
`> **Template**:` header line, which `/ux-design` writes — `UX Spec` → Phase 3A,
|
||||
`HUD Design` → 3B, `Interaction Pattern Library` → 3C. A file without that line
|
||||
is classified by name — `hud.md` → 3B, `interaction-patterns.md` → 3C, anything
|
||||
else → 3A — and the report says which checklist it assumed, and why.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Load Cross-Reference Context
|
||||
@@ -98,6 +109,8 @@ Run all checks against a `ux-spec.md`-based document.
|
||||
- [ ] Events Fired — every player action has a corresponding event or null
|
||||
explanation
|
||||
- [ ] Transitions & Animations — at least enter/exit transitions specified
|
||||
- [ ] Input Method Completeness Checklist — a block for each input method in
|
||||
the Platform Target line; any unticked item is listed under Open Questions
|
||||
- [ ] Accessibility Requirements — screen-level requirements present
|
||||
- [ ] Localization Considerations — max character counts for text elements
|
||||
- [ ] Acceptance Criteria — at least 5 specific testable criteria
|
||||
@@ -177,9 +190,12 @@ Run all checks against a `hud-design.md`-based document.
|
||||
source, priority)
|
||||
- [ ] HUD States by Gameplay Context covers at minimum: exploration, combat,
|
||||
dialogue/cutscene, paused
|
||||
- [ ] Information Hierarchy gives every HUD element a priority tier (MUST KEEP /
|
||||
SHOULD KEEP / CAN HIDE / ALWAYS HIDE)
|
||||
- [ ] Visual Budget defined (max simultaneous elements, max screen %)
|
||||
- [ ] Platform Adaptation covers all target platforms
|
||||
- [ ] Tuning Knobs present for player-adjustable elements
|
||||
- [ ] Acceptance Criteria — at least 5 specific testable criteria
|
||||
|
||||
### Quality Checks
|
||||
|
||||
@@ -222,6 +238,7 @@ Run all checks against a `hud-design.md`-based document.
|
||||
**Date**: [date]
|
||||
**Reviewer**: ux-review skill
|
||||
**Document**: [file path]
|
||||
**Checklist**: [3A / 3B / 3C — from its Template line, or assumed from the file name]
|
||||
**Platform Target**: [from header]
|
||||
**Accessibility Tier**: [from header or accessibility-requirements.md]
|
||||
|
||||
@@ -253,9 +270,22 @@ Run all checks against a `hud-design.md`-based document.
|
||||
> it was assumed rather than committed. Recommend `/ux-design accessibility` to
|
||||
> establish the tier.
|
||||
|
||||
### Pattern Library: [CONSISTENT / INCONSISTENCIES FOUND]
|
||||
### Pattern Library: [CONSISTENT / INCONSISTENCIES FOUND / N/A]
|
||||
- [findings]
|
||||
|
||||
> **For a HUD design there is no Pattern Library checklist to run it against (Phase 3B has none), so Pattern Library is N/A, excluded from the dimension count.**
|
||||
> Report `Pattern Library: N/A — no pattern library checklist for this document
|
||||
> type`.
|
||||
>
|
||||
> For a UX spec, this dimension does have a checklist — it is checked against
|
||||
> `design/ux/interaction-patterns.md`. If that file is absent: N/A only where
|
||||
> the workflow tier does not require the library (`minimal`) — report
|
||||
> `Pattern Library: N/A — interaction pattern library not required at this
|
||||
> tier`. At any tier that requires or recommends it (`standard`, `full`), report
|
||||
> `Pattern Library: NOT ASSESSED — design/ux/interaction-patterns.md not found`
|
||||
> instead: the library is missing, not out of scope, and NOT ASSESSED counts it
|
||||
> against the verdict as the unresolved item it is.
|
||||
|
||||
### Verdict: APPROVED / NOT ASSESSED / NEEDS REVISION / MAJOR REVISION NEEDED
|
||||
**Blocking issues**: [N] — must be resolved before implementation
|
||||
**Advisory issues**: [N] — recommended but not blocking
|
||||
|
||||
@@ -5,11 +5,13 @@ argument-hint: "[--review full|lean|solo]"
|
||||
user-invocable: true
|
||||
allowed-tools: Read, Glob, Grep, Write, Edit, Bash, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/vertical-slice/../../hooks/yaml-helper.sh" resolve_config *)
|
||||
model: sonnet
|
||||
isolation: worktree
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
|
||||
Resolved above — use as-is; `--review` overrides `review_mode` for this run. No
|
||||
block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
|
||||
## Purpose
|
||||
@@ -49,7 +51,9 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
Read the following files to understand the full design intent:
|
||||
- `CLAUDE.md` — tech stack and engine
|
||||
- `design/gdd/game-concept.md` — core fantasy and game pillars
|
||||
- `design/gdd/game-concept.md` — core fantasy and game pillars (or
|
||||
`design/game-brief.md`, the one-page brief that replaces it at `rigor: minimal` —
|
||||
pitch, core loop and "what they feel" line; it has no pillars)
|
||||
- `design/gdd/systems-index.md` — MVP systems and their priorities
|
||||
- `docs/architecture/architecture.md` — layer structure
|
||||
- `docs/architecture/control-manifest.md` — technical rules for implementation
|
||||
@@ -61,7 +65,7 @@ Read the following files to understand the full design intent:
|
||||
|
||||
Before building, define the **falsifiable validation question**:
|
||||
|
||||
> *"Does a player, starting from nothing, experience [core fantasy from game-concept.md]
|
||||
> *"Does a player, starting from nothing, experience [core fantasy from game-concept.md or game-brief.md]
|
||||
> within [N] minutes, without developer guidance — and can we build one such loop
|
||||
> in [X] days at representative quality?"*
|
||||
|
||||
@@ -96,7 +100,8 @@ Define in bullet points:
|
||||
- Specific, measurable success criteria for the validation question
|
||||
- Hard time limit: [X] days. If exceeded, scope was wrong — stop and reassess.
|
||||
|
||||
Ask the user to confirm scope before building.
|
||||
Ask the user to confirm scope before building. Name the checkpoint file in that
|
||||
confirmation: "May I record this plan in `production/session-state/active.md`?"
|
||||
|
||||
Once confirmed, write a session checkpoint to `production/session-state/active.md`
|
||||
(create `production/session-state/` if it does not exist). Include: concept name,
|
||||
@@ -115,11 +120,17 @@ Ask: "May I create the vertical slice directory at
|
||||
If yes, create the directory. Every file must begin with:
|
||||
|
||||
```
|
||||
// VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
// Validation Question: [What this build is proving]
|
||||
// Date: [Current date]
|
||||
[comment] VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
[comment] Validation Question: [What this build is proving]
|
||||
[comment] Date: [Current date]
|
||||
```
|
||||
|
||||
Write `[comment]` in each file's own comment syntax — `#` in GDScript (`.gd`) and
|
||||
Python, `//` in C#, C++ and JavaScript, `--` in Lua, `<!-- … -->` in HTML and
|
||||
Markdown. A header in another language's syntax is a parse error, not a label.
|
||||
Files that cannot hold a comment (JSON, engine-generated scene and project
|
||||
files) are exempt.
|
||||
|
||||
**Quality standards** — higher than concept prototype, not full production:
|
||||
- Follow architecture layers from `docs/architecture/control-manifest.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`
|
||||
@@ -197,7 +208,7 @@ Once the user returns, ask these questions **one at a time**:
|
||||
> where you felt like you were actually playing the game?"
|
||||
|
||||
3. **Core fantasy:**
|
||||
> "The game is supposed to make you feel [core fantasy from game-concept.md].
|
||||
> "The game is supposed to make you feel [core fantasy from game-concept.md or game-brief.md].
|
||||
> Did it? Be honest — not 'kind of' but specifically what you felt and when."
|
||||
|
||||
4. **Blockers:**
|
||||
@@ -214,6 +225,21 @@ Once the user returns, ask these questions **one at a time**:
|
||||
If any answer is vague, ask: "Can you give me the specific moment where that happened?"
|
||||
Precise observations populate the report. Vague ones produce a useless report.
|
||||
|
||||
**PROCEED is not available when a validation item is NO.** `/gate-check production`
|
||||
FAILs a built slice with any NO in its Vertical Slice Validation — a player got
|
||||
through the loop without developer guidance (question 1), learned what to do
|
||||
within the first 2 minutes (question 2 — longer is a no), the core mechanic feels
|
||||
good (question 3), no critical fun-blocker bug (question 4). If any of those
|
||||
answers is no, the verdict is PIVOT or KILL — the user chooses — and the report
|
||||
names the NO.
|
||||
|
||||
**NOT ASSESSED is the fourth verdict.** When nobody has yet played the complete
|
||||
loop from scratch — the user cannot play it this session, or stopped before the
|
||||
end — the validation did not run, and the verdict is **NOT ASSESSED**, with the
|
||||
reason. It ranks above PROCEED and below PIVOT and KILL: an unplayed slice has not
|
||||
earned PROCEED, and a slice known to fail is more actionable than one nobody
|
||||
played. It is never recorded as PROCEED.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Generate Vertical Slice Report
|
||||
@@ -230,26 +256,25 @@ skip it. It feeds directly into sprint planning.
|
||||
Read `.claude/docs/templates/vertical-slice-report.md` to get the report structure.
|
||||
If the template file is not found, use this fallback structure:
|
||||
- `## Vertical Slice Report — [Game Title] — [Date]`
|
||||
- `### Executive Summary` (PROCEED / PIVOT / STOP verdict + 2-sentence rationale)
|
||||
- `### Executive Summary` (PROCEED / PIVOT / KILL / NOT ASSESSED verdict + 2-sentence rationale)
|
||||
- `### Core Loop Validation` (what was tested, what passed, what failed)
|
||||
- `### Feel Assessment` (animation, controls, feedback — subjective notes)
|
||||
- `### Technical Findings` (performance, engine issues, architectural risks)
|
||||
- `### Velocity Log` (day-by-day actual progress — do not skip)
|
||||
- `### Lessons Learned` (assumptions broken by building to near-production
|
||||
quality; what surprised us about the pipeline or architecture; what we would
|
||||
change about the slice scope next time)
|
||||
- `### Recommended Next Steps`
|
||||
|
||||
Fill in every section based on what was observed and built during this session.
|
||||
The velocity log must reflect actual day-by-day progress, not estimates — this is
|
||||
the most honest production rate data you will ever have. Replace all placeholder
|
||||
text with real observations.
|
||||
|
||||
### Lessons Learned
|
||||
- What assumptions were broken by actually building to near-production quality?
|
||||
- What surprised us about the pipeline or architecture?
|
||||
- What would we change about the slice scope if we ran this again?
|
||||
```
|
||||
text with real observations. The recommendation carries the Phase 5 verdict,
|
||||
NOT ASSESSED included, with its reason.
|
||||
|
||||
Ask: "May I write this report to
|
||||
`prototypes/[concept-name]-vertical-slice/REPORT.md`?"
|
||||
`prototypes/[concept-name]-vertical-slice/REPORT.md` and add its row to
|
||||
`prototypes/index.md`?"
|
||||
|
||||
If yes, write the file. Then update `prototypes/index.md` (create if it does not
|
||||
exist) — append one row to the vertical slice table: concept name, date, verdict,
|
||||
@@ -265,14 +290,34 @@ the project — cross-reference it with sprint estimates.
|
||||
- `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 `Agent` using gate **CD-PLAYTEST**
|
||||
(`.claude/docs/director-gates/cd-playtest.md`).
|
||||
(`.claude/docs/director-gates/cd-playtest.md`) — unless the slice's verdict is
|
||||
NOT ASSESSED: with no playthrough there is nothing to review, so note
|
||||
"CD-PLAYTEST skipped — the slice has not been played yet."
|
||||
|
||||
Pass: the full REPORT.md content, the validation question, game pillars and core
|
||||
fantasy from `design/gdd/game-concept.md`.
|
||||
fantasy from `design/gdd/game-concept.md` (or the pitch and "what they feel" line
|
||||
from `design/game-brief.md` at `rigor: minimal`).
|
||||
|
||||
The creative director evaluates the vertical slice result against the game's
|
||||
creative vision and pillars, then confirms, modifies, or overrides the
|
||||
recommendation. Their verdict is final. Update REPORT.md if the verdict differs.
|
||||
creative vision and pillars and returns one of the gate's verdicts — APPROVE,
|
||||
CONCERNS or REJECT. Apply it to the recommendation:
|
||||
|
||||
- **APPROVE** → the recommendation stands.
|
||||
- **CONCERNS** → show the concerns alongside the recommendation, then use
|
||||
`AskUserQuestion`: `Revise the recommendation` / `Accept with noted concerns` /
|
||||
`Discuss further`. The user decides; the director does not.
|
||||
- **REJECT** (the core fantasy is not present) → a PROCEED recommendation cannot
|
||||
stand. Use `AskUserQuestion` to ask the user to choose `PIVOT` or `KILL`, and run
|
||||
Phase 8 for that choice. A PIVOT or KILL recommendation stands.
|
||||
- **NOT ASSESSED** [missing input] → the director made no judgement, so it neither
|
||||
backs nor overturns the recommendation (`.claude/docs/director-gates.md`): name
|
||||
what was missing, then supply it and re-run the gate, or record
|
||||
`CD-PLAYTEST: NOT ASSESSED — [input]` in the report.
|
||||
|
||||
When the director returned CONCERNS, REJECT or NOT ASSESSED, ask "May I update
|
||||
`prototypes/[concept-name]-vertical-slice/REPORT.md` and its
|
||||
`prototypes/index.md` row?", then record the director's verdict and reason in
|
||||
REPORT.md, and the final recommendation in both if it changed.
|
||||
|
||||
---
|
||||
|
||||
@@ -290,7 +335,7 @@ Recommended next steps:
|
||||
- `/create-epics layer:core` — plan Core layer epics
|
||||
- `/create-stories [epic-slug]` — break each epic into implementable stories
|
||||
- `/sprint-plan` — plan the first sprint using velocity data from the slice
|
||||
- `/gate-check pre-production` — formally advance the stage to Production
|
||||
- `/gate-check production` — formally advance the stage to Production
|
||||
|
||||
**Playtest note:** `/gate-check` will look for documented playtest evidence.
|
||||
At minimum, 1 documented session with a REPORT.md showing PROCEED is required
|
||||
@@ -343,6 +388,14 @@ Ask: "May I append this to `prototypes/GRAVEYARD.md`?" If yes, add one entry:
|
||||
- Return to `/brainstorm` with what you learned
|
||||
- Or run `/prototype [new-concept]` to test a new direction cheaply first
|
||||
|
||||
**If NOT ASSESSED:**
|
||||
|
||||
The slice is built but not validated. Say which reason applied, then finish the
|
||||
Phase 5 playthrough and debrief — the `production/session-state/active.md`
|
||||
checkpoint is where to resume — and, after asking, update REPORT.md and its
|
||||
`prototypes/index.md` row with the verdict. Do not take the slice to
|
||||
`/gate-check production` as if it had passed: NOT ASSESSED is not a PROCEED.
|
||||
|
||||
---
|
||||
|
||||
### Important Constraints
|
||||
|
||||
Reference in New Issue
Block a user