--- name: create-control-manifest description: "Builds a short list of must-do and never-do coding rules per system from accepted ADRs. Use when the user wants programmer rules or a cheat sheet from the ADRs, or needs it regenerated after ADR changes." argument-hint: "[update — regenerate from current ADRs] [--review full|lean|solo]" user-invocable: true allowed-tools: Read, Glob, Grep, Write, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/create-control-manifest/../../hooks/yaml-helper.sh" resolve_config *), Bash(bash .claude/scripts/adr-status.sh*), Bash(bash .claude/scripts/md-section.sh *) model: sonnet --- !`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,review_gate,automation` Resolved above — use as-is; `--review` overrides `review_mode` for this run. No block → defaults in `.claude/docs/config-resolution.md`. Ask with the question tool. Without one, list the options numbered and end your turn to wait. A skipped or dismissed question is not an answer: ask again in plain text. # Create Control Manifest The control manifest is a flat rules sheet for programmers: what to do and what never to do, by architectural layer, taken from the Accepted ADRs, the project's technical preferences and the engine reference docs. The ADRs say *why*; the manifest says *what*. **Writes:** `docs/architecture/control-manifest.md`, after the user's yes. **When:** after `/architecture-review` passes and the ADRs are Accepted. Run it again whenever an ADR is accepted or revised. Asks follow `.claude/docs/automation-modes.md` (collaborative always asks, guided asks on major choices, autonomous logs and goes on; `automation_always_ask` categories always ask). ## Phase 1: Load the inputs ### ADRs `bash .claude/scripts/adr-status.sh` reads every `docs/architecture/adr-*.md` in one pass: the counts first (`adrs`, then `accepted`, `proposed`, `deprecated`, `superseded`, `unfilled`, `other`, `no_status`), then one row per ADR with its status and layer. Establish the denominator first: decide from the counts, before reading any ADR: | Counts | Meaning | Action | |---|---|---| | `adrs 0` | No ADRs. | "No ADRs found — run `/architecture-decision` before building a control manifest." Stop. | | `accepted` ≥ 1 | Normal. | The Accepted rows are the set **A**. Name every other ADR, with its status, in the Phase 4 preview: the user approves a manifest knowing what it leaves out. | | `accepted 0`, some with a status | No Accepted ADRs. | "[N] ADRs found, none Accepted. A manifest built from Proposed ADRs would encode decisions that may still change." Ask whether to go on with the Proposed ones or stop. **Never write an empty manifest silently.** | | every ADR `no_status` | **Malformed ADRs, not an empty Accepted set.** | "[N] ADRs found, none has a `## Status` section, so acceptance cannot be told. Run `/architecture-decision retrofit [file]` on each." Stop. Never treat them as Accepted. | Each stop above ends with `Verdict: BLOCKED — [the reason]`. Note the number and title of every ADR a rule comes from. ### Project config - `naming.*` and `performance.*` from `project.yaml`; for any key absent or empty, `.claude/docs/technical-preferences.md`. - Approved libraries and forbidden patterns from `.claude/docs/technical-preferences.md` (not migrated to `project.yaml`). ### Engine reference - `docs/engine-reference/[engine]/VERSION.md` for the engine and version. - `docs/engine-reference/[engine]/deprecated-apis.md`: these become forbidden APIs. - `docs/engine-reference/[engine]/current-best-practices.md`, when it exists. ### What exists already `docs/architecture/control-manifest.md` present: this run regenerates it; read it before the Phase 5 write, which replaces it. `production/epics/*/EPIC.md` present: epics exist. Phase 6 picks its next step from both. Report: "Loaded [A] Accepted ADRs of [N], engine: [name + version]." ## Phase 2: Extract the rules from each ADR For each ADR in **A**, read only four sections, never the whole file: ``` bash .claude/scripts/md-section.sh extract docs/architecture/[adr-file].md "Decision" ``` and the same for `Alternatives Considered`, `Performance Implications` and `Engine Compatibility`. Context, Consequences, Migration Plan and Validation Criteria say why a decision was made; the manifest records what to do. A section an ADR lacks: note it for that ADR and go on. A section missing from **every** ADR in A: report "No Accepted ADR has a `[section]` section — the manifest's [category] rules will be empty. Verify this is intended." Read beyond the four only when a section points outside itself ("subject to the constraints in Context"), and then that one section. From each ADR: - **Required patterns** (Decision): every "must", "should", "required to", "always", and every pattern or approach it mandates, including any `### Implementation Guidelines` inside it. Never look for that sub-heading alone: many ADRs state their mandates directly under Decision, and a scan for the sub-heading alone yields an empty section. - **Forbidden approaches** (Alternatives Considered): every rejected alternative, with why it was rejected as the rule ("never use X because Y"), and any named anti-pattern. - **Performance guardrails** (Performance Implications): budgets ("max N ms per frame for this system") and memory limits. - **Engine API constraints** (Engine Compatibility): post-cutoff APIs that need verifying, behaviour that differs from what a model would assume, fields or methods that changed in the pinned version. **Layer.** Each rule goes under the layer of the system it governs, the ADR's `layer` column where it has one: - **Foundation:** scene management, event architecture, save/load, engine start-up - **Core:** core gameplay loop, main player systems, physics and collision - **Feature:** secondary systems and mechanics, AI - **Presentation:** rendering, audio, UI, VFX, shaders An ADR that spans layers puts its rule in each one. ## Phase 3: Add the global rules Rules for every layer, each with its source (the `project.yaml` key, `technical-preferences.md`, or the engine-reference file), as a layer rule has: - **Naming** from `naming.*`: classes, variables, signals and events, files, constants. - **Performance budgets** from `performance.*`: target frame rate, frame budget, draw calls, memory ceiling. - **Forbidden APIs** from `deprecated-apis.md`, **only those that apply to what this project builds.** Never copy the table whole: its `GodotPhysics3D → Jolt Physics 3D` row is 3D-only, and a 2D project does not use that engine. When you cannot tell whether an entry applies (2D or 3D, a module the project may not include), scope the rule ("when using 3D physics: …") or leave it out and list it as unresolved. `/create-stories` reads this file, and rules that do not apply are rules nobody reads. - **Required patterns** from `current-best-practices.md`, when it exists. - **Forbidden patterns** from `technical-preferences.md`, copied as written. ## Phase 4: Show the summary, then the review ``` ## Control Manifest Preview Engine: [name + version] ADRs covered: [ADR numbers] ADRs left out: [ADR-NNNN ([status]), … — every ADR not in A, or "None"] Rules extracted: - Foundation layer: [N] required, [M] forbidden, [P] guardrails - Core layer: [N] required, [M] forbidden, [P] guardrails - Feature layer: … - Presentation layer: … - Global: [N] naming conventions, [M] forbidden APIs, [P] approved libraries Unresolved: [engine entries left out because whether they apply is unclear, or "None"] ``` Ask: "Does this rule summary look complete?" Options: Yes — review and write it / Add rules — I have more to include / Remove rules — some should be dropped / Stop — I need to review the ADRs first. **The technical review.** Read the `review_gate` line above. `skill-gates=skip` (solo or lean): no agent; note `TD-MANIFEST skipped — [Solo | Lean] mode`. `skill-gates=run`: hand the review to the `technical-director` agent with gate **TD-MANIFEST** (`.claude/docs/director-gates/td-manifest.md`; the agent reads it itself). Brief: - **Objective:** check the extracted rules before they are written. - **Give it:** the preview above with the full rule list, the ADRs covered, the engine version, and the rules taken from technical preferences or the engine reference. - **Check:** every mandatory ADR pattern is captured and stated accurately; the forbidden approaches are complete and correctly attributed; no rule lacks a source ADR or preference document; the guardrails agree with the ADRs' constraints. - **Return:** APPROVE, CONCERNS, REJECT, or NOT ASSESSED naming a missing input. - **Boundaries:** it writes no file. Act on the verdict: - **APPROVE:** go to Phase 5. - **CONCERNS:** ask: "The technical director raised concerns. How do you want to go on?" Options: Revise the flagged rules / Accept and go on / Discuss further. - **REJECT:** write nothing; fix the flagged rules and show the summary again. - **NOT ASSESSED:** it is not an approval (`.claude/docs/director-gates.md`). Name what was missing, then supply it and run the review again; or, when the user chooses to go on without it, go to Phase 5 and state `TD-MANIFEST: NOT ASSESSED — [input]` in the reply and the final verdict line. ## Phase 5: Write the control manifest Ask: "May I write the control manifest to `docs/architecture/control-manifest.md`?" Options: Yes, write it / Show me the full draft first, then ask again / Not yet — I want more changes. Write only on an explicit yes. ```markdown # Control Manifest > **Engine**: [name + version] > **Last Updated**: [date] > **Manifest Version**: [date] > **ADRs Covered**: [ADR-NNNN, ADR-MMMM, ...] > **Status**: Active — regenerate with `/create-control-manifest update` when ADRs change `Manifest Version` is the date this manifest was generated. Stories embed it when they are written, and `/story-readiness` compares a story's version with this one to find stories written against old rules. It always equals `Last Updated`: the same date, for different readers. This manifest is a programmer's quick reference taken from the Accepted ADRs, the technical preferences and the engine reference docs. For the reason behind a rule, read its ADR. --- ## Foundation Layer Rules *Applies to: scene management, event architecture, save/load, engine start-up* ### Required Patterns - **[rule]** — source: [ADR-NNNN] ### Forbidden Approaches - **Never [anti-pattern]** — [brief reason] — source: [ADR-NNNN] ### Performance Guardrails - **[system]**: max [N]ms/frame — source: [ADR-NNNN] --- ## Core Layer Rules *Applies to: core gameplay loop, main player systems, physics, collision* ### Required Patterns ... ### Forbidden Approaches ... ### Performance Guardrails ... --- ## Feature Layer Rules *Applies to: secondary mechanics, AI systems, secondary features* ### Required Patterns ... ### Forbidden Approaches ... --- ## Presentation Layer Rules *Applies to: rendering, audio, UI, VFX, shaders, animations* ### Required Patterns ... ### Forbidden Approaches ... --- ## Global Rules (All Layers) ### Naming Conventions | Element | Convention | Example | Source | |---------|-----------|---------|--------| | Classes | [convention] | [example] | [`naming.classes` in project.yaml, or technical-preferences.md] | | Variables | [convention] | [example] | [`naming.variables` in project.yaml, or technical-preferences.md] | | Signals/Events | [convention] | [example] | [`naming.signals` in project.yaml, or technical-preferences.md] | | Files | [convention] | [example] | [`naming.files` in project.yaml, or technical-preferences.md] | | Constants | [convention] | [example] | [`naming.constants` in project.yaml, or technical-preferences.md] | ### Performance Budgets | Target | Value | Source | |--------|-------|--------| | Framerate | [value] | [`performance.target_framerate` in project.yaml, or technical-preferences.md] | | Frame budget | [value] | [`performance.frame_budget_ms` in project.yaml, or technical-preferences.md] | | Draw calls | [value] | [`performance.draw_call_limit` in project.yaml, or technical-preferences.md] | | Memory ceiling | [value] | [`performance.memory_ceiling_mb` in project.yaml, or technical-preferences.md] | ### Approved Libraries / Addons - [library] — approved for [purpose] — source: technical-preferences.md ### Forbidden APIs ([engine version]) These APIs are deprecated or unverified for [engine + version]: - `[api name]` — deprecated since [version] / unverified post-cutoff - Source: `docs/engine-reference/[engine]/deprecated-apis.md` ### Cross-Cutting Constraints - [constraint that applies in every layer] — source: [ADR-NNNN, preference key or engine-reference file] ``` ## Phase 6: Next steps - No epics yet: "Run `/create-epics layer: foundation`, then `/create-stories [epic-slug]`: stories embed this manifest's rules and version." - A regeneration: "Updated. Tell the team about the changed rules, above all any new Forbidden entries." Every rule traces to an ADR, a technical preference or an engine reference doc; none is invented, and none is paraphrased in a way that changes its meaning. End with `Verdict: COMPLETE — control manifest written` after the write, or `Verdict: BLOCKED — user declined the write` when declined.