Release 1.1.3 — long skills keep their later steps

Fix release for 1.1.2: the 14 longest skills keep their later phases
after a compaction, a question nobody answered is never taken as an
answer, settings read the same from a subfolder, the commit check works
for a project in a subfolder of a larger repository, every skill opens
with a title, and the shipped allow rules no longer approve deleting a
branch or writing files without asking. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.2 → v1.1.3).

Refs #83
Refs #133

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185en4t76fPn7315q4c3nko
This commit is contained in:
Donchitos
2026-10-08 17:52:48 +11:00
co-authored by Claude Opus 5.5
parent b21fa0f7f2
commit be8993bbc5
231 changed files with 12000 additions and 10527 deletions
+23 -6
View File
@@ -13,7 +13,7 @@ through `AskUserQuestion` or writes files should follow this pattern.
section `modes.automation` is the source of truth for behavior. This document
is the implementation pattern.
> **Do not read `effects-map.md` during a skill run** — it is ~110 KB, a
> **Do not read `effects-map.md` during a skill run** — it is a very large file, a
> reference for authoring the spec rather than a runtime input, and **this
> document is self-sufficient** for deciding what to ask and what to proceed on.
> If a case genuinely is not covered here, read only its `modes.automation`
@@ -77,8 +77,8 @@ the right rule.
- `AskUserQuestion` called for **major decisions only** (see classification below)
- Minor decisions: AI states recommendation inline and proceeds — e.g.
> *"Going with a static utility pattern here — it fits the existing architecture. Continuing unless you want to change direction."*
- Draft shown briefly before writing — proceeds after a short summary, does not wait for explicit "yes"
- "May I write?" asked for **new files only** — updates to existing files proceed directly
- Updates to existing files: draft shown briefly before writing — proceeds after a short summary, does not wait for explicit "yes"
- "May I write?" asked for **new files only**, and a new file waits for the answer — updates to existing files proceed directly
- Still presents options for major decisions but caps at 2 choices with a clear recommendation
- Multi-section authoring: writes each approved section immediately, no per-section confirmation
@@ -92,6 +92,21 @@ the right rule.
`production/session-logs/decision-log.md`
- User reviews decision log post-session to audit choices made
### Every mode: a question with no answer
A question that comes back **skipped, dismissed or empty is not an answer**, in
every mode and on every tool: the user closing the question, a headless run that
returns every question as skipped, a reply that picks nothing.
- Do not write a file, change a mode or setting, or pick an option on its behalf.
- Ask again in plain text, say what is waiting on the answer, and wait.
- In `autonomous`, a question the mode did not require can be decided as usual:
pick the recommended option and log it via `log_decision`. A question in an
`automation_always_ask` category, or in an exempt skill, is the user's: ask
again and wait.
- Where nobody can answer (CI, a headless run), stop and report what is waiting
rather than choosing.
---
## Major vs Minor Decision Classification
@@ -135,9 +150,9 @@ Even in `autonomous` mode, certain decision categories ALWAYS trigger
the categories actually listed in `modes.automation_always_ask` — the three
defaults above, unless the project overrides them — interrupt an `autonomous`
run. The other rows do nothing until a project opts into them. Read the resolved
list with `resolve_config` rather than assuming a row here is active; a real run
logged two `architecture_decisions` as rule violations on a project where that
category was never configured.
list with `resolve_config` rather than assuming a row here is active. Treating a
category the project never configured, such as `architecture_decisions`, as
active reports rule violations the project never asked for.
| Category | Examples of decisions in this category |
|----------|----------------------------------------|
@@ -255,6 +270,8 @@ At each decision point in this skill:
guided + minor: State recommendation inline, proceed.
autonomous + always_ask: AskUserQuestion (regardless of mode).
autonomous + other: Pick recommended, log via log_decision, proceed.
4. If the question comes back skipped, dismissed or empty, it is not an
answer: see §Every mode: a question with no answer.
```
This is the contract. Skills that follow this pattern produce
+2 -3
View File
@@ -1,9 +1,8 @@
# Code Root Resolution
Shared procedure for any skill that reads, scans, counts or writes game source
files. Referenced from the point of use in each such skill. Those skills keep
the one load-bearing imperative inline — **an unresolved code root means the
check did not run** — and cite this file for the resolution order.
files. **An unresolved code root means the check did not run.** This file gives
the resolution order.
`.claude/docs/directory-structure.md` is the authority for which directory holds
code. This file is the procedure for applying it.
+1 -2
View File
@@ -69,8 +69,7 @@ falling back to the defaults above when it is absent.
> **Exception — `/smoke-check`.** The ADVISORY default for **Config/Data** above
> applies to *per-story evidence* gates. `/smoke-check` is a build-health gate,
> not a per-story evidence gate, so its own unset default for
> `testing.strict.config` is **BLOCKING**. This divergence is intentional and is
> documented at both sites; do not reconcile one to the other.
> `testing.strict.config` is **BLOCKING**. The two defaults differ on purpose.
## Automated Test Rules
+21 -27
View File
@@ -38,12 +38,12 @@ a command that would normally just prompt — **aborts the whole invocation**, a
the model never sees the skill. A read-only command such as `git status`, which
Claude Code approves on its own, comes back "allow" and runs without a grant. A preloaded skill (`skills:` on an agent) is
checked the same way at agent launch, so a failing bootstrap line stops the agent
from starting. Measured on Claude Code 2.1.281 in default
mode:
from starting. In default
mode, the bootstrap forms behave as follows:
| Bootstrap form | Repo root | Subdirectory | Bash-less agent preloading it |
|---|---|---|---|
| `source "${CLAUDE_PROJECT_DIR:-.}/…" && resolve_config` (v1.1.0) | aborts | aborts | fails to launch |
| `source "${CLAUDE_PROJECT_DIR:-.}/…" && resolve_config` | aborts | aborts | fails to launch |
| same, with a bare `Bash` grant | aborts | — | — |
| `bash "${CLAUDE_PROJECT_DIR}/…"` + grant | runs | aborts | — |
| **`bash "${CLAUDE_SKILL_DIR}/../../hooks/…"` + per-skill grant** | **runs** | **runs** | **launches** |
@@ -181,8 +181,8 @@ set the sub-knob. Their effective values come from the rigor level:
Because `rigor` itself defaults to `minimal`, an unconfigured project resolves
these six to the lean row. That default was `standard`; it changed because the
heavier tier measured several times more expensive to reach working code without
producing a better result. See the rationale block above `_yaml_helper_defaults`
heavier tier costs more to reach working code without producing a better
result. See the rationale block above `_yaml_helper_defaults`
in `.claude/hooks/yaml-helper.sh` for the reasoning and the ordering
constraint. Raising the tier is one question in `/start` or one `/settings`
call, and `settings-guidance.md § 4`'s upward triggers are written to fire from
@@ -242,40 +242,34 @@ condition below degrades to defaults and is named on `notes:`:
| Locked key in `project.local.yaml` | ignored as always, but now **named** on `notes:` — `local: not locally overridable, ignored — modes.rigor (move to project.yaml or delete)` |
| No Python interpreter | legacy files and defaults only; **explicitly noted** on `notes:` |
| No block at all | shell preprocessing disabled (`disableSkillShellExecution`) — use the defaults table above |
| A task notice where the block should be ("Command did not complete within its 120s timeout and was moved to the background") | the settings line ran past Claude Code's 120-second limit for a skill's `!` line, because every process start was slowed — usually by antivirus real-time scanning of the project folder. The settings exist: read each key yourself from `project.local.yaml`, then `project.yaml`, then the defaults table above |
| Bootstrap line not approved, or exits non-zero | **not a degraded state — the skill never renders at all.** See "Why exactly this command" above |
A skill must never treat a missing block as "config is unset in an interesting
way". It means the block did not render; the defaults apply.
way". It means the block did not render; the defaults apply. The exception is
that task notice: the settings line ran out of time, not the settings, so read
the files as that row says instead of taking the defaults. If it keeps
happening, exclude the project folder from real-time scanning.
### Two behaviours that are correct but SILENT
### Two inputs that resolve without a note
In both cases the
resolved *value* is right — the chain falls through to the default — but the user
is told nothing, and their explicit configuration was discarded.
In both cases `resolve_config` follows a fixed rule and emits no note, so it does
not tell you that something you wrote was not used.
| Input | What happens | Note emitted |
|---|---|---|
| **Duplicate key** (`rigor:` twice in one block) | **the last occurrence wins**, deterministically | **none** |
| **Wrong shape** — a list where a scalar belongs (`rigor:` followed by `- standard`) | key resolves empty, falls through to the default | **none** |
**Why this is worth knowing rather than shrugging at.** An enum-*invalid* value is
announced (`modes.workflow: 'medium' is not a valid value … — ignored, chain
continued`). A structurally-invalid one is not. So a user who mistypes the value
gets told, and a user who mistypes the *structure* does not — and the second
mistake is the easier one to make by copy-paste. The framework has the mechanism
(`notes:`) and already uses it for absence, emptiness, tabs, locked keys, orphan
locals and bad enums. Shape is the gap.
An enum-*invalid* value is announced (`modes.workflow: 'medium' is not a valid
value … — ignored, chain continued`). A wrong shape is not: the key is present
but resolves to nothing, which is also what a key with an empty value does on
purpose (the "Key present, value empty" row above), and `resolve_config` does not
tell the two apart. When a setting seems ignored, check the structure of its key
in the file: one scalar on the key's own line, the key written once per block,
and no list under it. `/settings` shows the value that is actually in effect.
**Why it is not caught yet.** Detecting "this key is present in the file but
resolved to nothing" means changing the parser every config read in the framework
goes through, and the empty-value fall-through above is a *legitimate* case of
exactly that signature. Distinguishing "empty on purpose" from "unparseable" is
real work, not a one-liner, and it lands in the most load-bearing file there is.
Until then, check the structure yourself when a setting seems ignored.
**Duplicate-key precedence was undocumented before this entry.** Last-wins is
deterministic and reproducible, so it is not a bug — but nothing said so, which
meant nobody could rely on it either.
The last-wins rule for a duplicate key is fixed, so you can rely on it.
## Why not inject at session start
+6 -8
View File
@@ -32,13 +32,11 @@ The checkpoint holds: current task, next step, what it is blocked on, files in
progress, open questions. Write it so a cold reader can resume without opening
anything else.
> **Why the split.** One append-only file doing both jobs grows without bound —
> past 700 lines every consumer invents its own slice: a status line parsing a
> STATUS block nothing writes, `pre-compact` injecting `head -100` (12.7 KB, at
> the moment context is scarcest), `session-start` previewing `tail -20` — the
> opposite end. None was wrong, because nothing defined where
> the recoverable state lived. Now every consumer reads the named region, and
> the cost is fixed no matter how long the narrative grows.
> **Why the split.** One append-only file doing both jobs grows without bound,
> and every consumer then reads a different slice of it: the top, the bottom, or
> a block nothing writes. None of them is wrong, because nothing defines where
> the recoverable state lives. With a named region, every consumer reads the
> same part, and the cost is fixed no matter how long the narrative grows.
**Rotation.** When the narrative passes ~200 lines, move it into
`production/session-logs/`:
@@ -125,7 +123,7 @@ Current helpers:
- **`review-scope.sh`** — which GDDs changed since the last cross-review, plus
their declared dependencies. Replaces reasoning through git history.
Two rules when adding one:
Two rules for helpers:
1. **Grant it the way `.claude/docs/config-resolution.md` shows.** `allowed-tools`
pre-approves commands; it does not restrict them — a skill without the grant
+2 -3
View File
@@ -17,7 +17,7 @@
Read `.claude/docs/model-tiers.md` on demand. It carries the tier table, the
per-skill assignments and the authoring rule.
**Load-bearing enough to restate here:** whether a skill's `model:` is used
**Key point:** whether a skill's `model:` is used
depends on how the skill starts. Typed as `/skill-name`: yes, except a `haiku`
pin in auto mode. Started by Claude through the Skill tool: no. Never tell a
user a `haiku` skill saves money; an `opus` skill typed in a Sonnet session
@@ -43,8 +43,7 @@ must NOT be parallelised.
### Agent Teams (experimental — opt-in)
Multiple independent Claude Code *sessions* coordinated via a shared task list.
Opt-in and never yet used here — read `.claude/docs/agent-teams.md` on demand
before proposing one.
Opt-in only — read `.claude/docs/agent-teams.md` on demand before proposing one.
## Parallel Task Protocol
-13
View File
@@ -190,19 +190,6 @@ Collect every verdict from the directors that ran, then apply escalation rules:
---
## Adding New Gates
1. Assign a gate ID: `[DIRECTOR-PREFIX]-[DESCRIPTIVE-SLUG]`. Prefixes: `CD-`
`TD-` `PR-` `LP-` `QL-` `ND-` `AD-`; add new ones for new agents
(`audio-director` → `AU-`, `ux-designer` → `UX-`)
2. Create `.claude/docs/director-gates/[gate-id].md` (lowercase), starting with
the standard "> Gate definition..." header note, with all five fields:
Trigger, Context to pass, Prompt, Verdicts, special handling notes
3. Add its row to the Gate Index table above
4. Reference it in skills by ID only — never copy the prompt text into the skill
---
## Gate Coverage by Stage
| Stage | Required Gates | Optional Gates |
+84 -95
View File
@@ -2,11 +2,11 @@
> ## READ ONE SECTION, NEVER THIS WHOLE FILE
>
> This document is **~31,000 tokens** — roughly **four times an entire turn's
> context budget**, which sits near 8,300. It is organised as **36 sections of
> ~900 tokens each**, one per setting, headed `## <key>`.
> This document is very large, far more than any one lookup needs. It is
> organised as one section per setting, headed `## <key>`, so a reader can take
> only the section it wants.
>
> **So opening it costs 36× what you need.** To look up a setting:
> **So opening it whole costs many times what you need.** To look up a setting:
>
> ```
> Grep pattern="^## modes.review_mode" path=".claude/docs/effects-map.md" -A 40
@@ -15,13 +15,12 @@
> Read the section for your key and stop. The same rule the skills already apply
> to their own reference files — `/gate-check` loads only the row for the target
> phase and says "never load the others" — applies here, and this is the largest
> file in the framework by a factor of seven.
> file in the framework.
>
> This banner exists because six skills cite this document and **none of them
> scoped the citation**. None instructed a full read either, so
> nothing was actually loading 31k — but "see effects-map.md for full schema" in
> front of a file this size is an invitation, and the cost of accepting it is
> silent.
> Cite a section of this document, never the whole file. A pointer such as "see
> effects-map.md for full schema" invites a full read of a file this size, and
> the cost of accepting that invitation is silent. Name the `## <key>` section
> you need instead.
This document defines what each `project.yaml` setting actually does across
every skill that reads it. It is the tracked, authoritative reference.
@@ -341,22 +340,17 @@ behavior: strict project defaults for CI, looser developer overrides for local w
> **Hotfix / day-one-patch exception:** These skills are emergency or release-critical
> pipelines. They are never gated by `review_mode` — all agents always run.
> **Known inertness — `full` and `lean` barely differ in the nine `team-*`
> orchestrators.** Each documents a three-way split: `full` spawns every director
> and lead gate, `lean` skips director gates *unless* they are PHASE-GATE type,
> `solo` skips gate spawning entirely. But the director gates the team skills name
> are the four PHASE-GATEs, which `lean` keeps — and no team pipeline spawns one
> (`/gate-check` is their only spawner). Two things differ: `/team-release`'s
> technical-director release sign-off runs only at `full`, and `/team-narrative` at
> `team.size: small` adds `localization-lead` and `world-builder` only at `full`.
> **`review_mode` in the nine `team-*` orchestrators.** `review_mode` sets
> director-gate depth: `full` spawns every director gate a pipeline names, `lean`
> skips director gates unless they are PHASE-GATE type, and `solo` skips gate
> spawning entirely. No team pipeline spawns a PHASE-GATE (`/gate-check` is their
> only spawner), so in the orchestrators
> `lean` and `solo` behave the same, and `full` adds two things:
> `/team-release`'s technical-director release sign-off, and, at
> `team.size: small`, `/team-narrative`'s `localization-lead` and `world-builder`.
>
> `solo` genuinely differs, and outside the orchestrators (`/design-review`,
> `/architecture-review`) all three levels differ as documented.
>
> **This is recorded, not fixed.** Making `lean` mean something in the
> orchestrators requires deciding which non-phase-gate reviewers each of the nine
> should call at `full` — a design decision about review depth, not a wording fix,
> and one that changes how many agents a run spawns.
> Outside the orchestrators, the skills in the *Core skills* table below read
> `review_mode` as that table documents.
---
@@ -395,15 +389,18 @@ behavior: strict project defaults for CI, looser developer overrides for local w
---
### Skills to be made review-mode aware (currently ignore the setting)
### Skills that do not read `modes.review_mode`
| Skill | full | lean | solo |
|-------|------|------|------|
| **review-all-gdds** | Phase 2 consistency pass + Phase 3 design theory pass (parallel) | Phase 2 consistency pass only, Phase 3 skipped | Phase 2 only, Phase 3 skipped |
| **architecture-review** | Engine specialist + security-engineer (if online features) | Both skipped | Both skipped |
| **dev-story** | Core programmer routing always runs + engine-specialist escalation on HIGH risk stories | Core programmer routing always runs, engine-specialist escalation skipped | Core programmer routing always runs, engine-specialist escalation skipped |
| **code-review** | Language, shader, UI specialists + qa-tester | All optional specialists skipped | All optional specialists skipped |
| **security-audit** | security-engineer spawned | Skipped | Skipped |
These skills run the same way at `full`, `lean` and `solo`. None of them takes a
`--review` flag.
| Skill | What runs at every level |
|-------|--------------------------|
| **review-all-gdds** | Phase 2 consistency pass and Phase 3 design-theory pass, in parallel |
| **architecture-review** | The primary engine specialist is consulted after the engine audit (recorded as NOT ASSESSED when no engine is configured) |
| **dev-story** | Core programmer routing, plus the engine specialist when the story involves engine-specific APIs or patterns, and always when engine risk is HIGH |
| **code-review** | Language, shader and UI specialists when an engine is configured, plus `qa-tester` for Logic and Integration stories |
| **security-audit** | `security-engineer` is spawned to run the audit |
---
@@ -427,9 +424,9 @@ pipeline's own review steps run in every mode.
phase gates always run. Only `solo` skips them. This is intentional: phase
gates are the minimum quality bar, not optional extras. **How many directors
run is a separate axis** — `modes.workflow` sets panel width (`minimal` → PR
only, `standard` → TD + PR, `full` → all four), because a fixed four-director
Opus panel cost a two-system jam exactly what it cost a thirty-system
commercial project. Width never softens a verdict: the strictest verdict from
only, `standard` → TD + PR, `full` → all four), because directors are
Opus-tier and a small project should not pay for the same four-director panel
as a large one. Width never softens a verdict: the strictest verdict from
whoever ran still wins, and `/gate-check` names the perspectives it skipped.
- **art-bible** always spawns its section specialists regardless of mode — only
the final sign-off gate is controlled by `review_mode`. Specialist delegation is
@@ -459,8 +456,8 @@ pipeline's own review steps run in every mode.
`/start` asks that sets the six knobs below
**Values:** `minimal` | `standard` | `full`
**Default:** `minimal` — see the rationale block above `_yaml_helper_defaults`
in `.claude/hooks/yaml-helper.sh`. Short version: the heavier tier cost several
times more to reach working code without producing a better result.
in `.claude/hooks/yaml-helper.sh`. Short version: the heavier tier costs more to
reach working code without producing a better result.
**Set by:** `/start` (Phase 3d), `/settings`
**Read by:** nothing directly — it is read *through* the six knobs it supplies
@@ -646,8 +643,8 @@ checklists differ per phase per mode.
`minimal`. -->
**Director panel width** (`/gate-check` Section 4b) is workflow's second effect
here. Directors are Opus-tier, so a fixed four-director panel charged a
two-system jam exactly what it charged a thirty-system commercial project:
here. Directors are Opus-tier, so the panel is sized to the project rather than
fixed at four:
| `workflow` | Panel | Directors |
|---|---|---|
@@ -823,10 +820,10 @@ recommend and proceed — the tradeoff between user control and speed
- Minor decisions: AI states recommendation inline and proceeds — e.g.
*"Going with a static utility pattern here — it fits the existing architecture.
Continuing unless you want to change direction."*
- Draft shown briefly before writing — proceeds after a short summary, does not
wait for explicit "yes"
- "May I write?" asked for **new files only** — updates to existing files proceed
directly
- Updates to existing files: draft shown briefly before writing — proceeds after a
short summary, does not wait for explicit "yes"
- "May I write?" asked for **new files only**, and a new file waits for the answer
— updates to existing files proceed directly
- Still presents options for major decisions but caps at 2 choices with a clear
recommendation
- Multi-section authoring: writes each approved section immediately, no per-section
@@ -842,6 +839,18 @@ recommend and proceed — the tradeoff between user control and speed
with: timestamp, skill, decision point, option chosen, reasoning
- User reviews decision log post-session to audit choices made
#### every mode — a question with no answer
- A question that comes back skipped, dismissed or empty is **not an answer**, in
every mode and on every tool (a closed question, a headless run that returns
every question as skipped, a reply that picks nothing)
- Nothing is written, no mode or setting changes and no option is picked on its
behalf; the question is asked again in plain text, naming what waits on it
- `autonomous`: a question the mode did not require is decided and logged as
usual; an `automation_always_ask` category or an exempt skill asks again
- Where nobody can answer (CI, headless), the skill stops and reports what is
waiting rather than choosing
---
### Major vs minor decision classification (guided mode)
@@ -1239,7 +1248,7 @@ closing, or produces a warning and lets work continue — per test type
> **No skill or hook reads this setting. Setting it has no effect.** Everything
> below describes the intended design, not current behaviour.
>
> The value is checked for valid spelling when you set it, and then ignored.
> The value is not checked when you set it, and nothing reads it.
**Controls:** Whether phase gate failures block stage transition or just warn
**Values:** `true` | `false`
@@ -1437,7 +1446,7 @@ must tell them apart)
| Value | Required compliance | Best for |
|-------|---------------------|----------|
| `none` | No certification — internal release, alpha, jam game | Default |
| `none` | No certification | Internal releases, alphas, jam games (an explicit choice — unset is not `none`) |
| `itch` | itch.io upload requirements (build size, page setup, age tags) | Indie web/desktop releases |
| `steam` | Steamworks integration, store page, achievements, depot build, system requirements, common content rules | Commercial PC releases |
| `console` | Platform certification (PlayStation/Xbox/Switch) — heavy compliance: TRC/XR/Lotcheck, save data rules, controller mapping rules, age rating boards | Console releases |
@@ -1450,7 +1459,6 @@ must tell them apart)
|-------|------|------|-------|---------|
| **launch-checklist** | Internal launch only — no external requirements | + itch.io page setup, butler upload, build size | + Steamworks integration, store page, achievements depot, common content checks | + Platform-specific TRC, certification submission, console save format compliance |
| **release-checklist** | Smoke pass + version bump only | + itch.io page live, build uploaded to butler | + Steam store page live, depot pushed, achievements live | + Platform submission accepted, age rating boards cleared |
| **/pre-cert** (future) | Not applicable | Lightweight readiness check | Steam common content audit | Full TRC compliance audit |
---
@@ -1477,8 +1485,8 @@ must tell them apart)
> **Default is `none`, not `standard`.** Most CCGS users are solo devs and jam-game
> makers — defaulting to `standard` would auto-spawn the accessibility specialist
> for projects where it's overhead. `/start` asks the question explicitly so users
> who care can opt into `standard` or `aaa` consciously.
> for projects where it's overhead. `/start` does not ask about it; you set it with
> `/settings`.
---
@@ -1564,9 +1572,9 @@ must tell them apart)
>
> **Unset is not zero and not a default.** A budget nobody set is not a budget
> that was met — `/perf-profile` must report `NOT ASSESSED` for a metric with no
> committed target rather than measuring against a placeholder. That exact
> failure (">99% headroom against a 16.67ms budget", from zero profiler data)
> is one of the two instances that motivated `.claude/rules/skill-authoring.md`.
> committed target rather than measuring against a placeholder. A headroom figure
> computed against an invented budget, with no profiler data behind it, reads as
> a pass and is not one; see obligations 1 and 2 in `.claude/rules/skill-authoring.md`.
## performance.enforce
@@ -1832,7 +1840,8 @@ engine reference in this repo can source it. See `/setup-engine` §"The Godot
The Unreal row is Windows'. `/setup-engine` writes the Linux block (`Engine/Build/BatchFiles/RunUAT.sh`,
`Engine/Binaries/Linux/UnrealEditor`) on Linux, and on macOS only `build`, leaving `test`, `run` and
`smoke` as TODOs — see `docs/engine-reference/unreal/current-best-practices.md`, "Command Line".
`smoke` unset, with a comment in `project.yaml` asking you to set them via `/settings` — see
`docs/engine-reference/unreal/current-best-practices.md`, "Command Line".
> **`<PRESET>` and `<TARGET>` are placeholders, not values to copy.** A Godot
> export preset is whatever string the operator typed into `export_presets.cfg`;
@@ -1880,16 +1889,15 @@ conventions into a brief, manifest or spec. **NOT by `/code-review` and NOT by
> and `validate-commit.sh` does not warn on violations — neither contains any
> naming logic. If you need enforcement, it has to be added.
>
> **Known rough edge — asset filenames.** `validate-assets.sh` warns unless files
> under Godot's `assets/` are lowercase-with-underscores, and it takes no config
> input, while `/asset-spec` specifies asset names from `naming.*`. Unity's
> `Assets/` and Unreal's `Content/` are not naming-checked: those engines name
> assets in PascalCase. On Godot-C#, where `/setup-engine` sets
> `naming.files: PascalCase`, the hook will warn on assets named exactly as
> `/asset-spec` specified them. The two are
> measuring different things — `naming.files` describes **source** files by its
> own examples (`PlayerController.cs`), and no key currently governs asset
> filenames — so treat the hook's naming warning as advisory on those engines.
> **Asset filenames.** `validate-assets.sh` warns when a file under Godot's
> `assets/` has an uppercase letter, a space or a hyphen in its name (it expects
> lowercase with underscores), and it takes no config input. `/asset-spec`
> specifies asset names from `naming.*`. Unity's `Assets/` and Unreal's `Content/`
> are not naming-checked: those engines name assets in PascalCase. On Godot-C#,
> where `/setup-engine` sets `naming.files: PascalCase`, the hook warns on assets
> named exactly as `/asset-spec` specified them. `naming.files` describes
> **source** files by its own examples (`PlayerController.cs`), and no key governs
> asset filenames, so treat the hook's naming warning as advisory there.
> **Moved from `technical-preferences.md`**, which is being deleted. Naming
> conventions are project-level facts shared by everyone on the project, so they
@@ -1931,19 +1939,8 @@ No skill or hook validates code *against* these conventions — see the note abo
## features.session_state
> ⚠️ **`active.yaml` does not exist and nothing writes it — anywhere in this
> document.** It is deferred design. What ships is
> `production/session-state/**active.md**`, whose `<!-- CHECKPOINT -->` region
> `session-start.sh` and `pre-compact.sh` both read, and whose
> `<!-- STATUS -->` block `statusline.sh` parses. **Read every `active.yaml` and
> `status:` mention in this file — above and below — as the deferred design, and
> substitute `active.md` (and its STATUS block).** This scope note is
> document-wide on purpose: the equivalent warning under *Status line behavior*
> scoped itself to mentions "below", which left this section's own Controls line
> and Hook behavior table describing a file that does not exist.
**Controls:** Whether the harness runs a full session tracking pipeline (hooks,
log files, `active.yaml` checkpoint — see the scope note above) or relies on
log files, `active.md` checkpoint) or relies on
skeleton-first output files for recovery
**Values:** `off` | `on`
**Default:** `on`
@@ -2000,11 +1997,11 @@ skeleton-first output files for recovery
| Hook | session_state: off | session_state: on |
|------|--------------------|-------------------|
| **session-start.sh** | Runs normally (git/sprint context) — skips active.yaml preview block | Runs fully including active.yaml preview |
| **session-start.sh** | Runs normally (git/sprint context) — skips the `active.md` checkpoint preview | Runs fully, including the `active.md` checkpoint preview |
| **detect-gaps.sh** | Runs unchanged — gap detection is independent of session state | Runs unchanged |
| **pre-compact.sh** | No-op — exits silently (no compaction-log append) | The CHECKPOINT block (and any STATUS lines) from `active.md`, changed and untracked file names and design docs with WIP markers — each list capped at 20 — then a compaction-log append; the output goes to the debug log, since PreCompact output never reaches Claude |
| **post-compact.sh** | No-op — exits silently | Runs: prints a re-read reminder to the debug log (PostCompact output never reaches Claude; `session-start.sh` restores context) |
| **session-stop.sh** | No-op — exits silently | Archives active.yaml to session-log, appends commits and diffs |
| **session-stop.sh** | No-op — exits silently | Archives `active.md` to `session-log.md` when it has changed, appends commits and uncommitted file names |
| **log-agent.sh** | No-op — exits silently | Appends to agent-audit.log |
| **log-agent-stop.sh** | No-op — exits silently | Appends to agent-audit.log |
@@ -2015,7 +2012,7 @@ skeleton-first output files for recovery
| File | session_state: off | session_state: on |
|------|--------------------|-------------------|
| `production/session-state/active.md` | Still written by skills; session start does not show it | Written by skills; session start shows its checkpoint |
| `production/session-logs/session-log.md` | Not written | Append-only archive of each session's active.yaml |
| `production/session-logs/session-log.md` | Not written | Append-only archive of each session's `active.md` |
| `production/session-logs/compaction-log.txt` | Not written | Append-only timestamp log of compaction events |
| `production/session-logs/agent-audit.log` | Not written | Append-only log of agent spawn/complete events |
@@ -2044,7 +2041,7 @@ bodies and a `<!-- STATUS: incomplete -->` marker per section.
As each section is approved and written, the marker changes to `<!-- STATUS: done -->`.
On recovery (after /clear or compaction), the agent reads the skeleton, identifies
which sections are `done` vs `incomplete`, reads relevant ADRs and the systems index,
and resumes at the first `incomplete` section. No active.yaml needed.
and resumes at the first `incomplete` section. No `active.md` needed.
**Skills required to implement skeleton-first:**
@@ -2068,14 +2065,6 @@ and resumes at the first `incomplete` section. No active.yaml needed.
### Status line behavior
> ⚠️ **The table below describes POST-YAML-EXPANSION behavior, which is NOT
> IMPLEMENTED.** `active.yaml` does not exist and nothing writes it. What ships
> today: `statusline.sh` parses the `<!-- STATUS --> ... <!-- /STATUS -->`
> markdown comment block inside `production/session-state/active.md`. Substitute
> "the STATUS block in `active.md`" for every `active.yaml` / `status:` mention
> here. **The same substitution applies document-wide, not just below this
> point** — see the scope note under `## features.session_state`.
> **Stage detection is always independent of session state.** `statusline.sh`
> auto-detects stage from `project.yaml` `project.stage` or artifact heuristics regardless
> of `session_state` value, and so is the breadcrumb: `statusline.sh` never reads
@@ -2087,24 +2076,24 @@ and resumes at the first `incomplete` section. No active.yaml needed.
| Context % display | Always shown | Always shown |
| Model display | Always shown | Always shown |
| Stage display | From project.yaml or heuristics — except at `workflow: minimal`, where `Minimal · <done>/<total> stories` (or `Minimal · brief` before any story exists) replaces it | Same |
| Epic/Feature/Task breadcrumb | Parsed from `status:` block in `active.yaml` (not gated) | Parsed from `status:` block in `active.yaml` |
| Epic/Feature/Task breadcrumb | Parsed from the `<!-- STATUS -->` block in `active.md` (not gated) | Parsed from the `<!-- STATUS -->` block in `active.md` |
---
### Affected skills
Skills interact with session state in two ways: **inference** (reading active.yaml
Skills interact with session state in two ways: **inference** (reading `active.md`
to resolve a missing argument) and **extraction** (appending a SESSION EXTRACT
block after completing work). Neither is gated: no skill reads `session_state`,
so both happen whatever its value.
#### Inference — skills that read active.yaml to fill in missing arguments
#### Inference — skills that read `active.md` to fill in missing arguments
When active.yaml holds nothing to infer from, these skills must receive the
When `active.md` holds nothing to infer from, these skills must receive the
argument explicitly. If called without an argument, they should prompt the user
rather than fail silently.
| Skill | What it infers from active.yaml | Fallback when nothing is found |
| Skill | What it infers from `active.md` | Fallback when nothing is found |
|-------|----------------------------------|---------------------|
| **dev-story** | Active story path (when no arg given) | Prompt user for story path |
| **story-done** | In-progress story path (when no arg given) | Prompt user for story path |
@@ -2137,7 +2126,7 @@ the `<!-- CHECKPOINT -->` block; the others append a SESSION EXTRACT.
| Per session start | ~500 tokens (git/sprint context only) | ~500–1,250 tokens (+ checkpoint preview, at most ~750) |
| Per compaction event | 0 (compaction hook output never reaches Claude) | 0 (logged to disk only) |
| Per session end | 0 | File I/O only (no conversation tokens) |
| Recovery after /clear | Read skeleton + 2–3 docs (~1,000–3,000 tokens) | Read active.yaml (~200–500 tokens) |
| Recovery after /clear | Read skeleton + 2–3 docs (~1,000–3,000 tokens) | Read `active.md` (~200–500 tokens) |
> **Note:** The `off` recovery cost (reading skeleton + docs) is paid only when
> recovery is actually needed. The `on` session-start cost is paid every session
@@ -2152,7 +2141,7 @@ the `<!-- CHECKPOINT -->` block; the others append a SESSION EXTRACT.
> **No skill or hook reads this setting. Setting it has no effect.** Everything
> below describes the intended design, not current behaviour.
>
> The value is checked for valid spelling when you set it, and then ignored.
> The value is not checked when you set it, and nothing reads it.
> Nothing warns at any threshold.
**Controls:** Context usage threshold at which session warnings fire
@@ -2281,7 +2270,7 @@ preserved raw and flagged for manual resolution, never coerced.
Settings absent from the legacy files (new v1.1 settings like `qa.level`,
`docs.density`, `team.size`, etc.) get hardcoded defaults from the v1.1 schema.
### Cleanup (deferred, non-destructive)
### Cleanup (optional, non-destructive)
Migration is **non-destructive in v1.1**: legacy files are NOT auto-deleted.
Migration produces `project.yaml` and leaves the legacy files in place. Hooks
+13 -14
View File
@@ -1,10 +1,10 @@
# Error Recovery Protocol
Shared procedure for any skill that spawns agents via the `Agent` tool. Referenced from the
`## Error Recovery Protocol` section of each orchestration/review skill. Those
skills keep the two load-bearing imperatives (surface immediately, produce a
partial report) inline, and keep their own **Common blockers** list inline —
those are skill-specific. This file holds the full procedure.
Shared procedure for any skill that spawns agents via the `Agent` tool, used by
the `## Error Recovery Protocol` section of each orchestration and review skill.
Two imperatives apply to all of them: **surface a blocked agent immediately, and
produce a partial report.** Each skill's own **Common blockers** list is
skill-specific and is not repeated here.
## Trigger 0 — verify the artifact before reading the response
@@ -15,19 +15,18 @@ response reads.
This trigger exists because the three below are not sufficient. They fire on
BLOCKED, on an error, and on "cannot complete" — and an agent can fail in a way
that is none of those. Observed live: a `devops-engineer` spawned
as half of a parallel phase ran **26 tool calls and ~31,600 tokens**, then
returned a single fluent preamble — "I'll verify the build infrastructure…" —
with no path, no summary, no BLOCKED item, and **no file written**. Nothing in
that is none of those. A parallel agent can do a lot of work and then return a
single fluent preamble — "I'll verify the build infrastructure…" — with no
path, no summary, no BLOCKED item, and **no file written**. Nothing in
steps 1–4 matches that shape. An orchestrator reading the transcript sees a
plausible response and advances, and half a parallel phase disappears with no
signal at all.
The work was not lost — resumed with an explicit "you did not honour the return
contract" message, the same agent completed in **one tool call**, because its
investigation was still in context. Only the write-and-return step had failed.
So the recovery is cheap; the detection is the hard part, and the detection
cannot come from reading the response.
The work is usually not lost. Resume the agent with an explicit "you did not
honour the return contract" message. Its investigation is still in context, so
it only has to do the write-and-return step it skipped. So the recovery is
cheap; the detection is the hard part, and the detection cannot come from
reading the response.
**A fluent response is not evidence that a phase ran.** The artifact is —
observe the artifact, not the transcript. The rule applies to sub-agents
+9 -15
View File
@@ -35,17 +35,12 @@ YYYYMMDD_HHMMSS | <session_id> | Agent invoked: <agent_type>
to tally the current session, then writes a count plus a per-agent breakdown to
`production/session-logs/session-cost.md` and echoes a one-line total.
Three constraints that must not be "tidied" later:
The field order of that record is fixed. `session-stop.sh` matches it literally,
so a different order silently zeroes the spawn count instead of raising an error.
- **The field order is load-bearing.** Nothing else parses this log, so a
reformat looks free — but it silently zeroes the spawn count rather than
erroring.
- **`session-stop.sh` reads stdin last, on purpose.** Everything above the
tally block (notably archiving `active.md`) runs first, so a stdin read that
ever blocked would cost only the count, not the state archive.
- **No session id means no number.** The hook prints nothing rather than a
total spanning every session in the log. Silence here is correct; a
plausible-but-wrong cost figure is worse than none.
When the hook input has no session id, `session-stop.sh` prints no total. A
total spanning every session in the log would look plausible and be wrong, which
is worse than none.
`agent_type` — not `agent_name` — is the field carrying the agent name. See
`hooks-reference/hook-input-schemas.md`.
@@ -53,16 +48,15 @@ Three constraints that must not be "tidied" later:
## Events considered and deliberately not added
Claude Code offers many more hook events than the nine the hooks above use. These were
evaluated and rejected. Recorded so a future review does not re-propose them
from the event list alone.
evaluated and not adopted, for the reasons given.
| Event | Why not |
| ---- | ---- |
| `UserPromptSubmit` | Would re-inject session state on **every prompt**. `.claude/docs/config-resolution.md` already rejects the weaker version of this — injecting config at session start — because it "would cost tokens on every session whether or not any skill needs config, and it would go stale mid-session as `/settings` writes land". Firing per prompt is the same argument, multiplied. |
| `ConfigChange` | Fires only for Claude Code's own settings files — user, project, local, policy and skills. It does **not** fire for `project.yaml`, so a hook watching CCGS config here would never run. `FileChanged` is the event that watches arbitrary files. |
| `FileChanged` on `project.yaml` | Config is resolved per skill invocation, in the skill body, precisely so each run reads fresh values. The only staleness left is text already injected into an earlier invocation, which is the accepted trade in `config-resolution.md`. A warning hook would second-guess a settled decision. |
| `ConfigChange` | Fires only for Claude Code's own settings files — user, project, local, policy and skills. It does **not** fire for `project.yaml`, so a hook watching the framework's config here would never run. `FileChanged` is the event that watches arbitrary files. |
| `FileChanged` on `project.yaml` | Config is resolved per skill invocation, in the skill body, precisely so each run reads fresh values. The only staleness left is text already injected into an earlier invocation, which is the accepted trade in `config-resolution.md`. |
| `PreToolUse` `updatedInput` | Could rewrite a non-conventional commit message instead of blocking it. Silently editing the user's input contradicts the collaboration protocol: this project blocks and explains rather than acting unasked. |
| `PostToolUseFailure` | Would add another log with no reader. This repo has already been bitten by that — `log-agent.sh` wrote per-spawn records nothing consumed until `session-stop.sh` was given the job. |
| `PostToolUseFailure` | Would add another log with no reader. |
| `SessionEnd` | `session-stop.sh` stays on `Stop`. `SessionEnd` fires on termination, which a crash may never reach, and the content-hash guard already makes the per-response firing cheap. |
| `InstructionsLoaded` | Useful for debugging which CLAUDE.md and rules files actually loaded, but it is a diagnostic, not a project requirement. Wire it in your own `.claude/settings.local.json` when you need it rather than paying for it on every load. |
+7 -9
View File
@@ -4,14 +4,13 @@
>
> A skill's `model:` overrides the session model for the rest of the turn the
> skill runs in, and your next prompt returns to the session model. Whether the
> override happens depends on how the skill starts (measured on Claude Code
> 2.1.282):
> override happens depends on how the skill starts:
>
> | How the skill starts | Is `model:` used? |
> |---|---|
> | You type `/skill-name` in Manual (`default`) mode | Yes |
> | You type `/skill-name` in auto mode | `sonnet` and `opus`: yes. `haiku`: no — auto mode does not support Haiku, so the session keeps its model (documented) |
> | Claude starts the skill itself, through the Skill tool | No — the session model runs it (measured; the docs do not say) |
> | You type `/skill-name` in auto mode | `sonnet` and `opus`: yes. `haiku`: no — auto mode does not support Haiku, so the session keeps its model |
> | Claude starts the skill itself, through the Skill tool | No — the session model runs it |
>
> Two things follow:
>
@@ -59,10 +58,9 @@ Skills with `model: opus` (3): `/architecture-review`, `/gate-check`, `/review-a
All other skills are Sonnet. When creating a new skill, assign Haiku if it only
reads and formats; assign Opus if it must synthesize 5+ documents with
high-stakes output; otherwise write `model: sonnet` explicitly. Every skill in
this repo declares a tier, and the lists above are kept in step with what the
`SKILL.md` files declare. That is a check on two descriptions agreeing; it
proves nothing about which model actually runs.
high-stakes output; otherwise write `model: sonnet` explicitly. Every skill
declares a tier. Whether the tier takes effect depends on how the skill starts
(see the table at the top of this file).
**Agent model tiers.** 30 agents use `model: inherit` and run on the session's
model. 19 are pinned:
@@ -87,7 +85,7 @@ model. 19 are pinned:
writing player-facing text are Sonnet work, as they are for `/patch-notes`.
Every agent not named above is `inherit`. The `model:` line in the agent's own
file is what runs, and this list is kept in step with those files.
file is what runs.
A pin gets that model's context window, whatever the session runs. On the
Anthropic API `sonnet` currently resolves to Sonnet 5, which always has a 1M
+11 -10
View File
@@ -117,7 +117,7 @@ Ask yourself: "What department would handle this in a real studio?"
| `/ux-review` | Validate UX specs for accessibility and GDD alignment |
| `/create-architecture` | Master architecture document for the game |
| `/architecture-decision` | Creates an ADR |
| `/architecture-review` | Validate all ADRs, dependency ordering, GDD traceability |
| `/architecture-review` | Validate all ADRs, dependency ordering, GDD traceability — writes the index to `docs/architecture/requirements-traceability.md` |
| `/create-control-manifest` | Flat programmer rules sheet from Accepted ADRs |
| `/create-epics` | Translate GDDs + ADRs into epics (one per architectural module) |
| `/create-stories` | Break a single epic into implementable story files |
@@ -180,8 +180,9 @@ Templates are in `.claude/docs/templates/`:
- `game-design-document.md` -- for new mechanics and systems
- `architecture-decision-record.md` -- for technical decisions
- `architecture-traceability.md` -- maps GDD requirements to ADRs to story IDs
(`/architecture-review` writes it to `docs/architecture/requirements-traceability.md`)
- `architecture-traceability.md` -- sample layout for a GDD requirement to ADR to
story index (`/architecture-review` writes its own index to
`docs/architecture/requirements-traceability.md`)
- `risk-register-entry.md` -- for new risks
- `narrative-character-sheet.md` -- for new characters
- `test-plan.md` -- for feature test plans
@@ -247,13 +248,13 @@ If you already know what you need, jump directly to the relevant path:
current docs from the web so agents suggest correct APIs
3. **Validate the concept** — Run `/design-review design/gdd/game-concept.md`
(or `design/game-brief.md`, if `/brainstorm` wrote the one-page brief)
4. **Decompose into systems** — Run `/map-systems` to map all systems and dependencies
5. **Design each system** — Run `/design-system [system-name]` (or `/map-systems next`)
to write GDDs in dependency order
6. **Prototype the mechanic** — Run `/prototype [core-mechanic]` (1–3 days — before writing GDDs)
7. **Design each system** — Run `/design-system [system-name]` to write GDDs, informed by prototype findings
8. **Plan the first sprint** — After architecture and `/vertical-slice`, run `/sprint-plan new`
9. Start building
4. **Prototype the mechanic** — Run `/prototype [core-mechanic]` (1–3 days) to
test that the core idea is fun before you write GDDs
5. **Decompose into systems** — Run `/map-systems` to map all systems and dependencies
6. **Design each system** — Run `/design-system [system-name]` (or `/map-systems next`)
to write GDDs in dependency order, informed by the prototype findings
7. **Plan the first sprint** — After architecture and `/vertical-slice`, run `/sprint-plan new`
8. Start building
### Path B: "I know what I want to build"
+3 -4
View File
@@ -1,10 +1,9 @@
# Run and Observe
Shared procedure for any skill that closes a story which changes something a
player can see. Referenced from the point of use in `/dev-story` (Phase 6) and
`/story-done` (Phase 3). Those skills keep the one load-bearing imperative
inline — **a parse check is not a run, and a story nobody looked at does not
close** — and cite this file for how to look.
player can see. Used by `/dev-story` (Phase 6) and `/story-done` (Phase 3).
**A parse check is not a run, and a story nobody looked at does not close.**
This file explains how to look.
`.claude/docs/coding-standards.md` is the authority for *what* evidence a story
needs. This file is the procedure for *producing* the visual half of it.
+7 -8
View File
@@ -6,7 +6,7 @@ other doc does:
1. **Which value should a skill recommend** for a given project or user?
2. **When should a skill proactively suggest changing** a setting already set?
## Boundary with its siblings — do not duplicate their content here
## Boundary with its siblings
| Doc | Answers | Nature |
|---|---|---|
@@ -15,8 +15,8 @@ other doc does:
| **`settings-guidance.md`** (this file) | Which value to *recommend*, and *when* | Prescriptive |
Skills reference this doc **on demand**, only at a "recommend a setting" moment.
It is deliberately **not** a CLAUDE.md import — advisory content must not ride in
per-turn context (the same reason `context-management.md` was demoted).
It is **not** a CLAUDE.md import — advisory content must not ride in per-turn
context.
---
@@ -26,8 +26,7 @@ Almost every "what settings should I use?" question reduces to one choice:
`modes.rigor` (`minimal` | `standard` | `full`, default `minimal`). It fronts six
sub-knobs — `modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`,
`modes.review_mode`, `team.size`. Recommend **rigor**, not the six; let the
expansion do the rest. Full expansion table lives in `effects-map.md § modes.rigor`
— do not restate it here.
expansion do the rest. The full expansion table is in `effects-map.md § modes.rigor`.
`modes.automation` (`collaborative` | `guided` | `autonomous`) is a **separate
axis** — how often skills stop to confirm — and is *not* fronted by rigor. Pick it
@@ -73,8 +72,8 @@ rigor; want that?"). If the user has **no concept yet** (exploring), do not seed
"No concept yet" means **no signal**, not a particular onboarding path. A rough
one-line hint is still a description: if it trips the signals above, seed from the
signal. Only fall back to `minimal`-for-exploring when the user has given you
nothing to map. (`/start` Phase 3d states the same rule for its Path A/B branch —
the two must agree, since both drive the identical recommendation.)
nothing to map. (`/start` Phase 3d states the same rule for its Path A/B branch;
both drive the same recommendation.)
---
@@ -106,7 +105,7 @@ state is needed — but never emit the same suggestion twice in one session.
| `/gate-check` | on PASS into a new stage | § 4 (raise trigger) |
| `/settings` | view output — further reading | § 2 (choosing a value) |
Each skill carries a **one-line pointer** to this doc, not a copy of its tables.
These skills each carry a **one-line pointer** to this doc.
---
+26 -11
View File
@@ -98,19 +98,34 @@ available on native Windows, which is CCGS's primary platform.
### One setting CCGS does ship
`permissions.defaultMode` is set to `default` in `.claude/settings.json`, on
purpose. It makes Claude Code ask before acting, which is what every approval
gate in this framework depends on. Project settings outrank personal ones, so
this holds even if your own config sets `acceptEdits` or `auto` — otherwise
CCGS's collaboration protocol would be silently switched off for you and the
agents would write files you never approved.
purpose. A terminal session started **at the project root** then starts in
Claude Code's ask-first mode, so file edits wait for your approval even if your
own config sets `acceptEdits` or `auto`.
If you genuinely want it off, override it in `.claude/settings.local.json`,
which takes precedence. Understand what you are turning off first.
It sets the mode a session starts in. It is a backstop, not a guarantee, and
these routes go around it:
**The VS Code extension does not read it.** The extension never reads a
project's `.claude/settings.json` for the permission mode a conversation starts
in. To get the same behaviour there, set `claudeCode.initialPermissionMode` to
`default` in your VS Code user settings.
- **Starting in a subfolder** such as `design/` or the code root (`src/`,
`Assets/` or `Source/`, depending on the engine). Claude Code loads
`.claude/settings.json` only from the folder it starts in, so that session has
none of this project's hooks, deny rules or permission mode. Start at the root.
- **Resuming a session.** A resumed session keeps the mode it ended in.
- **Switching during a session**: Shift+Tab, answering "Yes, and switch to auto
mode", or allowing all edits for the session.
- **`claude --permission-mode auto`** on the command line.
- **The VS Code extension**, which never reads a project's `.claude/settings.json`
for the mode a conversation starts in. Set `claudeCode.initialPermissionMode`
to `default` in your VS Code user settings to get the same behaviour.
- **The Desktop app**, which remembers the mode you last picked for a folder and
uses that instead.
In any mode that accepts edits without asking, the framework's "May I write?" is
an instruction to the model, not a stop.
To start terminal sessions in a different mode, set `permissions.defaultMode` in
`.claude/settings.local.json`, which takes precedence. Terminal sessions accept
any mode from it except `auto` and `bypassPermissions`. Understand what you are
turning off first.
## Recommended IDE
+1 -1
View File
@@ -14,7 +14,7 @@
> - PlayStation Accessibility (Sony Guidelines) [Yes / No / Partial]
> - Apple / Google Accessibility Guidelines [Yes / No / N/A — mobile only]
> **Accessibility Consultant**: [Name and organization, or "None engaged"]
> **Linked Documents**: `design/gdd/systems-index.md`, `docs/ux/interaction-pattern-library.md`
> **Linked Documents**: `design/gdd/systems-index.md`, `design/ux/interaction-patterns.md`
> **Why this document exists**: Per-screen accessibility annotations belong in
> UX specs. This document captures the project-wide accessibility commitments,
+7 -9
View File
@@ -6,11 +6,10 @@
> **Who may move this to `Accepted`: the user, or `technical-director` on the
> user's explicit confirmation. No other agent, and no skill on its own.**
> Stated here because every consumer of this field enforces the *consequences*
> of acceptance (stories referencing a `Proposed` ADR are set `Blocked`; epics
> require `Accepted`), so something has to say who may produce it. `technical-director` is the role `coordination-rules.md`
> already escalates technical conflicts to, and an ADR is exactly that decision
> made durable.
> Why this is stated here: stories referencing a `Proposed` ADR are set `Blocked`,
> and epics require `Accepted`, so the field needs a named owner.
> `technical-director` is the role `coordination-rules.md` already escalates
> technical conflicts to, and an ADR is that decision made durable.
>
> This does **not** relax the existing rule that `Status: Accepted` is never set
> without explicit user confirmation — it narrows *which agent* may set it once
@@ -59,10 +58,9 @@ chosen approach.]
> `/architecture-decision`, `/story-readiness`, `/propagate-design-change` and
> `gate-pre-production.md`; a missing row counts as critical. At `standard`,
> `/create-stories` **stops** for a missing critical ADR and only **warns** for a
> non-critical one, so this row decides whether a run halts. Earlier revisions of
> this template recorded no layer at all, leaving those sites to infer one from
> the referencing epic — which gives the wrong answer whenever a Foundation-layer
> ADR is referenced by a Core-layer epic, the common case.
> non-critical one, so this row decides whether a run halts. Do not infer the
> layer from the referencing epic: a Foundation-layer ADR is commonly referenced
> by a Core-layer epic, which would give the wrong answer.
>
> The vocabulary is the same `Foundation / Core / Feature / Presentation` that
> epics and stories already carry — do not invent a fifth value, and do not
+1 -1
View File
@@ -3,7 +3,7 @@
> **Status**: Draft | In Review | Approved
> **Author**: [game-designer / systems-designer]
> **Last Updated**: [Date]
> **Links To**: `design/gdd/game-concept.md`
> **Links To**: `design/gdd/game-concept.md` (or `design/game-brief.md`)
> **Relevant GDDs**: [e.g., `design/gdd/combat.md`, `design/gdd/progression.md`]
---
+1 -1
View File
@@ -11,7 +11,7 @@
> **Related Documents**:
> - `design/art/art-bible.md` — visual standards (colors, typography, iconography)
> - `design/accessibility-requirements.md` — accessibility commitments per feature
> - `docs/ux/ux-spec-[screen].md` — individual screen specs that reference patterns
> - `design/ux/[screen].md` — individual screen specs that reference patterns
>
> **Template**: Interaction Pattern Library
+1 -1
View File
@@ -3,7 +3,7 @@
> **Status**: Draft | In Review | Approved
> **Author**: [game-designer / creative-director]
> **Last Updated**: [Date]
> **Links To**: `design/gdd/game-concept.md`, `design/gdd/game-pillars.md`
> **Links To**: `design/gdd/game-concept.md` (or `design/game-brief.md`), `design/gdd/game-pillars.md`
---
+1 -1
View File
@@ -2,7 +2,7 @@
> **Date**: [YYYY-MM-DD]
> **Prototype Path**: [HTML / Engine / Paper]
> **Concept File**: design/gdd/game-concept.md (if exists)
> **Concept File**: design/gdd/game-concept.md, or design/game-brief.md (if either exists)
---
+7 -9
View File
@@ -1,7 +1,7 @@
# Active Session State — [project or branch]
<!--
THE CONTRACT. Read this before editing the file or any hook that consumes it.
HOW THIS FILE WORKS. Read this before editing it.
This file has TWO regions and they are not interchangeable:
@@ -14,12 +14,10 @@
and for a returning agent that wants detail. No hook ever injects it, so
it may grow — but see Rotation below.
Why the split exists: before it, `active.md` was one append-only file doing
both jobs. It reached 712 lines / 44 KB, and each consumer invented its own
slice of it — the status line parsed for a STATUS block nothing wrote,
pre-compact injected `head -100` (12.7 KB), and session-start previewed
`tail -20`, the opposite end. They disagreed because there was no contract to
agree on. Now every consumer reads the named region.
Why the split exists: one append-only file doing both jobs grows without
bound, and every consumer then reads a different slice of it: the top, the
bottom, or a block nothing writes. They disagree because there is no contract
to agree on. With the named regions, every consumer reads the same part.
ROTATION. When the narrative below grows past ~200 lines, move it to
`production/session-logs/` and start it fresh:
@@ -71,6 +69,6 @@ or agent picking this up cold.]
long the narrative gets.
Write it so a cold reader can resume without reading anything else. "Current
task: fixing the thing" is useless; "Current task: wiring modes.rigor into
/gate-check section 6.4" is not.
task: fixing the thing" is useless; "Current task: adding wall-jump to
player_movement.gd" is not.
-->
+1 -1
View File
@@ -3,7 +3,7 @@
> **Status**: [Draft / Under Review / Approved]
> **Created**: [Date]
> **Last Updated**: [Date]
> **Source Concept**: design/gdd/game-concept.md
> **Source Concept**: design/gdd/game-concept.md (or design/game-brief.md)
---
+1 -1
View File
@@ -9,7 +9,7 @@
> **Platform Target**: [PC | Console | Mobile | All — list all that this spec covers]
> **Related GDDs**: [Links to the GDD sections that generated this UI requirement — e.g., `design/gdd/inventory.md § UI Requirements`]
> **Related ADRs**: [Any architectural decisions that constrain this screen — e.g., `ADR-0012: UI Framework Selection`]
> **Related UX Specs**: [Sibling and parent screens — e.g., `ux-spec-pause-menu.md`, `ux-spec-settings.md`]
> **Related UX Specs**: [Sibling and parent screens — e.g., `pause-menu.md`, `settings.md`]
> **Accessibility Tier**: Basic | Standard | Comprehensive | Exemplary
> **Template**: UX Spec
+1 -1
View File
@@ -3,7 +3,7 @@
> **Date**: [YYYY-MM-DD]
> **Slice Duration**: [N days]
> **Target Scope**: 3–5 minutes of polished, continuous gameplay
> **Source GDD**: design/gdd/game-concept.md
> **Source GDD**: design/gdd/game-concept.md (or design/game-brief.md)
---
+11 -21
View File
@@ -92,11 +92,10 @@ phases:
name: "Engine Setup"
command: /setup-engine
required: true
# v1.1: engine.name in project.yaml is the primary source; technical-
# preferences.md is the legacy fallback. Checking only the legacy file
# made a correctly-configured project fail this REQUIRED gate.
# engine.name in project.yaml is the primary source; technical-
# preferences.md is the legacy fallback. Either one completes the step.
# /setup-engine writes the value quoted (`name: "Godot"`), so the quote
# is optional; without it only the legacy alternative ever matched.
# is optional in the first alternative.
# Single-quoted so the `"` needs no escape — artifact-check.sh strips
# the outer quotes and does not unescape.
artifact:
@@ -104,9 +103,7 @@ phases:
- glob: "project.yaml"
pattern: 'name:[[:space:]]*"?(Godot|Unity|Unreal)'
# technical-preferences.md writes "- **Engine**: Godot 4.6", so the
# pattern must clear the bold markers. The previous "Engine: [^[]"
# required a literal "Engine: " and therefore never matched any
# file /setup-engine produces. The [^[] guard rejects the
# pattern must clear the bold markers. The [^[] guard rejects the
# "[TO BE CONFIGURED]" placeholder.
- glob: ".claude/docs/technical-preferences.md"
pattern: '\*\*Engine\*\*: [^[]'
@@ -219,11 +216,6 @@ phases:
- id: accessibility-doc
name: "Accessibility Requirements"
# This step had no `command:` at all -- the only artifact entry in the
# catalog that named no producer. It was REQUIRED, so the Technical
# Setup -> Pre-Production gate could never pass, and the remediation
# every skill printed ("run /ux-design") wrote into design/ux/ where
# this glob does not look. /ux-design now has an `accessibility` mode.
command: /ux-design
required: true
artifact:
@@ -289,10 +281,10 @@ phases:
command: /prototype
required: false
artifact:
# /prototype writes prototypes/[name]-concept/REPORT.md -- it has never
# written a README. The `-concept` suffix is load-bearing: /vertical-slice
# writes the same REPORT.md basename under `-vertical-slice`, so a bare
# `prototypes/*/REPORT.md` here would let either step satisfy the other.
# /prototype writes prototypes/[name]-concept/REPORT.md. The `-concept`
# suffix matters: /vertical-slice writes the same REPORT.md basename
# under `-vertical-slice`, so a bare `prototypes/*/REPORT.md` here
# would let either step satisfy the other.
glob: "prototypes/*-concept/REPORT.md"
min_count: 1
description: "Build a throwaway prototype to validate the core mechanic is fun before committing to full production. Recommended for first-time mechanics or high-risk design decisions. Solo devs with proven concepts may skip."
@@ -331,9 +323,9 @@ phases:
command: /vertical-slice
required: false
artifact:
# Must stay scoped to `-vertical-slice`: the untethered form matched
# /prototype's concept report, so running only /prototype silently
# marked the vertical slice complete and skipped the validation the
# Scoped to `-vertical-slice`: an unscoped form would match
# /prototype's concept report, so running only /prototype would mark
# the vertical slice complete and skip the validation the
# Pre-Production → Production gate exists to require.
glob: "prototypes/*-vertical-slice/REPORT.md"
min_count: 1
@@ -454,8 +446,6 @@ phases:
required: true
artifact:
# /playtest-report writes production/qa/playtests/, not production/playtests/.
# The old glob matched nothing on every project, so this REQUIRED step
# read as 0/3 forever no matter how many playtests were actually run.
glob: "production/qa/playtests/*.md"
min_count: 3
description: "Cover: new player experience, mid-game systems, difficulty curve"
+14 -14
View File
@@ -9,10 +9,10 @@ this document instead of embedding the tier tables inline.
sections `modes.workflow` and `workflow_overrides` are the source of
truth for behavior. This document is the implementation pattern.
> **Do not read `effects-map.md` during a skill run.** It is ~2,150 lines
> (~110 KB) — about five times the size of everything CLAUDE.md loads per
> session combined — and it is a reference for *authoring and changing the
> spec*, not a runtime input. **This document is self-sufficient** for resolving
> **Do not read `effects-map.md` during a skill run.** It is many times the
> size of everything CLAUDE.md loads per session combined — and it is a
> reference for *authoring and changing the spec*, not a runtime input.
> **This document is self-sufficient** for resolving
> the tier and applying it: the resolution chain, the three tiers, the required
> sections, and the override rules are all here. If you hit a case this document
> genuinely does not cover, read only the one `effects-map.md` section for the
@@ -50,8 +50,8 @@ its fallback will ignore `rigor: minimal` and `rigor: full` entirely.
### What `<system>` is — one derivation, everywhere
**`<system>` is the GDD filename stem**: `design/gdd/hammer-heat-system.md` →
`hammer-heat-system`. That is the key to write under
**`<system>` is the GDD filename stem**: `design/gdd/forge-heat-system.md` →
`forge-heat-system`. That is the key to write under
`workflow_overrides.system_overrides`, and every skill must derive it the same
way.
@@ -61,18 +61,18 @@ from it in preference to the stem.
> **Why this is stated here rather than per skill.** Reading *"the `[system]`
> segment of its `TR-[system]-NNN` ID (else its `design/gdd/` path)"* — TR-ID
> **first** — is the wrong order. A system whose GDD is `hammer-heat-system.md` and
> whose requirements are `TR-heat-001` then had **two different override keys
> depending on whether a registry entry existed**, and the documented remedy for
> a missing GDD section — "set
> `workflow_overrides.system_overrides.hammer-heat-system: full`" — was looked up
> under `heat`, found nothing, and continued at the project tier **silently**.
> The escape hatch existed and could not be reached.
> **first** — is the wrong order. A system whose GDD is `forge-heat-system.md` and
> whose requirements are `TR-forge-001` would then have **two different override
> keys depending on whether a registry entry existed**, and the documented remedy
> for a missing GDD section — "set
> `workflow_overrides.system_overrides.forge-heat-system: full`" — would be looked
> up under `forge`, find nothing, and continue at the project tier **silently**.
> The escape hatch would exist and could not be reached.
**A key that matches no system is an error, not a no-op.** If
`workflow_overrides.system_overrides` contains a key that resolves to no GDD stem
in `design/gdd/`, say so — naming the unmatched key and the stems available.
Silently ignoring it is how the above went unnoticed.
Silently ignoring it would leave an override that does nothing, unnoticed.
> **Checked where GDDs are expected to already exist — not by the skill that
> writes them.** `/gate-check` is the single implementing site (see