Files
Claude-Code-Game-Studios/.claude/docs/effects-map.md
T
DonchitosandClaude Opus 5.5 b21fa0f7f2 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
2026-09-29 21:32:19 +10:00

134 KiB
Raw Blame History

project.yaml — Effects Map

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>.

So opening it costs 36× what you need. To look up a setting:

Grep pattern="^## modes.review_mode" path=".claude/docs/effects-map.md" -A 40

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.

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.

This document defines what each project.yaml setting actually does across every skill that reads it. It is the tracked, authoritative reference.

Purpose: When a skill reads a setting, this document is the authoritative source for what each value means for that skill's behavior. Implementers update this file when adding a new setting or changing how a skill responds to one.

Format per setting:

  • Priority chain — which source wins when multiple are present
  • Per-value intent — what the value means in plain terms
  • Skill behavior table — exactly what changes per skill per value

Coverage scope: This document covers the skills most affected by each setting. Skills not listed (e.g. ux-review, balance-check, test-flakiness, test-helpers, test-setup, soak-test, perf-profile, launch-checklist, release-checklist, skill-test, skill-improve, vertical-slice) are not meaningfully affected by project.yaml settings and do not need entries here. Add a skill only when its behavior genuinely branches on a setting value.

Local override pattern: project.yaml is committed to git as the shared team config. Per-developer overrides live in project.local.yaml (gitignored). Priority chain across all settings: project.local.yaml → project.yaml → legacy mirror → modes.rigor expansion → hardcoded default. The expansion step applies only to the six knobs rigor fronts (modes.workflow, docs.density, qa.level, modes.story_granularity, modes.review_mode, team.size), which for that reason have no hardcoded default — see the modes.rigor section. Secrets do NOT belong in either file — use environment variables. See the "Local Override Pattern" section below for full design including the whitelist of which settings can be locally overridden.


Local Override Pattern — project.local.yaml

The project.local.yaml file lets each developer override specific settings for their own use without affecting the team. The file is gitignored and never committed.

How it works

Priority chain (every setting): project.local.yaml → project.yaml → hardcoded default

If a setting is present in project.local.yaml, that value wins. If absent, the value from project.yaml is used. If absent there too, the hardcoded default takes over.


Deep merge semantics

When both files set a nested value, only the explicitly-set key is overridden. Sibling keys in the same block are preserved.

Example:

project.yaml:

testing:
  strict:
    logic: true
    integration: true
    visual: false

project.local.yaml (sparse override):

testing:
  strict:
    logic: false

Effective config seen by skills: logic: false, integration: true, visual: false. Only the explicitly-set logic key is overridden; sibling keys come through from project.yaml.


Whitelist — which settings can be locally overridden

Only personal-experience settings can be locally overridden. Project-wide facts (engine, stage, naming conventions, what's required on disk) are locked to project.yaml because divergence between developers would break team coordination.

The rule for deciding which side a setting belongs on:

If a setting affects what artifacts exist or what they look like on disk, it must be locked to project.yaml. If a setting only changes your personal experience (which agents spawn for you, whether you get prompts, your local CI bypass), it can be locally overridden.

Locally overridable (personal experience only — no effect on artifacts on disk):

Setting Why local override makes sense
modes.review_mode How much AI review you personally want
modes.automation How often the AI prompts you
modes.automation_always_ask Your personal safety categories
team.size Which agents spawn for your reviews (review depth differs, artifacts don't)
testing.strict.* (each type) Whether failures block your local work (CI still enforces project.yaml defaults)
performance.enforce Whether budget violations block your local work (CI enforces project defaults)
features.session_state Your session tracking preference
features.token_budget_warn_at Your personal cost threshold

Locked to project.yaml (project-wide — would create artifact divergence if local):

Setting Why it must be project-wide
schema_version, framework.* File metadata, not preferences — exempt from the report below, since a project.local.yaml carrying schema_version: 1 is correct as written
project.name, version, genre, kind, stage Project identity
engine.*, specialists.* Whole team must use same engine
naming.* Code conventions must be consistent across team
platform.* Game facts (what platforms it ships on)
performance.target_framerate, frame_budget_ms, draw_call_limit, memory_ceiling_mb Game budgets, shared targets
accessibility.target Game commitment, project-wide
cadence.* Sprint/milestone length affects team coordination
modes.rigor Fronts the four below — locked for the same reason they are
modes.workflow and workflow_overrides Affects which sections are required in authored docs
modes.story_granularity Affects how big stories are in repo — team must be consistent
docs.density Affects how deep authored docs are — team must produce consistent docs
qa.level Affects what test evidence stories must include on disk
qa.coverage_minimum Project quality bar
strict_gate_checks Affects whether project.stage advances — a project-wide write
commands.* Build/test commands are project facts
testing.framework Whole project uses one framework

A locked key written into project.local.yaml by hand is reported, not swallowed. /settings --local refuses to write one, but the file is meant to be hand-edited and that path had no guard: modes.rigor: full there is a real key with a legal value, so enum validation passes it, and then resolution never consults the local file for that path — the setting vanishes and the user sees the default they were trying to override, with no error anywhere. Every check validated the value; nothing validated the location. validate_local_scope in yaml-helper.sh now names such keys on resolve_config's notes: line. It warns and never reconciles: it does not edit the file, does not begin honouring the key, and does not change resolution — a locked setting decides which artifacts exist on disk, so applying one quietly would produce exactly the divergence this table prevents. A clean file stays silent — you are only told when a key is actually in the wrong place.


/settings --local flag behavior

/settings workflow=minimal               → writes to project.yaml (team-wide)
/settings --local automation=autonomous  → writes to project.local.yaml (just you)

Behavior rules:

  • Default (no flag): writes to project.yaml
  • --local flag: writes to project.local.yaml (creates it if absent)
  • --local on a locked setting → error:

    "<setting> cannot be locally overridden — it's a project-wide setting. Use /settings <setting>=<value> (no --local) to change it for the whole team."

  • Writing to project.yaml when the same setting is currently locally overridden → warning:

    "This setting is currently locally overridden in project.local.yaml. Writing to project.yaml will not affect your effective value."


Schema validation on read

When skills or hooks read either file:

Issue Behavior
Unknown key (typo or stale setting) Session-start warning: "project.local.yaml has unknown key modes.automaton — typo? Ignored." Does NOT block (forwards-compat with future settings).
Invalid value not in enum (e.g. automation: chaotic) Hard error: skill exits with explanation of valid values.
Type mismatch (e.g. integer field set to a string) Hard error: skill exits with type expected.

Creation and error handling

Scenario Behavior
/start on fresh project Creates project.yaml only. Does NOT create project.local.yaml.
/settings --local <x>=<y> when local.yaml doesn't exist Creates project.local.yaml containing just that setting.
project.local.yaml exists but project.yaml doesn't Hard error: "project.yaml missing — run /start to create one. Local overrides require a base."
Both files exist Read project.yaml first, deep-merge project.local.yaml on top. Normal operation.
Both files set the same key project.local.yaml wins. No prompting.

Two-developer clash scenarios — and why the whitelist prevents them

File-level conflict (project.yaml): Standard git merge conflict. Each developer's project.local.yaml is gitignored and never collides with another developer's. Normal git workflow handles team-wide changes.

Logical inconsistency (prevented by whitelist):

Example of what the whitelist prevents:

Sarah sets modes.workflow: minimal locally to skip GDD requirements. She doesn't write GDDs because her local mode doesn't require them. Mike runs /gate-check with the team's project.yaml value, standard; gate-check sees missing GDDs and fails.

This can't happen because modes.workflow is locked to project.yaml. Same for qa.level, docs.density, strict_gate_checks, naming.*, and every other setting that affects what artifacts exist on disk.

Personal experience settings (automation, review_mode, team.size, testing.strict.*, performance.enforce) can diverge freely without affecting anyone else.


Stricter reviewer reviewing a looser reviewer's work

A common worry: "what if my teammate has stricter review settings than me? Will their /gate-check or /design-review flag things in my work?"

The answer depends on which kind of difference you're talking about:

Different review depth, same project requirements (HEALTHY):

  • Teammate A: local review_mode: full, automation: collaborative, testing.strict.logic: true
  • Teammate B: local review_mode: solo, automation: autonomous, testing.strict.logic: false
  • Both bound by the same project.yaml-locked settings (e.g. workflow: standard, qa.level: standard)

B writes a GDD that meets workflow: standard (all 5 required sections present). B's /design-review runs with review_mode: solo — fast advisory check, no specialists spawned. B moves on.

Later A reviews the same GDD with review_mode: full — spawns 5–15 specialists, finds polish opportunities and edge cases B's lighter review missed. A files findings as PR comments or follow-up issues. B addresses the ones that matter.

This is normal team collaboration. Different reviewers catching different things is the value of having multiple reviewers. The artifacts on disk are the same; only review depth differs. Nothing about this scenario creates project-state divergence.

Different requirements (PREVENTED by the whitelist):

If qa.level were locally overridable:

  • B sets qa.level: minimal locally. B's stories don't include test evidence.
  • B's /story-done accepts the story without evidence. Story marked Complete on disk.
  • A pulls. A's qa.level: standard requires evidence. A's /story-done would have rejected it.
  • A's next /gate-check fails because evidence is missing across multiple of B's "Complete" stories.

This is the artifact divergence problem. To prevent it, qa.level is locked to project.yaml. The team agrees together on what's required; individuals override only their personal experience, never the team's standards.

The pattern to remember:

Difference type Outcome
Different review depth (review_mode, team.size) Stricter reviewer surfaces more findings — healthy. Artifacts unchanged.
Different local strictness on failures (testing.strict.*, performance.enforce) Stricter dev's local /story-done blocks earlier — they fix it locally. CI uses project.yaml defaults so team-wide quality bar stays.
Different artifact requirements (workflow, qa.level, docs.density, etc.) Can't happen — these are locked. Team agrees once in project.yaml.

CI behavior

CI environments have no project.local.yaml — the file is gitignored and never present in a fresh clone. CI therefore always runs against project.yaml defaults: strict project standards, no developer-specific overrides.

This is intentional and important:

Setting Local default for fast iteration CI default (project.yaml)
modes.review_mode (locally overridable) solo for one developer lean (a team's usual choice — phase gates always run)
testing.strict.logic (locally overridable) false for fast WIP commits true (failing tests block CI)
modes.automation (locally overridable) autonomous for solo flow collaborative (the team's collab protocol, but CI doesn't ask questions anyway — this is mostly a no-op on CI)

A developer can iterate locally with relaxed gates, but CI catches issues using the strict project defaults. The team's quality bar is enforced at the CI level regardless of any individual developer's local config.


Secrets — never in either file

project.yaml and project.local.yaml are for preferences and configuration, never for secrets. API keys, tokens, and credentials belong in:

  • Environment variables (preferred for production/CI)
  • .env file (gitignored, local dev)
  • OS keychain (when integrating with services that support it)

When a skill needs an API key (e.g. /asset-spec calling Midjourney), it reads from the environment, not from project.yaml. project.yaml only stores which generator is used (art.generator: midjourney), not the API key for it.

CI environments typically have no project.local.yaml (gitignored, not in the clone) — so CI always runs against project.yaml defaults. This is correct behavior: strict project defaults for CI, looser developer overrides for local work.


modes.review_mode

Controls: How many specialist and director agents are spawned during skill execution
Values: full | lean | solo
Default: none — supplied by modes.rigor (minimal, the default, yields solo; standard yields lean; full yields full)
Set by: /settings, or migrate-v1-config.sh (which /adopt runs) when it carries over a v1.0 production/review-mode.txt. /start and /adopt never write it themselves — unset, it follows modes.rigor
Read by: See skill table below

Priority chain (all skills): inline argument flag → modes.review_mode in project.yaml → production/review-mode.txt (legacy fallback) → modes.rigor expansion (no terminal default; minimal→solo, standard→lean, full→full)

design-review follows the standard chain. modes.review_mode controls design-review depth, its inline flag is --review for consistency with every other review-mode-aware skill, and with nothing set it follows modes.rigor like them: solo at minimal (the default), lean at standard.

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.

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.


Value intent

Value Intent
full All director and specialist gates active. Best for teams, learning, or anyone who wants thorough AI feedback on every decision.
lean Phase gates only — per-skill director sign-offs skipped. The rigor: standard value. Balances quality with token cost.
solo No gates, no director spawns (a pipeline's own review, such as /team-narrative's ND-CONSISTENCY, still runs). Fastest. For confident solo iteration. The default, from rigor: minimal.

Core skills (currently review-mode aware)

Skill full lean solo
design-review 5–15 specialist agents spawned in Phase 3b No specialist agents — single-session analysis only Phases 1–4 only, no delegation, no next-steps prompt
gate-check Director panel runs in parallel — width set by modes.workflow, not by this axis Director panel runs in parallel — same width rule; phase gates always run Artifact existence checks only, no directors spawned
design-system All section specialists + CD-GDD-ALIGN sign-off gate Specialists for Sections D and H only (+ G when its knobs interact, + Visual/Audio when visual feedback is central); CD-GDD-ALIGN skipped No section specialists; CD-GDD-ALIGN skipped
art-bible All section specialists + AD-ART-BIBLE sign-off gate All section specialists, AD-ART-BIBLE skipped All section specialists, AD-ART-BIBLE skipped
architecture-decision Engine specialist + TD-ADR gate Engine specialist; TD-ADR skipped Engine specialist; TD-ADR skipped
create-architecture TD-ARCHITECTURE + LP-FEASIBILITY agents, in parallel Both skipped Both skipped
brainstorm CD-PILLARS, AD-CONCEPT-VISUAL, TD-FEASIBILITY, PR-SCOPE All skipped All skipped
map-systems TD-SYSTEM-BOUNDARY, PR-SCOPE, CD-SYSTEMS All skipped All skipped
story-done QL-TEST-COVERAGE + LP-CODE-REVIEW Both skipped Both skipped
sprint-plan PR-SPRINT feasibility check Skipped Skipped
create-epics PR-EPIC scope check Skipped Skipped
create-stories QL-STORY-READY + test case specs Skipped Skipped
prototype CD-PLAYTEST review — APPROVE keeps the recommendation; CONCERNS and REJECT go to the user, who decides Skipped — the recommendation stands unreviewed Skipped — the recommendation stands unreviewed
milestone-review PR-MILESTONE feasibility check Skipped — no producer verdict Skipped — no producer verdict
playtest-report CD-PLAYTEST creative assessment Skipped Skipped
story-readiness QL-STORY-READY acceptance criteria check Skipped Skipped
create-control-manifest TD-MANIFEST (technical-director) review Skipped Skipped
propagate-design-change TD-CHANGE-IMPACT (technical-director) review Skipped Skipped

Skills to be made review-mode aware (currently ignore the setting)

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

Team orchestration skills (pipeline behavior — different relationship)

Team skills are execution pipelines, not review gates. In them review_mode sets only director-gate depth; team.size picks the agents (see ## team.size), and a pipeline's own review steps run in every mode.

Skill full lean solo
All nine team-* Every director gate the pipeline names PHASE-GATE-type gates only No director gates
team-release + technical-director release sign-off before the go/no-go call Sign-off not run — recorded as not run (review_mode: lean) Sign-off not run — recorded as not run (review_mode: solo)
team-narrative ND-CONSISTENCY; at team.size: small, + localization-lead and world-builder ND-CONSISTENCY; at small, narrative-director + writer only ND-CONSISTENCY still runs when narrative-director is active

Special cases and notes

  • gate-check is the only skill where full and lean behave identically — 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 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 mandatory for the authoring output to be useful, and that has not changed. design-system is different: lean keeps the specialists for its high-risk sections only (D and H, plus G and Visual/Audio when they matter) and solo drafts every section without one, and each skipped spawn is announced by name. What sets art-bible's spawn count is therefore not review_mode but (a) modes.workflow, via how many sections get authored at all — standard requires sections 1–4, not all 9, and Phase 1 recommends the tier's set — and (b) batching consecutive sections that call the same agent with the same input into one delegation (2–4, and 5–6). Unbatched, sections 5 and 6 spawn art-director twice with the identical sections 1–4 brief. Every section is still specialist-authored; per-section approval and write-to-file are unchanged.
  • dev-story core programmer routing (gameplay-programmer, ui-programmer, etc.) always runs regardless of mode — only the optional engine-specialist escalation for HIGH risk stories is gated.
  • hotfix and day-one-patch are exempt — all agents always run.
  • When a gate is skipped, skills emit: "[GATE-ID] skipped — [mode] mode." before proceeding. This is consistent across all skills.

modes.rigor

Controls: How much process the project carries overall — the single question /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. Set by: /start (Phase 3d), /settings Read by: nothing directly — it is read through the six knobs it supplies

Priority chain: modes.rigor in project.yaml → hardcoded default minimal (locked — not overridable from project.local.yaml, like the four on-disk knobs it fronts — modes.workflow, docs.density, qa.level, modes.story_granularity — because those five change what artifacts exist on disk. The two personal-experience knobs it also fronts, modes.review_mode and team.size, stay locally overridable.)


Expansion table

modes.rigor modes.workflow docs.density qa.level modes.story_granularity modes.review_mode team.size
minimal (default) minimal terse minimal coarse solo individual
standard standard balanced standard balanced lean individual
full full thorough full fine full studio

It fronts, it does not replace

The expansion sits below every explicit source and above the terminal default:

project.local.yaml → project.yaml → legacy file → rigor expansion → default

That ordering is the back-compat guarantee, and it is what makes the migration free. Three consequences worth stating plainly:

  • An existing project.yaml behaves identically. If it already sets docs.density: terse, step 2 answers before the expansion is consulted — so the value and its reported source (project.yaml) are unchanged whether or not rigor is present. No migration, no schema_version bump.
  • Overrides go both ways. Unlike the workflow_overrides boolean flags — which are additive and stricter-only — an explicit knob may be looser than the rigor level implies. (workflow_overrides.system_overrides is also two-directional — it replaces a tier; only the flags are stricter-only.) Inheriting the stricter-only rule would make "comprehensive but compact" inexpressible, which is the one off-diagonal the docs have always cited.
  • modes.workflow keeps workflow_overrides.system_overrides. Per-system tiers still beat the rigor-derived project tier. workflow was fronted rather than folded away precisely because it drives ~5 distinct behaviors and owns the only per-system override mechanism.

The six fronted knobs therefore have no entry in _yaml_helper_defaults. A terminal default there would answer before the expansion and make rigor a no-op for anyone who had not also set the sub-knob.

Provenance

Derived values report their source as rigor:<level>, so the vocabulary is {project.local.yaml, project.yaml, <legacy path>, rigor:<level>, default, unset}. /settings renders this as (derived from rigor: standard) and force-appends the five to its view-all list — none of them is a leaf of either YAML file, so enumerating file leaves alone would hide exactly the settings the user just chose.


modes.workflow

Controls: How much design documentation is required before code can begin — the tradeoff between token/time cost of documentation and speed of reaching working code
Values: full | standard | minimal
Default: none — supplied by modes.rigor (minimal, the default, yields minimal; standard yields standard; full yields full)
Set by: /start (via modes.rigor), /settings
Read by: See skill tables below

Priority chain: modes.workflow in project.yaml → modes.rigor expansion → (no hardcoded default)

Why the middle level is standard, not indie. A developer-type label would conflate "type of developer" with "level of process". standard describes the amount of process, not the user, and pairs cleanly with minimal and full.

Permissive, not restrictive: workflow controls what is REQUIRED — not what is ALLOWED. Any skill can be run at any workflow level. The setting changes what gate-check enforces and what completeness checks validate, not what the user can invoke.

minimal floor: Even in minimal mode, engine choice and a filled design/game-brief.md are required before code starts — the brief's build-order field is the plan, so there is no separate sprint-plan step. Both take minutes and prevent real problems downstream. Everything else can be skipped.

Escape hatches via workflow_overrides: Users who want almost the standard set with one extra requirement (e.g. always force Edge Cases) use workflow_overrides rather than escalating to full. See next section.


Value intent

Value Token/time cost Required before code Best for
full High All 8 GDD sections per system, full architecture, all ADRs, art bible, UX specs per screen Projects where design correctness matters more than speed — teams, commercial titles, learning the full pipeline
standard Balanced 5 GDD sections per system, one architecture doc, critical ADRs, game concept, systems index Projects that have outgrown a brief — several interacting systems, or a design someone else has to implement
minimal Low One-page design/game-brief.md + engine choice (build order in the brief = the plan; no separate sprint plan) Default. Get to code fast — small scope, jam projects, or the design already in your head. Raise it when the project grows

standard required GDD sections: Overview, Detailed Rules, Edge Cases, Dependencies, Acceptance Criteria. standard conditional: Formulas — required when the system defines numeric rules: rates, curves, thresholds, costs, damage, drop weights, or any value a balance pass would tune. Optional only when the system defines no such value.

The test is what the system defines, not what it is called. The Category column in systems-index.md is a hint — Gameplay, Economy and Progression systems almost always qualify — but it is not the test, and a Core, UI or Persistence system that defines a numeric rule qualifies too.

Do not restate it as "required when system category is combat, economy, progression, or AI". Those four tokens are not the vocabulary /map-systems writes: templates/systems-index.md defines the categories as Core · Gameplay · Progression · Economy · Persistence · UI · Audio · Narrative · Meta, and lists combat and AI as example systems under Gameplay. A combat system categorised exactly as the template instructs therefore matched none of the four, and Formulas was silently dropped for the system most likely to need it. coding-standards.md and rules/design-docs.md already stated the "has math" test; the skills are reconciled to them rather than the other way round.

Edge Cases is required at standard. Skipping it consistently produces "wait, what happens if X is null?" debt during implementation. These 5 required sections are the minimum that produces implementable code.

Art bible is conditional in standard. It is required only if visual asset stories exist in the project. Code-focused projects can skip it entirely at standard level.


Authoring skills

Skill full standard minimal
design-system All 8 sections required 5 required sections + conditional Formulas; Player Fantasy, Tuning Knobs skipped Not required — game brief replaces GDDs. Can still be run voluntarily.
art-bible All 9 sections required Required only if visual asset stories exist; sections 1–4 minimum when required Not required. Can still be run voluntarily.
create-architecture Full architecture — all layers, module ownership, data flow, API boundaries, full ADR audit Simplified — system layer map + critical ADR list only Not required. Can still be run voluntarily.
ux-design UX spec required per screen Core screens only (main menu, HUD, primary game loop) Not required. Can still be run voluntarily.
map-systems Required before design-system Required before design-system Not required
architecture-decision All ADRs on required ADR list must be completed Critical ADRs only — Foundation layer systems Not required

Review and validation skills

Skill full standard minimal
design-review All 8 sections validated — any missing section blocks approval 5 required sections validated; missing optional sections warned but do not block Not applicable — no GDDs to review
review-all-gdds Validates all 8 sections across all GDDs Validates 5 required sections across all GDDs; optional sections surfaced as advisory only Not applicable
architecture-review Full traceability matrix — all GDDs, all ADRs Reduced scope — architecture doc + critical ADRs only Not applicable
consistency-check Full entity registry cross-check against all GDD sections Entity registry check against required sections only Not meaningful — no GDDs to check
content-audit Full content count audit against all GDD specs Limited audit — only specs in required sections counted Cannot run — no systems index exists

Phase gate enforcement (gate-check)

gate-check is where workflow has the most visible impact — the artifact checklists differ per phase per mode.

Gate full standard minimal
Concept → Systems Design game-concept.md, pillars, Visual Identity Anchor game-concept.md only design/game-brief.md only (content check, not section check)
Systems Design → Technical Setup systems-index, all MVP GDDs reviewed (8 sections), cross-GDD review systems-index, 5-section GDDs reviewed, cross-GDD review optional Not applicable — no gates between brief and code; the gate PASSes with that note
Technical Setup → Pre-Production engine, art bible sections 1–4+, 3+ ADRs, architecture, UX specs started engine, art bible only if visual assets, critical ADRs, architecture engine configured (required floor)
Pre-Production → Production sprint plan, complete art bible, epics, UX specs, control manifest; Vertical Slice + its playtest recommended (absent → CONCERNS) epics, sprint plan; complete art bible, UX specs, control manifest recommended; Vertical Slice recommended the brief's Build order + stories under production/epics/; the Vertical Slice items drop — the core loop is fun and runs end to end, checked on the current build
Production → Polish core mechanics, tests, smoke check, QA sign-off, 3+ playtests core mechanics, smoke check, playable end to end, 1+ playtest, no open S1 bugs smoke check, playable end to end, no open S1 bugs
Polish → Release all features, content complete, localization (/localize qa per locale), QA, smoke, no open S1–S3 bugs, newest /security-audit with no open CRITICAL/HIGH all features, smoke, no open S1 bugs, the security audit smoke, no open S1 bugs

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:

workflow Panel Directors
full 4 creative-director, technical-director, producer, art-director
standard 2 technical-director, producer
minimal 1 producer

review_mode remains the axis that decides whether the panel runs at all (solo skips it entirely); workflow decides only how wide it is. Narrowing never softens a verdict — the strictest verdict from whoever ran still wins, and /gate-check names the perspectives that did not run.


Planning and implementation skills

Skill full standard minimal
create-epics Requires all GDDs approved (8 sections) Requires 5-section GDDs approved Skipped (Option A) — no separate epic doc. /create-stories reads design/game-brief.md directly and synthesizes the implicit epic container itself.
create-stories Requires all ADRs on required list present Requires critical ADRs present No ADR requirement
dev-story Requires TR registry + governing ADR — blocks without them, and on a Proposed, Deprecated or Superseded ADR; a missing control manifest warns TR registry optional; blocks only on a referenced ADR that is missing, Proposed, Deprecated or Superseded No TR registry or ADR required — implements against design/game-brief.md; a referenced ADR that is missing, Proposed, Deprecated or Superseded still blocks
story-readiness Full TR registry + ADR + control manifest validation; any referenced ADR that is missing, Proposed, Deprecated or Superseded BLOCKS TR registry optional; critical ADR check, and any referenced ADR that is missing, Proposed, Deprecated or Superseded BLOCKS Acceptance-criteria check (the brief stands in for the GDD); any referenced ADR that is missing, Proposed, Deprecated or Superseded still BLOCKS
story-done Full GDD traceability + ADR consistency check 5-section GDD traceability check Acceptance criteria check only
qa-plan Full test plan derived from all 8 GDD sections Test plan from 5 required sections Test plan from acceptance criteria only
regression-suite Critical paths mapped from all sections including Edge Cases Critical paths from required sections (including Edge Cases) Smoke test coverage only
release-checklist Open S1, S2 or S3 bug in production/qa/bugs/ fails its Quality Gates item Open S1 fails; open S2/S3 listed as risks Open S1 fails; open S2/S3 listed as risks
launch-checklist Zero open S1–S3 bugs, no exceptions Zero open S1; S2 or a documented exception Zero open S1; S2 or a documented exception
team-release qa-lead verifies no open S1–S3 bugs qa-lead verifies no open S1 bugs qa-lead verifies no open S1 bugs

Support skills

Skill full standard minimal
project-stage-detect Checks for all doc types; missing art bible or UX specs flagged as gaps Adjusts expectations — art bible only flagged if visual-asset stories exist; non-core UX specs not flagged design/game-brief.md + engine present = normal state; no gaps flagged for absent GDDs
adopt Full format compliance audit across all doc types Audit scope reduced to required docs only design/game-brief.md format check only
reverse-document Generates full 8-section GDD from code Generates 5-section GDD from code Generates design/game-brief.md from code
propagate-design-change Full cascading impact analysis across all ADRs Checks critical ADRs for references only Not applicable
help Full artifact detection — surfaces all missing docs as next steps Adjusts "what's missing" to required docs only — optional docs not surfaced as gaps design/game-brief.md + engine present = next step is code

Workflow change mid-project

When workflow changes via /settings, the skill emits an informational note:

"Workflow changed from [old] to [new]. Run /content-audit to see what's now required or extra. No automatic migration — existing files stay in place."

No documents are auto-deleted, auto-generated, or blocked. The setting only affects new enforcement going forward.


workflow_overrides

Controls: Opt-in granular requirements that override the chosen workflow level Location: top level of project.yaml — a sibling of modes:, not a child of it Values: object with sub-flags (see below) Default: all false / empty Set by: /settings Read by: /design-system, /design-review, /art-bible, /gate-check, /review-all-gdds, /qa-plan

Why the location is called out. resolve_config reads workflow_overrides.system_overrides.* from the document root (yaml-helper.sh), and all 14 consuming skill files grep the same top-level path. Nested under modes: it is still valid YAML, so nothing errors — the setting is simply never read. If you copied a workflow_overrides block from anywhere, check its indentation: it belongs at the document root, never under modes:.

Priority chain: the three workflow_overrides boolean flags (edge_cases, tuning_knobs, art_bible_strict) are additive on top of the chosen workflow level — they make things stricter, never looser. None of them has a value that opts out of a requirement the workflow level imposes.

workflow_overrides.system_overrides is not a flag and is not additive — it replaces a tier in both directions. This rule does not extend to it. On a full project, system_overrides.inventory: minimal really does drop that system's required sections to zero. Intended — see .claude/docs/workflow-modes.md § workflow_overrides. Stating the additive rule over the whole key is wrong: the guarantee never held for system_overrides, so do not rely on it as a safety net.


Fields

workflow_overrides:
  edge_cases: false          # force Edge Cases section required (no-op at standard since already required; relevant at minimal)
  tuning_knobs: false        # force Tuning Knobs section required (relevant at standard, no-op at full)
  art_bible_strict: false    # force all 9 art bible sections required regardless of asset stories
  system_overrides: {}       # per-system tier overrides — see below

Per-system overrides

workflow_overrides:
  system_overrides:
    combat: full              # combat-system GDD requires full (8 sections) regardless of project workflow
    boss-encounters: full
    inventory: minimal        # inventory needs no GDD — the game brief covers it (minimal = no required sections)

system_overrides is a map of system_name: workflow_level. The named system uses the override; all other systems use the project-level workflow.


Affected skills

Skill How workflow_overrides changes behavior
design-system Reads system_overrides[system_name] first; falls back to project workflow. Applies override-specific section requirements.
design-review Same lookup — validates against the override tier, not the project default, for the named system.
art-bible If art_bible_strict: true, requires all 9 sections regardless of workflow level.
gate-check Considers system_overrides when validating that all required GDDs are complete. A system at system_overrides.combat: full blocks the gate until all 8 sections exist for combat.
review-all-gdds Validates each GDD against its effective tier (project workflow + any system override).

modes.automation

Controls: Whether skills ask for decisions and approval before acting, or recommend and proceed — the tradeoff between user control and speed
Values: collaborative | guided | autonomous
Default: collaborative
Set by: /start, /settings
Read by: All 68 skills that use AskUserQuestion or write files

Priority chain: modes.automation in project.yaml → hardcoded default

Unlike review_mode and workflow, this setting is not a per-skill table. It defines universal interaction rules that apply across all skills. A per-skill breakdown would repeat the same answer 68 times.

Overrides COLLABORATIVE-DESIGN-PRINCIPLE.md: guided and autonomous modes intentionally relax the Q→O→D→Draft→Approval protocol defined in that document. This is opt-in. collaborative preserves the protocol exactly.

Safety net — automation_always_ask: Even in autonomous mode, certain categories of decision can be configured to always prompt. See next section.


Value intent

Value Speed Control What changes
collaborative Slowest Full — every decision is the user's Current behavior. Q→O→D→Draft→Approval strictly followed.
guided Balanced High — major decisions are the user's, minor ones proceed automatically AI states recommendation and proceeds for minor decisions. AskUserQuestion reserved for major/irreversible decisions.
autonomous Fastest Low — AI decides, logs, and proceeds No AskUserQuestion (except categories in automation_always_ask). No draft review. No write approval. All decisions logged to decision log.

Universal rules per mode

collaborative (current behavior — no change)

  • AskUserQuestion called for every multi-option decision
  • 2–4 options presented with pros/cons for every design choice
  • Full draft shown and approved before every file write
  • "May I write this to [filepath]?" asked before every write
  • "May I create [filepath] with skeleton?" asked before skeleton creation
  • Section-by-section approval in multi-section authoring skills
  • Multi-file changes require explicit approval of the full changeset

guided

  • 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
  • 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 prompt

autonomous

  • No AskUserQuestion calls except for categories listed in automation_always_ask
  • No draft review
  • No "May I write?" prompts — writes directly
  • Picks the recommended option for every decision without presenting alternatives
  • All decisions logged immediately to production/session-logs/decision-log.md with: timestamp, skill, decision point, option chosen, reasoning
  • User reviews decision log post-session to audit choices made

Major vs minor decision classification (guided mode)

Major — always use AskUserQuestion in guided mode:

Decision type Example
Choosing a system name or document path "What should we call this system?"
Mutually exclusive design directions "Real-time or turn-based?"
Any choice that gates downstream work Engine choice, architecture approach
Scope changes "Cut this feature or slip the deadline?"
Any decision that can't be changed without significant rework Core loop mechanic

Minor — AI recommends and proceeds in guided mode:

Decision type Example
Which section to work on next "Moving to Edge Cases next"
Optional section inclusion "Adding a Visual Notes section — fits the system"
Formatting and structure choices Heading levels, table vs prose
Adding detail to an already-decided direction Sub-options within an approved approach
Next-step routing after a phase completes "Running design-review now"

Affected skills by category

Authoring skills — highest impact. Each pauses 10–15 times per document in collaborative. Drops to 2–3 in guided, zero in autonomous.

brainstorm, design-system, art-bible, create-architecture, ux-design, map-systems, architecture-decision, create-epics, create-stories, sprint-plan, prototype

Review skills — medium impact. Pause after presenting findings to ask what to do next. In guided routing decisions proceed automatically. In autonomous the recommended path is taken and logged.

design-review, architecture-review, gate-check, review-all-gdds, story-readiness, story-done, milestone-review, playtest-report

Team orchestration skills — medium impact. Pause between phases for check-in. In guided the pipeline advances automatically unless BLOCKED. In autonomous the full pipeline runs end to end.

team-combat, team-ui, team-audio, team-qa, team-release, team-narrative, team-polish, team-level, team-live-ops

Implementation skills — lower impact. Pause for architectural questions before writing code. In guided only genuinely ambiguous decisions stop. In autonomous the conventional approach is picked and logged.

dev-story, code-review

Setup and utility skills — lowest impact. Pause for initial configuration or routing questions. In guided defaults are applied automatically. In autonomous recommended defaults are taken without prompting.

start, adopt, setup-engine, retrospective, localize, propagate-design-change, asset-spec, smoke-check, qa-plan, story-readiness


Exemptions — skills that ignore the automation setting

These skills always behave as collaborative regardless of the setting. The reasons are noted.

Skill Why always collaborative
hotfix Emergency decisions — user must approve scope and risk before any action
gate-check Results must be reviewed — a gate verdict without user acknowledgement defeats the purpose
day-one-patch Release-critical — every action needs explicit sign-off
setup-engine One-time irreversible choice that affects the entire project

Decision log format (autonomous mode)

Written to production/session-logs/decision-log.md — append-only.

## [timestamp] — [skill-name]

**Decision point:** [what was being decided]
**Options considered:** [list of options that would have been presented]
**Chosen:** [what was picked]
**Reason:** [one-line rationale]
**Category:** [scope_changes | file_deletions | schema_changes | etc., or "minor"]

If the file does not exist, it is created. It is never truncated — each session appends to the existing log.


modes.automation_always_ask

Controls: Decision categories that ALWAYS trigger AskUserQuestion regardless of automation mode Values: list of category names Default: [scope_changes, file_deletions, schema_changes] Set by: /settings Read by: All skills that respect modes.automation

Makes autonomous safe. Without this, autonomous is "AI does literally everything, no questions asked." With it, AI does most things but stops on destructive or irreversible decisions you specifically named.


Recognized categories

Category Examples of decisions in this category
scope_changes Cutting a feature, slipping a deadline, splitting/merging an epic, removing acceptance criteria
file_deletions Removing a story, deleting a GDD, removing a system, removing a test file
schema_changes Changes to project.yaml, story template, control manifest, ADR template, GDD template
architecture_decisions New ADR creation, ADR replacement, system boundary changes
version_bumps Engine version change, framework version bump, dependency major version change
external_calls Invoking external APIs (asset gen, AI services) when in autonomous mode

The list is a YAML list of these strings. Skills check whether the current decision falls into one of the configured categories and prompt regardless of automation value.


Affected skills

Skill Categories typically triggered
scope-check scope_changes
propagate-design-change schema_changes, architecture_decisions
architecture-decision architecture_decisions
setup-engine version_bumps, schema_changes
story-done file_deletions (when removing/replacing test files)
asset-spec external_calls (when calling external generators)

modes.story_granularity

Controls: How big each story is and how many stories per epic/sprint Values: coarse | balanced | fine Default: none — supplied by modes.rigor (minimal, the default, yields coarse; standard yields balanced; full yields fine) Set by: /start (via modes.rigor), /settings Read by: /create-epics, /create-stories, /dev-story, /sprint-plan, /story-done, /sprint-status

Priority chain: modes.story_granularity in project.yaml → modes.rigor expansion → (no hardcoded default)


Value intent

Value Story shape Stories per sprint Best for
coarse 1 story = 1 feature. 3–5 days work each. 5–10 ACs per story. The default, from rigor: minimal. 2–4 Solo devs, prototyping, "I know what I'm building"
balanced 1 story = 1 task. 1–2 days work each. 2–4 ACs per story. The rigor: standard value. 6–10 Most projects
fine 1 story = 1 AC. Hours of work each. Easy code review. Frequent /story-done. 15–25 Teams, learning, anything needing fine handoffs

Affected skills

Skill coarse balanced fine
create-epics Generates 3–5 child stories per epic Generates 5–10 child stories per epic Generates 10–20 child stories per epic
create-stories Each story carries 5–10 ACs covering an entire feature Each story carries 2–4 ACs covering one task Each story carries 1 AC; story name = AC restatement
dev-story Routing prompt expects multi-day implementation cycle. Subagent given longer working context. Standard 1–2 day expectation. Each story implementable in hours; subagent given tighter context.
sprint-plan Allocates 2–4 stories per sprint based on velocity. Allocates 6–10 stories per sprint. Allocates 15–25 stories per sprint.
story-done Fires every 3–5 days on average. Fires every 1–2 days on average. Fires multiple times per day.
sprint-status Burn-down reads in feature-sized chunks. Burn-down reads in task-sized chunks. Burn-down reads in AC-sized chunks.

docs.density

Controls: How deep each section in authored docs goes — independent of which sections are required Values: terse | balanced | thorough Default: none — supplied by modes.rigor (minimal, the default, yields terse; standard yields balanced; full yields thorough) Set by: /start (via modes.rigor), /settings Read by: /design-system, /art-bible, /create-architecture, /ux-design, /map-systems, /brainstorm

Priority chain: docs.density in project.yaml → modes.rigor expansion → (no hardcoded default)

Distinct from workflow, but no longer independent by default. workflow controls which sections exist; density controls how deep each section goes. modes.rigor now sets both together, so the diagonal (rigor: full → 8 sections and thorough prose) is what you get without asking. The off-diagonal is still reachable and is the reason rigor overrides both ways: rigor: full

  • an explicit docs.density: terse gives "all sections but each is compact" — the "comprehensive but tight" mode, which neither knob expresses alone.

Value intent

Value Per-section output style
terse Bullet points. 2–5 lines per section. Skip rationale and narrative framing. Skip preambles like "In this game..." Just facts needed to implement. The default, from rigor: minimal.
balanced Paragraphs with light rationale. Examples where helpful. The rigor: standard value.
thorough Full prose. Rationale for every decision. Examples, alternatives considered, design history.

Combination matrix with workflow

docs.density: terse balanced thorough
workflow: minimal Game brief in bullets (default) Game brief in prose Game brief + rationale
workflow: standard 5 sections, bullets 5 sections, paragraphs 5 sections + examples
workflow: full 8 sections, bullets (comprehensive but compact) 8 sections, paragraphs (current full) 8 sections + rationale + examples

Affected skills

Skill terse balanced thorough
design-system Each GDD section is 2–5 bullets. Skip Player Fantasy preambles. Paragraphs with key decisions explained. Full prose, decision history, alternatives considered.
art-bible Each art bible section is a bulleted list of constraints + references. Paragraphs explaining each visual choice. Full prose including style explorations, references, rationale per choice.
create-architecture Layer diagrams + decision bullets. No essays. Diagrams + paragraph explanations of layer choices. Full prose with rationale, trade-offs, alternatives considered per layer.
ux-design Wireframe descriptions + interaction bullets. Wireframes + paragraph descriptions of flows. Full prose including user research summaries, alternative flow considerations.
map-systems One-line system descriptions. Brief paragraph per system + dependency notes. Full system-by-system rationale + relationship analysis.
brainstorm Pillar bullets + concept bullets. Pillars + concept with brief rationale. Pillars + concept + extensive rationale + alternatives.

testing.framework

Controls: Which test framework the project uses — drives test-runner commands and per-engine assumptions in CI Values: engine-specific (see table) Default: auto-populated by /setup-engine based on engine choice Set by: /setup-engine, /settings Read by: /test-helpers — the only skill that references it. /qa-plan, /dev-story, /regression-suite, /test-setup and /smoke-check do not name the key, despite being plausible readers. (Derived by grep. A helper-based read such as session_state_enabled() would not show up, so treat this list as the verified floor, not a ceiling.)

Priority chain: testing.framework in project.yaml → engine default

Migrated from technical-preferences.md.


Engine defaults

Engine Default test framework Alternatives
Godot gdunit4 godot-test, WAT
Unity unity-test-framework nunit, custom
Unreal unreal-automation Google Test, custom

Affected skills

Skill How testing.framework is used
qa-plan Test plan tailored to framework's idioms (assertion style, fixture pattern, parameterized tests)
dev-story Test framework name passed to programmer subagent in implementation brief
regression-suite Test file naming and discovery patterns match framework conventions
test-setup Scaffolds the right test layout for the engine (gdUnit4 under addons/gdUnit4/ + tests/ for Godot; Assets/Tests/ asmdefs for Unity; Source/<Module>/Private/Tests/ for Unreal)
smoke-check Invokes framework-appropriate test runner

testing.strict

Controls: Whether failing or missing test evidence blocks a story from closing, or produces a warning and lets work continue — per test type Values: map of {logic, integration, visual, ui, config} → true | false Default: {logic: true, integration: true, visual: true, ui: true, config: false} Set by: /settings Read by: story-done, story-readiness, gate-check, smoke-check, dev-story, test-evidence-review

Per-type, not a single bool. A global testing.strict: true|false forces all-or-nothing: either all test failures block or none do. Per-type matches how most teams actually work — strict logic and visual gates, an advisory smoke check.

Composes with qa.level: qa.level controls whether evidence is REQUIRED. testing.strict controls whether failures BLOCK when evidence exists. If qa.level: minimal, the strict map is effectively ignored (no evidence required means nothing to be strict about).


Value intent per type

Type true false
logic (formulas, AI, state machines) Unit test failures BLOCK — story cannot close Failures WARN — story can close with warning
integration (multi-system) Integration test failures BLOCK Failures WARN
visual (animation, VFX, feel) Missing/failing screenshot evidence BLOCKS (default) Advisory only — story can close
ui (menus, HUD, screens) Missing screenshot of the screen BLOCKS (default) Advisory only — story can close
config (balance tuning) Failing smoke check BLOCKS Advisory only — story can close (default)

Affected skills

Skill strict.[type]: true strict.[type]: false
story-done Story of that type cannot close on test/evidence failure Story can close; warning logged in story file
story-readiness Validates test requirements exist before implementation — blocks if absent Validates but does not block — surfaces as warnings
gate-check CI failures of that type block phase transition CI failures of that type surfaced as concerns, not blockers
smoke-check Failing smoke (config strict) blocks QA handoff Failing smoke flagged but handoff proceeds
dev-story References test requirements — flags story as unverifiable if absent References test requirements — advisory only
test-evidence-review A gap in that type's evidence is a BLOCKING item (the run ends CONCERNS) The gap is ADVISORY

Unset-key resolution. Each skill reads testing.strict.<type>; if absent it reads testing.strict as a plain boolean (legacy form); if still absent it falls back to a hardcoded default. For story-done, story-readiness, gate-check, and dev-story the hardcoded default is the per-type default map above (logic/integration/visual/ui strict, config advisory). smoke-check is the exception: it is a build-health gate, so an unset testing.strict.config defaults to strict (a FAIL blocks QA hand-off) — preserving its v1.0 behavior. Only an explicit testing.strict.config: false makes a failing smoke advisory.


qa.level

Controls: What test evidence is required to mark stories Done Values: minimal | standard | full Default: none — supplied by modes.rigor (minimal, the default, yields minimal; standard yields standard; full yields full) Set by: /start (via modes.rigor), /settings Read by: /story-done, /story-readiness, /dev-story, /smoke-check, /gate-check, /qa-plan, /regression-suite, /team-qa, /test-evidence-review, /create-stories, /retrospective, /test-setup

Priority chain: qa.level in project.yaml → modes.rigor expansion → (no hardcoded default)

Different axis from testing.strict. qa.level = what evidence is required. testing.strict = do failures block. A user wanting "minimal QA" sets qa.level: minimal and the strict map becomes effectively a no-op.


Value intent

Aspect minimal standard full
Logic stories No test required, no gap flagged Unit test required (strict.logic controls block) Unit test + coverage minimum
Integration stories No test required Integration test or playtest doc required Same + regression coverage
Visual stories Screenshot + lead sign-off required — the look is never waived (strict.visual controls block) Same Same
UI stories Screenshot of each screen touched required — never waived (strict.ui controls block) Same Same
Config/Data stories No evidence required Smoke check advisory Smoke check required
/story-done test gate Acceptance criteria only, except the UI and Visual/Feel screenshot, which is never waived Enforced per story type Enforced for every story type
/gate-check phase enforcement No test gates Logic + integration must pass Full coverage + regression suite
/dev-story routing prompt No "Test required: ..." line Per-type test requirement included Per-type + coverage target included
Regression suite required by Never Polish stage Production stage
Best for Jam games, throwaway prototypes, fast iteration Most projects Commercial, console cert, learning, paranoid teams

Affected skills

Skill minimal standard full
story-done Acceptance criteria check only — no test evidence required, except the UI and Visual/Feel screenshot, which is never waived Per-type evidence required; strictness from testing.strict All types require evidence; strictness from testing.strict
story-readiness No test requirement validated, except the UI and Visual/Feel screenshot requirement Test requirement per story type validated Test requirement + coverage target validated
dev-story Routing prompt has no "Test required" line Per-type test requirement passed to programmer agent Coverage target passed to programmer agent
smoke-check Optional; with no game tests (WAIVED), commands.smoke (else commands.build) when set and the launch and critical-path checks carry the verdict; a build nobody launched is NOT ASSESSED Required before phase transition Required before every commit
gate-check No test enforcement at phase transitions Logic + integration tests must pass Full coverage check + regression suite
qa-plan Skipped entirely or minimal smoke plan Full plan per story type Full plan + coverage targets per system
regression-suite Not generated Generated at Polish stage entry Generated at Production stage entry
team-qa A Logic, Integration or Config/Data story without a test is WAIVED; its acceptance-criteria walk in manual QA is its evidence The automated test is the evidence for those types Same
test-evidence-review A story with no test evidence is WAIVED, not MISSING; gaps in existing tests are ADVISORY; screenshots never waived Per-type evidence reviewed; BLOCKING/ADVISORY from testing.strict Same

qa.coverage_minimum

Controls: Minimum code coverage percentage enforced at qa.level: full Values: integer 0–100, or null for unset Default: null Set by: /settings Read by: /gate-check only. /story-done does not reference the key, and no CI runner reads it. (Derived by grep. A helper-based read such as session_state_enabled() would not show up, so treat this list as the verified floor, not a ceiling.)

Priority chain: qa.coverage_minimum in project.yaml → no enforcement if null

Only meaningful at qa.level: full. Ignored at minimal and standard. A non-null value at standard or minimal level emits a warning at session-start: "coverage_minimum is set but qa.level is not full — value will not be enforced."

Implementation is engine-specific. Coverage measurement is different per engine:

  • Godot: gdunit4 coverage report (markdown export)
  • Unity: Unity Test Framework coverage (xml export)
  • Unreal: gcov-style coverage from clang flags CCGS does not unify these — gate-check reads the engine-appropriate report.

strict_gate_checks

RESERVED - NOT IMPLEMENTED

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.

Controls: Whether phase gate failures block stage transition or just warn Values: true | false Default: true Set by: /settings Read by: nothing yet (intended reader: /gate-check)

Priority chain: strict_gate_checks in project.yaml → hardcoded default of true

Different from review_mode: solo. review_mode: solo skips the gate entirely — directors don't even run. strict_gate_checks: false runs the gate normally but treats the verdict as advisory.


Value intent

Value Behavior
true Default. FAIL or BLOCKING-CONCERNS verdict stops the stage transition. project.stage is not advanced. User must address findings and re-run gate.
false All gate verdicts are advisory. /gate-check still runs and reports findings. project.stage advances on user confirmation regardless of verdict.

Affected skills

Skill true false
gate-check FAIL verdict stops execution before writing new stage; CONCERNS verdict prompts user but defaults to "stay at current stage." All verdicts surfaced as informational; user is asked "advance anyway?" with default Yes.

team.size

Controls: Which agents are active by default — solo devs shouldn't get studio-grade gating on every change Values: individual | small | studio Default: none — supplied by modes.rigor (minimal/standard yield individual, full yields studio) Set by: /start (via modes.rigor), /settings Read by: All team-* skills, /gate-check, all skills that spawn agents via Agent

Priority chain: team.size in project.local.yaml → project.yaml → the modes.rigor expansion (full → studio, else individual) → no terminal default. Locally overridable — it is a personal-experience knob, not an on-disk artifact.

individual at minimal/standard, studio at full. CCGS's audience is overwhelmingly solo indie developers, so the two lighter rigor tiers resolve team.size to individual — a minimal (default) or standard project gets one active agent per role, not 15 (directors and leads included). Only rigor: full opts into the full studio roster; a smaller team on a big project sets team.size: small explicitly, which wins over the rigor-derived value.

Different axis from workflow. workflow controls what docs are required. team.size controls which agents exist to make them. A solo dev on workflow: full still doesn't need all 49 agents — they need the same coverage from a smaller active set.


Active agent set per value

Value Active set Notes
individual Core 8: producer, game-designer, gameplay-programmer, engine-specialist (engine-driven), technical-artist, sound-designer, qa-tester, writer. Default. Directors and lead-* run only on explicit invocation (e.g. via /architecture-decision). Specialists outside the core 8 routed through their nearest core agent. Each team-* skill names its own set per value, which can sit outside the core 8 (team-release runs release-manager); each skill's own team.size list is authoritative, and the Affected skills table below mirrors it.
small Core 15: directors (CD, TD, PR) + leads (LP, AD, QL, ND) + game-designer + systems-designer + engine-specialist + technical-artist + sound-designer + qa-tester + ux-designer + writer team-* skills add their small set (below); most reach their full pipeline only at studio.
studio All 49 agents available. Engine sub-specialists (e.g. unity-dots-specialist separate from unity-specialist) routed when relevant. The adversarial review pass in team-combat, team-ui and team-polish. Commercial titles, learning the full org chart, large teams with parallel work.

Affected skills

Skill individual small studio
team-combat Single agent (gameplay-programmer) runs the pipeline; ai-programmer escalated only if AI work flagged Default pipeline as documented Default + the primary engine specialist may use its sub-specialists + adversarial review pass (Phase 5's qa-tester looks for how it breaks)
team-narrative writer only; narrative-director invoked only on explicit pillar conflict narrative-director + writer, + localization-lead and world-builder at review_mode: full All six narrative agents, whatever the review mode
team-ui ui-programmer + ux-designer + accessibility-specialist + art-director + engine UI specialist + adversarial review pass (Phase 4's reviewers look for where it fails its spec)
team-audio sound-designer only + audio-director + technical-artist + gameplay-programmer + accessibility-specialist + the primary engine specialist
team-level level-designer only + systems-designer + art-director + qa-tester + narrative-director + world-builder + accessibility-specialist
team-qa qa-tester only; qa-lead invoked at phase gates only qa-lead + qa-tester pipeline qa-lead + per-story qa-tester spawn + sign-off
team-release release-manager only + producer + devops-engineer + qa-lead + community-manager + security-engineer + analytics-engineer + localization-lead + performance-analyst, and network-programmer when the game is multiplayer
team-polish performance-analyst + technical-artist; no programmer is active, so Phase 2's optimisation list is handed to /dev-story + sound-designer + qa-tester + engine-programmer (implements Phase 2's optimisation list), and tools-programmer when Phase 1 traces a cause to a content authoring tool engine-programmer, as at small, + adversarial review pass (Phase 5's qa-tester looks for how it breaks)
team-live-ops live-ops-designer + economy-designer + analytics-engineer + community-manager + writer + narrative-director
gate-check Panel width is modes.workflow's axis, not this one (gates always run) — team.size affects only specialist depth within each director's review Same as individual for directors; specialists within directors' reviews use small set Same plus engine sub-specialists
architecture-decision TD-ADR (in full review mode) + the primary engine specialist Same Same — no sub-specialist or adversarial reviewer at any size

Special cases

  • team.size does not decide whether directors run: /gate-check's panel follows review_mode and modes.workflow, and no team-* pipeline spawns a director phase gate. In a team skill, a "phase gate" is one of the decision points its own pipeline lists, whatever the automation mode.
  • individual does not disable agents — it just changes which are active by default. Any agent can still be invoked by name.
  • When team.size: individual and a non-core agent is needed (e.g. network-programmer for a multiplayer story), the skill emits an informational note and routes through the nearest active core agent.

platform.multiplayer

Controls: Whether the project includes real-time online multiplayer — determines which specialists are routed and which architecture sections are required
Values: true | false
Default: none — unset is not false
Set by: /settings
Read by: security-audit, team-release (and the security-engineer agent)

Priority chain: platform.multiplayer in project.yaml → unset (platform.* is locked to project.yaml, so project.local.yaml cannot set it). Nothing writes it except /settings, so on most projects it is unset: /security-audit and /team-release ask whether the game is multiplayer rather than reading unset as false.

Distinct from platform.online. multiplayer is real-time multiplayer specifically (network specialist, netcode review, replication architecture). platform.online covers everything else online (cloud saves, leaderboards, telemetry). See next section.

This is a project attribute, not a mode. It describes what the game is, not how the pipeline operates. It lives in platform alongside targets, primary_input, and gamepad_support — not in modes.


Value intent

Value Meaning
true Game has real-time online multiplayer. /security-audit runs its netcode category and rates a HIGH finding as release-blocking; /team-release adds network-programmer's sign-off.
false No real-time multiplayer. /security-audit skips the netcode category and says so; /team-release does not spawn network-programmer.

Affected skills

Skill multiplayer: true multiplayer: false
security-audit Includes netcode review — authentication, replication, cheat vectors Netcode review skipped, and the report says so
team-release network-programmer included in release sign-off pipeline network-programmer excluded

No other skill reads this key: /dev-story, /create-architecture and /gate-check decide networking scope from the story, GDD or architecture in front of them.


platform.online

Controls: Whether the project has any online features (leaderboards, cloud saves, telemetry, IAP) Values: true | false Default: none — unset is not false Set by: /settings Read by: security-audit, team-release (and the security-engineer agent)

Priority chain: platform.online in project.yaml → unset (platform.* is locked to project.yaml, so project.local.yaml cannot set it). Nothing writes it except /settings: /security-audit and /team-release ask rather than reading unset as false.

Independent of platform.multiplayer. A single-player game with Steam Cloud and leaderboards is online: true, multiplayer: false. The two settings have different specialist routing implications.


Value intent

Value Meaning
true Project includes online services (cloud saves, leaderboards, achievements, telemetry, IAP, anything calling external APIs at runtime). /security-audit runs Category 2 (network and multiplayer — including a plaintext-token check) when this or platform.multiplayer is true or unset; /team-release adds a security-engineer sign-off.
false Project is fully offline. /security-audit skips Category 2 only when platform.multiplayer is also false.

Affected skills

Skill online: true online: false
security-audit Category 2 (network) runs — server authority, packet validation, rate limits, plaintext tokens Category 2 skipped only when platform.multiplayer is also false
team-release security-engineer sign-off when the game is online or stores player data No online-driven security sign-off

No other skill reads this key: /create-architecture, /dev-story, /team-live-ops and /gate-check decide online scope from the documents in front of them.


platform.cert_tier

WIRED — this setting is live

/launch-checklist and /release-checklist both resolve it and branch on its four values — none emits no certification section, itch and steam their storefront's requirements, console full platform certification — and ask which platforms are in scope when it is unset.

Controls: Certification target — scopes what /launch-checklist asks for Values: none | itch | steam | console Default: none — unset stays unset, so the skills ask Set by: /settings — nothing else writes it, so it stays unset (and the skills ask) until you set it Read by: /launch-checklist, /release-checklist

Priority chain: platform.cert_tier in project.yaml → unset (no default is substituted: unset is a missing decision, none is a made one, and the skills must tell them apart)


Value intent

Value Required compliance Best for
none No certification — internal release, alpha, jam game Default
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

Affected skills

Skill none itch steam console
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

accessibility.target

RESERVED - NOT IMPLEMENTED

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 accessibility-specialist routing and the Polish-stage audit described below do not happen at any level — /team-ui, /team-level, /team-polish and /gate-check do not read this setting, and /start does not ask for it.

Controls: Accessibility commitment level — routes accessibility specialist and gates audit requirements Values: none | standard | aaa Default: none Set by: /settings Read by: nothing yet (intended readers: /team-ui, /team-level, /team-polish, /gate-check)

Priority chain: accessibility.target in project.yaml → hardcoded default of none

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.


Value intent

Value Required features Specialist routing
none None enforced accessibility-specialist not spawned
standard Colorblind-safe palette, subtitles for any voice content, key remapping accessibility-specialist runs in team-ui, team-level
aaa Full Game Accessibility Guidelines: motor, vision, hearing, cognitive categories accessibility-specialist runs in all team-* skills; mandatory audit at Polish stage

Affected skills

Skill none standard aaa
team-ui accessibility-specialist not spawned accessibility-specialist included for HUD/menu reviews accessibility-specialist included for every screen + accessibility audit pass
team-level accessibility-specialist not spawned accessibility-specialist reviews level for colorblind safety and signposting accessibility-specialist reviews for full mobility/audio/cognitive considerations
team-polish No accessibility pass Final accessibility pass added Full accessibility audit required before completion
gate-check No accessibility check at any stage Polish gate checks for the standard required features Polish gate requires full Game Accessibility Guidelines compliance audit

cadence.sprint_length and cadence.milestone_length

RESERVED - NOT IMPLEMENTED

No skill or hook reads this setting. Setting it has no effect. Everything below describes the intended design, not current behaviour.

No reference anywhere outside this file.

Controls: Default sprint and milestone durations for planning Values:

  • sprint_length: 1w | 2w | 3w | 4w | none
  • milestone_length: 4w | 6w | 8w | 12w Defaults: sprint_length: 2w, milestone_length: 8w Set by: /settings Read by: nothing yet (intended readers: /sprint-plan, /milestone-review, /sprint-status, future velocity tracking)

Priority chain: cadence.* in project.yaml → hardcoded defaults

none for sprint_length means continuous-flow / kanban-style — no sprint boundaries. /sprint-plan is then invoked manually as needed. Velocity tracking is per-week rather than per-sprint.


Affected skills

Skill What changes
sprint-plan Capacity calculated as sprint_length × team.size velocity baseline. none makes the skill emit a continuous-flow plan instead.
milestone-review Milestone window for retrospective scope = milestone_length.
sprint-status Burn-down chart x-axis spans sprint_length.
retrospective Sprint retro fires at sprint_length cadence (or weekly when sprint_length is none).

performance.target_framerate and performance.frame_budget_ms

Controls: The frame-rate target and its per-frame millisecond budget Values: integers (e.g. 60, 16.67) Default: none — unset means no budget was ever committed to Set by: the user, by hand or via /settings Read by: /perf-profile, /gate-check, /team-polish

performance.draw_call_limit and performance.memory_ceiling_mb

Controls: Per-frame draw-call ceiling and total memory ceiling Values: integers Default: none — unset means no budget was ever committed to Set by: the user, by hand or via /settings Read by: /perf-profile, /gate-check, /team-polish

Every setting needs its own ## heading in this file, not just a table row. The dead-settings audit derives what it checks from those headings, so a setting mentioned only inside a table is invisible to it — it can neither be reported DEAD if it loses its reader, nor caught if it gains one. A setting outside the audit's field of view is exactly how a documented-but-dead entry, or a working-but-listed-as-dead one, survives unnoticed.

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.

performance.enforce

Controls: Whether performance budget violations warn or block Values: warn | block | off Default: warn Set by: /settings Read by: /perf-profile, /gate-check, CI runner

Priority chain: performance.enforce in project.local.yaml → project.yaml → hardcoded default of warn, resolved by resolve_config --keys performance.enforce

Read it from the resolved block, never from project.yaml directly. The key is on the /settings --local whitelist. /perf-profile Phase 0 and /gate-check Section 3 are the two readers the table above promises — a key that is enum-validated, accepted and displayed while nothing reads it is exactly the failure this warning guards against.

Mirrors the testing.strict pattern. Defines what happens when a budget defined in performance.target_framerate, frame_budget_ms, draw_call_limit, or memory_ceiling_mb is exceeded.


Value intent

Value Behavior
warn Default. Profile runs flag violations as findings. CI logs them but doesn't fail. /gate-check surfaces them as concerns, not blockers.
block Profile failures block CI. /gate-check treats violations as FAIL verdict (Polish stage onward).
off Performance budgets are informational only — no profile runs gated, no findings surfaced.

project.stage

Controls: The current development phase — determines which gate-check validates and what artifacts are expected to exist
Values: Concept | Systems Design | Technical Setup | Pre-Production | Production | Polish | Release
Default: Concept
Set by: /gate-check on a PASS, or on a CONCERNS the user explicitly accepts (the accepted risks are recorded); a FAIL never advances it — never set manually
Read by: gate-check, project-stage-detect, help, day-one-patch, team-release, launch-checklist, release-checklist, map-systems, team-qa, adopt

Stage count: This document uses the 7-stage reality implemented by gate-check: Concept | Systems Design | Technical Setup | Pre-Production | Production | Polish | Release

This is a project attribute, not a mode. It records where the project is in its lifecycle. Only /start (at onboarding) and /gate-check write it — /gate-check on a PASS verdict with user confirmation, or on a CONCERNS verdict whose risks the user explicitly accepts (they are recorded); a FAIL never advances it. Never write it manually mid-session except to correct an incorrect auto-detect.

Legacy fallback + dual-write. Stage is read from project.stage in project.yaml first, then legacy production/stage.txt, then artifact auto-detection. When /gate-check advances the stage it dual-writes BOTH project.yaml and production/stage.txt, so hooks that have not migrated still resolve correctly. /start also dual-writes the initial stage. The legacy .txt file is retired at .claude/scripts/migrate-v1-config.sh --finalize.


Stage progression and gate requirements

Each row is the gate that must be passed to advance FROM that stage.

From stage Key artifacts required to pass gate-check writes
Concept game-concept.md, design pillars, Visual Identity Anchor Systems Design
Systems Design systems-index.md, all MVP GDDs reviewed, cross-GDD consistency check Technical Setup
Technical Setup Engine configured, art bible sections 1–4 (at standard, only if visual stories exist), 3+ ADRs, architecture doc, traceability index, test framework, accessibility and interaction-pattern docs Pre-Production
Pre-Production Epics defined, first sprint plan, UX specs, control manifest (a Vertical Slice is recommended, not required) Production
Production Core mechanics implemented, main path playable, smoke check passes, QA sign-off Polish
Polish All features complete, content complete, localization, security audit, no open S1–S3 bugs Release

Gates adjust per modes.workflow — see modes.workflow section for what is required at standard and minimal levels.


Affected skills

Skill How it uses stage
gate-check Reads current stage to determine which gate to validate. Writes next stage on PASS, or on a CONCERNS the user explicitly accepts.
project-stage-detect Reads project.stage first — if set, uses it as authoritative. Falls back to heuristic detection only if absent.
help Uses stage to determine "where are you in the pipeline" and surfaces the correct next steps.
sprint-status Displays current stage in status summary.
day-one-patch Proceeds only when the stage is Release or Polish; otherwise says it is not appropriate yet.
team-release Stops before Phase 1 unless the stage is Release ("run /gate-check release first"); proceeding takes an explicit override, recorded in the go/no-go record and the report. Never writes the stage.

project.kind

RESERVED - NOT IMPLEMENTED

No skill or hook reads this setting. Setting it has no effect. Everything below describes the intended design, not current behaviour.

No reference anywhere outside this file.

Controls: What type of project this is — routes skill subsets Values: game | tool | engine | mod | library Default: game Set by: /start, /setup-engine Read by: Many skills (advisory routing — see below)

Priority chain: project.kind in project.yaml → hardcoded default of game


Value intent

Value Meaning What's deactivated
game Default. Full CCGS framework applies. Nothing
tool Developer tool, not a game Skip art bible, narrative, level design, playtesting
engine Custom engine or library underneath games Skip game-specific concerns entirely (narrative, art, playtest)
mod Mod for an existing game Skip engine setup; assume parent engine; reduce architecture scope
library Reusable library Emphasize tests + API design; design docs lighter; no asset pipeline

Affected skills

Skill game tool engine mod library
brainstorm Full game-concept output Tool concept output (user, problem, solution) Engine concept (target use cases, scope) Mod concept (what changes) Library concept (API surface, target consumers)
art-bible Required at appropriate workflow level Skipped Skipped Optional (depends on visual scope) Skipped
map-systems Full game systems decomposition Tool subsystems Engine subsystems Modified-system map Library module map
playtest-report Required at appropriate stages Skipped or replaced with user testing Skipped Required (compatibility testing) Skipped or replaced with API usage testing
setup-engine Game engine setup Skipped or replaced with build tool setup Self-referential — engine IS the project Parent engine assumed Skipped or replaced with library scaffolding

engine.name and specialists

Controls: Which engine-specific specialist agents are routed to for code implementation, review, and architecture validation
Values: Godot | Unity | Unreal
Default: [UNSET] — must be configured via /setup-engine
Set by: /setup-engine
Read by: dev-story, code-review, architecture-decision, create-architecture, team-combat, team-ui, team-audio

Currently stored in technical-preferences.md, not project.yaml. After YAML expansion, engine.name and the specialist routing table move to project.yaml specialists block. Skill behavior is unchanged — only the source file changes.

This is a project attribute, not a mode. Engine choice drives specialist routing the same way platform.multiplayer drives network routing — skills respond to a fact about the project, not a process preference.


Specialist routing by engine

Engine Language/code specialist Shader specialist UI specialist Additional specialists
Godot godot-gdscript-specialist (GDScript) or godot-csharp-specialist (C#) — driven by engine.language godot-shader-specialist godot-specialist godot-gdextension-specialist
Unity unity-specialist unity-shader-specialist unity-ui-specialist unity-addressables-specialist, unity-dots-specialist
Unreal unreal-specialist unreal-specialist ue-umg-specialist ue-gas-specialist, ue-blueprint-specialist, ue-replication-specialist
[UNSET] No specialist spawned — warning emitted No specialist spawned No specialist spawned None

Affected skills

Skill How engine.name is used
dev-story Routes code stories to language specialist. Spawns engine specialist alongside for HIGH engine-risk stories or engine-specific API usage.
code-review Routes review to language, shader, or UI specialist based on file type being reviewed.
architecture-decision Loads docs/engine-reference/[engine]/VERSION.md before authoring. Spawns engine specialist to validate ADR for API correctness and post-cutoff compatibility.
create-architecture Includes engine-specific constraints and patterns in architecture doc based on engine choice.
team-combat / team-ui / team-audio Spawn the engine specialist their pipeline names: team-combat the primary engine specialist (from team.size: small), team-ui the engine UI specialist (specialists.ui, at studio), team-audio the primary engine specialist (at studio). The other six team-* skills spawn none.

commands

Live since the run-and-observe step. This block was RESERVED — written by /setup-engine, read by nothing — through most of v1.1. test, smoke and build gained readers as the parse-check and smoke gates landed; run gained its reader last, when /dev-story Phase 6 step 4 started launching the game to look at it. The per-skill table at the bottom is now current behaviour, not intent. validate-push.sh was once named as a reader and never was.

Controls: Explicit shell commands to build, test, run, and smoke-test the project Values: strings — shell-executable commands Default: [UNSET] — populated by /setup-engine with engine-typical defaults Set by: /setup-engine, /settings Written by: /setup-engine, /settings. Read by: test — /smoke-check, /hotfix (narrowed to the affected suite), /bug-report (verify mode, narrowed to the affected suite), /day-one-patch (targeted fix and, when set, the broader regression — NOT ASSESSED if unset), /dev-story (Godot parse-check executable resolution), /test-setup (the <Project>. filter root on Unreal), project-coherence.sh; smoke — /dev-story (Unity parse check), /smoke-check (build check when tests are WAIVED); build — /smoke-check (build check when tests are WAIVED and smoke is unset), project-coherence.sh; run — /dev-story (Phase 6 step 4, the run-and-observe step). /launch-checklist and /regression-suite name these commands but do not run them. (Derived by grep. A helper-based read would not show up, so treat this list as the verified floor, not a ceiling.)

Priority chain: commands.* in project.yaml → engine-typical default → no command available

Why explicit: Without this block, CCGS has to guess engine-typical conventions for invoking the project. Better to be explicit per-project — covers cases where projects customize their build (e.g., a Godot project using gdunit4 for tests but a custom export script for builds).


Fields

Each command can be a simple string (used on all OSes) or an OS-aware map:

Simple form (one command, used on every OS):

commands:
  build: "godot --headless --export-debug '<PRESET>'"   # ask; see the note below
  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"

Note that build is the one row the simple form suits least: an export preset names a platform, so a single build string is portable only for a project that builds one platform. The other three rows are genuinely OS-independent.

OS-aware form (different commands per OS):

commands:
  build:
    default: "godot --headless --export-debug 'Linux/X11'"
    windows: "godot.exe --headless --export-debug 'Windows Desktop'"
    macos:   "godot --headless --export-debug 'macOS'"
  test:
    default: "godot --headless -s -d --remote-debug tcp://127.0.0.1:0 res://addons/gdUnit4/bin/GdUnitCmdTool.gd -a res://tests --ignoreHeadlessMode"
  run:
    default: "godot --path . --windowed --resolution 1280x720"
  smoke:
    default: "godot --headless --quit-after 5"

Resolution rule: if the value is a string, use it as-is on any OS. If the value is a map, skills/hooks read the current OS and pick the matching key (linux, windows, macos). Fall back to default if no OS-specific key matches.

This solves the Windows/Linux/macOS path-and-binary-name differences without breaking the whitelist (commands stays locked to project.yaml — the OS-specific keys are inside the locked file, not a local override).

Field Purpose
build Full project build for CI or release. /smoke-check runs it only as the WAIVED-path build check when commands.smoke is unset; project-coherence.sh (which /smoke-check runs first) checks the export preset it names, and /launch-checklist only asks whether the build produces a valid artifact.
test Run the full test suite. Run by /smoke-check and, narrowed to the affected suite, by /hotfix, /bug-report (verify mode) and /day-one-patch; project-coherence.sh checks the runner it names. /regression-suite does not run it.
run Launch the game windowed at a fixed resolution — not the editor. Used by /dev-story Phase 6 step 4 to observe the feature and retain a screenshot; see .claude/docs/run-and-observe.md for the per-engine capture flags that are appended to it.
smoke Minimal "does it boot?" check. Run by /dev-story as the Unity parse check (Phase 6 step 2), and by /smoke-check as the build check when qa.level: minimal waives tests.

Engine defaults

When /setup-engine runs, it populates commands based on engine choice — except the build row, which it must ask for. The build artifact is named by a project-defined string (a Godot export preset, a Unity build target), and no engine reference in this repo can source it. See /setup-engine §"The Godot build row must not hardcode 'Linux/X11'".

Engine build test run smoke
Godot godot --headless --export-debug '<PRESET>' 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 "<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 -
Unreal `"/Engine/Binaries/DotNET/AutomationTool/AutomationTool.exe" BuildCookRun -project="$(pwd -W 2>/dev/null pwd)/.uproject" -platform=Win64 -build -cook` (confirm per project) `"/Engine/Binaries/Win64/UnrealEditor-Cmd.exe" "$(pwd -W 2>/dev/null

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".

<PRESET> and <TARGET> are placeholders, not values to copy. A Godot export preset is whatever string the operator typed into export_presets.cfg; the shipped defaults are per-platform (Windows Desktop, macOS, Web, Linux/X11). Copying a preset name you do not have gives you a build command that fails with Unknown export preset; copying one you do have, but did not mean, gives you a command that succeeds and builds the wrong platform. The second is the dangerous one. If no presets exist yet — common, since /setup-engine usually runs before the project has any — write [TO BE CONFIGURED] rather than guessing a name.

Users override per-project as needed via /settings commands.<field>=<value> or by editing project.yaml directly.


Affected skills

Skill How commands is used
smoke-check Runs commands.test, or the engine's default when it is unset; on Unreal it builds the editor target first. Critical path for QA hand-off.
launch-checklist Emits a checklist item asking whether the build produces a valid artifact. It does not run commands.build; the verification is a human step.
validate-push.sh Does not read commands.*. It warns on pushes to protected branches (main/master/release/*) and runs no build or smoke command — the block path in it is commented out, so it never fails a push.
dev-story Phase 6 step 2 is the parse check: .claude/scripts/godot-parse-check.gd on Godot, commands.smoke on Unity, the editor-target build on Unreal. Phase 6 step 4 runs commands.run — the windowed game launch — to observe the feature and retain a screenshot (.claude/docs/run-and-observe.md).
regression-suite Maps coverage by globbing test filenames. It does not invoke commands.test, so coverage here means "a test file exists", never "a test passed".

naming

Controls: Code naming conventions for the project Values: see field list below Default: engine-specific (auto-populated by /setup-engine) Set by: /setup-engine, /settings Read by: /adopt, /architecture-review, /asset-spec, /create-architecture, /create-control-manifest, /dev-story, /vertical-slice — each reads naming.* from project.yaml and feeds the conventions into a brief, manifest or spec. NOT by /code-review and NOT by validate-commit.sh. (Reader list derived by grep, so treat it as the verified floor rather than a ceiling — a skill reading the value through a helper would not show up.)

These conventions are guidance, not a gate. They reach your project by being passed into briefs, manifests and specs for whoever writes the code. Nothing checks the result: /code-review does not validate files against them 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.

Moved from technical-preferences.md, which is being deleted. Naming conventions are project-level facts shared by everyone on the project, so they belong in project.yaml alongside the rest of your structured config.


Fields

Field Values Godot default Unity default Unreal default
classes PascalCase | snake_case | camelCase PascalCase PascalCase PascalCase
variables snake_case | camelCase snake_case camelCase camelCase
constants SCREAMING_SNAKE | PascalCase SCREAMING_SNAKE SCREAMING_SNAKE SCREAMING_SNAKE
signals (Godot) / events (Unity, Unreal) past_tense | on_event_name past_tense on_event_name OnEventName
files snake_case | PascalCase | kebab-case snake_case PascalCase PascalCase
scenes / prefabs snake_case | PascalCase snake_case PascalCase PascalCase

signals vs events: Godot uses signals natively; Unity uses C# events or UnityEvents; Unreal uses delegates and dynamic multicast. The field stays named signals in project.yaml for consistency across engines — interpret as "event-like callbacks" regardless of engine.


Affected skills

Skill How naming is used
dev-story Passes the naming conventions to the programmer subagent as part of the implementation context
create-control-manifest Emits the conventions as manifest rows (classes, variables, signals/events, files, constants)
asset-spec Specifies asset naming per the configured convention
create-architecture / architecture-review Read as project config alongside performance.*
vertical-slice / adopt Read as project config; /adopt audits conformance at MEDIUM severity

No skill or hook validates code against these conventions — see the note above.


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 skeleton-first output files for recovery
Values: off | on
Default: on
Set by: /settings
Read by: Six hooks — session-start.sh (its recovery preview only), pre-compact.sh, post-compact.sh, session-stop.sh, log-agent.sh and log-agent-stop.sh. No skill reads it, and neither does statusline.sh.

on is the recommended setting. Long-form skills write self-describing skeleton files upfront, which covers much of mid-task recovery on its own; the session pipeline adds the checkpoint preview at session start, the session archive and the subagent tally. Turn it off only to save that preview's tokens.

Priority chain: features.session_state in project.local.yaml → project.yaml → hardcoded default of on. Hooks read it via session_state_enabled() in yaml-helper.sh and exit early when off. Skills do not read it: /dev-story and /story-done update the checkpoint in active.md whatever its value.

The default is on, deliberately. .claude/docs/context-management.md tells you to rely on production/session-state/active.md as your crash-recovery checkpoint, so defaulting this off would quietly take away recovery, the session archive and the subagent tally. What off saves — the checkpoint preview, at most ~750 tokens per session start — is an explicit opt-out (/settings features.session_state=off), never a silent default.

session-start.sh is gated per-block, not at the top. Its sprint, milestone and git context is not part of the session-state pipeline; only the active.md recovery preview is gated. Its check also fails OPEN — that hook sources yaml-helper.sh conditionally, and an undefined function is falsey, which would suppress the recovery checkpoint invisibly.


Value intent

Value Intent
off Recovery via skeleton-first output files. Long-form skills write a complete skeleton (all section headers, empty bodies) before starting. If context clears or compacts, the agent reads the skeleton + relevant docs and resumes. The six session-state hooks do nothing, so no logs; skills still update the checkpoint in active.md, but session start does not show it. Saves at most ~750 tokens per session start.
on Full session tracking. Session-stop archival, compaction log and agent audit log all active. Adds the checkpoint preview to each session start, capped at 25 lines or 3,000 characters (at most ~750 tokens). Compaction hooks log to disk and add nothing to Claude's context.

Hook behavior

Implementation note: The feature flag check lives inside each hook script, not at the harness level. Every session-state-aware hook calls session_state_enabled() from yaml-helper.sh at its top (an awk read of project.local.yaml, then project.yaml) and exits silently with no output if the value is off — except session-start.sh, which skips only its recovery preview. This ensures the harness always fires the hook — the hook decides whether to act.

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
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
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

File existence by mode

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/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

Skeleton-first pattern (session_state: off recovery mechanism)

Long-form skills must write a skeleton file as their first action — before any section discussion begins. The skeleton contains all section headers with empty bodies and a <!-- STATUS: incomplete --> marker per section.

# Combat System — GDD

## Overview
<!-- STATUS: incomplete -->

## Player Fantasy
<!-- STATUS: incomplete -->

## Detailed Rules
<!-- STATUS: incomplete -->
...

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.

Skills required to implement skeleton-first:

Skill Output file Skeleton written when
design-system design/gdd/[system].md Before Phase 1 (section discussion)
art-bible design/art/art-bible.md From .claude/docs/templates/art-bible.md, after asking, when section 1 is approved
create-architecture docs/architecture/architecture.md Not skeleton-first: written once at Phase 7 after its ask (an existing document is updated in place)
ux-design design/ux/[screen].md Before screen discussion
create-stories production/epics/[epic-slug]/story-NNN-[slug].md Not skeleton-first: written in Step 6, after the ask names every file
create-epics production/epics/[epic-slug]/EPIC.md Not skeleton-first: written after its per-epic "May I write production/epics/[epic-slug]/EPIC.md and add its row to production/epics/index.md" ask
map-systems design/gdd/systems-index.md Before system enumeration
brainstorm design/gdd/game-concept.md (standard/full) · design/game-brief.md (minimal) Before concept discussion

Note on agents: world-builder and narrative-director are agents, not invocable skills — they do not have SKILL.md files. Long-form output from these agents is produced via the skills above (design-system, art-bible, etc.) which are responsible for skeleton-first enforcement.


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 session_state. (At workflow: minimal the status line shows the story count instead of the stage.)

Feature session_state: off session_state: on
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

Affected skills

Skills interact with session state in two ways: inference (reading active.yaml 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

When active.yaml 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
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
team-release Target version (when no arg given) Prompt user for version
team-qa Active sprint (when no arg given) Prompt user for sprint file
help Current task and STATUS block for context-aware suggestions Responds without session context — surfaces next steps from sprint/epics only

Extraction — skills that write session state to active.md

These skills write a structured block after completing work, whatever session_state is. /dev-story and /story-done overwrite the <!-- CHECKPOINT --> block; the others append a SESSION EXTRACT.

Skill What it writes to active.md
dev-story Checkpoint: story path, next step, blockers, files changed, run result
story-done Checkpoint: verdict, story path, next story, tech debt count
architecture-review Verdict, TR coverage counts, new TR-IDs, GDD flags, ADR gaps, report path
prototype Prototype scope, current phase, key decisions
vertical-slice Slice concept, current phase, blocked items
team-qa QA phase comment, blocking issues
map-systems Task record: systems enumerated, current phase

Token cost summary

Scenario session_state: off session_state: on
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)

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 whether recovery is needed or not.


features.token_budget_warn_at

RESERVED - NOT IMPLEMENTED

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. Nothing warns at any threshold.

Controls: Context usage threshold at which session warnings fire Values: float between 0.0 and 1.0 Default: 0.7 (warn at 70%) Set by: /settings Read by: nothing yet (intended readers: pre-compact.sh, session-start.sh, statusline.sh)

Priority chain: features.token_budget_warn_at in project.yaml → hardcoded default of 0.7

Surfaces a warning when session context usage exceeds the threshold. Helps cost-conscious users hit /clear before runaway sessions. Set to 1.0 to disable.


Behavior

Threshold What fires
Below warn_at No warning
At or above warn_at statusline.sh shows context usage in yellow; next session-start hook emits a one-line note: "Last session reached [X]% context — consider /clear if continuing work."
At 90%+ Yellow becomes red regardless of warn_at value

schema_version

Controls: Which version of the project.yaml schema this file conforms to Values: integer Default: 1 (for v1.1 of CCGS) Set by: /start, /adopt Read by: All skills and hooks that parse project.yaml (for migration safety)

Lets future CCGS versions detect and migrate old project.yaml files. The migration logic compares schema_version in the file against the current CCGS's expected version. If newer, warn. If older, run migrations.


Migration behavior

project.yaml schema_version Current CCGS expects Behavior
Matches expected — Normal operation
Lower than expected — /adopt warns and offers migration; skills run with deprecation warnings
Higher than expected — All skills warn: "This project.yaml was created by a newer CCGS version. Some settings may be ignored."
Missing — Treated as legacy (pre-v1.1); migration prompted on next /start or /adopt

framework

Controls: Tracks which CCGS version created or last touched this project Values: framework.version (semver string) + framework.last_upgraded (ISO date) Default: stamped in the template's project.yaml at each release Set by: the template; /start (Phase 3c), /setup-engine and /gate-check write the block into a project.yaml they create, and migrate-v1-config.sh (which /adopt runs) writes framework.version into the one it builds Read by: no skill branches on it — it is file metadata, not a behavioural setting. It appears in /start, /gate-check, /settings and /setup-engine as part of the project.yaml block they write or display, and in yaml-helper.sh. (The four skills above were verified to name it; whether each reads it or merely emits it was NOT separated, so this says 'appears in', not 'read by'.)


Fields

framework:
  version: "1.1.0"
  last_upgraded: "2026-05-14"
Field Purpose
version The CCGS version that created the project (or was last updated to — see UPGRADING.md).
last_upgraded ISO date of the most recent template update.

Affected skills

None. No skill or hook reads framework.version or last_upgraded — /adopt does not consult them and no hook checks their age. They record which template version the project came from; UPGRADING.md is the upgrade path.


Migration from v1.0 → v1.1

When a v1.0 CCGS project upgrades to v1.1, migration tooling (run via /adopt) converts legacy files to project.yaml. This section specifies the intended behavior.

Detection

A project is detected as needing migration when:

  • project.yaml does NOT exist at the repo root, AND
  • One or more legacy files exists:
    • production/stage.txt
    • production/review-mode.txt
    • .claude/docs/technical-preferences.md

Preservation

Legacy source Migrates to
production/stage.txt (single line) project.stage
production/review-mode.txt (single line) modes.review_mode
.claude/docs/technical-preferences.md → "Engine & Language" section engine.name, engine.version, engine.language, engine.rendering, engine.physics
technical-preferences.md → "Input & Platform" section platform.targets, platform.primary_input, platform.gamepad_support, platform.touch_support
technical-preferences.md → "Naming Conventions" section naming.classes, naming.variables, naming.constants, naming.signals, naming.files, naming.scenes
technical-preferences.md → "Performance Budgets" section performance.target_framerate, performance.frame_budget_ms, performance.draw_call_limit, performance.memory_ceiling_mb
technical-preferences.md → "Testing" section testing.framework, qa.coverage_minimum (bare number only — prose is reported for manual entry)
technical-preferences.md → "Engine Specialists" section specialists.code, specialists.shader, specialists.ui, specialists.additional

Value rename — review_mode: none → solo. v1.0 used none for the "no director reviews" tier; v1.1 renamed that tier to solo (the enum is full | lean | solo). Migration coerces a legacy none to solo and reports the rename in the migration report's Warnings. This is the one documented value rename, so it is mapped-and-flagged rather than preserved raw: writing none verbatim would produce an enum-invalid project.yaml that resolve_config rejects and falls back to the modes.rigor value — at standard that is lean, reviews on — inverting the user's intent. The --finalize preservation check applies the same mapping so it does not falsely refuse. Every other non-v1.1 stage/review value is a fork, not a rename: 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)

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 and skills read project.yaml first; they fall back to the legacy file if a specific key is missing.

Legacy files are deleted only when the user runs .claude/scripts/migrate-v1-config.sh --finalize (driven by /adopt, which detects a v1.0 project automatically at Phase 2g). The cleanup step verifies that every legacy file's content has been preserved in project.yaml before deleting.

Failure modes

Problem Behavior
Legacy file is malformed (can't parse) Migration emits warning per file, leaves it untouched, continues with the others. project.yaml gets the parseable values + defaults for the rest.
Parsed value doesn't match v1.1 enum (e.g. stage: Alpha from a fork) Migration writes the raw value with a _migration_warning comment in project.yaml. User resolves manually.
Both project.yaml AND a legacy file exist (split-brain) Migration tooling refuses to run. Error: "Both project.yaml and legacy files exist — resolve which is authoritative before migrating."
Custom sections in forked technical-preferences.md Custom content logged to production/migration-report.md as "not migrated — please integrate manually."

Migration report

Every migration run writes production/migration-report.md:

  • Source files detected
  • Values preserved (per file → per setting)
  • Defaults applied (for v1.1-new settings)
  • Warnings encountered (malformed, mismatched enums, etc.)
  • Manual review items

User reads the report before running --finalize.


Complete example project.yaml

A full project.yaml with every setting, showing sensible defaults for a solo Godot project. Use this as the reference shape when authoring or migrating.

schema_version: 1

framework:
  version: "1.1.0"
  last_upgraded: "2026-05-15"

project:
  name: "Forge Knights"
  genre: "ARPG"
  version: "0.1.0"
  stage: Concept             # Concept | Systems Design | Technical Setup | Pre-Production | Production | Polish | Release
  kind: game                 # game | tool | engine | mod | library

modes:
  review_mode: lean          # full | lean | solo
  workflow: standard         # minimal | standard | full
  automation: collaborative  # collaborative | guided | autonomous
  automation_always_ask:     # decision categories that always prompt regardless of mode
    - scope_changes
    - file_deletions
    - schema_changes
  story_granularity: balanced  # coarse | balanced | fine

# TOP-LEVEL, not nested under `modes:` — resolve_config reads
# `workflow_overrides.system_overrides.*` from the document root
# (yaml-helper.sh), and every skill greps the same top-level path.
# Nesting it under `modes:` parses as valid YAML and is silently never read.
workflow_overrides:
  edge_cases: false          # force GDD Edge Cases section required
  tuning_knobs: false        # force GDD Tuning Knobs section required
  art_bible_strict: false    # force all 9 art bible sections regardless of asset stories
  system_overrides: {}       # { combat: full, inventory: minimal }

docs:
  density: balanced          # terse | balanced | thorough

testing:
  framework: gdunit4         # engine-specific — auto-populated by /setup-engine
  strict:
    logic: true              # unit test failures BLOCK story closure
    integration: true        # integration test failures BLOCK
    visual: true             # missing screenshot BLOCKS
    ui: true                 # missing screenshot BLOCKS
    config: false            # advisory only

qa:
  level: standard            # minimal | standard | full
  coverage_minimum: null     # integer 0-100; only enforced at level: full

strict_gate_checks: true     # phase gate failures block stage transition

team:
  size: individual           # individual | small | studio

platform:
  multiplayer: false         # real-time multiplayer
  online: false              # any online features (leaderboards, cloud, telemetry)
  targets: [PC]              # [PC, Mobile, Web, Console]
  primary_input: "Keyboard/Mouse"
  gamepad_support: "Full"    # Full | Partial | None
  touch_support: "None"      # Full | Partial | None
  cert_tier: none            # none | itch | steam | console

engine:
  name: "Godot"              # Godot | Unity | Unreal — set by /setup-engine
  version: "4.6"
  language: "GDScript"       # GDScript | C# | C++ | Blueprint
  rendering: "Forward+"
  physics: "Jolt"

specialists:                 # auto-populated by /setup-engine
  code: "godot-gdscript-specialist"
  shader: "godot-shader-specialist"
  ui: "godot-specialist"
  additional: ["godot-gdextension-specialist"]

naming:
  classes: PascalCase        # PascalCase | snake_case | camelCase
  variables: snake_case
  constants: SCREAMING_SNAKE
  signals: past_tense        # past_tense | on_event_name (engine-interpreted)
  files: snake_case
  scenes: snake_case

accessibility:
  target: none               # none | standard | aaa

cadence:
  sprint_length: "2w"        # 1w | 2w | 3w | 4w | none
  milestone_length: "8w"     # 4w | 6w | 8w | 12w

performance:
  target_framerate: 60
  frame_budget_ms: 16.67
  draw_call_limit: null
  memory_ceiling_mb: null
  enforce: warn              # warn | block | off

commands:                    # simple string OR OS-aware map per command
  build: "godot --headless --export-debug '<PRESET>'"   # your export_presets.cfg name
  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"

features:
  session_state: on          # off | on
  token_budget_warn_at: 0.7  # 0.0-1.0; warn at this context % usage

And a minimal sparse project.local.yaml example — a single developer who wants autonomous mode locally:

modes:
  automation: autonomous
features:
  session_state: on

Only the overridden keys are present; everything else cascades from project.yaml. See "Local Override Pattern" section for full whitelist of what can/cannot be overridden locally.