mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 01:37:05 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be8993bbc5 |
@@ -58,23 +58,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -155,23 +155,14 @@ You: [Creates ADR, updates docs, notifies relevant agents]
|
||||
- Once decided, commit fully — document and cascade the decision
|
||||
- Set up success metrics — "we'll know this was right if..."
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present strategic decisions as a selectable UI.
|
||||
Follow the **Explain → Capture** pattern:
|
||||
|
||||
1. **Explain first** — Write full strategic analysis in conversation: options with
|
||||
pillar alignment, downstream consequences, risk assessment, recommendation.
|
||||
2. **Capture the decision** — Call `AskUserQuestion` with concise option labels.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (strategic options in step 3, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence with key trade-off.
|
||||
- Add "(Recommended)" to your preferred option's label
|
||||
- For open-ended context gathering, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Registry Awareness
|
||||
|
||||
|
||||
@@ -62,23 +62,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
@@ -106,7 +97,8 @@ plain text. Follow the **Explain -> Capture** pattern:
|
||||
how the design handles them. Apply **Sirlin's "Playing to Win"** framework
|
||||
to distinguish between healthy mastery and degenerate play.
|
||||
6. **Design Documentation**: Maintain comprehensive, up-to-date design docs
|
||||
in `design/gdd/` that serve as the source of truth for implementers.
|
||||
in `design/gdd/` (at `minimal`, `design/game-brief.md`) that serve as the
|
||||
source of truth for implementers.
|
||||
|
||||
### Theoretical Frameworks
|
||||
|
||||
|
||||
@@ -89,12 +89,12 @@ Before writing any code:
|
||||
|
||||
If the reference files do not cover an API or a difference, say so and mark it unverified rather than asserting it from memory.
|
||||
|
||||
**ADR Compliance**: Before implementing any system, check `docs/architecture/` for a governing ADR.
|
||||
**ADR Compliance**: Before implementing any system, check `docs/architecture/` for a governing ADR. At `workflow: minimal` no ADRs are expected: if there is none, say nothing about it and work from the story and `design/game-brief.md`.
|
||||
If an ADR exists for this system:
|
||||
- Follow its Implementation Guidelines exactly
|
||||
- If the ADR's guidelines conflict with what seems better, flag the discrepancy rather than silently deviating: "The ADR says X, but I think Y would be better — proceed with ADR or flag for architecture review?"
|
||||
- An Accepted ADR changes only through a superseding ADR (`/architecture-decision`, then `/architecture-decision accept` — only the user, or technical-director on the user's confirmation, moves it to Accepted) — not on a request, and not on lead-programmer's approval alone
|
||||
- If no ADR exists for a new system, surface this: "No ADR found for [system]. Consider running /architecture-decision first."
|
||||
- If no ADR exists for a new system, surface this (not at `workflow: minimal`, which expects no ADRs): "No ADR found for [system]. Consider running /architecture-decision first."
|
||||
|
||||
### Code Standards
|
||||
|
||||
@@ -104,7 +104,7 @@ If an ADR exists for this system:
|
||||
- No direct references to UI code (use events/signals)
|
||||
- Frame-rate independent logic (delta time everywhere)
|
||||
- Document the design doc each feature implements in code comments
|
||||
- Implement the GDD's Edge Cases section along with its rules — an unhandled edge case is a deviation from the spec
|
||||
- Implement the GDD's Edge Cases section along with its rules (at `minimal`, the story's acceptance criteria) — an unhandled edge case is a deviation from the spec
|
||||
|
||||
### What This Agent Must NOT Do
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -49,23 +49,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain → Capture** pattern:
|
||||
|
||||
1. **Explain first** — Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** — Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
## Core Responsibilities
|
||||
- Design seasonal content calendars and event cadences
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ When the user asks you to make a decision or resolve a conflict:
|
||||
- Once decided, commit fully — document and cascade the decision
|
||||
- Set up success metrics — "we'll know this was right if..."
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present strategic decisions as a selectable UI.
|
||||
Follow the **Explain → Capture** pattern:
|
||||
|
||||
1. **Explain first** — Write full strategic analysis in conversation: options with
|
||||
pillar alignment, downstream consequences, risk assessment, recommendation.
|
||||
2. **Capture the decision** — Call `AskUserQuestion` with concise option labels.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (strategic options in step 3, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence with key trade-off.
|
||||
- Add "(Recommended)" to your preferred option's label
|
||||
- For open-ended context gathering, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Registry Awareness
|
||||
|
||||
|
||||
@@ -59,23 +59,14 @@ When the user asks you to make a decision or resolve a conflict:
|
||||
- Once decided, commit fully — document and cascade the decision
|
||||
- Set up success metrics — "we'll know this was right if..."
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present strategic decisions as a selectable UI.
|
||||
Follow the **Explain → Capture** pattern:
|
||||
|
||||
1. **Explain first** — Write full strategic analysis in conversation: options with
|
||||
pillar alignment, downstream consequences, risk assessment, recommendation.
|
||||
2. **Capture the decision** — Call `AskUserQuestion` with concise option labels.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (strategic options in step 3, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence with key trade-off.
|
||||
- Add "(Recommended)" to your preferred option's label
|
||||
- For open-ended context gathering, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -53,23 +53,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -60,23 +60,14 @@ Before proposing any design:
|
||||
- Iterate based on feedback without defensiveness
|
||||
- Celebrate when the user's modifications improve your suggestion
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool to present decisions as a selectable UI instead of
|
||||
plain text. Follow the **Explain -> Capture** pattern:
|
||||
|
||||
1. **Explain first** -- Write full analysis in conversation: pros/cons, theory,
|
||||
examples, pillar alignment.
|
||||
2. **Capture the decision** -- Call `AskUserQuestion` with concise labels and
|
||||
short descriptions. User picks or types a custom answer.
|
||||
|
||||
**Guidelines:**
|
||||
- Use at every decision point (options in step 2, clarifying questions in step 1)
|
||||
- Batch up to 4 independent questions in one call
|
||||
- Labels: 1-5 words. Descriptions: 1 sentence. Add "(Recommended)" to your pick.
|
||||
- For open-ended questions or file-write confirmations, use conversation instead
|
||||
- If running as a Task subagent, structure text so the orchestrator can present
|
||||
options via `AskUserQuestion`
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. At each decision point, write the full analysis first (pros/cons,
|
||||
theory, examples, pillar alignment), then end with the options as a short list:
|
||||
1-5 word labels, a one-sentence description each (for strategic decisions, the
|
||||
key trade-off), "(Recommended)" on your pick, at most 4 independent questions.
|
||||
Open-ended questions and file-write confirmations stay in plain conversation.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -67,12 +67,12 @@ Before drafting anything:
|
||||
- Flag conflicts with other documents explicitly — their owners should know
|
||||
- You do not write game code — route implementation to the programmer who owns it
|
||||
|
||||
#### Structured Decision UI
|
||||
#### Structured Decisions
|
||||
|
||||
Use the `AskUserQuestion` tool for implementation choices and next-step decisions.
|
||||
Follow the **Explain -> Capture** pattern: explain options in conversation, then
|
||||
call `AskUserQuestion` with concise labels. Batch up to 4 questions in one call.
|
||||
For open-ended writing questions, use conversation instead.
|
||||
`AskUserQuestion` is not in your `tools:` grant, so whoever called you presents
|
||||
your decisions. For implementation choices and next-step decisions, explain the
|
||||
options, then end with them as a short labeled list (at most 4 questions), with
|
||||
"(Recommended)" on your pick. Use conversation for open-ended writing questions.
|
||||
|
||||
### Key Responsibilities
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ through `AskUserQuestion` or writes files should follow this pattern.
|
||||
section `modes.automation` is the source of truth for behavior. This document
|
||||
is the implementation pattern.
|
||||
|
||||
> **Do not read `effects-map.md` during a skill run** — it is ~110 KB, a
|
||||
> **Do not read `effects-map.md` during a skill run** — it is a very large file, a
|
||||
> reference for authoring the spec rather than a runtime input, and **this
|
||||
> document is self-sufficient** for deciding what to ask and what to proceed on.
|
||||
> If a case genuinely is not covered here, read only its `modes.automation`
|
||||
@@ -77,8 +77,8 @@ the right rule.
|
||||
- `AskUserQuestion` called for **major decisions only** (see classification below)
|
||||
- Minor decisions: AI states recommendation inline and proceeds — e.g.
|
||||
> *"Going with a static utility pattern here — it fits the existing architecture. Continuing unless you want to change direction."*
|
||||
- Draft shown briefly before writing — proceeds after a short summary, does not wait for explicit "yes"
|
||||
- "May I write?" asked for **new files only** — updates to existing files proceed directly
|
||||
- Updates to existing files: draft shown briefly before writing — proceeds after a short summary, does not wait for explicit "yes"
|
||||
- "May I write?" asked for **new files only**, and a new file waits for the answer — updates to existing files proceed directly
|
||||
- Still presents options for major decisions but caps at 2 choices with a clear recommendation
|
||||
- Multi-section authoring: writes each approved section immediately, no per-section confirmation
|
||||
|
||||
@@ -92,6 +92,21 @@ the right rule.
|
||||
`production/session-logs/decision-log.md`
|
||||
- User reviews decision log post-session to audit choices made
|
||||
|
||||
### Every mode: a question with no answer
|
||||
|
||||
A question that comes back **skipped, dismissed or empty is not an answer**, in
|
||||
every mode and on every tool: the user closing the question, a headless run that
|
||||
returns every question as skipped, a reply that picks nothing.
|
||||
|
||||
- Do not write a file, change a mode or setting, or pick an option on its behalf.
|
||||
- Ask again in plain text, say what is waiting on the answer, and wait.
|
||||
- In `autonomous`, a question the mode did not require can be decided as usual:
|
||||
pick the recommended option and log it via `log_decision`. A question in an
|
||||
`automation_always_ask` category, or in an exempt skill, is the user's: ask
|
||||
again and wait.
|
||||
- Where nobody can answer (CI, a headless run), stop and report what is waiting
|
||||
rather than choosing.
|
||||
|
||||
---
|
||||
|
||||
## Major vs Minor Decision Classification
|
||||
@@ -135,9 +150,9 @@ Even in `autonomous` mode, certain decision categories ALWAYS trigger
|
||||
the categories actually listed in `modes.automation_always_ask` — the three
|
||||
defaults above, unless the project overrides them — interrupt an `autonomous`
|
||||
run. The other rows do nothing until a project opts into them. Read the resolved
|
||||
list with `resolve_config` rather than assuming a row here is active; a real run
|
||||
logged two `architecture_decisions` as rule violations on a project where that
|
||||
category was never configured.
|
||||
list with `resolve_config` rather than assuming a row here is active. Treating a
|
||||
category the project never configured, such as `architecture_decisions`, as
|
||||
active reports rule violations the project never asked for.
|
||||
|
||||
| Category | Examples of decisions in this category |
|
||||
|----------|----------------------------------------|
|
||||
@@ -255,6 +270,8 @@ At each decision point in this skill:
|
||||
guided + minor: State recommendation inline, proceed.
|
||||
autonomous + always_ask: AskUserQuestion (regardless of mode).
|
||||
autonomous + other: Pick recommended, log via log_decision, proceed.
|
||||
4. If the question comes back skipped, dismissed or empty, it is not an
|
||||
answer: see §Every mode: a question with no answer.
|
||||
```
|
||||
|
||||
This is the contract. Skills that follow this pattern produce
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# Code Root Resolution
|
||||
|
||||
Shared procedure for any skill that reads, scans, counts or writes game source
|
||||
files. Referenced from the point of use in each such skill. Those skills keep
|
||||
the one load-bearing imperative inline — **an unresolved code root means the
|
||||
check did not run** — and cite this file for the resolution order.
|
||||
files. **An unresolved code root means the check did not run.** This file gives
|
||||
the resolution order.
|
||||
|
||||
`.claude/docs/directory-structure.md` is the authority for which directory holds
|
||||
code. This file is the procedure for applying it.
|
||||
|
||||
@@ -69,8 +69,7 @@ falling back to the defaults above when it is absent.
|
||||
> **Exception — `/smoke-check`.** The ADVISORY default for **Config/Data** above
|
||||
> applies to *per-story evidence* gates. `/smoke-check` is a build-health gate,
|
||||
> not a per-story evidence gate, so its own unset default for
|
||||
> `testing.strict.config` is **BLOCKING**. This divergence is intentional and is
|
||||
> documented at both sites; do not reconcile one to the other.
|
||||
> `testing.strict.config` is **BLOCKING**. The two defaults differ on purpose.
|
||||
|
||||
## Automated Test Rules
|
||||
|
||||
|
||||
@@ -38,12 +38,12 @@ a command that would normally just prompt — **aborts the whole invocation**, a
|
||||
the model never sees the skill. A read-only command such as `git status`, which
|
||||
Claude Code approves on its own, comes back "allow" and runs without a grant. A preloaded skill (`skills:` on an agent) is
|
||||
checked the same way at agent launch, so a failing bootstrap line stops the agent
|
||||
from starting. Measured on Claude Code 2.1.281 in default
|
||||
mode:
|
||||
from starting. In default
|
||||
mode, the bootstrap forms behave as follows:
|
||||
|
||||
| Bootstrap form | Repo root | Subdirectory | Bash-less agent preloading it |
|
||||
|---|---|---|---|
|
||||
| `source "${CLAUDE_PROJECT_DIR:-.}/…" && resolve_config` (v1.1.0) | aborts | aborts | fails to launch |
|
||||
| `source "${CLAUDE_PROJECT_DIR:-.}/…" && resolve_config` | aborts | aborts | fails to launch |
|
||||
| same, with a bare `Bash` grant | aborts | — | — |
|
||||
| `bash "${CLAUDE_PROJECT_DIR}/…"` + grant | runs | aborts | — |
|
||||
| **`bash "${CLAUDE_SKILL_DIR}/../../hooks/…"` + per-skill grant** | **runs** | **runs** | **launches** |
|
||||
@@ -181,8 +181,8 @@ set the sub-knob. Their effective values come from the rigor level:
|
||||
|
||||
Because `rigor` itself defaults to `minimal`, an unconfigured project resolves
|
||||
these six to the lean row. That default was `standard`; it changed because the
|
||||
heavier tier measured several times more expensive to reach working code without
|
||||
producing a better result. See the rationale block above `_yaml_helper_defaults`
|
||||
heavier tier costs more to reach working code without producing a better
|
||||
result. See the rationale block above `_yaml_helper_defaults`
|
||||
in `.claude/hooks/yaml-helper.sh` for the reasoning and the ordering
|
||||
constraint. Raising the tier is one question in `/start` or one `/settings`
|
||||
call, and `settings-guidance.md § 4`'s upward triggers are written to fire from
|
||||
@@ -242,40 +242,34 @@ condition below degrades to defaults and is named on `notes:`:
|
||||
| Locked key in `project.local.yaml` | ignored as always, but now **named** on `notes:` — `local: not locally overridable, ignored — modes.rigor (move to project.yaml or delete)` |
|
||||
| No Python interpreter | legacy files and defaults only; **explicitly noted** on `notes:` |
|
||||
| No block at all | shell preprocessing disabled (`disableSkillShellExecution`) — use the defaults table above |
|
||||
| A task notice where the block should be ("Command did not complete within its 120s timeout and was moved to the background") | the settings line ran past Claude Code's 120-second limit for a skill's `!` line, because every process start was slowed — usually by antivirus real-time scanning of the project folder. The settings exist: read each key yourself from `project.local.yaml`, then `project.yaml`, then the defaults table above |
|
||||
| Bootstrap line not approved, or exits non-zero | **not a degraded state — the skill never renders at all.** See "Why exactly this command" above |
|
||||
|
||||
A skill must never treat a missing block as "config is unset in an interesting
|
||||
way". It means the block did not render; the defaults apply.
|
||||
way". It means the block did not render; the defaults apply. The exception is
|
||||
that task notice: the settings line ran out of time, not the settings, so read
|
||||
the files as that row says instead of taking the defaults. If it keeps
|
||||
happening, exclude the project folder from real-time scanning.
|
||||
|
||||
### Two behaviours that are correct but SILENT
|
||||
### Two inputs that resolve without a note
|
||||
|
||||
In both cases the
|
||||
resolved *value* is right — the chain falls through to the default — but the user
|
||||
is told nothing, and their explicit configuration was discarded.
|
||||
In both cases `resolve_config` follows a fixed rule and emits no note, so it does
|
||||
not tell you that something you wrote was not used.
|
||||
|
||||
| Input | What happens | Note emitted |
|
||||
|---|---|---|
|
||||
| **Duplicate key** (`rigor:` twice in one block) | **the last occurrence wins**, deterministically | **none** |
|
||||
| **Wrong shape** — a list where a scalar belongs (`rigor:` followed by `- standard`) | key resolves empty, falls through to the default | **none** |
|
||||
|
||||
**Why this is worth knowing rather than shrugging at.** An enum-*invalid* value is
|
||||
announced (`modes.workflow: 'medium' is not a valid value … — ignored, chain
|
||||
continued`). A structurally-invalid one is not. So a user who mistypes the value
|
||||
gets told, and a user who mistypes the *structure* does not — and the second
|
||||
mistake is the easier one to make by copy-paste. The framework has the mechanism
|
||||
(`notes:`) and already uses it for absence, emptiness, tabs, locked keys, orphan
|
||||
locals and bad enums. Shape is the gap.
|
||||
An enum-*invalid* value is announced (`modes.workflow: 'medium' is not a valid
|
||||
value … — ignored, chain continued`). A wrong shape is not: the key is present
|
||||
but resolves to nothing, which is also what a key with an empty value does on
|
||||
purpose (the "Key present, value empty" row above), and `resolve_config` does not
|
||||
tell the two apart. When a setting seems ignored, check the structure of its key
|
||||
in the file: one scalar on the key's own line, the key written once per block,
|
||||
and no list under it. `/settings` shows the value that is actually in effect.
|
||||
|
||||
**Why it is not caught yet.** Detecting "this key is present in the file but
|
||||
resolved to nothing" means changing the parser every config read in the framework
|
||||
goes through, and the empty-value fall-through above is a *legitimate* case of
|
||||
exactly that signature. Distinguishing "empty on purpose" from "unparseable" is
|
||||
real work, not a one-liner, and it lands in the most load-bearing file there is.
|
||||
Until then, check the structure yourself when a setting seems ignored.
|
||||
|
||||
**Duplicate-key precedence was undocumented before this entry.** Last-wins is
|
||||
deterministic and reproducible, so it is not a bug — but nothing said so, which
|
||||
meant nobody could rely on it either.
|
||||
The last-wins rule for a duplicate key is fixed, so you can rely on it.
|
||||
|
||||
## Why not inject at session start
|
||||
|
||||
|
||||
@@ -32,13 +32,11 @@ The checkpoint holds: current task, next step, what it is blocked on, files in
|
||||
progress, open questions. Write it so a cold reader can resume without opening
|
||||
anything else.
|
||||
|
||||
> **Why the split.** One append-only file doing both jobs grows without bound —
|
||||
> past 700 lines every consumer invents its own slice: a status line parsing a
|
||||
> STATUS block nothing writes, `pre-compact` injecting `head -100` (12.7 KB, at
|
||||
> the moment context is scarcest), `session-start` previewing `tail -20` — the
|
||||
> opposite end. None was wrong, because nothing defined where
|
||||
> the recoverable state lived. Now every consumer reads the named region, and
|
||||
> the cost is fixed no matter how long the narrative grows.
|
||||
> **Why the split.** One append-only file doing both jobs grows without bound,
|
||||
> and every consumer then reads a different slice of it: the top, the bottom, or
|
||||
> a block nothing writes. None of them is wrong, because nothing defines where
|
||||
> the recoverable state lives. With a named region, every consumer reads the
|
||||
> same part, and the cost is fixed no matter how long the narrative grows.
|
||||
|
||||
**Rotation.** When the narrative passes ~200 lines, move it into
|
||||
`production/session-logs/`:
|
||||
@@ -125,7 +123,7 @@ Current helpers:
|
||||
- **`review-scope.sh`** — which GDDs changed since the last cross-review, plus
|
||||
their declared dependencies. Replaces reasoning through git history.
|
||||
|
||||
Two rules when adding one:
|
||||
Two rules for helpers:
|
||||
|
||||
1. **Grant it the way `.claude/docs/config-resolution.md` shows.** `allowed-tools`
|
||||
pre-approves commands; it does not restrict them — a skill without the grant
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
Read `.claude/docs/model-tiers.md` on demand. It carries the tier table, the
|
||||
per-skill assignments and the authoring rule.
|
||||
|
||||
**Load-bearing enough to restate here:** whether a skill's `model:` is used
|
||||
**Key point:** whether a skill's `model:` is used
|
||||
depends on how the skill starts. Typed as `/skill-name`: yes, except a `haiku`
|
||||
pin in auto mode. Started by Claude through the Skill tool: no. Never tell a
|
||||
user a `haiku` skill saves money; an `opus` skill typed in a Sonnet session
|
||||
@@ -43,8 +43,7 @@ must NOT be parallelised.
|
||||
|
||||
### Agent Teams (experimental — opt-in)
|
||||
Multiple independent Claude Code *sessions* coordinated via a shared task list.
|
||||
Opt-in and never yet used here — read `.claude/docs/agent-teams.md` on demand
|
||||
before proposing one.
|
||||
Opt-in only — read `.claude/docs/agent-teams.md` on demand before proposing one.
|
||||
|
||||
## Parallel Task Protocol
|
||||
|
||||
|
||||
@@ -190,19 +190,6 @@ Collect every verdict from the directors that ran, then apply escalation rules:
|
||||
|
||||
---
|
||||
|
||||
## Adding New Gates
|
||||
|
||||
1. Assign a gate ID: `[DIRECTOR-PREFIX]-[DESCRIPTIVE-SLUG]`. Prefixes: `CD-`
|
||||
`TD-` `PR-` `LP-` `QL-` `ND-` `AD-`; add new ones for new agents
|
||||
(`audio-director` → `AU-`, `ux-designer` → `UX-`)
|
||||
2. Create `.claude/docs/director-gates/[gate-id].md` (lowercase), starting with
|
||||
the standard "> Gate definition..." header note, with all five fields:
|
||||
Trigger, Context to pass, Prompt, Verdicts, special handling notes
|
||||
3. Add its row to the Gate Index table above
|
||||
4. Reference it in skills by ID only — never copy the prompt text into the skill
|
||||
|
||||
---
|
||||
|
||||
## Gate Coverage by Stage
|
||||
|
||||
| Stage | Required Gates | Optional Gates |
|
||||
|
||||
+84
-95
@@ -2,11 +2,11 @@
|
||||
|
||||
> ## READ ONE SECTION, NEVER THIS WHOLE FILE
|
||||
>
|
||||
> This document is **~31,000 tokens** — roughly **four times an entire turn's
|
||||
> context budget**, which sits near 8,300. It is organised as **36 sections of
|
||||
> ~900 tokens each**, one per setting, headed `## <key>`.
|
||||
> This document is very large, far more than any one lookup needs. It is
|
||||
> organised as one section per setting, headed `## <key>`, so a reader can take
|
||||
> only the section it wants.
|
||||
>
|
||||
> **So opening it costs 36× what you need.** To look up a setting:
|
||||
> **So opening it whole costs many times what you need.** To look up a setting:
|
||||
>
|
||||
> ```
|
||||
> Grep pattern="^## modes.review_mode" path=".claude/docs/effects-map.md" -A 40
|
||||
@@ -15,13 +15,12 @@
|
||||
> Read the section for your key and stop. The same rule the skills already apply
|
||||
> to their own reference files — `/gate-check` loads only the row for the target
|
||||
> phase and says "never load the others" — applies here, and this is the largest
|
||||
> file in the framework by a factor of seven.
|
||||
> file in the framework.
|
||||
>
|
||||
> This banner exists because six skills cite this document and **none of them
|
||||
> scoped the citation**. None instructed a full read either, so
|
||||
> nothing was actually loading 31k — but "see effects-map.md for full schema" in
|
||||
> front of a file this size is an invitation, and the cost of accepting it is
|
||||
> silent.
|
||||
> Cite a section of this document, never the whole file. A pointer such as "see
|
||||
> effects-map.md for full schema" invites a full read of a file this size, and
|
||||
> the cost of accepting that invitation is silent. Name the `## <key>` section
|
||||
> you need instead.
|
||||
|
||||
This document defines what each `project.yaml` setting actually does across
|
||||
every skill that reads it. It is the tracked, authoritative reference.
|
||||
@@ -341,22 +340,17 @@ behavior: strict project defaults for CI, looser developer overrides for local w
|
||||
> **Hotfix / day-one-patch exception:** These skills are emergency or release-critical
|
||||
> pipelines. They are never gated by `review_mode` — all agents always run.
|
||||
|
||||
> **Known inertness — `full` and `lean` barely differ in the nine `team-*`
|
||||
> orchestrators.** Each documents a three-way split: `full` spawns every director
|
||||
> and lead gate, `lean` skips director gates *unless* they are PHASE-GATE type,
|
||||
> `solo` skips gate spawning entirely. But the director gates the team skills name
|
||||
> are the four PHASE-GATEs, which `lean` keeps — and no team pipeline spawns one
|
||||
> (`/gate-check` is their only spawner). Two things differ: `/team-release`'s
|
||||
> technical-director release sign-off runs only at `full`, and `/team-narrative` at
|
||||
> `team.size: small` adds `localization-lead` and `world-builder` only at `full`.
|
||||
> **`review_mode` in the nine `team-*` orchestrators.** `review_mode` sets
|
||||
> director-gate depth: `full` spawns every director gate a pipeline names, `lean`
|
||||
> skips director gates unless they are PHASE-GATE type, and `solo` skips gate
|
||||
> spawning entirely. No team pipeline spawns a PHASE-GATE (`/gate-check` is their
|
||||
> only spawner), so in the orchestrators
|
||||
> `lean` and `solo` behave the same, and `full` adds two things:
|
||||
> `/team-release`'s technical-director release sign-off, and, at
|
||||
> `team.size: small`, `/team-narrative`'s `localization-lead` and `world-builder`.
|
||||
>
|
||||
> `solo` genuinely differs, and outside the orchestrators (`/design-review`,
|
||||
> `/architecture-review`) all three levels differ as documented.
|
||||
>
|
||||
> **This is recorded, not fixed.** Making `lean` mean something in the
|
||||
> orchestrators requires deciding which non-phase-gate reviewers each of the nine
|
||||
> should call at `full` — a design decision about review depth, not a wording fix,
|
||||
> and one that changes how many agents a run spawns.
|
||||
> Outside the orchestrators, the skills in the *Core skills* table below read
|
||||
> `review_mode` as that table documents.
|
||||
|
||||
---
|
||||
|
||||
@@ -395,15 +389,18 @@ behavior: strict project defaults for CI, looser developer overrides for local w
|
||||
|
||||
---
|
||||
|
||||
### Skills to be made review-mode aware (currently ignore the setting)
|
||||
### Skills that do not read `modes.review_mode`
|
||||
|
||||
| Skill | full | lean | solo |
|
||||
|-------|------|------|------|
|
||||
| **review-all-gdds** | Phase 2 consistency pass + Phase 3 design theory pass (parallel) | Phase 2 consistency pass only, Phase 3 skipped | Phase 2 only, Phase 3 skipped |
|
||||
| **architecture-review** | Engine specialist + security-engineer (if online features) | Both skipped | Both skipped |
|
||||
| **dev-story** | Core programmer routing always runs + engine-specialist escalation on HIGH risk stories | Core programmer routing always runs, engine-specialist escalation skipped | Core programmer routing always runs, engine-specialist escalation skipped |
|
||||
| **code-review** | Language, shader, UI specialists + qa-tester | All optional specialists skipped | All optional specialists skipped |
|
||||
| **security-audit** | security-engineer spawned | Skipped | Skipped |
|
||||
These skills run the same way at `full`, `lean` and `solo`. None of them takes a
|
||||
`--review` flag.
|
||||
|
||||
| Skill | What runs at every level |
|
||||
|-------|--------------------------|
|
||||
| **review-all-gdds** | Phase 2 consistency pass and Phase 3 design-theory pass, in parallel |
|
||||
| **architecture-review** | The primary engine specialist is consulted after the engine audit (recorded as NOT ASSESSED when no engine is configured) |
|
||||
| **dev-story** | Core programmer routing, plus the engine specialist when the story involves engine-specific APIs or patterns, and always when engine risk is HIGH |
|
||||
| **code-review** | Language, shader and UI specialists when an engine is configured, plus `qa-tester` for Logic and Integration stories |
|
||||
| **security-audit** | `security-engineer` is spawned to run the audit |
|
||||
|
||||
---
|
||||
|
||||
@@ -427,9 +424,9 @@ pipeline's own review steps run in every mode.
|
||||
phase gates always run. Only `solo` skips them. This is intentional: phase
|
||||
gates are the minimum quality bar, not optional extras. **How many directors
|
||||
run is a separate axis** — `modes.workflow` sets panel width (`minimal` → PR
|
||||
only, `standard` → TD + PR, `full` → all four), because a fixed four-director
|
||||
Opus panel cost a two-system jam exactly what it cost a thirty-system
|
||||
commercial project. Width never softens a verdict: the strictest verdict from
|
||||
only, `standard` → TD + PR, `full` → all four), because directors are
|
||||
Opus-tier and a small project should not pay for the same four-director panel
|
||||
as a large one. Width never softens a verdict: the strictest verdict from
|
||||
whoever ran still wins, and `/gate-check` names the perspectives it skipped.
|
||||
- **art-bible** always spawns its section specialists regardless of mode — only
|
||||
the final sign-off gate is controlled by `review_mode`. Specialist delegation is
|
||||
@@ -459,8 +456,8 @@ pipeline's own review steps run in every mode.
|
||||
`/start` asks that sets the six knobs below
|
||||
**Values:** `minimal` | `standard` | `full`
|
||||
**Default:** `minimal` — see the rationale block above `_yaml_helper_defaults`
|
||||
in `.claude/hooks/yaml-helper.sh`. Short version: the heavier tier cost several
|
||||
times more to reach working code without producing a better result.
|
||||
in `.claude/hooks/yaml-helper.sh`. Short version: the heavier tier costs more to
|
||||
reach working code without producing a better result.
|
||||
**Set by:** `/start` (Phase 3d), `/settings`
|
||||
**Read by:** nothing directly — it is read *through* the six knobs it supplies
|
||||
|
||||
@@ -646,8 +643,8 @@ checklists differ per phase per mode.
|
||||
`minimal`. -->
|
||||
|
||||
**Director panel width** (`/gate-check` Section 4b) is workflow's second effect
|
||||
here. Directors are Opus-tier, so a fixed four-director panel charged a
|
||||
two-system jam exactly what it charged a thirty-system commercial project:
|
||||
here. Directors are Opus-tier, so the panel is sized to the project rather than
|
||||
fixed at four:
|
||||
|
||||
| `workflow` | Panel | Directors |
|
||||
|---|---|---|
|
||||
@@ -823,10 +820,10 @@ recommend and proceed — the tradeoff between user control and speed
|
||||
- Minor decisions: AI states recommendation inline and proceeds — e.g.
|
||||
*"Going with a static utility pattern here — it fits the existing architecture.
|
||||
Continuing unless you want to change direction."*
|
||||
- Draft shown briefly before writing — proceeds after a short summary, does not
|
||||
wait for explicit "yes"
|
||||
- "May I write?" asked for **new files only** — updates to existing files proceed
|
||||
directly
|
||||
- Updates to existing files: draft shown briefly before writing — proceeds after a
|
||||
short summary, does not wait for explicit "yes"
|
||||
- "May I write?" asked for **new files only**, and a new file waits for the answer
|
||||
— updates to existing files proceed directly
|
||||
- Still presents options for major decisions but caps at 2 choices with a clear
|
||||
recommendation
|
||||
- Multi-section authoring: writes each approved section immediately, no per-section
|
||||
@@ -842,6 +839,18 @@ recommend and proceed — the tradeoff between user control and speed
|
||||
with: timestamp, skill, decision point, option chosen, reasoning
|
||||
- User reviews decision log post-session to audit choices made
|
||||
|
||||
#### every mode — a question with no answer
|
||||
|
||||
- A question that comes back skipped, dismissed or empty is **not an answer**, in
|
||||
every mode and on every tool (a closed question, a headless run that returns
|
||||
every question as skipped, a reply that picks nothing)
|
||||
- Nothing is written, no mode or setting changes and no option is picked on its
|
||||
behalf; the question is asked again in plain text, naming what waits on it
|
||||
- `autonomous`: a question the mode did not require is decided and logged as
|
||||
usual; an `automation_always_ask` category or an exempt skill asks again
|
||||
- Where nobody can answer (CI, headless), the skill stops and reports what is
|
||||
waiting rather than choosing
|
||||
|
||||
---
|
||||
|
||||
### Major vs minor decision classification (guided mode)
|
||||
@@ -1239,7 +1248,7 @@ closing, or produces a warning and lets work continue — per test type
|
||||
> **No skill or hook reads this setting. Setting it has no effect.** Everything
|
||||
> below describes the intended design, not current behaviour.
|
||||
>
|
||||
> The value is checked for valid spelling when you set it, and then ignored.
|
||||
> The value is not checked when you set it, and nothing reads it.
|
||||
|
||||
**Controls:** Whether phase gate failures block stage transition or just warn
|
||||
**Values:** `true` | `false`
|
||||
@@ -1437,7 +1446,7 @@ must tell them apart)
|
||||
|
||||
| Value | Required compliance | Best for |
|
||||
|-------|---------------------|----------|
|
||||
| `none` | No certification — internal release, alpha, jam game | Default |
|
||||
| `none` | No certification | Internal releases, alphas, jam games (an explicit choice — unset is not `none`) |
|
||||
| `itch` | itch.io upload requirements (build size, page setup, age tags) | Indie web/desktop releases |
|
||||
| `steam` | Steamworks integration, store page, achievements, depot build, system requirements, common content rules | Commercial PC releases |
|
||||
| `console` | Platform certification (PlayStation/Xbox/Switch) — heavy compliance: TRC/XR/Lotcheck, save data rules, controller mapping rules, age rating boards | Console releases |
|
||||
@@ -1450,7 +1459,6 @@ must tell them apart)
|
||||
|-------|------|------|-------|---------|
|
||||
| **launch-checklist** | Internal launch only — no external requirements | + itch.io page setup, butler upload, build size | + Steamworks integration, store page, achievements depot, common content checks | + Platform-specific TRC, certification submission, console save format compliance |
|
||||
| **release-checklist** | Smoke pass + version bump only | + itch.io page live, build uploaded to butler | + Steam store page live, depot pushed, achievements live | + Platform submission accepted, age rating boards cleared |
|
||||
| **/pre-cert** (future) | Not applicable | Lightweight readiness check | Steam common content audit | Full TRC compliance audit |
|
||||
|
||||
---
|
||||
|
||||
@@ -1477,8 +1485,8 @@ must tell them apart)
|
||||
|
||||
> **Default is `none`, not `standard`.** Most CCGS users are solo devs and jam-game
|
||||
> makers — defaulting to `standard` would auto-spawn the accessibility specialist
|
||||
> for projects where it's overhead. `/start` asks the question explicitly so users
|
||||
> who care can opt into `standard` or `aaa` consciously.
|
||||
> for projects where it's overhead. `/start` does not ask about it; you set it with
|
||||
> `/settings`.
|
||||
|
||||
---
|
||||
|
||||
@@ -1564,9 +1572,9 @@ must tell them apart)
|
||||
>
|
||||
> **Unset is not zero and not a default.** A budget nobody set is not a budget
|
||||
> that was met — `/perf-profile` must report `NOT ASSESSED` for a metric with no
|
||||
> committed target rather than measuring against a placeholder. That exact
|
||||
> failure (">99% headroom against a 16.67ms budget", from zero profiler data)
|
||||
> is one of the two instances that motivated `.claude/rules/skill-authoring.md`.
|
||||
> committed target rather than measuring against a placeholder. A headroom figure
|
||||
> computed against an invented budget, with no profiler data behind it, reads as
|
||||
> a pass and is not one; see obligations 1 and 2 in `.claude/rules/skill-authoring.md`.
|
||||
|
||||
## performance.enforce
|
||||
|
||||
@@ -1832,7 +1840,8 @@ engine reference in this repo can source it. See `/setup-engine` §"The Godot
|
||||
|
||||
The Unreal row is Windows'. `/setup-engine` writes the Linux block (`Engine/Build/BatchFiles/RunUAT.sh`,
|
||||
`Engine/Binaries/Linux/UnrealEditor`) on Linux, and on macOS only `build`, leaving `test`, `run` and
|
||||
`smoke` as TODOs — see `docs/engine-reference/unreal/current-best-practices.md`, "Command Line".
|
||||
`smoke` unset, with a comment in `project.yaml` asking you to set them via `/settings` — see
|
||||
`docs/engine-reference/unreal/current-best-practices.md`, "Command Line".
|
||||
|
||||
> **`<PRESET>` and `<TARGET>` are placeholders, not values to copy.** A Godot
|
||||
> export preset is whatever string the operator typed into `export_presets.cfg`;
|
||||
@@ -1880,16 +1889,15 @@ conventions into a brief, manifest or spec. **NOT by `/code-review` and NOT by
|
||||
> and `validate-commit.sh` does not warn on violations — neither contains any
|
||||
> naming logic. If you need enforcement, it has to be added.
|
||||
>
|
||||
> **Known rough edge — asset filenames.** `validate-assets.sh` warns unless files
|
||||
> under Godot's `assets/` are lowercase-with-underscores, and it takes no config
|
||||
> input, while `/asset-spec` specifies asset names from `naming.*`. Unity's
|
||||
> `Assets/` and Unreal's `Content/` are not naming-checked: those engines name
|
||||
> assets in PascalCase. On Godot-C#, where `/setup-engine` sets
|
||||
> `naming.files: PascalCase`, the hook will warn on assets named exactly as
|
||||
> `/asset-spec` specified them. The two are
|
||||
> measuring different things — `naming.files` describes **source** files by its
|
||||
> own examples (`PlayerController.cs`), and no key currently governs asset
|
||||
> filenames — so treat the hook's naming warning as advisory on those engines.
|
||||
> **Asset filenames.** `validate-assets.sh` warns when a file under Godot's
|
||||
> `assets/` has an uppercase letter, a space or a hyphen in its name (it expects
|
||||
> lowercase with underscores), and it takes no config input. `/asset-spec`
|
||||
> specifies asset names from `naming.*`. Unity's `Assets/` and Unreal's `Content/`
|
||||
> are not naming-checked: those engines name assets in PascalCase. On Godot-C#,
|
||||
> where `/setup-engine` sets `naming.files: PascalCase`, the hook warns on assets
|
||||
> named exactly as `/asset-spec` specified them. `naming.files` describes
|
||||
> **source** files by its own examples (`PlayerController.cs`), and no key governs
|
||||
> asset filenames, so treat the hook's naming warning as advisory there.
|
||||
|
||||
> **Moved from `technical-preferences.md`**, which is being deleted. Naming
|
||||
> conventions are project-level facts shared by everyone on the project, so they
|
||||
@@ -1931,19 +1939,8 @@ No skill or hook validates code *against* these conventions — see the note abo
|
||||
|
||||
## features.session_state
|
||||
|
||||
> ⚠️ **`active.yaml` does not exist and nothing writes it — anywhere in this
|
||||
> document.** It is deferred design. What ships is
|
||||
> `production/session-state/**active.md**`, whose `<!-- CHECKPOINT -->` region
|
||||
> `session-start.sh` and `pre-compact.sh` both read, and whose
|
||||
> `<!-- STATUS -->` block `statusline.sh` parses. **Read every `active.yaml` and
|
||||
> `status:` mention in this file — above and below — as the deferred design, and
|
||||
> substitute `active.md` (and its STATUS block).** This scope note is
|
||||
> document-wide on purpose: the equivalent warning under *Status line behavior*
|
||||
> scoped itself to mentions "below", which left this section's own Controls line
|
||||
> and Hook behavior table describing a file that does not exist.
|
||||
|
||||
**Controls:** Whether the harness runs a full session tracking pipeline (hooks,
|
||||
log files, `active.yaml` checkpoint — see the scope note above) or relies on
|
||||
log files, `active.md` checkpoint) or relies on
|
||||
skeleton-first output files for recovery
|
||||
**Values:** `off` | `on`
|
||||
**Default:** `on`
|
||||
@@ -2000,11 +1997,11 @@ skeleton-first output files for recovery
|
||||
|
||||
| Hook | session_state: off | session_state: on |
|
||||
|------|--------------------|-------------------|
|
||||
| **session-start.sh** | Runs normally (git/sprint context) — skips active.yaml preview block | Runs fully including active.yaml preview |
|
||||
| **session-start.sh** | Runs normally (git/sprint context) — skips the `active.md` checkpoint preview | Runs fully, including the `active.md` checkpoint preview |
|
||||
| **detect-gaps.sh** | Runs unchanged — gap detection is independent of session state | Runs unchanged |
|
||||
| **pre-compact.sh** | No-op — exits silently (no compaction-log append) | The CHECKPOINT block (and any STATUS lines) from `active.md`, changed and untracked file names and design docs with WIP markers — each list capped at 20 — then a compaction-log append; the output goes to the debug log, since PreCompact output never reaches Claude |
|
||||
| **post-compact.sh** | No-op — exits silently | Runs: prints a re-read reminder to the debug log (PostCompact output never reaches Claude; `session-start.sh` restores context) |
|
||||
| **session-stop.sh** | No-op — exits silently | Archives active.yaml to session-log, appends commits and diffs |
|
||||
| **session-stop.sh** | No-op — exits silently | Archives `active.md` to `session-log.md` when it has changed, appends commits and uncommitted file names |
|
||||
| **log-agent.sh** | No-op — exits silently | Appends to agent-audit.log |
|
||||
| **log-agent-stop.sh** | No-op — exits silently | Appends to agent-audit.log |
|
||||
|
||||
@@ -2015,7 +2012,7 @@ skeleton-first output files for recovery
|
||||
| File | session_state: off | session_state: on |
|
||||
|------|--------------------|-------------------|
|
||||
| `production/session-state/active.md` | Still written by skills; session start does not show it | Written by skills; session start shows its checkpoint |
|
||||
| `production/session-logs/session-log.md` | Not written | Append-only archive of each session's active.yaml |
|
||||
| `production/session-logs/session-log.md` | Not written | Append-only archive of each session's `active.md` |
|
||||
| `production/session-logs/compaction-log.txt` | Not written | Append-only timestamp log of compaction events |
|
||||
| `production/session-logs/agent-audit.log` | Not written | Append-only log of agent spawn/complete events |
|
||||
|
||||
@@ -2044,7 +2041,7 @@ bodies and a `<!-- STATUS: incomplete -->` marker per section.
|
||||
As each section is approved and written, the marker changes to `<!-- STATUS: done -->`.
|
||||
On recovery (after /clear or compaction), the agent reads the skeleton, identifies
|
||||
which sections are `done` vs `incomplete`, reads relevant ADRs and the systems index,
|
||||
and resumes at the first `incomplete` section. No active.yaml needed.
|
||||
and resumes at the first `incomplete` section. No `active.md` needed.
|
||||
|
||||
**Skills required to implement skeleton-first:**
|
||||
|
||||
@@ -2068,14 +2065,6 @@ and resumes at the first `incomplete` section. No active.yaml needed.
|
||||
|
||||
### Status line behavior
|
||||
|
||||
> ⚠️ **The table below describes POST-YAML-EXPANSION behavior, which is NOT
|
||||
> IMPLEMENTED.** `active.yaml` does not exist and nothing writes it. What ships
|
||||
> today: `statusline.sh` parses the `<!-- STATUS --> ... <!-- /STATUS -->`
|
||||
> markdown comment block inside `production/session-state/active.md`. Substitute
|
||||
> "the STATUS block in `active.md`" for every `active.yaml` / `status:` mention
|
||||
> here. **The same substitution applies document-wide, not just below this
|
||||
> point** — see the scope note under `## features.session_state`.
|
||||
|
||||
> **Stage detection is always independent of session state.** `statusline.sh`
|
||||
> auto-detects stage from `project.yaml` `project.stage` or artifact heuristics regardless
|
||||
> of `session_state` value, and so is the breadcrumb: `statusline.sh` never reads
|
||||
@@ -2087,24 +2076,24 @@ and resumes at the first `incomplete` section. No active.yaml needed.
|
||||
| Context % display | Always shown | Always shown |
|
||||
| Model display | Always shown | Always shown |
|
||||
| Stage display | From project.yaml or heuristics — except at `workflow: minimal`, where `Minimal · <done>/<total> stories` (or `Minimal · brief` before any story exists) replaces it | Same |
|
||||
| Epic/Feature/Task breadcrumb | Parsed from `status:` block in `active.yaml` (not gated) | Parsed from `status:` block in `active.yaml` |
|
||||
| Epic/Feature/Task breadcrumb | Parsed from the `<!-- STATUS -->` block in `active.md` (not gated) | Parsed from the `<!-- STATUS -->` block in `active.md` |
|
||||
|
||||
---
|
||||
|
||||
### Affected skills
|
||||
|
||||
Skills interact with session state in two ways: **inference** (reading active.yaml
|
||||
Skills interact with session state in two ways: **inference** (reading `active.md`
|
||||
to resolve a missing argument) and **extraction** (appending a SESSION EXTRACT
|
||||
block after completing work). Neither is gated: no skill reads `session_state`,
|
||||
so both happen whatever its value.
|
||||
|
||||
#### Inference — skills that read active.yaml to fill in missing arguments
|
||||
#### Inference — skills that read `active.md` to fill in missing arguments
|
||||
|
||||
When active.yaml holds nothing to infer from, these skills must receive the
|
||||
When `active.md` holds nothing to infer from, these skills must receive the
|
||||
argument explicitly. If called without an argument, they should prompt the user
|
||||
rather than fail silently.
|
||||
|
||||
| Skill | What it infers from active.yaml | Fallback when nothing is found |
|
||||
| Skill | What it infers from `active.md` | Fallback when nothing is found |
|
||||
|-------|----------------------------------|---------------------|
|
||||
| **dev-story** | Active story path (when no arg given) | Prompt user for story path |
|
||||
| **story-done** | In-progress story path (when no arg given) | Prompt user for story path |
|
||||
@@ -2137,7 +2126,7 @@ the `<!-- CHECKPOINT -->` block; the others append a SESSION EXTRACT.
|
||||
| Per session start | ~500 tokens (git/sprint context only) | ~500–1,250 tokens (+ checkpoint preview, at most ~750) |
|
||||
| Per compaction event | 0 (compaction hook output never reaches Claude) | 0 (logged to disk only) |
|
||||
| Per session end | 0 | File I/O only (no conversation tokens) |
|
||||
| Recovery after /clear | Read skeleton + 2–3 docs (~1,000–3,000 tokens) | Read active.yaml (~200–500 tokens) |
|
||||
| Recovery after /clear | Read skeleton + 2–3 docs (~1,000–3,000 tokens) | Read `active.md` (~200–500 tokens) |
|
||||
|
||||
> **Note:** The `off` recovery cost (reading skeleton + docs) is paid only when
|
||||
> recovery is actually needed. The `on` session-start cost is paid every session
|
||||
@@ -2152,7 +2141,7 @@ the `<!-- CHECKPOINT -->` block; the others append a SESSION EXTRACT.
|
||||
> **No skill or hook reads this setting. Setting it has no effect.** Everything
|
||||
> below describes the intended design, not current behaviour.
|
||||
>
|
||||
> The value is checked for valid spelling when you set it, and then ignored.
|
||||
> The value is not checked when you set it, and nothing reads it.
|
||||
> Nothing warns at any threshold.
|
||||
|
||||
**Controls:** Context usage threshold at which session warnings fire
|
||||
@@ -2281,7 +2270,7 @@ preserved raw and flagged for manual resolution, never coerced.
|
||||
Settings absent from the legacy files (new v1.1 settings like `qa.level`,
|
||||
`docs.density`, `team.size`, etc.) get hardcoded defaults from the v1.1 schema.
|
||||
|
||||
### Cleanup (deferred, non-destructive)
|
||||
### Cleanup (optional, non-destructive)
|
||||
|
||||
Migration is **non-destructive in v1.1**: legacy files are NOT auto-deleted.
|
||||
Migration produces `project.yaml` and leaves the legacy files in place. Hooks
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Error Recovery Protocol
|
||||
|
||||
Shared procedure for any skill that spawns agents via the `Agent` tool. Referenced from the
|
||||
`## Error Recovery Protocol` section of each orchestration/review skill. Those
|
||||
skills keep the two load-bearing imperatives (surface immediately, produce a
|
||||
partial report) inline, and keep their own **Common blockers** list inline —
|
||||
those are skill-specific. This file holds the full procedure.
|
||||
Shared procedure for any skill that spawns agents via the `Agent` tool, used by
|
||||
the `## Error Recovery Protocol` section of each orchestration and review skill.
|
||||
Two imperatives apply to all of them: **surface a blocked agent immediately, and
|
||||
produce a partial report.** Each skill's own **Common blockers** list is
|
||||
skill-specific and is not repeated here.
|
||||
|
||||
## Trigger 0 — verify the artifact before reading the response
|
||||
|
||||
@@ -15,19 +15,18 @@ response reads.
|
||||
|
||||
This trigger exists because the three below are not sufficient. They fire on
|
||||
BLOCKED, on an error, and on "cannot complete" — and an agent can fail in a way
|
||||
that is none of those. Observed live: a `devops-engineer` spawned
|
||||
as half of a parallel phase ran **26 tool calls and ~31,600 tokens**, then
|
||||
returned a single fluent preamble — "I'll verify the build infrastructure…" —
|
||||
with no path, no summary, no BLOCKED item, and **no file written**. Nothing in
|
||||
that is none of those. A parallel agent can do a lot of work and then return a
|
||||
single fluent preamble — "I'll verify the build infrastructure…" — with no
|
||||
path, no summary, no BLOCKED item, and **no file written**. Nothing in
|
||||
steps 1–4 matches that shape. An orchestrator reading the transcript sees a
|
||||
plausible response and advances, and half a parallel phase disappears with no
|
||||
signal at all.
|
||||
|
||||
The work was not lost — resumed with an explicit "you did not honour the return
|
||||
contract" message, the same agent completed in **one tool call**, because its
|
||||
investigation was still in context. Only the write-and-return step had failed.
|
||||
So the recovery is cheap; the detection is the hard part, and the detection
|
||||
cannot come from reading the response.
|
||||
The work is usually not lost. Resume the agent with an explicit "you did not
|
||||
honour the return contract" message. Its investigation is still in context, so
|
||||
it only has to do the write-and-return step it skipped. So the recovery is
|
||||
cheap; the detection is the hard part, and the detection cannot come from
|
||||
reading the response.
|
||||
|
||||
**A fluent response is not evidence that a phase ran.** The artifact is —
|
||||
observe the artifact, not the transcript. The rule applies to sub-agents
|
||||
|
||||
@@ -35,17 +35,12 @@ YYYYMMDD_HHMMSS | <session_id> | Agent invoked: <agent_type>
|
||||
to tally the current session, then writes a count plus a per-agent breakdown to
|
||||
`production/session-logs/session-cost.md` and echoes a one-line total.
|
||||
|
||||
Three constraints that must not be "tidied" later:
|
||||
The field order of that record is fixed. `session-stop.sh` matches it literally,
|
||||
so a different order silently zeroes the spawn count instead of raising an error.
|
||||
|
||||
- **The field order is load-bearing.** Nothing else parses this log, so a
|
||||
reformat looks free — but it silently zeroes the spawn count rather than
|
||||
erroring.
|
||||
- **`session-stop.sh` reads stdin last, on purpose.** Everything above the
|
||||
tally block (notably archiving `active.md`) runs first, so a stdin read that
|
||||
ever blocked would cost only the count, not the state archive.
|
||||
- **No session id means no number.** The hook prints nothing rather than a
|
||||
total spanning every session in the log. Silence here is correct; a
|
||||
plausible-but-wrong cost figure is worse than none.
|
||||
When the hook input has no session id, `session-stop.sh` prints no total. A
|
||||
total spanning every session in the log would look plausible and be wrong, which
|
||||
is worse than none.
|
||||
|
||||
`agent_type` — not `agent_name` — is the field carrying the agent name. See
|
||||
`hooks-reference/hook-input-schemas.md`.
|
||||
@@ -53,16 +48,15 @@ Three constraints that must not be "tidied" later:
|
||||
## Events considered and deliberately not added
|
||||
|
||||
Claude Code offers many more hook events than the nine the hooks above use. These were
|
||||
evaluated and rejected. Recorded so a future review does not re-propose them
|
||||
from the event list alone.
|
||||
evaluated and not adopted, for the reasons given.
|
||||
|
||||
| Event | Why not |
|
||||
| ---- | ---- |
|
||||
| `UserPromptSubmit` | Would re-inject session state on **every prompt**. `.claude/docs/config-resolution.md` already rejects the weaker version of this — injecting config at session start — because it "would cost tokens on every session whether or not any skill needs config, and it would go stale mid-session as `/settings` writes land". Firing per prompt is the same argument, multiplied. |
|
||||
| `ConfigChange` | Fires only for Claude Code's own settings files — user, project, local, policy and skills. It does **not** fire for `project.yaml`, so a hook watching CCGS config here would never run. `FileChanged` is the event that watches arbitrary files. |
|
||||
| `FileChanged` on `project.yaml` | Config is resolved per skill invocation, in the skill body, precisely so each run reads fresh values. The only staleness left is text already injected into an earlier invocation, which is the accepted trade in `config-resolution.md`. A warning hook would second-guess a settled decision. |
|
||||
| `ConfigChange` | Fires only for Claude Code's own settings files — user, project, local, policy and skills. It does **not** fire for `project.yaml`, so a hook watching the framework's config here would never run. `FileChanged` is the event that watches arbitrary files. |
|
||||
| `FileChanged` on `project.yaml` | Config is resolved per skill invocation, in the skill body, precisely so each run reads fresh values. The only staleness left is text already injected into an earlier invocation, which is the accepted trade in `config-resolution.md`. |
|
||||
| `PreToolUse` `updatedInput` | Could rewrite a non-conventional commit message instead of blocking it. Silently editing the user's input contradicts the collaboration protocol: this project blocks and explains rather than acting unasked. |
|
||||
| `PostToolUseFailure` | Would add another log with no reader. This repo has already been bitten by that — `log-agent.sh` wrote per-spawn records nothing consumed until `session-stop.sh` was given the job. |
|
||||
| `PostToolUseFailure` | Would add another log with no reader. |
|
||||
| `SessionEnd` | `session-stop.sh` stays on `Stop`. `SessionEnd` fires on termination, which a crash may never reach, and the content-hash guard already makes the per-response firing cheap. |
|
||||
| `InstructionsLoaded` | Useful for debugging which CLAUDE.md and rules files actually loaded, but it is a diagnostic, not a project requirement. Wire it in your own `.claude/settings.local.json` when you need it rather than paying for it on every load. |
|
||||
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
>
|
||||
> A skill's `model:` overrides the session model for the rest of the turn the
|
||||
> skill runs in, and your next prompt returns to the session model. Whether the
|
||||
> override happens depends on how the skill starts (measured on Claude Code
|
||||
> 2.1.282):
|
||||
> override happens depends on how the skill starts:
|
||||
>
|
||||
> | How the skill starts | Is `model:` used? |
|
||||
> |---|---|
|
||||
> | You type `/skill-name` in Manual (`default`) mode | Yes |
|
||||
> | You type `/skill-name` in auto mode | `sonnet` and `opus`: yes. `haiku`: no — auto mode does not support Haiku, so the session keeps its model (documented) |
|
||||
> | Claude starts the skill itself, through the Skill tool | No — the session model runs it (measured; the docs do not say) |
|
||||
> | You type `/skill-name` in auto mode | `sonnet` and `opus`: yes. `haiku`: no — auto mode does not support Haiku, so the session keeps its model |
|
||||
> | Claude starts the skill itself, through the Skill tool | No — the session model runs it |
|
||||
>
|
||||
> Two things follow:
|
||||
>
|
||||
@@ -59,10 +58,9 @@ Skills with `model: opus` (3): `/architecture-review`, `/gate-check`, `/review-a
|
||||
|
||||
All other skills are Sonnet. When creating a new skill, assign Haiku if it only
|
||||
reads and formats; assign Opus if it must synthesize 5+ documents with
|
||||
high-stakes output; otherwise write `model: sonnet` explicitly. Every skill in
|
||||
this repo declares a tier, and the lists above are kept in step with what the
|
||||
`SKILL.md` files declare. That is a check on two descriptions agreeing; it
|
||||
proves nothing about which model actually runs.
|
||||
high-stakes output; otherwise write `model: sonnet` explicitly. Every skill
|
||||
declares a tier. Whether the tier takes effect depends on how the skill starts
|
||||
(see the table at the top of this file).
|
||||
|
||||
**Agent model tiers.** 30 agents use `model: inherit` and run on the session's
|
||||
model. 19 are pinned:
|
||||
@@ -87,7 +85,7 @@ model. 19 are pinned:
|
||||
writing player-facing text are Sonnet work, as they are for `/patch-notes`.
|
||||
|
||||
Every agent not named above is `inherit`. The `model:` line in the agent's own
|
||||
file is what runs, and this list is kept in step with those files.
|
||||
file is what runs.
|
||||
|
||||
A pin gets that model's context window, whatever the session runs. On the
|
||||
Anthropic API `sonnet` currently resolves to Sonnet 5, which always has a 1M
|
||||
|
||||
+11
-10
@@ -117,7 +117,7 @@ Ask yourself: "What department would handle this in a real studio?"
|
||||
| `/ux-review` | Validate UX specs for accessibility and GDD alignment |
|
||||
| `/create-architecture` | Master architecture document for the game |
|
||||
| `/architecture-decision` | Creates an ADR |
|
||||
| `/architecture-review` | Validate all ADRs, dependency ordering, GDD traceability |
|
||||
| `/architecture-review` | Validate all ADRs, dependency ordering, GDD traceability — writes the index to `docs/architecture/requirements-traceability.md` |
|
||||
| `/create-control-manifest` | Flat programmer rules sheet from Accepted ADRs |
|
||||
| `/create-epics` | Translate GDDs + ADRs into epics (one per architectural module) |
|
||||
| `/create-stories` | Break a single epic into implementable story files |
|
||||
@@ -180,8 +180,9 @@ Templates are in `.claude/docs/templates/`:
|
||||
|
||||
- `game-design-document.md` -- for new mechanics and systems
|
||||
- `architecture-decision-record.md` -- for technical decisions
|
||||
- `architecture-traceability.md` -- maps GDD requirements to ADRs to story IDs
|
||||
(`/architecture-review` writes it to `docs/architecture/requirements-traceability.md`)
|
||||
- `architecture-traceability.md` -- sample layout for a GDD requirement to ADR to
|
||||
story index (`/architecture-review` writes its own index to
|
||||
`docs/architecture/requirements-traceability.md`)
|
||||
- `risk-register-entry.md` -- for new risks
|
||||
- `narrative-character-sheet.md` -- for new characters
|
||||
- `test-plan.md` -- for feature test plans
|
||||
@@ -247,13 +248,13 @@ If you already know what you need, jump directly to the relevant path:
|
||||
current docs from the web so agents suggest correct APIs
|
||||
3. **Validate the concept** — Run `/design-review design/gdd/game-concept.md`
|
||||
(or `design/game-brief.md`, if `/brainstorm` wrote the one-page brief)
|
||||
4. **Decompose into systems** — Run `/map-systems` to map all systems and dependencies
|
||||
5. **Design each system** — Run `/design-system [system-name]` (or `/map-systems next`)
|
||||
to write GDDs in dependency order
|
||||
6. **Prototype the mechanic** — Run `/prototype [core-mechanic]` (1–3 days — before writing GDDs)
|
||||
7. **Design each system** — Run `/design-system [system-name]` to write GDDs, informed by prototype findings
|
||||
8. **Plan the first sprint** — After architecture and `/vertical-slice`, run `/sprint-plan new`
|
||||
9. Start building
|
||||
4. **Prototype the mechanic** — Run `/prototype [core-mechanic]` (1–3 days) to
|
||||
test that the core idea is fun before you write GDDs
|
||||
5. **Decompose into systems** — Run `/map-systems` to map all systems and dependencies
|
||||
6. **Design each system** — Run `/design-system [system-name]` (or `/map-systems next`)
|
||||
to write GDDs in dependency order, informed by the prototype findings
|
||||
7. **Plan the first sprint** — After architecture and `/vertical-slice`, run `/sprint-plan new`
|
||||
8. Start building
|
||||
|
||||
### Path B: "I know what I want to build"
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# Run and Observe
|
||||
|
||||
Shared procedure for any skill that closes a story which changes something a
|
||||
player can see. Referenced from the point of use in `/dev-story` (Phase 6) and
|
||||
`/story-done` (Phase 3). Those skills keep the one load-bearing imperative
|
||||
inline — **a parse check is not a run, and a story nobody looked at does not
|
||||
close** — and cite this file for how to look.
|
||||
player can see. Used by `/dev-story` (Phase 6) and `/story-done` (Phase 3).
|
||||
**A parse check is not a run, and a story nobody looked at does not close.**
|
||||
This file explains how to look.
|
||||
|
||||
`.claude/docs/coding-standards.md` is the authority for *what* evidence a story
|
||||
needs. This file is the procedure for *producing* the visual half of it.
|
||||
|
||||
@@ -6,7 +6,7 @@ other doc does:
|
||||
1. **Which value should a skill recommend** for a given project or user?
|
||||
2. **When should a skill proactively suggest changing** a setting already set?
|
||||
|
||||
## Boundary with its siblings — do not duplicate their content here
|
||||
## Boundary with its siblings
|
||||
|
||||
| Doc | Answers | Nature |
|
||||
|---|---|---|
|
||||
@@ -15,8 +15,8 @@ other doc does:
|
||||
| **`settings-guidance.md`** (this file) | Which value to *recommend*, and *when* | Prescriptive |
|
||||
|
||||
Skills reference this doc **on demand**, only at a "recommend a setting" moment.
|
||||
It is deliberately **not** a CLAUDE.md import — advisory content must not ride in
|
||||
per-turn context (the same reason `context-management.md` was demoted).
|
||||
It is **not** a CLAUDE.md import — advisory content must not ride in per-turn
|
||||
context.
|
||||
|
||||
---
|
||||
|
||||
@@ -26,8 +26,7 @@ Almost every "what settings should I use?" question reduces to one choice:
|
||||
`modes.rigor` (`minimal` | `standard` | `full`, default `minimal`). It fronts six
|
||||
sub-knobs — `modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`,
|
||||
`modes.review_mode`, `team.size`. Recommend **rigor**, not the six; let the
|
||||
expansion do the rest. Full expansion table lives in `effects-map.md § modes.rigor`
|
||||
— do not restate it here.
|
||||
expansion do the rest. The full expansion table is in `effects-map.md § modes.rigor`.
|
||||
|
||||
`modes.automation` (`collaborative` | `guided` | `autonomous`) is a **separate
|
||||
axis** — how often skills stop to confirm — and is *not* fronted by rigor. Pick it
|
||||
@@ -73,8 +72,8 @@ rigor; want that?"). If the user has **no concept yet** (exploring), do not seed
|
||||
"No concept yet" means **no signal**, not a particular onboarding path. A rough
|
||||
one-line hint is still a description: if it trips the signals above, seed from the
|
||||
signal. Only fall back to `minimal`-for-exploring when the user has given you
|
||||
nothing to map. (`/start` Phase 3d states the same rule for its Path A/B branch —
|
||||
the two must agree, since both drive the identical recommendation.)
|
||||
nothing to map. (`/start` Phase 3d states the same rule for its Path A/B branch;
|
||||
both drive the same recommendation.)
|
||||
|
||||
---
|
||||
|
||||
@@ -106,7 +105,7 @@ state is needed — but never emit the same suggestion twice in one session.
|
||||
| `/gate-check` | on PASS into a new stage | § 4 (raise trigger) |
|
||||
| `/settings` | view output — further reading | § 2 (choosing a value) |
|
||||
|
||||
Each skill carries a **one-line pointer** to this doc, not a copy of its tables.
|
||||
These skills each carry a **one-line pointer** to this doc.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -98,19 +98,34 @@ available on native Windows, which is CCGS's primary platform.
|
||||
### One setting CCGS does ship
|
||||
|
||||
`permissions.defaultMode` is set to `default` in `.claude/settings.json`, on
|
||||
purpose. It makes Claude Code ask before acting, which is what every approval
|
||||
gate in this framework depends on. Project settings outrank personal ones, so
|
||||
this holds even if your own config sets `acceptEdits` or `auto` — otherwise
|
||||
CCGS's collaboration protocol would be silently switched off for you and the
|
||||
agents would write files you never approved.
|
||||
purpose. A terminal session started **at the project root** then starts in
|
||||
Claude Code's ask-first mode, so file edits wait for your approval even if your
|
||||
own config sets `acceptEdits` or `auto`.
|
||||
|
||||
If you genuinely want it off, override it in `.claude/settings.local.json`,
|
||||
which takes precedence. Understand what you are turning off first.
|
||||
It sets the mode a session starts in. It is a backstop, not a guarantee, and
|
||||
these routes go around it:
|
||||
|
||||
**The VS Code extension does not read it.** The extension never reads a
|
||||
project's `.claude/settings.json` for the permission mode a conversation starts
|
||||
in. To get the same behaviour there, set `claudeCode.initialPermissionMode` to
|
||||
`default` in your VS Code user settings.
|
||||
- **Starting in a subfolder** such as `design/` or the code root (`src/`,
|
||||
`Assets/` or `Source/`, depending on the engine). Claude Code loads
|
||||
`.claude/settings.json` only from the folder it starts in, so that session has
|
||||
none of this project's hooks, deny rules or permission mode. Start at the root.
|
||||
- **Resuming a session.** A resumed session keeps the mode it ended in.
|
||||
- **Switching during a session**: Shift+Tab, answering "Yes, and switch to auto
|
||||
mode", or allowing all edits for the session.
|
||||
- **`claude --permission-mode auto`** on the command line.
|
||||
- **The VS Code extension**, which never reads a project's `.claude/settings.json`
|
||||
for the mode a conversation starts in. Set `claudeCode.initialPermissionMode`
|
||||
to `default` in your VS Code user settings to get the same behaviour.
|
||||
- **The Desktop app**, which remembers the mode you last picked for a folder and
|
||||
uses that instead.
|
||||
|
||||
In any mode that accepts edits without asking, the framework's "May I write?" is
|
||||
an instruction to the model, not a stop.
|
||||
|
||||
To start terminal sessions in a different mode, set `permissions.defaultMode` in
|
||||
`.claude/settings.local.json`, which takes precedence. Terminal sessions accept
|
||||
any mode from it except `auto` and `bypassPermissions`. Understand what you are
|
||||
turning off first.
|
||||
|
||||
## Recommended IDE
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
> - PlayStation Accessibility (Sony Guidelines) [Yes / No / Partial]
|
||||
> - Apple / Google Accessibility Guidelines [Yes / No / N/A — mobile only]
|
||||
> **Accessibility Consultant**: [Name and organization, or "None engaged"]
|
||||
> **Linked Documents**: `design/gdd/systems-index.md`, `docs/ux/interaction-pattern-library.md`
|
||||
> **Linked Documents**: `design/gdd/systems-index.md`, `design/ux/interaction-patterns.md`
|
||||
|
||||
> **Why this document exists**: Per-screen accessibility annotations belong in
|
||||
> UX specs. This document captures the project-wide accessibility commitments,
|
||||
|
||||
+7
-9
@@ -6,11 +6,10 @@
|
||||
|
||||
> **Who may move this to `Accepted`: the user, or `technical-director` on the
|
||||
> user's explicit confirmation. No other agent, and no skill on its own.**
|
||||
> Stated here because every consumer of this field enforces the *consequences*
|
||||
> of acceptance (stories referencing a `Proposed` ADR are set `Blocked`; epics
|
||||
> require `Accepted`), so something has to say who may produce it. `technical-director` is the role `coordination-rules.md`
|
||||
> already escalates technical conflicts to, and an ADR is exactly that decision
|
||||
> made durable.
|
||||
> Why this is stated here: stories referencing a `Proposed` ADR are set `Blocked`,
|
||||
> and epics require `Accepted`, so the field needs a named owner.
|
||||
> `technical-director` is the role `coordination-rules.md` already escalates
|
||||
> technical conflicts to, and an ADR is that decision made durable.
|
||||
>
|
||||
> This does **not** relax the existing rule that `Status: Accepted` is never set
|
||||
> without explicit user confirmation — it narrows *which agent* may set it once
|
||||
@@ -59,10 +58,9 @@ chosen approach.]
|
||||
> `/architecture-decision`, `/story-readiness`, `/propagate-design-change` and
|
||||
> `gate-pre-production.md`; a missing row counts as critical. At `standard`,
|
||||
> `/create-stories` **stops** for a missing critical ADR and only **warns** for a
|
||||
> non-critical one, so this row decides whether a run halts. Earlier revisions of
|
||||
> this template recorded no layer at all, leaving those sites to infer one from
|
||||
> the referencing epic — which gives the wrong answer whenever a Foundation-layer
|
||||
> ADR is referenced by a Core-layer epic, the common case.
|
||||
> non-critical one, so this row decides whether a run halts. Do not infer the
|
||||
> layer from the referencing epic: a Foundation-layer ADR is commonly referenced
|
||||
> by a Core-layer epic, which would give the wrong answer.
|
||||
>
|
||||
> The vocabulary is the same `Foundation / Core / Feature / Presentation` that
|
||||
> epics and stories already carry — do not invent a fifth value, and do not
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
> **Status**: Draft | In Review | Approved
|
||||
> **Author**: [game-designer / systems-designer]
|
||||
> **Last Updated**: [Date]
|
||||
> **Links To**: `design/gdd/game-concept.md`
|
||||
> **Links To**: `design/gdd/game-concept.md` (or `design/game-brief.md`)
|
||||
> **Relevant GDDs**: [e.g., `design/gdd/combat.md`, `design/gdd/progression.md`]
|
||||
|
||||
---
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
> **Related Documents**:
|
||||
> - `design/art/art-bible.md` — visual standards (colors, typography, iconography)
|
||||
> - `design/accessibility-requirements.md` — accessibility commitments per feature
|
||||
> - `docs/ux/ux-spec-[screen].md` — individual screen specs that reference patterns
|
||||
> - `design/ux/[screen].md` — individual screen specs that reference patterns
|
||||
>
|
||||
> **Template**: Interaction Pattern Library
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
> **Status**: Draft | In Review | Approved
|
||||
> **Author**: [game-designer / creative-director]
|
||||
> **Last Updated**: [Date]
|
||||
> **Links To**: `design/gdd/game-concept.md`, `design/gdd/game-pillars.md`
|
||||
> **Links To**: `design/gdd/game-concept.md` (or `design/game-brief.md`), `design/gdd/game-pillars.md`
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
> **Date**: [YYYY-MM-DD]
|
||||
> **Prototype Path**: [HTML / Engine / Paper]
|
||||
> **Concept File**: design/gdd/game-concept.md (if exists)
|
||||
> **Concept File**: design/gdd/game-concept.md, or design/game-brief.md (if either exists)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+7
-9
@@ -1,7 +1,7 @@
|
||||
# Active Session State — [project or branch]
|
||||
|
||||
<!--
|
||||
THE CONTRACT. Read this before editing the file or any hook that consumes it.
|
||||
HOW THIS FILE WORKS. Read this before editing it.
|
||||
|
||||
This file has TWO regions and they are not interchangeable:
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
and for a returning agent that wants detail. No hook ever injects it, so
|
||||
it may grow — but see Rotation below.
|
||||
|
||||
Why the split exists: before it, `active.md` was one append-only file doing
|
||||
both jobs. It reached 712 lines / 44 KB, and each consumer invented its own
|
||||
slice of it — the status line parsed for a STATUS block nothing wrote,
|
||||
pre-compact injected `head -100` (12.7 KB), and session-start previewed
|
||||
`tail -20`, the opposite end. They disagreed because there was no contract to
|
||||
agree on. Now every consumer reads the named region.
|
||||
Why the split exists: one append-only file doing both jobs grows without
|
||||
bound, and every consumer then reads a different slice of it: the top, the
|
||||
bottom, or a block nothing writes. They disagree because there is no contract
|
||||
to agree on. With the named regions, every consumer reads the same part.
|
||||
|
||||
ROTATION. When the narrative below grows past ~200 lines, move it to
|
||||
`production/session-logs/` and start it fresh:
|
||||
@@ -71,6 +69,6 @@ or agent picking this up cold.]
|
||||
long the narrative gets.
|
||||
|
||||
Write it so a cold reader can resume without reading anything else. "Current
|
||||
task: fixing the thing" is useless; "Current task: wiring modes.rigor into
|
||||
/gate-check section 6.4" is not.
|
||||
task: fixing the thing" is useless; "Current task: adding wall-jump to
|
||||
player_movement.gd" is not.
|
||||
-->
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
> **Status**: [Draft / Under Review / Approved]
|
||||
> **Created**: [Date]
|
||||
> **Last Updated**: [Date]
|
||||
> **Source Concept**: design/gdd/game-concept.md
|
||||
> **Source Concept**: design/gdd/game-concept.md (or design/game-brief.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@
|
||||
> **Platform Target**: [PC | Console | Mobile | All — list all that this spec covers]
|
||||
> **Related GDDs**: [Links to the GDD sections that generated this UI requirement — e.g., `design/gdd/inventory.md § UI Requirements`]
|
||||
> **Related ADRs**: [Any architectural decisions that constrain this screen — e.g., `ADR-0012: UI Framework Selection`]
|
||||
> **Related UX Specs**: [Sibling and parent screens — e.g., `ux-spec-pause-menu.md`, `ux-spec-settings.md`]
|
||||
> **Related UX Specs**: [Sibling and parent screens — e.g., `pause-menu.md`, `settings.md`]
|
||||
> **Accessibility Tier**: Basic | Standard | Comprehensive | Exemplary
|
||||
> **Template**: UX Spec
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
> **Date**: [YYYY-MM-DD]
|
||||
> **Slice Duration**: [N days]
|
||||
> **Target Scope**: 3–5 minutes of polished, continuous gameplay
|
||||
> **Source GDD**: design/gdd/game-concept.md
|
||||
> **Source GDD**: design/gdd/game-concept.md (or design/game-brief.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -92,11 +92,10 @@ phases:
|
||||
name: "Engine Setup"
|
||||
command: /setup-engine
|
||||
required: true
|
||||
# v1.1: engine.name in project.yaml is the primary source; technical-
|
||||
# preferences.md is the legacy fallback. Checking only the legacy file
|
||||
# made a correctly-configured project fail this REQUIRED gate.
|
||||
# engine.name in project.yaml is the primary source; technical-
|
||||
# preferences.md is the legacy fallback. Either one completes the step.
|
||||
# /setup-engine writes the value quoted (`name: "Godot"`), so the quote
|
||||
# is optional; without it only the legacy alternative ever matched.
|
||||
# is optional in the first alternative.
|
||||
# Single-quoted so the `"` needs no escape — artifact-check.sh strips
|
||||
# the outer quotes and does not unescape.
|
||||
artifact:
|
||||
@@ -104,9 +103,7 @@ phases:
|
||||
- glob: "project.yaml"
|
||||
pattern: 'name:[[:space:]]*"?(Godot|Unity|Unreal)'
|
||||
# technical-preferences.md writes "- **Engine**: Godot 4.6", so the
|
||||
# pattern must clear the bold markers. The previous "Engine: [^[]"
|
||||
# required a literal "Engine: " and therefore never matched any
|
||||
# file /setup-engine produces. The [^[] guard rejects the
|
||||
# pattern must clear the bold markers. The [^[] guard rejects the
|
||||
# "[TO BE CONFIGURED]" placeholder.
|
||||
- glob: ".claude/docs/technical-preferences.md"
|
||||
pattern: '\*\*Engine\*\*: [^[]'
|
||||
@@ -219,11 +216,6 @@ phases:
|
||||
|
||||
- id: accessibility-doc
|
||||
name: "Accessibility Requirements"
|
||||
# This step had no `command:` at all -- the only artifact entry in the
|
||||
# catalog that named no producer. It was REQUIRED, so the Technical
|
||||
# Setup -> Pre-Production gate could never pass, and the remediation
|
||||
# every skill printed ("run /ux-design") wrote into design/ux/ where
|
||||
# this glob does not look. /ux-design now has an `accessibility` mode.
|
||||
command: /ux-design
|
||||
required: true
|
||||
artifact:
|
||||
@@ -289,10 +281,10 @@ phases:
|
||||
command: /prototype
|
||||
required: false
|
||||
artifact:
|
||||
# /prototype writes prototypes/[name]-concept/REPORT.md -- it has never
|
||||
# written a README. The `-concept` suffix is load-bearing: /vertical-slice
|
||||
# writes the same REPORT.md basename under `-vertical-slice`, so a bare
|
||||
# `prototypes/*/REPORT.md` here would let either step satisfy the other.
|
||||
# /prototype writes prototypes/[name]-concept/REPORT.md. The `-concept`
|
||||
# suffix matters: /vertical-slice writes the same REPORT.md basename
|
||||
# under `-vertical-slice`, so a bare `prototypes/*/REPORT.md` here
|
||||
# would let either step satisfy the other.
|
||||
glob: "prototypes/*-concept/REPORT.md"
|
||||
min_count: 1
|
||||
description: "Build a throwaway prototype to validate the core mechanic is fun before committing to full production. Recommended for first-time mechanics or high-risk design decisions. Solo devs with proven concepts may skip."
|
||||
@@ -331,9 +323,9 @@ phases:
|
||||
command: /vertical-slice
|
||||
required: false
|
||||
artifact:
|
||||
# Must stay scoped to `-vertical-slice`: the untethered form matched
|
||||
# /prototype's concept report, so running only /prototype silently
|
||||
# marked the vertical slice complete and skipped the validation the
|
||||
# Scoped to `-vertical-slice`: an unscoped form would match
|
||||
# /prototype's concept report, so running only /prototype would mark
|
||||
# the vertical slice complete and skip the validation the
|
||||
# Pre-Production → Production gate exists to require.
|
||||
glob: "prototypes/*-vertical-slice/REPORT.md"
|
||||
min_count: 1
|
||||
@@ -454,8 +446,6 @@ phases:
|
||||
required: true
|
||||
artifact:
|
||||
# /playtest-report writes production/qa/playtests/, not production/playtests/.
|
||||
# The old glob matched nothing on every project, so this REQUIRED step
|
||||
# read as 0/3 forever no matter how many playtests were actually run.
|
||||
glob: "production/qa/playtests/*.md"
|
||||
min_count: 3
|
||||
description: "Cover: new player experience, mid-game systems, difficulty curve"
|
||||
|
||||
@@ -9,10 +9,10 @@ this document instead of embedding the tier tables inline.
|
||||
sections `modes.workflow` and `workflow_overrides` are the source of
|
||||
truth for behavior. This document is the implementation pattern.
|
||||
|
||||
> **Do not read `effects-map.md` during a skill run.** It is ~2,150 lines
|
||||
> (~110 KB) — about five times the size of everything CLAUDE.md loads per
|
||||
> session combined — and it is a reference for *authoring and changing the
|
||||
> spec*, not a runtime input. **This document is self-sufficient** for resolving
|
||||
> **Do not read `effects-map.md` during a skill run.** It is many times the
|
||||
> size of everything CLAUDE.md loads per session combined — and it is a
|
||||
> reference for *authoring and changing the spec*, not a runtime input.
|
||||
> **This document is self-sufficient** for resolving
|
||||
> the tier and applying it: the resolution chain, the three tiers, the required
|
||||
> sections, and the override rules are all here. If you hit a case this document
|
||||
> genuinely does not cover, read only the one `effects-map.md` section for the
|
||||
@@ -50,8 +50,8 @@ its fallback will ignore `rigor: minimal` and `rigor: full` entirely.
|
||||
|
||||
### What `<system>` is — one derivation, everywhere
|
||||
|
||||
**`<system>` is the GDD filename stem**: `design/gdd/hammer-heat-system.md` →
|
||||
`hammer-heat-system`. That is the key to write under
|
||||
**`<system>` is the GDD filename stem**: `design/gdd/forge-heat-system.md` →
|
||||
`forge-heat-system`. That is the key to write under
|
||||
`workflow_overrides.system_overrides`, and every skill must derive it the same
|
||||
way.
|
||||
|
||||
@@ -61,18 +61,18 @@ from it in preference to the stem.
|
||||
|
||||
> **Why this is stated here rather than per skill.** Reading *"the `[system]`
|
||||
> segment of its `TR-[system]-NNN` ID (else its `design/gdd/` path)"* — TR-ID
|
||||
> **first** — is the wrong order. A system whose GDD is `hammer-heat-system.md` and
|
||||
> whose requirements are `TR-heat-001` then had **two different override keys
|
||||
> depending on whether a registry entry existed**, and the documented remedy for
|
||||
> a missing GDD section — "set
|
||||
> `workflow_overrides.system_overrides.hammer-heat-system: full`" — was looked up
|
||||
> under `heat`, found nothing, and continued at the project tier **silently**.
|
||||
> The escape hatch existed and could not be reached.
|
||||
> **first** — is the wrong order. A system whose GDD is `forge-heat-system.md` and
|
||||
> whose requirements are `TR-forge-001` would then have **two different override
|
||||
> keys depending on whether a registry entry existed**, and the documented remedy
|
||||
> for a missing GDD section — "set
|
||||
> `workflow_overrides.system_overrides.forge-heat-system: full`" — would be looked
|
||||
> up under `forge`, find nothing, and continue at the project tier **silently**.
|
||||
> The escape hatch would exist and could not be reached.
|
||||
|
||||
**A key that matches no system is an error, not a no-op.** If
|
||||
`workflow_overrides.system_overrides` contains a key that resolves to no GDD stem
|
||||
in `design/gdd/`, say so — naming the unmatched key and the stems available.
|
||||
Silently ignoring it is how the above went unnoticed.
|
||||
Silently ignoring it would leave an override that does nothing, unnoticed.
|
||||
|
||||
> **Checked where GDDs are expected to already exist — not by the skill that
|
||||
> writes them.** `/gate-check` is the single implementing site (see
|
||||
|
||||
@@ -98,15 +98,11 @@ echo ""
|
||||
echo "## Files Modified (git working tree)"
|
||||
|
||||
# BOUNDED. These three lists must never be emitted in full, one line per
|
||||
# file, with no cap. (They were bounded believing this output goes into the
|
||||
# compacting context; it reaches the debug log, where an unbounded dump still
|
||||
# costs time and log size.) The checkpoint above was redesigned to be by-reference for exactly
|
||||
# that reason (see the note at the top of this file); the lists below were left
|
||||
# unbounded, so the hook still dumped whatever the working tree happened to
|
||||
# contain at the moment context was scarcest. Measured on a tree with ~5k
|
||||
# untracked files: 181,125 bytes, roughly 45,000 tokens, of which ~4,984 lines
|
||||
# were this section. A fresh asset import or un-gitignored build output is
|
||||
# enough to trigger it.
|
||||
# file, with no cap. This output reaches the debug log, where an unbounded dump
|
||||
# still costs time and log size: a tree with thousands of untracked files (a
|
||||
# fresh asset import, or build output that is not gitignored) would otherwise
|
||||
# print one line per file on every compaction. The checkpoint above is
|
||||
# by-reference for the same reason (see the note at the top of this file).
|
||||
#
|
||||
# A count plus a sample is what this section is actually for -- orienting the
|
||||
# agent after compaction -- and the full list is one `git status` away.
|
||||
@@ -141,8 +137,8 @@ WIP_FOUND=false
|
||||
# BOUNDED and BATCHED. One `grep -n` per design doc, printing every matching
|
||||
# line from every file, fails twice over -- the same two ways as above:
|
||||
# unbounded OUTPUT into a compacting context, and unbounded
|
||||
# COST -- ~85ms per file, crossing this hook's 10s budget at roughly 90 GDDs.
|
||||
# Measured: 220 docs 18262ms, 420 docs killed at the timeout.
|
||||
# COST -- one process spawn per file, which grows past this hook's 10s budget
|
||||
# on a project with a large set of GDDs.
|
||||
#
|
||||
# `xargs -0` bounds the spawn count by ARG_MAX rather than by file count, and
|
||||
# the NUL delimiter keeps it portable: `-d` is GNU-only, BSD xargs rejects it,
|
||||
|
||||
@@ -51,16 +51,12 @@ MODIFIED_FILES=$(git diff --name-only 2>/dev/null)
|
||||
# It is only valid to delete active.md manually or when explicitly superseded.
|
||||
# APPEND ONLY WHEN THE CONTENT CHANGED.
|
||||
#
|
||||
# The Stop hook fires once per RESPONSE, not once per session. Both blocks below
|
||||
# appended unconditionally, so a long session wrote the whole of active.md on
|
||||
# every turn. Measured on this repository before this guard:
|
||||
#
|
||||
# 3,187 Stop firings, 665 archived copies, session-log.md at 17.5 MB
|
||||
#
|
||||
# and session-logs/ is gitignored, so nothing ever surfaced it. The growth
|
||||
# compounds: the larger active.md gets, the more each firing appends -- and
|
||||
# rotate-session-state.sh caps active.md precisely because it grows, while the
|
||||
# log accumulating full copies of it had no cap at all.
|
||||
# The Stop hook fires once per RESPONSE, not once per session. Appending
|
||||
# unconditionally in the two blocks below would write the whole of active.md on
|
||||
# every turn of a long session, and session-logs/ is gitignored, so nothing
|
||||
# would surface the growth. It compounds: the larger active.md gets, the more
|
||||
# each firing appends -- and rotate-session-state.sh caps active.md precisely
|
||||
# because it grows, so a log accumulating full copies of it needs a guard too.
|
||||
#
|
||||
# Content hash, not mtime: an editor that rewrites a file unchanged would
|
||||
# otherwise re-archive it. Same reasoning and same tool as review-receipts.sh --
|
||||
|
||||
@@ -38,7 +38,7 @@ INPUT=$(cat)
|
||||
|
||||
# Most Bash and PowerShell calls do not mention git at all. Leave before any
|
||||
# parsing: this hook runs on every one of them, and the parse is most of its
|
||||
# cost (~350 ms a call measured; the early exit is the shell start-up alone).
|
||||
# cost (the early exit is the shell start-up alone).
|
||||
# Tested only after the "tool_input" key: matching the whole payload also
|
||||
# tests cwd and transcript_path, so a project path containing "GitHub" or
|
||||
# "digital" never took this exit and paid the full parse on every call.
|
||||
@@ -253,6 +253,15 @@ fi
|
||||
# `cd assets && git commit -m x data/item.json` named nothing here and the file
|
||||
# went unchecked. There, and whenever a pathspec names no tracked file, every
|
||||
# modified tracked file is checked (`:/`), and the index with it.
|
||||
#
|
||||
# A `git add` (or `git stage`) earlier in the same command stages its files
|
||||
# after this hook has read the index, so `git add -A && git commit` committed a
|
||||
# new broken data file unchecked. Each add before a commit is read too, and
|
||||
# what it will stage -- modified tracked files, and untracked ones unless it is
|
||||
# -u (ignored ones only with -f) -- is checked as working copies. A dry run
|
||||
# (-n) stages nothing, an add after the commit is for a later one, a
|
||||
# path-limited commit still records only its own paths, and after a cd or -C
|
||||
# an add's pathspecs are read as the whole tree, as above.
|
||||
if [ -n "$_VC_PY" ]; then
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
_VC_CWD=$(echo "$INPUT" | jq -r '.cwd // empty')
|
||||
@@ -280,9 +289,37 @@ def words(line):
|
||||
def git(*args):
|
||||
return subprocess.run(["git", "-c", "core.quotePath=false"] + list(args),
|
||||
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
|
||||
def add(w, k): # git add/stage from w[k] -> pathspecs, takes untracked, -f, -n, next k
|
||||
specs, rest, alln, upd, force, dry = [], False, False, False, False, False
|
||||
while k < len(w):
|
||||
a = w[k]
|
||||
if a.isdigit() and k + 1 < len(w) and w[k + 1][:1] in "<>":
|
||||
k += 1
|
||||
continue
|
||||
if REDIR.match(a):
|
||||
k += 2
|
||||
continue
|
||||
if a and set(a) <= OPS:
|
||||
break
|
||||
if rest or not a.startswith("-") or a == "-":
|
||||
specs.append(a)
|
||||
elif a == "--":
|
||||
rest = True
|
||||
elif a.startswith("--"):
|
||||
alln = alln or a in ("--all", "--no-ignore-removal")
|
||||
upd, force, dry = upd or a == "--update", force or a == "--force", dry or a == "--dry-run"
|
||||
if a.startswith("--pathspec-from-file"):
|
||||
specs.append(":/") # paths only git reads
|
||||
else: # no short option of git add takes a value: -Av is -A -v
|
||||
alln, upd, force, dry = alln or "A" in a, upd or "u" in a, force or "f" in a, dry or "n" in a
|
||||
k += 1
|
||||
if not specs and (alln or upd):
|
||||
specs = [":/"] # -A and -u with no pathspec take the whole tree
|
||||
return specs, alln or not upd, force, dry, k
|
||||
text = sys.stdin.buffer.read().decode("utf-8", "replace")
|
||||
away = sys.argv[1] == "1" or re.search(r"(^|[^\w.-])(cd|pushd|popd)(\s|[;&|)]|$)", text, re.M) is not None
|
||||
specs, commits, only = [], 0, True
|
||||
adds, pending = [], [] # what each git add stages: before a commit, not yet
|
||||
for line in text.splitlines():
|
||||
w, i = words(line), 0
|
||||
while i < len(w):
|
||||
@@ -293,10 +330,16 @@ for line in text.splitlines():
|
||||
while j < len(w) and w[j].startswith("-"):
|
||||
away = away or w[j] in ("-C", "--git-dir", "--work-tree") or w[j].startswith(("--git-dir=", "--work-tree="))
|
||||
j += 2 if w[j] in GIT_ARG else 1
|
||||
if j < len(w) and w[j] in ("add", "stage"):
|
||||
s, new, force, dry, i = add(w, j + 1)
|
||||
if not dry:
|
||||
pending.append((s, new, force))
|
||||
continue
|
||||
if j >= len(w) or w[j] != "commit":
|
||||
i = j
|
||||
continue
|
||||
commits += 1
|
||||
adds, pending = adds + pending, []
|
||||
k, rest, mine, index = j + 1, False, [], False
|
||||
while k < len(w):
|
||||
a = w[k]
|
||||
@@ -344,7 +387,13 @@ out = git("diff", "--name-only", "HEAD", "--", *specs) if only else None
|
||||
if out is None or out.returncode != 0: # not path-limited, or no HEAD yet
|
||||
only = False
|
||||
out = git("diff", "--name-only", "--", *specs) if specs else None
|
||||
sys.stdout.buffer.write((b"CCGS-ONLY\n" if only else b"CCGS-INDEX\n") + (out.stdout if out else b""))
|
||||
more = b""
|
||||
for s, new, force in ([] if only else adds):
|
||||
s = [":/"] if away else s
|
||||
more += git("diff", "--name-only", "--", *s).stdout
|
||||
if new:
|
||||
more += git("ls-files", "--others", "--full-name", *([] if force else ["--exclude-standard"]), "--", *s).stdout
|
||||
sys.stdout.buffer.write((b"CCGS-ONLY\n" if only else b"CCGS-INDEX\n") + (out.stdout if out else b"") + more)
|
||||
' "$_VC_AWAY" 2>/dev/null)
|
||||
case "$_VC_TOK" in CCGS-ONLY*) INDEX_FILES="" ;; esac
|
||||
WT_FILES=$(printf '%s\n%s' "$WT_FILES" "$(printf '%s\n' "$_VC_TOK" | tail -n +2)")
|
||||
@@ -355,8 +404,24 @@ else
|
||||
for _p in $(printf '%s' "$_AFTER" | LC_ALL=C grep -oE '(assets|Assets|Content)/[^[:space:]"'"'"';|&)]*'); do
|
||||
WT_FILES=$(printf '%s\n%s' "$WT_FILES" "$($_GIT diff --name-only -- "$_p" 2>/dev/null)")
|
||||
done
|
||||
# No tokeniser to read a `git add`'s paths: take every change and new file.
|
||||
if git_segment add "$COMMAND" >/dev/null || git_segment stage "$COMMAND" >/dev/null; then
|
||||
WT_FILES=$(printf '%s\n%s\n%s' "$WT_FILES" "$($_GIT diff --name-only 2>/dev/null)" \
|
||||
"$($_GIT ls-files --others --exclude-standard --full-name 2>/dev/null)")
|
||||
fi
|
||||
fi
|
||||
WT_FILES=$(printf '%s\n' "$WT_FILES" | grep -v '^$' | sort -u)
|
||||
# A project in a subfolder of a larger repository (game/ in a monorepo): git
|
||||
# names every path above from the repository's top level, and every check below
|
||||
# matches from the PROJECT root (^assets/, ^design/gdd/, the code root) and
|
||||
# reads files relative to it. Unconverted, nothing matched and the commit went
|
||||
# through unchecked. Keep this project's paths with the prefix dropped; files
|
||||
# outside the project are not ours to check. "" at the top level.
|
||||
_VC_PREFIX=$(git rev-parse --show-prefix 2>/dev/null)
|
||||
if [ -n "$_VC_PREFIX" ]; then
|
||||
INDEX_FILES=$(printf '%s\n' "$INDEX_FILES" | LC_ALL=C awk -v p="$_VC_PREFIX" 'index($0, p) == 1 { print substr($0, length(p) + 1) }')
|
||||
WT_FILES=$(printf '%s\n' "$WT_FILES" | LC_ALL=C awk -v p="$_VC_PREFIX" 'index($0, p) == 1 { print substr($0, length(p) + 1) }')
|
||||
fi
|
||||
STAGED=$(printf '%s\n%s\n' "$INDEX_FILES" "$WT_FILES" | grep -v '^$' | sort -u)
|
||||
if [ -z "$STAGED" ]; then
|
||||
exit 0
|
||||
@@ -390,14 +455,11 @@ trap '[ -n "$TMP_DESIGN" ] && rm -f "$TMP_DESIGN"' EXIT
|
||||
# it appends to $WARNINGS and the hook still exits 0. This block is the only one
|
||||
# that can exit 2, and exit 2 is the entire reason the hook is registered.
|
||||
#
|
||||
# Running it THIRD, after the design-section scan, and validating one file
|
||||
# per `python -m json.tool` invocation -- one interpreter spawn each, ~110ms on
|
||||
# Windows -- gets the hook killed by its 15s timeout on a large commit before
|
||||
# it reaches the corrupt file, so whether a bad file is caught depends on where
|
||||
# its NAME SORTED. Measured with 201 staged files and one corrupt:
|
||||
#
|
||||
# corrupt sorts FIRST -> 730ms, rc=2, BLOCKED emitted
|
||||
# corrupt sorts LAST -> 15217ms, rc=124, nothing emitted, commit not blocked
|
||||
# Running it after the design-section scan, and validating one file per
|
||||
# `python -m json.tool` invocation -- one interpreter spawn each -- would get the
|
||||
# hook killed by its 15s timeout on a large commit before it reaches a corrupt
|
||||
# file, so whether a bad file is caught would depend on where its NAME SORTS: a
|
||||
# corrupt file sorting first is blocked, one sorting last lets the commit through.
|
||||
#
|
||||
# Two independent fixes, because either alone is a mitigation rather than a
|
||||
# guarantee:
|
||||
@@ -432,17 +494,19 @@ if [ -n "$DATA_FILES" ]; then
|
||||
JSON_OUT=$(LC_ALL=C awk -v OFS='\t' 'NR == FNR { if ($0 != "") wt[$0] = 1; next }
|
||||
$0 != "" { print (($0 in wt) ? "W" : "I"), $0 }' \
|
||||
<(printf '%s\n' "$WT_FILES") <(printf '%s\n' "$DATA_FILES") \
|
||||
| "$PYTHON_CMD" -c '
|
||||
| CCGS_VC_PREFIX="$_VC_PREFIX" "$PYTHON_CMD" -c '
|
||||
import json, sys, os, subprocess
|
||||
bad = []
|
||||
bad, lfs_unread = [], []
|
||||
# Bytes in, decoded as UTF-8: a Windows console code page would mangle a
|
||||
# non-ASCII path before it reached os.path or git.
|
||||
items = [l.split("\t", 1) for l in sys.stdin.buffer.read().decode("utf-8").splitlines() if "\t" in l]
|
||||
staged = [p for mode, p in items if mode == "I"]
|
||||
# Paths are project-relative; the index names them from the repository top.
|
||||
prefix = os.environ.get("CCGS_VC_PREFIX", "")
|
||||
blobs = {}
|
||||
if staged:
|
||||
out = subprocess.run(["git", "cat-file", "--batch"], stdout=subprocess.PIPE,
|
||||
input="".join(":" + p + "\n" for p in staged).encode("utf-8")).stdout
|
||||
input="".join(":" + prefix + p + "\n" for p in staged).encode("utf-8")).stdout
|
||||
pos = 0
|
||||
for p in staged:
|
||||
end = out.index(b"\n", pos)
|
||||
@@ -458,6 +522,16 @@ for mode, p in items:
|
||||
if p not in blobs:
|
||||
continue # removed from the index: nothing of it is committed
|
||||
data = blobs[p]
|
||||
if data.startswith(b"version https://git-lfs.github.com/spec/"):
|
||||
# A Git LFS pointer: git add stored the file in LFS and staged
|
||||
# this stub, which is never JSON. The working copy is the file
|
||||
# it stored. With no working copy there is nothing to read --
|
||||
# say so, do not block a valid file or pass it in silence.
|
||||
if not os.path.isfile(p):
|
||||
lfs_unread.append(p)
|
||||
continue
|
||||
with open(p, "rb") as fh:
|
||||
data = fh.read()
|
||||
else:
|
||||
if not os.path.isfile(p):
|
||||
continue
|
||||
@@ -470,13 +544,20 @@ for mode, p in items:
|
||||
# putting a CR inside every path but the last. Invisible in a terminal and in
|
||||
# a line-by-line diff -- only a byte comparison against the pre-batch
|
||||
# implementation surfaced it. get_yaml_key writes bytes for the same reason.
|
||||
sys.stdout.buffer.write(("CCGS-JSON-CHECKED\n" + "\n".join(bad)).encode("utf-8"))
|
||||
# One line per file: "B<tab>path" not valid JSON, "S<tab>path" an LFS pointer
|
||||
# with no working copy to read.
|
||||
sys.stdout.buffer.write(("CCGS-JSON-CHECKED\n" + "".join("B\t" + p + "\n" for p in bad)
|
||||
+ "".join("S\t" + p + "\n" for p in lfs_unread)).encode("utf-8"))
|
||||
' 2>/dev/null)
|
||||
if [ "$(printf '%s\n' "$JSON_OUT" | head -1)" != "CCGS-JSON-CHECKED" ]; then
|
||||
echo "BLOCKED: $(printf '%s\n' "$DATA_FILES" | grep -c .) staged data file(s) could not be validated -- the JSON check did not run under '$PYTHON_CMD'. Check that it is a working Python 3 and commit again." >&2
|
||||
exit 2
|
||||
fi
|
||||
BAD_JSON=$(printf '%s\n' "$JSON_OUT" | tail -n +2)
|
||||
BAD_JSON=$(printf '%s\n' "$JSON_OUT" | tail -n +2 | LC_ALL=C awk -F'\t' '$1 == "B" { print $2 }')
|
||||
LFS_UNREAD=$(printf '%s\n' "$JSON_OUT" | tail -n +2 | LC_ALL=C awk -F'\t' '$1 == "S" { print $2 }')
|
||||
if [ -n "$LFS_UNREAD" ]; then
|
||||
WARNINGS="$WARNINGS\nSKIPPED: $(printf '%s\n' "$LFS_UNREAD" | grep -c .) staged data file(s) are Git LFS pointers with no working copy, so the JSON check did NOT read them: $(printf '%s' "$LFS_UNREAD" | tr '\n' ' ')"
|
||||
fi
|
||||
if [ -n "$BAD_JSON" ]; then
|
||||
# Every offender at once. The per-file loop reported only the first
|
||||
# and exited, so a commit with several bad files took several
|
||||
@@ -518,7 +599,12 @@ if [ -f .claude/hooks/yaml-helper.sh ]; then
|
||||
command -v resolve_setting >/dev/null 2>&1 && _VC_HELPER=1
|
||||
fi
|
||||
|
||||
DESIGN_FILES=$(echo "$STAGED" | grep -E '^design/gdd/')
|
||||
# design/gdd/ also holds governance and registry files that are not system
|
||||
# GDDs and have none of these sections, so they warned on every commit (#133).
|
||||
# Skip the names not_a_system_gdd() skips in gdd-structure-check.sh and
|
||||
# review-scope.sh; keep the three lists the same.
|
||||
DESIGN_FILES=$(echo "$STAGED" | grep -E '^design/gdd/' \
|
||||
| grep -vE '/(game-concept|systems-index|game-pillars|gdd-cross-review-[^/]*|gameplay-tags|fixture-swap-ledger|entity-registry|sound-bible)\.md$')
|
||||
if [ -n "$DESIGN_FILES" ]; then
|
||||
WORKFLOW="standard"
|
||||
if [ "$_VC_HELPER" = 1 ]; then
|
||||
@@ -545,11 +631,9 @@ if [ -n "$DESIGN_FILES" ]; then
|
||||
#
|
||||
# A nested shell loop -- for each staged design doc, `echo |
|
||||
# tr | while read` then one `grep -qi` per required section -- does not
|
||||
# scale. At
|
||||
# workflow=full that is 8 greps per file, and each is a process. 50
|
||||
# design docs measured 14644ms -- 97% of this hook's 15s budget, from
|
||||
# the ADVISORY half alone. 50 GDDs is an ordinary project, not a
|
||||
# stress case.
|
||||
# scale. At workflow=full that is 8 greps per file, and each is a
|
||||
# process, so an ordinary project of about 50 GDDs would use nearly all
|
||||
# of this hook's 15s budget on the ADVISORY half alone.
|
||||
#
|
||||
# Matching is unchanged on purpose: case-insensitive SUBSTRING anywhere
|
||||
# in the file, exactly what `grep -qi "$section"` did. It is looser than
|
||||
|
||||
@@ -39,7 +39,7 @@ INPUT=$(cat)
|
||||
|
||||
# Most Bash and PowerShell calls do not mention git at all. Leave before any
|
||||
# parsing: this hook runs on every one of them, and the parse is most of its
|
||||
# cost (~350 ms a call measured; the early exit is the shell start-up alone).
|
||||
# cost (the early exit is the shell start-up alone).
|
||||
# Tested only after the "tool_input" key: matching the whole payload also
|
||||
# tests cwd and transcript_path, so a project path containing "GitHub" or
|
||||
# "digital" never took this exit and paid the full parse on every call.
|
||||
|
||||
@@ -569,7 +569,11 @@ EOF
|
||||
# and must agree on YAML edge cases exactly, and a shared copy that drifted
|
||||
# would make two functions disagree about what a file says.
|
||||
validate_local_scope() {
|
||||
local file="${1:-project.local.yaml}"
|
||||
local file="${1:-}"
|
||||
# Default to the PROJECT ROOT's local file, not the working directory's: run
|
||||
# from src/, a bare `project.local.yaml` names a file that is not there, and
|
||||
# the check passes because it found nothing to check.
|
||||
if [ -z "$file" ]; then _yaml_helper_set_root; file="$_YH_ROOT/project.local.yaml"; fi
|
||||
[ -f "$file" ] || return 0
|
||||
if ! _yaml_helper_resolve_python; then return 0; fi
|
||||
local found key rc=0
|
||||
@@ -646,7 +650,10 @@ def walk(node, prefix):
|
||||
elif dotted.startswith(EXEMPT_PREFIX):
|
||||
continue
|
||||
else:
|
||||
print(dotted)
|
||||
# Bytes, not print(): on Windows print() writes CRLF, bash keeps
|
||||
# the CR, and every key but the last reached the notes line with
|
||||
# a carriage return on it. The other parsers here write this way.
|
||||
sys.stdout.buffer.write((dotted + '\n').encode('utf-8'))
|
||||
|
||||
walk(data, '')
|
||||
PYEOF
|
||||
@@ -682,7 +689,9 @@ EOF
|
||||
# would be self-defeating.
|
||||
session_state_enabled() {
|
||||
local f v
|
||||
for f in project.local.yaml project.yaml; do
|
||||
# The root, not the working directory (builtins only -- no added spawn).
|
||||
_yaml_helper_set_root
|
||||
for f in "$_YH_ROOT/project.local.yaml" "$_YH_ROOT/project.yaml"; do
|
||||
[ -f "$f" ] || continue
|
||||
v=$(awk '
|
||||
/^features:[[:space:]]*$/ { inf=1; next }
|
||||
@@ -792,8 +801,8 @@ data = parse(raw_lines)
|
||||
# default. Every enum check below passed on such a file, because a key that
|
||||
# cannot be read cannot hold an invalid value. That is rc=0 on a config that
|
||||
# configures nothing, byte-identical in outcome to a genuinely clean file.
|
||||
# Measured before this check: the same file with tabs instead of spaces
|
||||
# reported no errors while `modes.review_mode: BOGUS_VALUE` sat in it unread.
|
||||
# Without this check, the same file with tabs instead of spaces reports no
|
||||
# errors while `modes.review_mode: BOGUS_VALUE` sits in it unread.
|
||||
#
|
||||
# This is the validator's own version of the rule the skills are held to --
|
||||
# absence of evidence is not evidence of absence. It cannot report "no invalid
|
||||
@@ -944,12 +953,12 @@ EOF
|
||||
# Whole-config resolution.
|
||||
#
|
||||
# WHY THIS EXISTS
|
||||
# ~51 SKILL.md files each carried an English description of a deterministic
|
||||
# fallback chain ("1. If --review passed -> use that; 2. Else read
|
||||
# modes.review_mode from project.yaml; 3. Else production/review-mode.txt;
|
||||
# 4. Else lean"), re-interpreted by a model on every invocation at roughly
|
||||
# +1,360 tokens per skill. resolve_config computes the same answer once, in
|
||||
# ~150 tokens, deterministically -- and testably, which prose never was.
|
||||
# Every skill that reads a setting needs the same deterministic fallback chain
|
||||
# ("1. If --review passed -> use that; 2. Else read modes.review_mode from
|
||||
# project.yaml; 3. Else production/review-mode.txt; 4. Else lean"). Written out
|
||||
# in each SKILL.md, a model would re-interpret that prose on every invocation.
|
||||
# resolve_config computes the same answer once, deterministically -- and
|
||||
# testably, which prose never was.
|
||||
#
|
||||
# CONTRACT BOUNDARY
|
||||
# This layer resolves SOURCES. It does not own per-skill policy. Anything
|
||||
@@ -969,32 +978,31 @@ EOF
|
||||
# and this table. Leaving a terminal default here as well would shadow the
|
||||
# expansion and make `rigor` a no-op for anyone who had not also set the sub-knob.
|
||||
# modes.review_mode is fronted by rigor so `rigor: minimal` resolves
|
||||
# review_mode to `solo` (skipping the ~44k-token director/specialist gates),
|
||||
# `standard` yields `lean` and `full` yields `full`. team.size joined the fronted
|
||||
# set the same way: `full` yields `studio` (the whole roster) while
|
||||
# review_mode to `solo` (skipping the director and specialist gates),
|
||||
# `standard` yields `lean` and `full` yields `full`. team.size is fronted the
|
||||
# same way: `full` yields `studio` (the whole roster) while
|
||||
# `minimal`/`standard` yield `individual`. Both stay locally overridable (they
|
||||
# are personal-experience knobs, not on-disk artifacts): that source sits ABOVE
|
||||
# the expansion, so only the terminal fallback moved.
|
||||
# the expansion, so a local value wins over the rigor level.
|
||||
#
|
||||
# --- WHY modes.rigor DEFAULTS TO `minimal` -----------------------------------
|
||||
#
|
||||
# It defaulted to `standard`. Building the same project both ways showed the
|
||||
# heavier tier costing several times as much to reach working code without
|
||||
# producing a better result, and giving nothing back when a fresh developer
|
||||
# picked the project up. A default that costs more and does not repay is the
|
||||
# wrong default, and it was what every user who never opened /settings received.
|
||||
# The heavier tier costs more to reach working code without producing a better
|
||||
# result, and gives nothing back when a new contributor picks the project up. A
|
||||
# default that costs more and does not repay is the wrong default, and it is
|
||||
# what every user who never opens /settings would receive.
|
||||
#
|
||||
# Raising rigor stays one question in /start and one `/settings` call, and
|
||||
# Raising rigor is one question in /start and one `/settings` call, and
|
||||
# settings-guidance.md's upward triggers ("system-GDD count crosses ~9",
|
||||
# "gate-check PASS into Production while rigor is minimal") are written to fire
|
||||
# from exactly this starting state. The cost of under-running is one prompt.
|
||||
#
|
||||
# ORDER MATTERS: this default is only safe while /gate-check keeps its floors.
|
||||
# `rigor: minimal` expands to `workflow: minimal` + `qa.level: minimal`, which
|
||||
# together once left the Production->Polish gate with ZERO required artifacts --
|
||||
# a vacuous PASS. That is fixed (the smoke-report floor and the "nothing
|
||||
# required -> NOT ASSESSED, never PASS" rule). Do not move this default again
|
||||
# without re-checking that the gates below it still require something.
|
||||
# together would leave the Production->Polish gate with ZERO required artifacts
|
||||
# -- a vacuous PASS -- without the smoke-report floor and the "nothing required
|
||||
# -> NOT ASSESSED, never PASS" rule. Do not change this default without
|
||||
# re-checking that each /gate-check gate still requires something.
|
||||
_yaml_helper_defaults="\
|
||||
modes.automation::collaborative
|
||||
modes.rigor::minimal
|
||||
@@ -1002,12 +1010,11 @@ performance.enforce::warn"
|
||||
|
||||
# Rigor expansion — one asked-at-/start knob that supplies four.
|
||||
#
|
||||
# WHY: /start has never asked about workflow, docs.density, qa.level or
|
||||
# story_granularity, so in practice every project ran all four at their defaults.
|
||||
# Between them the latter three drive ONE behaviour each (prose verbosity, is-
|
||||
# evidence-required, story size) restated across 19 skills with 17 "we are
|
||||
# orthogonal" disclaimers. `rigor` makes the common case reachable in one
|
||||
# question while each knob stays individually settable.
|
||||
# WHY: /start does not ask about workflow, docs.density, qa.level or
|
||||
# story_granularity, so in practice a project runs all four at their defaults.
|
||||
# The latter three each drive one behaviour (prose verbosity, whether evidence
|
||||
# is required, story size) that many skills read. `rigor` makes the common case
|
||||
# reachable in one question while each knob stays individually settable.
|
||||
#
|
||||
# modes.workflow is fronted, NOT replaced: it drives ~5 distinct behaviours and
|
||||
# owns the only per-system override mechanism (workflow_overrides.system_
|
||||
@@ -1120,6 +1127,8 @@ get_legacy_key() {
|
||||
[ -z "$path" ] && return 0
|
||||
file=$(_yaml_helper_legacy_file_for "$path")
|
||||
[ -z "$file" ] && return 0
|
||||
_yaml_helper_set_root
|
||||
file="$_YH_ROOT/$file"
|
||||
[ -f "$file" ] || return 0
|
||||
awk 'BEGIN{FS="\n"} { gsub(/\r/,""); sub(/^[ \t]+/,""); sub(/[ \t]+$/,"");
|
||||
if (length($0) > 0) { print; exit } }' "$file"
|
||||
@@ -1153,7 +1162,8 @@ resolve_setting() {
|
||||
|
||||
if [ -z "$val" ]; then
|
||||
legacy=$(_yaml_helper_legacy_file_for "$path")
|
||||
if [ -n "$legacy" ] && [ -f "$legacy" ]; then
|
||||
# Checked under the root; labelled with the short path the user knows.
|
||||
if [ -n "$legacy" ] && [ -f "$_YH_ROOT/$legacy" ]; then
|
||||
val=$(get_legacy_key "$path")
|
||||
if [ -n "$val" ] && ! validate_enum_value "$path" "$val" 2>/dev/null; then val=""; fi
|
||||
[ -n "$val" ] && src="$legacy"
|
||||
@@ -1330,11 +1340,9 @@ PYEOF
|
||||
# a truncated block a skill might half-read.
|
||||
# resolve_config [--keys k1,k2,...] [<system>]
|
||||
#
|
||||
# --keys restricts output to the named knobs. USE IT. Emitting all 12 lines costs
|
||||
# ~188 tokens, while the resolution prose it replaces averages only ~101 tokens
|
||||
# per skill -- so a full block is a NET LOSS for any skill that reads 2-3 knobs.
|
||||
# A 3-knob block costs ~45 tokens, which is the actual win. Measured, not
|
||||
# estimated.
|
||||
# --keys restricts output to the named knobs. USE IT. A block of every knob
|
||||
# costs more than the resolution prose it replaces in a skill that reads 2-3
|
||||
# knobs; a block of just those knobs is the saving.
|
||||
# Valid key names are the output labels: rigor, review_mode, automation, workflow,
|
||||
# docs.density, story_granularity, qa.level, team.size, project.stage,
|
||||
# automation_always_ask, engine, testing.strict, system_overrides.
|
||||
@@ -1363,11 +1371,14 @@ resolve_config() {
|
||||
orphan=$(validate_local_yaml_base 2>&1) || notes="${notes:+$notes; }$orphan"
|
||||
|
||||
# Collect enum complaints from both files so a typo is visible, not silent.
|
||||
# Every file below is named under $_YH_ROOT. A bare `project.yaml` is the
|
||||
# WORKING directory's, so run from src/ these checks found no file and
|
||||
# reported nothing, while the values above them resolved from the root.
|
||||
local enum_err
|
||||
enum_err=$(validate_yaml_enum project.yaml 2>&1 >/dev/null)
|
||||
enum_err=$(validate_yaml_enum "$_YH_ROOT/project.yaml" 2>&1 >/dev/null)
|
||||
[ -n "$enum_err" ] && notes="${notes:+$notes; }$(echo "$enum_err" | tr '\n' ';' | sed 's/;$//') — ignored, chain continued"
|
||||
if [ -f "$_YH_ROOT/project.local.yaml" ]; then
|
||||
enum_err=$(validate_yaml_enum project.local.yaml 2>&1 >/dev/null)
|
||||
enum_err=$(validate_yaml_enum "$_YH_ROOT/project.local.yaml" 2>&1 >/dev/null)
|
||||
[ -n "$enum_err" ] && notes="${notes:+$notes; }local: $(echo "$enum_err" | tr '\n' ';' | sed 's/;$//')"
|
||||
# Locked keys in the local file. Separate from the enum check
|
||||
# above because their VALUES are legal — it is the location that is not, so
|
||||
@@ -1377,17 +1388,16 @@ resolve_config() {
|
||||
# full remedy sentence per key for direct callers, and three copies of it
|
||||
# would cost more of this block than every resolved value put together.
|
||||
local scope_err scope_keys
|
||||
scope_err=$(validate_local_scope project.local.yaml 2>&1 >/dev/null)
|
||||
scope_err=$(validate_local_scope "$_YH_ROOT/project.local.yaml" 2>&1 >/dev/null)
|
||||
if [ -n "$scope_err" ]; then
|
||||
scope_keys=$(printf '%s\n' "$scope_err" | sed -n 's/.*`\([^`]*\)`.*/\1/p' | paste -sd, - | sed 's/,/, /g')
|
||||
notes="${notes:+$notes; }local: not locally overridable, ignored — $scope_keys (move to project.yaml or delete)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Framing costs ~81 chars. For a skill reading 1-2 knobs that is more than the
|
||||
# For a skill reading 1-2 knobs the block's framing would cost more than the
|
||||
# inline chain it replaced, so bare lines are emitted instead -- "automation:
|
||||
# guided (project.local.yaml)" is self-describing without a banner. Measured:
|
||||
# single-knob skills were +226 chars WITH framing, negative without it.
|
||||
# guided (project.local.yaml)" is self-describing without a banner.
|
||||
local nkeys=0
|
||||
if [ -n "$want" ]; then
|
||||
nkeys=$(printf '%s' "$want" | tr ',' '\n' | grep -c '[a-z]')
|
||||
@@ -1418,13 +1428,21 @@ resolve_config() {
|
||||
done
|
||||
|
||||
# automation_always_ask: array-valued, so it does not go through resolve_setting.
|
||||
# Joined item by item. It used to join on commas and then turn every comma
|
||||
# into ", ", so one quoted item holding a comma printed as two items. An item
|
||||
# that holds a comma is now quoted, so one item stays one item.
|
||||
_rc_join() {
|
||||
printf '%s\n' "$1" | awk '/^[[:space:]]*$/ { next }
|
||||
{ s = $0; if (index(s, ",")) s = "\"" s "\""; out = out (n++ ? ", " : "") s }
|
||||
END { print out }'
|
||||
}
|
||||
local aaa
|
||||
if _rc_want automation_always_ask; then
|
||||
aaa=$(get_effective_yaml_array modes.automation_always_ask 2>/dev/null)
|
||||
if [ -n "$aaa" ]; then
|
||||
echo "automation_always_ask: $(echo "$aaa" | tr '\n' ',' | sed 's/,$//; s/,/, /g') (configured)"
|
||||
echo "automation_always_ask: $(_rc_join "$aaa") (configured)"
|
||||
else
|
||||
echo "automation_always_ask: $(echo "$_yaml_helper_always_ask_default" | tr '\n' ',' | sed 's/,$//; s/,/, /g') (default)"
|
||||
echo "automation_always_ask: $(_rc_join "$_yaml_helper_always_ask_default") (default)"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1444,11 +1462,29 @@ resolve_config() {
|
||||
|
||||
# testing.strict.*: reported as CONFIGURED STATE ONLY, never defaulted here.
|
||||
# Its unset default differs per skill by design.
|
||||
local ts_out="" k tv
|
||||
#
|
||||
# Each value is validated before it counts: get_effective_yaml_key printed an
|
||||
# invalid value (`logic: maybe`) as the value while the notes line said it was
|
||||
# ignored. Local first (the keys are locally overridable), then project.yaml,
|
||||
# then the scalar shorthand (`testing.strict: true`), each checked against
|
||||
# true|false. Not resolve_setting: that adds a rigor lookup per type, and
|
||||
# testing.strict is neither rigor-fronted nor defaulted -- five more
|
||||
# interpreter spawns for nothing. validate_enum_value is bash only.
|
||||
local ts_out="" k tv ts_all
|
||||
if _rc_want testing.strict; then
|
||||
ts_all=$(get_yaml_key "$_YH_ROOT/project.yaml" testing.strict 2>/dev/null)
|
||||
if [ -n "$ts_all" ] && ! validate_enum_value testing.strict.logic "$ts_all" 2>/dev/null; then ts_all=""; fi
|
||||
for k in logic integration visual ui config; do
|
||||
tv=$(get_effective_yaml_key "testing.strict.$k" 2>/dev/null)
|
||||
[ -z "$tv" ] && tv=$(get_yaml_key "$_YH_ROOT/project.yaml" testing.strict 2>/dev/null)
|
||||
tv=""
|
||||
if [ -f "$_YH_ROOT/project.local.yaml" ]; then
|
||||
tv=$(get_yaml_key "$_YH_ROOT/project.local.yaml" "testing.strict.$k" 2>/dev/null)
|
||||
if [ -n "$tv" ] && ! validate_enum_value "testing.strict.$k" "$tv" 2>/dev/null; then tv=""; fi
|
||||
fi
|
||||
if [ -z "$tv" ]; then
|
||||
tv=$(get_yaml_key "$_YH_ROOT/project.yaml" "testing.strict.$k" 2>/dev/null)
|
||||
if [ -n "$tv" ] && ! validate_enum_value "testing.strict.$k" "$tv" 2>/dev/null; then tv=""; fi
|
||||
fi
|
||||
[ -z "$tv" ] && tv="$ts_all"
|
||||
ts_out="$ts_out $k=${tv:-unset}"
|
||||
done
|
||||
echo "testing.strict:${ts_out} (unset = each skill applies its own default)"
|
||||
@@ -1498,11 +1534,18 @@ resolve_config() {
|
||||
# skill-authoring.md. Substituting `none` would make the question unaskable;
|
||||
# substituting anything else would emit every track, which is the ~150-item
|
||||
# checklist a single-platform jam project once received.
|
||||
local ct
|
||||
#
|
||||
# Through resolve_setting, as performance.enforce above. get_effective_yaml_key
|
||||
# let a hand-edited project.local.yaml win although platform.* is locked, and
|
||||
# printed an invalid value (`banana`) as the value while the notes line said
|
||||
# it was ignored. Only project.yaml can set it, so any other source -- there is
|
||||
# no default to fall to -- leaves it unset and the skill asks.
|
||||
local ct cs
|
||||
if _rc_want cert_tier || _rc_want platform.cert_tier; then
|
||||
ct=$(get_effective_yaml_key platform.cert_tier 2>/dev/null)
|
||||
if [ -n "$ct" ]; then
|
||||
echo "platform.cert_tier: $ct"
|
||||
ct=$(resolve_setting platform.cert_tier)
|
||||
cs="${ct#*$(printf '\t')}"; ct="${ct%%$(printf '\t')*}"
|
||||
if [ -n "$ct" ] && [ "$cs" = "project.yaml" ]; then
|
||||
echo "platform.cert_tier: $ct ($cs)"
|
||||
else
|
||||
echo "platform.cert_tier: (unset -- ask which platforms are in scope)"
|
||||
fi
|
||||
@@ -1512,7 +1555,7 @@ resolve_config() {
|
||||
# second call. A named <system> is echoed explicitly for convenience.
|
||||
local so_keys so_out="" sk sv
|
||||
if _rc_want system_overrides; then
|
||||
so_keys=$(get_yaml_child_keys project.yaml workflow_overrides.system_overrides 2>/dev/null)
|
||||
so_keys=$(get_yaml_child_keys "$_YH_ROOT/project.yaml" workflow_overrides.system_overrides 2>/dev/null)
|
||||
if [ -n "$so_keys" ]; then
|
||||
while IFS= read -r sk; do
|
||||
[ -z "$sk" ] && continue
|
||||
@@ -1582,7 +1625,7 @@ hook_warn() {
|
||||
# Skills cannot `source` this file in their `` !`cmd` `` bootstrap line. Claude
|
||||
# Code permission-checks every injected command before the skill renders, and
|
||||
# outside auto mode anything short of "allow" ABORTS the whole invocation --
|
||||
# measured on 2.1.281, see .claude/docs/config-resolution.md. A `${VAR:-x}` or
|
||||
# see .claude/docs/config-resolution.md. A `${VAR:-x}` or
|
||||
# `$( )` in the command fails that check as "Contains expansion" and no grant can
|
||||
# approve it; a `source … && resolve_config` compound needs every part approved.
|
||||
# `${CLAUDE_SKILL_DIR}` is substituted as text before the check, so one plain
|
||||
@@ -1594,7 +1637,7 @@ hook_warn() {
|
||||
# every name added here widens what a skill grant can reach.
|
||||
#
|
||||
# ROOT. Run from a subdirectory, the skill shell's cwd has no project.yaml and
|
||||
# $CLAUDE_PROJECT_DIR is the launch directory, not the repo root (measured), so
|
||||
# $CLAUDE_PROJECT_DIR is the launch directory, not the repo root, so
|
||||
# rules 1-3 of _yaml_helper_set_root all miss. This file's own location is the
|
||||
# one anchor that cannot drift: hooks/ sits two levels below the root. It only
|
||||
# fills CLAUDE_PROJECT_DIR when that has no project.yaml, so rules 1-2 (cwd
|
||||
|
||||
@@ -5,16 +5,25 @@ paths:
|
||||
|
||||
# Agent Memory Rules
|
||||
|
||||
**Agent memory is the one place an agent may write without asking — and the only
|
||||
one.** `.claude/agent-memory/` is gitignored, per-agent, and never ships. That
|
||||
exemption exists because the memory is the agent's own working notes about how to
|
||||
do its job, not a project artifact.
|
||||
**Agent memory is one of three writes that need no "May I write?"** The other two
|
||||
are named in `CLAUDE.md`:
|
||||
|
||||
It does **not** extend anywhere else. The Collaboration Protocol still governs
|
||||
every file under the code root (`src/`, `Assets/` or `Source/`), `design/`,
|
||||
`docs/`, `production/` and `assets/`: ask
|
||||
first, naming the path. Writing a memory is never a substitute for asking, and a
|
||||
memory must never be used to record something the user declined to have written.
|
||||
- **Appends to `production/session-state/active.md`** — the session checkpoint
|
||||
the hooks and the next session rely on. An append, never a rewrite of what is
|
||||
already there.
|
||||
- **A subagent's new file at the path its orchestrating skill named.** Only a
|
||||
new file under `production/`, `docs/` or `tests/`, only at a path the skill's
|
||||
prompt names (never one you chose), and only inside a phase the user approved.
|
||||
|
||||
`.claude/agent-memory/` is gitignored, per-agent, and never ships. Its exemption
|
||||
exists because the memory is the agent's own working notes about how to do its
|
||||
job, not a project artifact.
|
||||
|
||||
None of the three extends anywhere else. The Collaboration Protocol still governs
|
||||
every other write under the code root (`src/`, `Assets/` or `Source/`),
|
||||
`design/`, `docs/`, `production/` and `assets/`: ask first, naming the path.
|
||||
Writing a memory is never a substitute for asking, and a memory must never be
|
||||
used to record something the user declined to have written.
|
||||
|
||||
## Never record a temporary absence as a durable fact
|
||||
|
||||
|
||||
@@ -78,32 +78,16 @@ list.** A gate that fires on forty files does not get fixed, it gets muted — a
|
||||
a muted gate is worse than a narrow one, because it reads as coverage. When you
|
||||
keep a list, record *why* derivation failed and state the obligation to extend it.
|
||||
|
||||
Two further gate rules earned the hard way:
|
||||
Two further gate rules:
|
||||
|
||||
- **Assert something that cannot be true by accident.** A check for the word
|
||||
"unity" was satisfied by a file path, and case-insensitively by "community".
|
||||
"unity" is satisfied by a file path, and case-insensitively by "community".
|
||||
Assert a distinctive token instead.
|
||||
- **A gate you have not watched fail is not a gate.** Break the thing it guards,
|
||||
confirm it fails, restore. One mutation per tool invocation — a batch that
|
||||
times out leaves the repo holding a broken file, and `trap … EXIT` does not
|
||||
survive `SIGTERM`.
|
||||
|
||||
## Evidence
|
||||
|
||||
Every row below is a real instance this rule was written to prevent.
|
||||
|
||||
| Where | What was indistinguishable from success |
|
||||
|---|---|
|
||||
| `team-*` engine step | Specialist skipped when no engine configured — output identical to a run that consulted one |
|
||||
| `team-ui` accessibility gate | Passed vacuously; its criterion file did not exist |
|
||||
| `yaml-helper` | Locked key in `project.local.yaml` dropped in silence; user saw the default they were overriding |
|
||||
| all nine `team-*` | Pipeline printed six agents and ran one, with no statement of the difference |
|
||||
| `/security-audit` | Godot-only greps returned zero hits on Unity/Unreal, and zero hits read as clean |
|
||||
| `unity/VERSION.md` | "Post-cutoff" table listed pre-cutoff versions, inverting the signal it exists to send |
|
||||
| `/security-audit` | `platform.multiplayer` had a reader and no writer; the network category never ran, on any project |
|
||||
| `test-evidence-review` | No verdict for "could not check", so an unverifiable story got a verdict saying it was verified |
|
||||
| the gate meant to catch all of this | Was a hand-written list, and read green over the gap |
|
||||
|
||||
## The test to apply
|
||||
|
||||
Before shipping a skill or gate, ask: **if this step silently did not run, what
|
||||
|
||||
@@ -569,7 +569,7 @@ fi
|
||||
echo "schema_version: 1"
|
||||
echo ""
|
||||
echo "framework:"
|
||||
echo " version: 1.1.2"
|
||||
echo " version: 1.1.3"
|
||||
echo ""
|
||||
# Emit `project:` only when there is a stage to put in it -- same rule as the
|
||||
# `modes:` block below. Writing `stage: null` produced a file that FAILED THIS
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
set -u
|
||||
export LC_ALL=C
|
||||
|
||||
ROOT="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "$0")/../.." && pwd)}"
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
if [ -n "${CLAUDE_PROJECT_DIR:-}" ] && [ -f "$CLAUDE_PROJECT_DIR/project.yaml" ]; then
|
||||
ROOT="$CLAUDE_PROJECT_DIR"
|
||||
fi
|
||||
cd "$ROOT" || exit 0
|
||||
|
||||
DIFFERS=0
|
||||
@@ -163,7 +166,45 @@ case "$ENGINE_LC" in
|
||||
fi
|
||||
[ -n "$UEXE" ] && [ -x "$UEXE" ] && PROBE="$("$UEXE" -version 2>/dev/null | head -1)"
|
||||
;;
|
||||
unreal) command -v UnrealEditor-Cmd >/dev/null 2>&1 && PROBE="$(UnrealEditor-Cmd -version 2>/dev/null | head -1)" ;;
|
||||
unreal)
|
||||
# Never start the editor to learn its version: UnrealEditor-Cmd has no
|
||||
# -version flag (UE 5.8), so it opened the editor and ran until killed, and
|
||||
# /smoke-check's step 0 waited for ever. Read the engine's own
|
||||
# Engine/Build/Build.version instead, under the first engine root found:
|
||||
# engine.path (/setup-engine writes the UE root there), the editor path in
|
||||
# commands.test, the launcher folder for the .uproject's EngineAssociation,
|
||||
# then UnrealEditor-Cmd on PATH. A candidate that is not itself a root is
|
||||
# cut back to the folder above its last /Engine. A source build's
|
||||
# EngineAssociation is a GUID with no folder to derive, so it adds nothing.
|
||||
UASSOC="$(sed -n 's/.*"EngineAssociation"[[:space:]]*:[[:space:]]*"\([0-9][0-9.]*\)".*/\1/p' ./*.uproject 2>/dev/null | head -1)"
|
||||
ULAUNCH=""
|
||||
if [ -n "$UASSOC" ]; then
|
||||
case "$(uname -s)" in
|
||||
Darwin) ULAUNCH="/Users/Shared/Epic Games/UE_$UASSOC" ;;
|
||||
Linux) ;;
|
||||
*) ULAUNCH="C:/Program Files/Epic Games/UE_$UASSOC" ;;
|
||||
esac
|
||||
fi
|
||||
UROOT=""
|
||||
for UCAND in \
|
||||
"$(yaml_block_value engine path)" \
|
||||
"$(yaml_block_value commands test | grep -oE '"[^"]*UnrealEditor[^"]*"' | head -1 | tr -d '"')" \
|
||||
"$ULAUNCH" \
|
||||
"$(command -v UnrealEditor-Cmd 2>/dev/null)"; do
|
||||
[ -n "$UCAND" ] || continue
|
||||
UCAND="$(printf '%s' "$UCAND" | tr '\\' '/')"
|
||||
for UTRY in "$UCAND" "$(printf '%s' "$UCAND" | sed -E 's#^(.*)/Engine(/.*)?$#\1#')"; do
|
||||
if [ -f "$UTRY/Engine/Build/Build.version" ]; then UROOT="$UTRY"; break 2; fi
|
||||
done
|
||||
done
|
||||
if [ -n "$UROOT" ]; then
|
||||
UBV="$(tr -d '\r\n' < "$UROOT/Engine/Build/Build.version")"
|
||||
UMAJ="$(printf '%s' "$UBV" | grep -oE '"MajorVersion"[[:space:]]*:[[:space:]]*[0-9]+' | grep -oE '[0-9]+$')"
|
||||
UMIN="$(printf '%s' "$UBV" | grep -oE '"MinorVersion"[[:space:]]*:[[:space:]]*[0-9]+' | grep -oE '[0-9]+$')"
|
||||
UPAT="$(printf '%s' "$UBV" | grep -oE '"PatchVersion"[[:space:]]*:[[:space:]]*[0-9]+' | grep -oE '[0-9]+$')"
|
||||
[ -n "$UMAJ" ] && [ -n "$UMIN" ] && PROBE="$UMAJ.$UMIN${UPAT:+.$UPAT} (Engine/Build/Build.version)"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$PROBE" ]; then
|
||||
@@ -171,6 +212,8 @@ if [ -z "$PROBE" ]; then
|
||||
skipped "declared version vs installed binary — no Unity editor at the path in commands.test or in the Hub folder for engine.version. A probe that could not run has not established absence."
|
||||
elif [ "$ENGINE_LC" = "godot" ]; then
|
||||
skipped "declared version vs installed binary — no Godot executable found (commands.test, engine.path, PATH). A probe that could not run has not established absence."
|
||||
elif [ "$ENGINE_LC" = "unreal" ]; then
|
||||
skipped "declared version vs installed engine — no readable Engine/Build/Build.version under engine.path, the editor in commands.test, the launcher folder for the .uproject's EngineAssociation, or UnrealEditor-Cmd on PATH. A probe that could not run has not established absence."
|
||||
else
|
||||
skipped "declared version vs installed binary — no $ENGINE binary found on PATH. A probe that could not run has not established absence."
|
||||
fi
|
||||
|
||||
@@ -7,14 +7,7 @@
|
||||
"permissions": {
|
||||
"defaultMode": "default",
|
||||
"allow": [
|
||||
"Bash(git status*)",
|
||||
"Bash(git diff*)",
|
||||
"Bash(git log*)",
|
||||
"Bash(git branch*)",
|
||||
"Bash(git rev-parse*)",
|
||||
"Bash(ls *)",
|
||||
"Bash(dir *)",
|
||||
"Bash(python -m json.tool*)",
|
||||
"Bash(python -m pytest *)",
|
||||
"Bash(py -m pytest *)"
|
||||
],
|
||||
@@ -95,6 +88,7 @@
|
||||
"Bash(cat *.env*)",
|
||||
"Bash(type *.env*)",
|
||||
"Read(**/.env*)",
|
||||
"Edit(**/.env*)",
|
||||
"PowerShell(Remove-Item *-Recurse*)",
|
||||
"PowerShell(Remove-Item * -r*)",
|
||||
"PowerShell(Remove-Item -r*)",
|
||||
|
||||
@@ -13,7 +13,6 @@ Resolved above — use as-is. `/adopt` also inspects `project.yaml` and the lega
|
||||
config files directly when reporting and writing migration state; that raw
|
||||
inspection is deliberate and separate from the resolved values above.
|
||||
|
||||
|
||||
# Adopt — Brownfield Template Adoption
|
||||
|
||||
This skill audits an existing project's artifacts for **format compliance** with
|
||||
@@ -53,510 +52,31 @@ only the required docs/sections (optional sections are informational, not gaps);
|
||||
|
||||
## Phase 1: Detect Project State
|
||||
|
||||
Emit one line before reading: `"Scanning project artifacts..."` — this confirms the
|
||||
skill is running during the silent read phase.
|
||||
|
||||
Then read silently before presenting anything else.
|
||||
|
||||
### Existence check
|
||||
- `project.stage` in `project.yaml` (fallback `production/stage.txt`) — if either is present, use that value (authoritative phase)
|
||||
- `design/gdd/game-concept.md` (or, at the minimal tier, `design/game-brief.md`) — concept exists?
|
||||
- `design/gdd/systems-index.md` — systems index exists?
|
||||
- Count GDD files: `design/gdd/*.md` (excluding game-concept.md and systems-index.md)
|
||||
- Count ADR files: `docs/architecture/adr-*.md`
|
||||
- Count story files: `production/epics/**/*.md` (excluding EPIC.md)
|
||||
- `project.yaml` (`engine.name`) / `.claude/docs/technical-preferences.md` — engine configured?
|
||||
- `docs/engine-reference/` — engine reference docs present?
|
||||
- Glob `docs/adoption-plan-*.md` — note the filename of the most recent prior plan if any exist
|
||||
|
||||
### Infer phase (if no project.stage / stage.txt)
|
||||
Use the same heuristic as `/project-stage-detect`:
|
||||
- 10+ source files in the code root → Production
|
||||
- Stories in `production/epics/` → Pre-Production
|
||||
- ADRs exist → Technical Setup
|
||||
- systems-index.md exists → Systems Design
|
||||
- game-concept.md (or `design/game-brief.md`) exists → Concept
|
||||
- Nothing → Fresh (not a brownfield project — suggest `/start`)
|
||||
|
||||
If the project appears fresh (no artifacts at all), use `AskUserQuestion`:
|
||||
- "This looks like a fresh project — no existing artifacts found. `/adopt` is for
|
||||
projects with work to migrate. What would you like to do?"
|
||||
- "Run `/start` — begin guided first-time onboarding"
|
||||
- "My artifacts are in a non-standard location — help me find them"
|
||||
- "Cancel"
|
||||
|
||||
Then stop — do not proceed with the audit regardless of which option the user picks
|
||||
(each option leads to a different skill or manual investigation).
|
||||
|
||||
Report: "Detected phase: [phase]. Found: [N] GDDs, [M] ADRs, [P] stories."
|
||||
|
||||
---
|
||||
**Read `references/1-detect.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 2: Format Audit
|
||||
|
||||
For each artifact type in scope (based on argument mode **and the resolved
|
||||
workflow tier**), check not just that the file exists but that it contains the
|
||||
internal structure the template requires. At `minimal`, scope the audit to
|
||||
`design/game-brief.md` — do not audit for GDDs, ADRs, or UX specs (they are not expected).
|
||||
Steps 2e (the Engine reference row only), 2f (project config) and 2g (v1.0
|
||||
migration check) run at every tier.
|
||||
|
||||
### 2a: GDD Format Audit
|
||||
|
||||
**Gather section presence deterministically — do not read the GDDs to count
|
||||
headings.** For each GDD discovered in Phase 1, pass its path explicitly to the
|
||||
structure-check script:
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/gdd-structure-check.sh [path-to-gdd]
|
||||
```
|
||||
|
||||
**Pass paths one at a time; do not invoke it bare.** The no-argument form sweeps
|
||||
`design/gdd/` only, and a brownfield project's GDDs are not guaranteed to live
|
||||
there — pass whatever paths Phase 1 found. The script prints a `PRESENT:` list
|
||||
and, when applicable, an `ABSENT:` list per file. It reports **presence only**
|
||||
and makes no REQUIRED/ADVISORY judgment (that is the tier logic below), and it
|
||||
already accepts `## Detailed Design` as satisfying the `Detailed Rules`
|
||||
requirement, so do not flag that alias as missing.
|
||||
|
||||
If the script prints `Not found:` for a path or errors, that is a **discovery
|
||||
failure, not a format gap** — report it as "could not audit [path]" and do not
|
||||
count it as a missing-sections finding.
|
||||
|
||||
**Then apply the workflow tier** resolved above to each file's PRESENT/ABSENT
|
||||
lists. Which sections are **required** (a miss = gap) vs **advisory** (a miss =
|
||||
informational):
|
||||
- **`full`** — all 8 sections are required.
|
||||
- **`standard`** — the 5 required (Overview, Detailed Rules, Edge Cases,
|
||||
Dependencies, Acceptance Criteria) + Formulas for any system that defines
|
||||
numeric rules (rates, curves, thresholds, costs — the system's `Category` is a
|
||||
hint, not the test); Player Fantasy and Tuning Knobs are advisory.
|
||||
- **`minimal`** — GDDs are not expected; audit `design/game-brief.md` instead,
|
||||
against `.claude/docs/templates/game-brief.md`: each of the six required fields
|
||||
present and not a placeholder; the three one-liners advisory. Any GDD that
|
||||
does exist is checked at the `standard` bar, advisorily.
|
||||
|
||||
The script's 8 canonical labels are: Overview, Player Fantasy, Detailed Rules,
|
||||
Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria.
|
||||
|
||||
A section reported PRESENT can still be an empty heading. For each GDD, also
|
||||
record with a targeted grep (not a full read):
|
||||
- Placeholder-only sections — `Grep pattern="\[To be designed\]"` (or an
|
||||
equivalent empty/single-line body) marks a present-but-unwritten section.
|
||||
- The `**Status**:` header field — `Grep pattern="^>?[[:space:]]*\*\*Status\*\*:"`.
|
||||
Valid values: `Draft`, `In Design`, `Designed`, `In Review`, `Approved`,
|
||||
`Implemented`, `Needs Revision`.
|
||||
|
||||
> **The `>?` is load-bearing, and so are `Draft`/`Implemented`.** Both emitters
|
||||
> write this field inside a blockquote — `.claude/docs/templates/game-design-document.md`
|
||||
> and `/design-system` produce `> **Status**: …` — so an anchor of
|
||||
> `^\*\*Status\*\*:` matches nothing and reports *every* template-compliant GDD
|
||||
> as missing its Status. The template's own value list offers `Draft` and
|
||||
> `Implemented`, so both must count as valid.
|
||||
|
||||
### 2b: ADR Format Audit
|
||||
|
||||
For each ADR file found, check for these critical sections:
|
||||
|
||||
| Section | Impact if missing |
|
||||
|---|---|
|
||||
| `## Status` | **BLOCKING** — `/story-readiness` ADR status check silently passes everything |
|
||||
| `## ADR Dependencies` | HIGH — dependency ordering in `/architecture-review` breaks |
|
||||
| `## Engine Compatibility` | HIGH — post-cutoff API risk is unknown |
|
||||
| `## GDD Requirements Addressed` | MEDIUM — traceability matrix loses coverage |
|
||||
| `## Performance Implications` | LOW — not pipeline-critical |
|
||||
|
||||
For each ADR, record: which sections present, which missing, current Status value
|
||||
if the Status section exists.
|
||||
|
||||
### 2c: systems-index.md Format Audit
|
||||
|
||||
If `design/gdd/systems-index.md` exists:
|
||||
|
||||
1. **Parenthetical status values** — Grep for any Status cell containing
|
||||
parentheses: `"Needs Revision ("`, `"In Progress ("`, etc.
|
||||
These break exact-string matching in `/gate-check`, `/create-stories`,
|
||||
and `/architecture-review`. **BLOCKING.**
|
||||
|
||||
2. **Valid status values** — check that Status column values are only from:
|
||||
`Not Started`, `In Progress`, `In Review`, `Designed`, `Approved`, `Needs Revision`
|
||||
Flag any unrecognised values.
|
||||
|
||||
3. **Column structure** — check that the table has at minimum: System name,
|
||||
Layer, Priority, Status columns. Missing columns degrade skill functionality.
|
||||
|
||||
### 2d: Story Format Audit
|
||||
|
||||
For each story file found:
|
||||
|
||||
- **`Manifest Version:` field** — present in story header? (LOW — auto-passes if absent)
|
||||
- **TR-ID reference** — does story contain `TR-[a-z]+-[0-9]+` pattern? (MEDIUM — no staleness tracking)
|
||||
- **ADR reference** — does story reference at least one ADR? (check for `ADR-` pattern)
|
||||
- **Status field** — present and readable?
|
||||
- **Acceptance criteria** — does the story have a checkbox list (`- [ ]`)?
|
||||
|
||||
### 2e: Infrastructure Audit
|
||||
|
||||
| Artifact | Path | Impact if missing |
|
||||
|---|---|---|
|
||||
| TR registry | `docs/architecture/tr-registry.yaml` | HIGH — no stable requirement IDs |
|
||||
| Control manifest | `docs/architecture/control-manifest.md` | HIGH — no layer rules for stories |
|
||||
| Manifest version stamp | In manifest header: `Manifest Version:` | MEDIUM — staleness checks blind |
|
||||
| Sprint status | `production/sprint-status.yaml` | MEDIUM — `/sprint-status` falls back to markdown |
|
||||
| Stage file | `project.stage` in `project.yaml` (fallback `production/stage.txt`) | MEDIUM — phase auto-detect unreliable |
|
||||
| Engine reference | `docs/engine-reference/[engine]/VERSION.md` | HIGH — ADR engine checks blind |
|
||||
| Architecture traceability | `docs/architecture/requirements-traceability.md` | MEDIUM — no persistent matrix |
|
||||
|
||||
At `workflow: minimal` only the Engine reference row applies. The TR registry,
|
||||
control manifest and its version stamp, sprint status, stage file and
|
||||
traceability matrix are not on the minimal path, so their absence is not a gap.
|
||||
|
||||
### 2f: Project Config Audit
|
||||
|
||||
Read `project.yaml` (the primary config store) and `.claude/docs/technical-preferences.md` (legacy mirror). A setting counts as configured if EITHER source has a real value (in technical-preferences.md, `[TO BE CONFIGURED]` means unconfigured):
|
||||
- `engine.name`/`version`/`language`/`rendering`/`physics` (else the Engine/Language/Rendering/Physics fields) → HIGH if unconfigured in both (ADR skills fail)
|
||||
- `naming.*` (else Naming conventions) → MEDIUM
|
||||
- `performance.*` (else Performance budgets) → MEDIUM
|
||||
- Forbidden Patterns, Allowed Libraries (technical-preferences.md only — not migrated to project.yaml) → LOW (starts empty by design)
|
||||
|
||||
### 2g: v1.0 Migration Check
|
||||
|
||||
A project is a **v1.0 project needing migration** when `project.yaml` does NOT
|
||||
exist at the repo root AND at least one legacy file does: `production/stage.txt`,
|
||||
`production/review-mode.txt`, or a `.claude/docs/technical-preferences.md` with
|
||||
real values.
|
||||
|
||||
"Real values" means one of the keys the converter actually migrates — Engine,
|
||||
Language, Rendering, Physics, the naming, platform and performance fields,
|
||||
Framework, or the specialists. Not merely "some bullet is filled in": the
|
||||
shipped template ships one prose default (`- **Required Tests**: …`) that is
|
||||
never migrated, and counting it made every fresh clone read as a v1.0 project.
|
||||
|
||||
Do not hand-migrate. Run the converter, which is deterministic and covered by
|
||||
the framework's own test suite:
|
||||
|
||||
```bash
|
||||
bash .claude/scripts/migrate-v1-config.sh --dry-run
|
||||
```
|
||||
|
||||
The dry run writes nothing; record what it lists for the report. Do not run the
|
||||
converter during the audit — Phase 2 reads silently. The migration is
|
||||
classified BLOCKING in Phase 3, heads the plan, and **Phase 7 offers it as the
|
||||
first action**: report what the dry run listed, then ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`." If
|
||||
the user approves, run it without `--dry-run`. It
|
||||
writes `project.yaml` plus `production/migration-report.md` and **deletes
|
||||
nothing** — the whole operation stays reversible with `git checkout`.
|
||||
|
||||
Then tell the user to read `production/migration-report.md` before running:
|
||||
|
||||
```bash
|
||||
bash .claude/scripts/migrate-v1-config.sh --finalize
|
||||
```
|
||||
|
||||
`--finalize` deletes a legacy file only after proving its value is present in
|
||||
`project.yaml`; on mismatch it deletes nothing and exits 4. It never deletes
|
||||
`technical-preferences.md`, which still holds Forbidden Patterns and Allowed
|
||||
Libraries.
|
||||
|
||||
**If the script refuses with exit 3**, do not work around it. Exit 3 means one
|
||||
of two things, and the message says which:
|
||||
|
||||
- **the values DISAGREE** — two sources of truth and no way to know which the
|
||||
user edited last. Surface it and let them decide.
|
||||
- **a `production/migration-report.md` is already present** — a migration ran
|
||||
here, so these are post-migration leftovers and `--finalize` is the next step,
|
||||
not a second `migrate`.
|
||||
|
||||
Both files merely *existing* is not exit 3 and must not be reported as a
|
||||
conflict: `/start` writes `production/stage.txt` on every new v1.1 project as a
|
||||
mirror, so agreement is the normal state. The script says
|
||||
`the legacy files mirror it (values agree)` and exits 0 for that.
|
||||
|
||||
Classify as **BLOCKING** in Phase 3: until migration runs, every skill reads
|
||||
config through the legacy fallback chain, and v1.1 settings are unavailable.
|
||||
|
||||
---
|
||||
**Read `references/2-format-audit.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 3: Classify and Prioritise Gaps
|
||||
|
||||
Organise every gap found across all audits into four severity tiers:
|
||||
|
||||
**BLOCKING** — Will cause template skills to silently produce wrong results *right now*.
|
||||
Examples: ADR missing Status field, systems-index parenthetical status values,
|
||||
engine not configured when ADRs exist.
|
||||
|
||||
**HIGH** — Will cause stories to be generated with missing safety checks, or
|
||||
infrastructure bootstrapping will fail.
|
||||
Examples: ADRs missing Engine Compatibility, GDDs missing Acceptance Criteria
|
||||
(stories can't be generated from them), tr-registry.yaml missing.
|
||||
|
||||
**MEDIUM** — Degrades quality and pipeline tracking but does not break functionality.
|
||||
Examples: GDDs missing Tuning Knobs or Formulas sections, stories missing TR-IDs,
|
||||
sprint-status.yaml missing.
|
||||
|
||||
**LOW** — Retroactive improvements that are nice-to-have but not urgent.
|
||||
Examples: Stories missing Manifest Version stamps, GDDs missing Open Questions section.
|
||||
|
||||
Count totals per tier. If zero BLOCKING and zero HIGH gaps: report that the project
|
||||
is template-compatible and only advisory improvements remain.
|
||||
|
||||
---
|
||||
**Read `references/3-classify.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 4: Build the Migration Plan
|
||||
|
||||
Compose a numbered, ordered action plan. Ordering rules:
|
||||
1. BLOCKING gaps first (must fix before any pipeline skill runs reliably)
|
||||
2. HIGH gaps next, infrastructure before GDD/ADR content (bootstrapping needs correct formats)
|
||||
3. MEDIUM gaps ordered: GDD gaps before ADR gaps before story gaps (stories depend on GDDs and ADRs)
|
||||
4. LOW gaps last
|
||||
|
||||
For each gap, produce a plan entry with:
|
||||
- A clear problem statement (one sentence, no jargon)
|
||||
- The exact command to fix it, if a skill handles it
|
||||
- Manual steps if it requires direct editing
|
||||
- A time estimate (rough: 5 min / 30 min / 1 session)
|
||||
- A checkbox `- [ ]` for tracking
|
||||
|
||||
**Special case — systems-index parenthetical status values:**
|
||||
This is always the first item if present. Show the exact values that need changing
|
||||
and the exact replacement text. Offer to fix this immediately before writing the plan.
|
||||
|
||||
**Special case — ADRs missing Status field:**
|
||||
For each affected ADR, the fix is:
|
||||
`/architecture-decision retrofit docs/architecture/adr-[NNNN]-[slug].md`
|
||||
List each ADR as a separate checkable item.
|
||||
|
||||
**Special case — GDDs missing sections:**
|
||||
For each affected GDD, list which sections are missing and the fix:
|
||||
`/design-system retrofit design/gdd/[filename].md`
|
||||
|
||||
**Infrastructure bootstrap ordering** — always present in this sequence:
|
||||
1. Fix ADR formats first (registry depends on reading ADR Status fields)
|
||||
2. Run `/architecture-review` → bootstraps `tr-registry.yaml`
|
||||
3. Run `/create-control-manifest` → creates manifest with version stamp
|
||||
4. Run `/sprint-plan update` → creates `sprint-status.yaml`
|
||||
5. Run `/gate-check [phase]` (the gate into the phase the project is in; at Concept there is none — Concept is the default stage, nothing to run) → writes `project.stage` in `project.yaml` (and legacy `stage.txt`) authoritatively
|
||||
|
||||
**At `workflow: minimal` the plan prescribes none of this sequence.** None of it
|
||||
is on the minimal path: ADRs are not expected, the brief's build order is the
|
||||
plan (no `/sprint-plan`), and nothing there runs `/gate-check`. The plan's
|
||||
Step 3 says so in one line and names the path's next step instead —
|
||||
`/create-stories` when no stories exist, else `/dev-story`.
|
||||
|
||||
**Existing stories** — note explicitly:
|
||||
> "Existing stories continue to work with all template skills — all new format
|
||||
> checks auto-pass when the fields are absent. They won't benefit from TR-ID
|
||||
> staleness tracking or manifest version checks until they're regenerated. This
|
||||
> is intentional: do not regenerate stories that are already in progress."
|
||||
|
||||
---
|
||||
**Read `references/4-migration-plan.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 5: Present Summary and Ask to Write
|
||||
|
||||
Present a compact summary before writing:
|
||||
|
||||
```
|
||||
## Adoption Audit Summary
|
||||
Phase detected: [phase]
|
||||
Engine: [configured / NOT CONFIGURED]
|
||||
GDDs audited: [N] ([X] fully compliant, [Y] with gaps)
|
||||
ADRs audited: [N] ([X] fully compliant, [Y] with gaps)
|
||||
Stories audited: [N]
|
||||
|
||||
Gap counts:
|
||||
BLOCKING: [N] — template skills will malfunction without these fixes
|
||||
HIGH: [N] — unsafe to run /create-stories or /story-readiness
|
||||
MEDIUM: [N] — quality degradation
|
||||
LOW: [N] — optional improvements
|
||||
|
||||
Estimated remediation: [X blocking items × ~Y min each = roughly Z hours]
|
||||
```
|
||||
|
||||
Before asking to write, show a **Gap Preview**:
|
||||
- List every BLOCKING gap as a one-line bullet describing the actual problem
|
||||
(e.g. `systems-index.md: 3 rows have parenthetical status values`,
|
||||
`adr-0002.md: missing ## Status section`). No counts — show the actual items.
|
||||
- Show HIGH / MEDIUM / LOW as counts only (e.g. `HIGH: 4, MEDIUM: 2, LOW: 1`).
|
||||
|
||||
This gives the user enough context to judge scope before committing to writing the file.
|
||||
|
||||
If a prior adoption plan was detected in Phase 1, add a note:
|
||||
> "A previous plan exists at `docs/adoption-plan-[prior-date].md`. The new plan will
|
||||
> reflect current project state — it does not diff against the prior run."
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- "Ready to write the migration plan?"
|
||||
- "Yes — write `docs/adoption-plan-[date].md`"
|
||||
- "Show me the full plan preview first (don't write yet)"
|
||||
- "Cancel — I'll handle migration manually"
|
||||
|
||||
If the user picks "Show me the full plan preview", output the complete plan as a
|
||||
fenced markdown block. Then ask again with the same three options.
|
||||
|
||||
---
|
||||
**Read `references/5-summary.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 6: Write the Adoption Plan
|
||||
|
||||
If approved, write `docs/adoption-plan-[date].md` with this structure:
|
||||
|
||||
```markdown
|
||||
# Adoption Plan
|
||||
|
||||
> **Generated**: [date]
|
||||
> **Project phase**: [phase]
|
||||
> **Engine**: [name + version, or "Not configured"]
|
||||
> **Template version**: v1.0+
|
||||
|
||||
Work through these steps in order. Check off each item as you complete it.
|
||||
Re-run `/adopt` anytime to check remaining gaps.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Fix Blocking Gaps
|
||||
|
||||
[One sub-section per blocking gap with problem, fix command, time estimate, checkbox]
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Fix High-Priority Gaps
|
||||
|
||||
[One sub-section per high gap]
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Bootstrap Infrastructure
|
||||
|
||||
[At `workflow: minimal`, replace 3a–3d with one line: "Not on the minimal path —
|
||||
the brief's build order is the plan. Next: `/create-stories` (or `/dev-story`
|
||||
once stories exist)."]
|
||||
|
||||
### 3a. Register existing requirements (creates tr-registry.yaml)
|
||||
Run `/architecture-review` — even if ADRs already exist, this run bootstraps
|
||||
the TR registry from your existing GDDs and ADRs.
|
||||
**Time**: 1 session (review can be long for large codebases)
|
||||
- [ ] tr-registry.yaml created
|
||||
|
||||
### 3b. Create control manifest
|
||||
Run `/create-control-manifest`
|
||||
**Time**: 30 min
|
||||
- [ ] docs/architecture/control-manifest.md created
|
||||
|
||||
### 3c. Create sprint tracking file
|
||||
Run `/sprint-plan update`
|
||||
**Time**: 5 min (if sprint plan already exists as markdown)
|
||||
- [ ] production/sprint-status.yaml created
|
||||
|
||||
### 3d. Set authoritative project stage
|
||||
Run `/gate-check [current-phase]` (the gate into the phase the project is in;
|
||||
at Concept there is none — Concept is the default stage, nothing to run)
|
||||
**Time**: 5 min
|
||||
- [ ] `project.stage` in `project.yaml` written (legacy `production/stage.txt` also updated)
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Medium-Priority Gaps
|
||||
|
||||
[One sub-section per medium gap]
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Optional Improvements
|
||||
|
||||
[One sub-section per low gap]
|
||||
|
||||
---
|
||||
|
||||
## What to Expect from Existing Stories
|
||||
|
||||
Existing stories continue to work with all template skills. New format checks
|
||||
(TR-ID validation, manifest version staleness) auto-pass when the fields are
|
||||
absent — so nothing breaks. They won't benefit from staleness tracking until
|
||||
regenerated. Do not regenerate stories that are in progress or done.
|
||||
|
||||
---
|
||||
|
||||
## Re-run
|
||||
|
||||
Run `/adopt` again after completing Step 3 to verify all blocking and high gaps
|
||||
are resolved. The new run will reflect the current state of the project.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6b: Report Review Mode
|
||||
|
||||
**Do not write a review mode.** `modes.review_mode` is one of the six knobs
|
||||
`modes.rigor` fronts: pinning it in `project.yaml` shadows the rigor expansion, and
|
||||
the legacy `production/review-mode.txt` sits *above* that expansion in resolution,
|
||||
so either write would freeze director-review depth for good — the rule `/start`
|
||||
and `project.yaml`'s header comment both state.
|
||||
|
||||
Report the value the bootstrap above resolved instead: "Review mode resolves to
|
||||
`[value]` — from `modes.rigor`, unless something pins it." If the user wants a
|
||||
different depth, point them to changing `modes.rigor`, or to pinning it on purpose
|
||||
with `/settings --local modes.review_mode=<full|lean|solo>` (a personal override in
|
||||
`project.local.yaml`).
|
||||
|
||||
---
|
||||
**Read `references/6-write.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 7: Offer First Action
|
||||
|
||||
After writing the plan, don't stop there. Pick the single highest-priority gap
|
||||
and offer to handle it immediately using `AskUserQuestion`. Choose the first
|
||||
branch that applies:
|
||||
|
||||
**If Phase 2g found a v1.0 project needing migration:** offer the converter run
|
||||
described there — report what the dry run listed and ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`."
|
||||
Every other fix reads config through it, so it comes first.
|
||||
|
||||
**If there are parenthetical status values in systems-index.md:**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent fix is `systems-index.md` — [N] rows have parenthetical status
|
||||
values (e.g. `Needs Revision (see notes)`) that break /gate-check,
|
||||
/create-stories, and /architecture-review right now. I can fix these in-place."
|
||||
- "Fix it now — edit systems-index.md"
|
||||
- "I'll fix it myself"
|
||||
- "Done — leave me with the plan"
|
||||
|
||||
**If ADRs are missing `## Status` (and no parenthetical issue):**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent fix is adding `## Status` to [N] ADR(s): [list filenames].
|
||||
Without it, /story-readiness silently passes all ADR checks. Start with
|
||||
[first affected filename]?"
|
||||
- "Yes — retrofit [first affected filename] now"
|
||||
- "Retrofit all [N] ADRs one by one"
|
||||
- "I'll handle ADRs myself"
|
||||
|
||||
**If GDDs are missing Acceptance Criteria (and no blocking issues above):**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent gap is missing Acceptance Criteria in [N] GDD(s):
|
||||
[list filenames]. Without them, /create-stories can't generate stories.
|
||||
Start with [highest-priority GDD filename]?"
|
||||
- "Yes — add Acceptance Criteria to [GDD filename] now"
|
||||
- "Do all [N] GDDs one by one"
|
||||
- "I'll handle GDDs myself"
|
||||
|
||||
**Otherwise, if any BLOCKING or HIGH gap remains** (one no branch above names —
|
||||
e.g. a missing TR registry):
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent remaining gap is [first BLOCKING or HIGH item in the plan] —
|
||||
[one line on what it breaks]. Start on it now?"
|
||||
- "Yes — start on [item]"
|
||||
- "Show me that plan item first"
|
||||
- "Done — leave me with the plan"
|
||||
|
||||
**If no BLOCKING or HIGH gaps exist:**
|
||||
Use `AskUserQuestion`:
|
||||
- "No blocking gaps — this project is template-compatible. What next?"
|
||||
- "Walk me through the medium-priority improvements"
|
||||
- "Run /project-stage-detect for a broader health check"
|
||||
- "Done — I'll work through the plan at my own pace"
|
||||
|
||||
> **Adoption plan saved to `docs/adoption-plan-[date].md`.** Re-run `/adopt` at any time to re-check remaining gaps as you complete them.
|
||||
|
||||
---
|
||||
**Read `references/7-first-action.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Collaborative Protocol
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# /adopt — Phase 1: Detect Project State
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 1: Detect Project State
|
||||
|
||||
Emit one line before reading: `"Scanning project artifacts..."` — this confirms the
|
||||
skill is running during the silent read phase.
|
||||
|
||||
Then read silently before presenting anything else.
|
||||
|
||||
### Existence check
|
||||
- `project.stage` in `project.yaml` (fallback `production/stage.txt`) — if either is present, use that value (authoritative phase)
|
||||
- `design/gdd/game-concept.md` (or, at the minimal tier, `design/game-brief.md`) — concept exists?
|
||||
- `design/gdd/systems-index.md` — systems index exists?
|
||||
- Count GDD files: `design/gdd/*.md` (excluding game-concept.md and systems-index.md)
|
||||
- Count ADR files: `docs/architecture/adr-*.md`
|
||||
- Count story files: `production/epics/**/*.md` (excluding EPIC.md)
|
||||
- `project.yaml` (`engine.name`) / `.claude/docs/technical-preferences.md` — engine configured?
|
||||
- `docs/engine-reference/` — engine reference docs present?
|
||||
- Glob `docs/adoption-plan-*.md` — note the filename of the most recent prior plan if any exist
|
||||
|
||||
### Infer phase (if no project.stage / stage.txt)
|
||||
Use the same heuristic as `/project-stage-detect`:
|
||||
- 10+ source files in the code root → Production
|
||||
- Stories in `production/epics/` → Pre-Production
|
||||
- ADRs exist → Technical Setup
|
||||
- systems-index.md exists → Systems Design
|
||||
- game-concept.md (or `design/game-brief.md`) exists → Concept
|
||||
- Nothing → Fresh (not a brownfield project — suggest `/start`)
|
||||
|
||||
If the project appears fresh (no artifacts at all), use `AskUserQuestion`:
|
||||
- "This looks like a fresh project — no existing artifacts found. `/adopt` is for
|
||||
projects with work to migrate. What would you like to do?"
|
||||
- "Run `/start` — begin guided first-time onboarding"
|
||||
- "My artifacts are in a non-standard location — help me find them"
|
||||
- "Cancel"
|
||||
|
||||
Then stop — do not proceed with the audit regardless of which option the user picks
|
||||
(each option leads to a different skill or manual investigation).
|
||||
|
||||
Report: "Detected phase: [phase]. Found: [N] GDDs, [M] ADRs, [P] stories."
|
||||
|
||||
---
|
||||
@@ -0,0 +1,200 @@
|
||||
# /adopt — Phase 2: Format Audit
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 2: Format Audit
|
||||
|
||||
**In this file:**
|
||||
|
||||
- 2a: GDD Format Audit
|
||||
- 2b: ADR Format Audit
|
||||
- 2c: systems-index.md Format Audit
|
||||
- 2d: Story Format Audit
|
||||
- 2e: Infrastructure Audit
|
||||
- 2f: Project Config Audit
|
||||
- 2g: v1.0 Migration Check
|
||||
|
||||
For each artifact type in scope (based on argument mode **and the resolved
|
||||
workflow tier**), check not just that the file exists but that it contains the
|
||||
internal structure the template requires. At `minimal`, scope the audit to
|
||||
`design/game-brief.md` — do not audit for GDDs, ADRs, or UX specs (they are not expected).
|
||||
Steps 2e (the Engine reference row only), 2f (project config) and 2g (v1.0
|
||||
migration check) run at every tier.
|
||||
|
||||
### 2a: GDD Format Audit
|
||||
|
||||
**Gather section presence deterministically — do not read the GDDs to count
|
||||
headings.** For each GDD discovered in Phase 1, pass its path explicitly to the
|
||||
structure-check script:
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/gdd-structure-check.sh [path-to-gdd]
|
||||
```
|
||||
|
||||
**Pass paths one at a time; do not invoke it bare.** The no-argument form sweeps
|
||||
`design/gdd/` only, and a brownfield project's GDDs are not guaranteed to live
|
||||
there — pass whatever paths Phase 1 found. The script prints a `PRESENT:` list
|
||||
and, when applicable, an `ABSENT:` list per file. It reports **presence only**
|
||||
and makes no REQUIRED/ADVISORY judgment (that is the tier logic below), and it
|
||||
already accepts `## Detailed Design` as satisfying the `Detailed Rules`
|
||||
requirement, so do not flag that alias as missing.
|
||||
|
||||
If the script prints `Not found:` for a path or errors, that is a **discovery
|
||||
failure, not a format gap** — report it as "could not audit [path]" and do not
|
||||
count it as a missing-sections finding.
|
||||
|
||||
**Then apply the workflow tier** resolved above to each file's PRESENT/ABSENT
|
||||
lists. Which sections are **required** (a miss = gap) vs **advisory** (a miss =
|
||||
informational):
|
||||
- **`full`** — all 8 sections are required.
|
||||
- **`standard`** — the 5 required (Overview, Detailed Rules, Edge Cases,
|
||||
Dependencies, Acceptance Criteria) + Formulas for any system that defines
|
||||
numeric rules (rates, curves, thresholds, costs — the system's `Category` is a
|
||||
hint, not the test); Player Fantasy and Tuning Knobs are advisory.
|
||||
- **`minimal`** — GDDs are not expected; audit `design/game-brief.md` instead,
|
||||
against `.claude/docs/templates/game-brief.md`: each of the six required fields
|
||||
present and not a placeholder; the three one-liners advisory. Any GDD that
|
||||
does exist is checked at the `standard` bar, advisorily.
|
||||
|
||||
The script's 8 canonical labels are: Overview, Player Fantasy, Detailed Rules,
|
||||
Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria.
|
||||
|
||||
A section reported PRESENT can still be an empty heading. For each GDD, also
|
||||
record with a targeted grep (not a full read):
|
||||
- Placeholder-only sections — `Grep pattern="\[To be designed\]"` (or an
|
||||
equivalent empty/single-line body) marks a present-but-unwritten section.
|
||||
- The `**Status**:` header field — `Grep pattern="^>?[[:space:]]*\*\*Status\*\*:"`.
|
||||
Valid values: `Draft`, `In Design`, `Designed`, `In Review`, `Approved`,
|
||||
`Implemented`, `Needs Revision`.
|
||||
|
||||
> **The `>?` is load-bearing, and so are `Draft`/`Implemented`.** Both emitters
|
||||
> write this field inside a blockquote — `.claude/docs/templates/game-design-document.md`
|
||||
> and `/design-system` produce `> **Status**: …` — so an anchor of
|
||||
> `^\*\*Status\*\*:` matches nothing and reports *every* template-compliant GDD
|
||||
> as missing its Status. The template's own value list offers `Draft` and
|
||||
> `Implemented`, so both must count as valid.
|
||||
|
||||
### 2b: ADR Format Audit
|
||||
|
||||
For each ADR file found, check for these critical sections:
|
||||
|
||||
| Section | Impact if missing |
|
||||
|---|---|
|
||||
| `## Status` | **BLOCKING** — `/story-readiness` ADR status check silently passes everything |
|
||||
| `## ADR Dependencies` | HIGH — dependency ordering in `/architecture-review` breaks |
|
||||
| `## Engine Compatibility` | HIGH — post-cutoff API risk is unknown |
|
||||
| `## GDD Requirements Addressed` | MEDIUM — traceability matrix loses coverage |
|
||||
| `## Performance Implications` | LOW — not pipeline-critical |
|
||||
|
||||
For each ADR, record: which sections present, which missing, current Status value
|
||||
if the Status section exists.
|
||||
|
||||
### 2c: systems-index.md Format Audit
|
||||
|
||||
If `design/gdd/systems-index.md` exists:
|
||||
|
||||
1. **Parenthetical status values** — Grep for any Status cell containing
|
||||
parentheses: `"Needs Revision ("`, `"In Progress ("`, etc.
|
||||
These break exact-string matching in `/gate-check`, `/create-stories`,
|
||||
and `/architecture-review`. **BLOCKING.**
|
||||
|
||||
2. **Valid status values** — check that Status column values are only from:
|
||||
`Not Started`, `In Progress`, `In Review`, `Designed`, `Approved`, `Needs Revision`
|
||||
Flag any unrecognised values.
|
||||
|
||||
3. **Column structure** — check that the table has at minimum: System name,
|
||||
Layer, Priority, Status columns. Missing columns degrade skill functionality.
|
||||
|
||||
### 2d: Story Format Audit
|
||||
|
||||
For each story file found:
|
||||
|
||||
- **`Manifest Version:` field** — present in story header? (LOW — auto-passes if absent)
|
||||
- **TR-ID reference** — does story contain `TR-[a-z]+-[0-9]+` pattern? (MEDIUM — no staleness tracking)
|
||||
- **ADR reference** — does story reference at least one ADR? (check for `ADR-` pattern)
|
||||
- **Status field** — present and readable?
|
||||
- **Acceptance criteria** — does the story have a checkbox list (`- [ ]`)?
|
||||
|
||||
### 2e: Infrastructure Audit
|
||||
|
||||
| Artifact | Path | Impact if missing |
|
||||
|---|---|---|
|
||||
| TR registry | `docs/architecture/tr-registry.yaml` | HIGH — no stable requirement IDs |
|
||||
| Control manifest | `docs/architecture/control-manifest.md` | HIGH — no layer rules for stories |
|
||||
| Manifest version stamp | In manifest header: `Manifest Version:` | MEDIUM — staleness checks blind |
|
||||
| Sprint status | `production/sprint-status.yaml` | MEDIUM — `/sprint-status` falls back to markdown |
|
||||
| Stage file | `project.stage` in `project.yaml` (fallback `production/stage.txt`) | MEDIUM — phase auto-detect unreliable |
|
||||
| Engine reference | `docs/engine-reference/[engine]/VERSION.md` | HIGH — ADR engine checks blind |
|
||||
| Architecture traceability | `docs/architecture/requirements-traceability.md` | MEDIUM — no persistent matrix |
|
||||
|
||||
At `workflow: minimal` only the Engine reference row applies. The TR registry,
|
||||
control manifest and its version stamp, sprint status, stage file and
|
||||
traceability matrix are not on the minimal path, so their absence is not a gap.
|
||||
|
||||
### 2f: Project Config Audit
|
||||
|
||||
Read `project.yaml` (the primary config store) and `.claude/docs/technical-preferences.md` (legacy mirror). A setting counts as configured if EITHER source has a real value (in technical-preferences.md, `[TO BE CONFIGURED]` means unconfigured):
|
||||
- `engine.name`/`version`/`language`/`rendering`/`physics` (else the Engine/Language/Rendering/Physics fields) → HIGH if unconfigured in both (ADR skills fail)
|
||||
- `naming.*` (else Naming conventions) → MEDIUM
|
||||
- `performance.*` (else Performance budgets) → MEDIUM
|
||||
- Forbidden Patterns, Allowed Libraries (technical-preferences.md only — not migrated to project.yaml) → LOW (starts empty by design)
|
||||
|
||||
### 2g: v1.0 Migration Check
|
||||
|
||||
A project is a **v1.0 project needing migration** when `project.yaml` does NOT
|
||||
exist at the repo root AND at least one legacy file does: `production/stage.txt`,
|
||||
`production/review-mode.txt`, or a `.claude/docs/technical-preferences.md` with
|
||||
real values.
|
||||
|
||||
"Real values" means one of the keys the converter actually migrates — Engine,
|
||||
Language, Rendering, Physics, the naming, platform and performance fields,
|
||||
Framework, or the specialists. Not merely "some bullet is filled in": the
|
||||
shipped template ships one prose default (`- **Required Tests**: …`) that is
|
||||
never migrated, and counting it made every fresh clone read as a v1.0 project.
|
||||
|
||||
Do not hand-migrate. Run the converter, which is deterministic and covered by
|
||||
the framework's own test suite:
|
||||
|
||||
```bash
|
||||
bash .claude/scripts/migrate-v1-config.sh --dry-run
|
||||
```
|
||||
|
||||
The dry run writes nothing; record what it lists for the report. Do not run the
|
||||
converter during the audit — Phase 2 reads silently. The migration is
|
||||
classified BLOCKING in Phase 3, heads the plan, and **Phase 7 offers it as the
|
||||
first action**: report what the dry run listed, then ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`." If
|
||||
the user approves, run it without `--dry-run`. It
|
||||
writes `project.yaml` plus `production/migration-report.md` and **deletes
|
||||
nothing** — the whole operation stays reversible with `git checkout`.
|
||||
|
||||
Then tell the user to read `production/migration-report.md` before running:
|
||||
|
||||
```bash
|
||||
bash .claude/scripts/migrate-v1-config.sh --finalize
|
||||
```
|
||||
|
||||
`--finalize` deletes a legacy file only after proving its value is present in
|
||||
`project.yaml`; on mismatch it deletes nothing and exits 4. It never deletes
|
||||
`technical-preferences.md`, which still holds Forbidden Patterns and Allowed
|
||||
Libraries.
|
||||
|
||||
**If the script refuses with exit 3**, do not work around it. Exit 3 means one
|
||||
of two things, and the message says which:
|
||||
|
||||
- **the values DISAGREE** — two sources of truth and no way to know which the
|
||||
user edited last. Surface it and let them decide.
|
||||
- **a `production/migration-report.md` is already present** — a migration ran
|
||||
here, so these are post-migration leftovers and `--finalize` is the next step,
|
||||
not a second `migrate`.
|
||||
|
||||
Both files merely *existing* is not exit 3 and must not be reported as a
|
||||
conflict: `/start` writes `production/stage.txt` on every new v1.1 project as a
|
||||
mirror, so agreement is the normal state. The script says
|
||||
`the legacy files mirror it (values agree)` and exits 0 for that.
|
||||
|
||||
Classify as **BLOCKING** in Phase 3: until migration runs, every skill reads
|
||||
config through the legacy fallback chain, and v1.1 settings are unavailable.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,29 @@
|
||||
# /adopt — Phase 3: Classify and Prioritise Gaps
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 3: Classify and Prioritise Gaps
|
||||
|
||||
Organise every gap found across all audits into four severity tiers:
|
||||
|
||||
**BLOCKING** — Will cause template skills to silently produce wrong results *right now*.
|
||||
Examples: ADR missing Status field, systems-index parenthetical status values,
|
||||
engine not configured when ADRs exist.
|
||||
|
||||
**HIGH** — Will cause stories to be generated with missing safety checks, or
|
||||
infrastructure bootstrapping will fail.
|
||||
Examples: ADRs missing Engine Compatibility, GDDs missing Acceptance Criteria
|
||||
(stories can't be generated from them), tr-registry.yaml missing.
|
||||
|
||||
**MEDIUM** — Degrades quality and pipeline tracking but does not break functionality.
|
||||
Examples: GDDs missing Tuning Knobs or Formulas sections, stories missing TR-IDs,
|
||||
sprint-status.yaml missing.
|
||||
|
||||
**LOW** — Retroactive improvements that are nice-to-have but not urgent.
|
||||
Examples: Stories missing Manifest Version stamps, GDDs missing Open Questions section.
|
||||
|
||||
Count totals per tier. If zero BLOCKING and zero HIGH gaps: report that the project
|
||||
is template-compatible and only advisory improvements remain.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,53 @@
|
||||
# /adopt — Phase 4: Build the Migration Plan
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 4: Build the Migration Plan
|
||||
|
||||
Compose a numbered, ordered action plan. Ordering rules:
|
||||
1. BLOCKING gaps first (must fix before any pipeline skill runs reliably)
|
||||
2. HIGH gaps next, infrastructure before GDD/ADR content (bootstrapping needs correct formats)
|
||||
3. MEDIUM gaps ordered: GDD gaps before ADR gaps before story gaps (stories depend on GDDs and ADRs)
|
||||
4. LOW gaps last
|
||||
|
||||
For each gap, produce a plan entry with:
|
||||
- A clear problem statement (one sentence, no jargon)
|
||||
- The exact command to fix it, if a skill handles it
|
||||
- Manual steps if it requires direct editing
|
||||
- A time estimate (rough: 5 min / 30 min / 1 session)
|
||||
- A checkbox `- [ ]` for tracking
|
||||
|
||||
**Special case — systems-index parenthetical status values:**
|
||||
This is always the first item if present. Show the exact values that need changing
|
||||
and the exact replacement text. Offer to fix this immediately before writing the plan.
|
||||
|
||||
**Special case — ADRs missing Status field:**
|
||||
For each affected ADR, the fix is:
|
||||
`/architecture-decision retrofit docs/architecture/adr-[NNNN]-[slug].md`
|
||||
List each ADR as a separate checkable item.
|
||||
|
||||
**Special case — GDDs missing sections:**
|
||||
For each affected GDD, list which sections are missing and the fix:
|
||||
`/design-system retrofit design/gdd/[filename].md`
|
||||
|
||||
**Infrastructure bootstrap ordering** — always present in this sequence:
|
||||
1. Fix ADR formats first (registry depends on reading ADR Status fields)
|
||||
2. Run `/architecture-review` → bootstraps `tr-registry.yaml`
|
||||
3. Run `/create-control-manifest` → creates manifest with version stamp
|
||||
4. Run `/sprint-plan update` → creates `sprint-status.yaml`
|
||||
5. Run `/gate-check [phase]` (the gate into the phase the project is in; at Concept there is none — Concept is the default stage, nothing to run) → writes `project.stage` in `project.yaml` (and legacy `stage.txt`) authoritatively
|
||||
|
||||
**At `workflow: minimal` the plan prescribes none of this sequence.** None of it
|
||||
is on the minimal path: ADRs are not expected, the brief's build order is the
|
||||
plan (no `/sprint-plan`), and nothing there runs `/gate-check`. The plan's
|
||||
Step 3 says so in one line and names the path's next step instead —
|
||||
`/create-stories` when no stories exist, else `/dev-story`.
|
||||
|
||||
**Existing stories** — note explicitly:
|
||||
> "Existing stories continue to work with all template skills — all new format
|
||||
> checks auto-pass when the fields are absent. They won't benefit from TR-ID
|
||||
> staleness tracking or manifest version checks until they're regenerated. This
|
||||
> is intentional: do not regenerate stories that are already in progress."
|
||||
|
||||
---
|
||||
@@ -0,0 +1,48 @@
|
||||
# /adopt — Phase 5: Present Summary and Ask to Write
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 5: Present Summary and Ask to Write
|
||||
|
||||
Present a compact summary before writing:
|
||||
|
||||
```
|
||||
## Adoption Audit Summary
|
||||
Phase detected: [phase]
|
||||
Engine: [configured / NOT CONFIGURED]
|
||||
GDDs audited: [N] ([X] fully compliant, [Y] with gaps)
|
||||
ADRs audited: [N] ([X] fully compliant, [Y] with gaps)
|
||||
Stories audited: [N]
|
||||
|
||||
Gap counts:
|
||||
BLOCKING: [N] — template skills will malfunction without these fixes
|
||||
HIGH: [N] — unsafe to run /create-stories or /story-readiness
|
||||
MEDIUM: [N] — quality degradation
|
||||
LOW: [N] — optional improvements
|
||||
|
||||
Estimated remediation: [X blocking items × ~Y min each = roughly Z hours]
|
||||
```
|
||||
|
||||
Before asking to write, show a **Gap Preview**:
|
||||
- List every BLOCKING gap as a one-line bullet describing the actual problem
|
||||
(e.g. `systems-index.md: 3 rows have parenthetical status values`,
|
||||
`adr-0002.md: missing ## Status section`). No counts — show the actual items.
|
||||
- Show HIGH / MEDIUM / LOW as counts only (e.g. `HIGH: 4, MEDIUM: 2, LOW: 1`).
|
||||
|
||||
This gives the user enough context to judge scope before committing to writing the file.
|
||||
|
||||
If a prior adoption plan was detected in Phase 1, add a note:
|
||||
> "A previous plan exists at `docs/adoption-plan-[prior-date].md`. The new plan will
|
||||
> reflect current project state — it does not diff against the prior run."
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- "Ready to write the migration plan?"
|
||||
- "Yes — write `docs/adoption-plan-[date].md`"
|
||||
- "Show me the full plan preview first (don't write yet)"
|
||||
- "Cancel — I'll handle migration manually"
|
||||
|
||||
If the user picks "Show me the full plan preview", output the complete plan as a
|
||||
fenced markdown block. Then ask again with the same three options.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,113 @@
|
||||
# /adopt — Phases 6 and 6b: Write the Adoption Plan and Report Review Mode
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 6: Write the Adoption Plan
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Phase 6: the adoption plan template, then the write
|
||||
- Phase 6b: Report Review Mode
|
||||
|
||||
If approved, write `docs/adoption-plan-[date].md` with this structure:
|
||||
|
||||
```markdown
|
||||
# Adoption Plan
|
||||
|
||||
> **Generated**: [date]
|
||||
> **Project phase**: [phase]
|
||||
> **Engine**: [name + version, or "Not configured"]
|
||||
> **Template version**: v1.0+
|
||||
|
||||
Work through these steps in order. Check off each item as you complete it.
|
||||
Re-run `/adopt` anytime to check remaining gaps.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Fix Blocking Gaps
|
||||
|
||||
[One sub-section per blocking gap with problem, fix command, time estimate, checkbox]
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Fix High-Priority Gaps
|
||||
|
||||
[One sub-section per high gap]
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Bootstrap Infrastructure
|
||||
|
||||
[At `workflow: minimal`, replace 3a–3d with one line: "Not on the minimal path —
|
||||
the brief's build order is the plan. Next: `/create-stories` (or `/dev-story`
|
||||
once stories exist)."]
|
||||
|
||||
### 3a. Register existing requirements (creates tr-registry.yaml)
|
||||
Run `/architecture-review` — even if ADRs already exist, this run bootstraps
|
||||
the TR registry from your existing GDDs and ADRs.
|
||||
**Time**: 1 session (review can be long for large codebases)
|
||||
- [ ] tr-registry.yaml created
|
||||
|
||||
### 3b. Create control manifest
|
||||
Run `/create-control-manifest`
|
||||
**Time**: 30 min
|
||||
- [ ] docs/architecture/control-manifest.md created
|
||||
|
||||
### 3c. Create sprint tracking file
|
||||
Run `/sprint-plan update`
|
||||
**Time**: 5 min (if sprint plan already exists as markdown)
|
||||
- [ ] production/sprint-status.yaml created
|
||||
|
||||
### 3d. Set authoritative project stage
|
||||
Run `/gate-check [current-phase]` (the gate into the phase the project is in;
|
||||
at Concept there is none — Concept is the default stage, nothing to run)
|
||||
**Time**: 5 min
|
||||
- [ ] `project.stage` in `project.yaml` written (legacy `production/stage.txt` also updated)
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Medium-Priority Gaps
|
||||
|
||||
[One sub-section per medium gap]
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Optional Improvements
|
||||
|
||||
[One sub-section per low gap]
|
||||
|
||||
---
|
||||
|
||||
## What to Expect from Existing Stories
|
||||
|
||||
Existing stories continue to work with all template skills. New format checks
|
||||
(TR-ID validation, manifest version staleness) auto-pass when the fields are
|
||||
absent — so nothing breaks. They won't benefit from staleness tracking until
|
||||
regenerated. Do not regenerate stories that are in progress or done.
|
||||
|
||||
---
|
||||
|
||||
## Re-run
|
||||
|
||||
Run `/adopt` again after completing Step 3 to verify all blocking and high gaps
|
||||
are resolved. The new run will reflect the current state of the project.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6b: Report Review Mode
|
||||
|
||||
**Do not write a review mode.** `modes.review_mode` is one of the six knobs
|
||||
`modes.rigor` fronts: pinning it in `project.yaml` shadows the rigor expansion, and
|
||||
the legacy `production/review-mode.txt` sits *above* that expansion in resolution,
|
||||
so either write would freeze director-review depth for good — the rule `/start`
|
||||
and `project.yaml`'s header comment both state.
|
||||
|
||||
Report the value the bootstrap above resolved instead: "Review mode resolves to
|
||||
`[value]` — from `modes.rigor`, unless something pins it." If the user wants a
|
||||
different depth, point them to changing `modes.rigor`, or to pinning it on purpose
|
||||
with `/settings --local modes.review_mode=<full|lean|solo>` (a personal override in
|
||||
`project.local.yaml`).
|
||||
|
||||
---
|
||||
@@ -0,0 +1,62 @@
|
||||
# /adopt — Phase 7: Offer First Action
|
||||
|
||||
> Part of `/adopt`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 7: Offer First Action
|
||||
|
||||
After writing the plan, don't stop there. Pick the single highest-priority gap
|
||||
and offer to handle it immediately using `AskUserQuestion`. Choose the first
|
||||
branch that applies:
|
||||
|
||||
**If Phase 2g found a v1.0 project needing migration:** offer the converter run
|
||||
described there — report what the dry run listed and ask "May I run the
|
||||
converter? It writes `project.yaml` and `production/migration-report.md`."
|
||||
Every other fix reads config through it, so it comes first.
|
||||
|
||||
**If there are parenthetical status values in systems-index.md:**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent fix is `systems-index.md` — [N] rows have parenthetical status
|
||||
values (e.g. `Needs Revision (see notes)`) that break /gate-check,
|
||||
/create-stories, and /architecture-review right now. I can fix these in-place."
|
||||
- "Fix it now — edit systems-index.md"
|
||||
- "I'll fix it myself"
|
||||
- "Done — leave me with the plan"
|
||||
|
||||
**If ADRs are missing `## Status` (and no parenthetical issue):**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent fix is adding `## Status` to [N] ADR(s): [list filenames].
|
||||
Without it, /story-readiness silently passes all ADR checks. Start with
|
||||
[first affected filename]?"
|
||||
- "Yes — retrofit [first affected filename] now"
|
||||
- "Retrofit all [N] ADRs one by one"
|
||||
- "I'll handle ADRs myself"
|
||||
|
||||
**If GDDs are missing Acceptance Criteria (and no blocking issues above):**
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent gap is missing Acceptance Criteria in [N] GDD(s):
|
||||
[list filenames]. Without them, /create-stories can't generate stories.
|
||||
Start with [highest-priority GDD filename]?"
|
||||
- "Yes — add Acceptance Criteria to [GDD filename] now"
|
||||
- "Do all [N] GDDs one by one"
|
||||
- "I'll handle GDDs myself"
|
||||
|
||||
**Otherwise, if any BLOCKING or HIGH gap remains** (one no branch above names —
|
||||
e.g. a missing TR registry):
|
||||
Use `AskUserQuestion`:
|
||||
- "The most urgent remaining gap is [first BLOCKING or HIGH item in the plan] —
|
||||
[one line on what it breaks]. Start on it now?"
|
||||
- "Yes — start on [item]"
|
||||
- "Show me that plan item first"
|
||||
- "Done — leave me with the plan"
|
||||
|
||||
**If no BLOCKING or HIGH gaps exist:**
|
||||
Use `AskUserQuestion`:
|
||||
- "No blocking gaps — this project is template-compatible. What next?"
|
||||
- "Walk me through the medium-priority improvements"
|
||||
- "Run /project-stage-detect for a broader health check"
|
||||
- "Done — I'll work through the plan at my own pace"
|
||||
|
||||
> **Adoption plan saved to `docs/adoption-plan-[date].md`.** Re-run `/adopt` at any time to re-check remaining gaps as you complete them.
|
||||
|
||||
---
|
||||
@@ -12,15 +12,14 @@ model: sonnet
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
|
||||
defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
# Architecture Decision
|
||||
|
||||
When this skill is invoked:
|
||||
|
||||
## 0. Parse Arguments — Detect Retrofit / Acceptance Mode
|
||||
|
||||
|
||||
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
|
||||
|
||||
|
||||
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
(collaborative asks always · guided major-only · autonomous logs and proceeds;
|
||||
`automation_always_ask` categories always prompt).
|
||||
@@ -46,135 +45,12 @@ density.
|
||||
- `minimal` — not required. Can still be run voluntarily.
|
||||
|
||||
**If the argument starts with `retrofit` followed by a file path**
|
||||
(e.g., `/architecture-decision retrofit docs/architecture/adr-0001-event-system.md`):
|
||||
|
||||
Enter **retrofit mode**:
|
||||
|
||||
1. Read the existing ADR file completely.
|
||||
2. Identify which template sections are present by scanning headings:
|
||||
- `## Status` — **BLOCKING if missing**: `/story-readiness` cannot check ADR acceptance
|
||||
- `## ADR Dependencies` — HIGH if missing: dependency ordering breaks
|
||||
- `## Engine Compatibility` — HIGH if missing: post-cutoff risk unknown
|
||||
- `## GDD Requirements Addressed` — MEDIUM if missing: traceability lost
|
||||
- `## Date` — MEDIUM if missing, and no `## Last Verified` either: `/create-stories`
|
||||
stamps stories with it and `/dev-story` compares against it, so without it a
|
||||
story can never tell whether the ADR changed
|
||||
3. Present to the user:
|
||||
```
|
||||
## Retrofit: [ADR title]
|
||||
File: [path]
|
||||
|
||||
Sections already present (will not be touched):
|
||||
✓ Status: [current value, or "MISSING — will add"]
|
||||
✓ [section]
|
||||
|
||||
Missing sections to add:
|
||||
✗ Status — BLOCKING (stories cannot validate ADR acceptance without this)
|
||||
✗ ADR Dependencies — HIGH
|
||||
✗ Engine Compatibility — HIGH
|
||||
```
|
||||
4. Ask: "Shall I add the [N] missing sections? I will not modify any existing content."
|
||||
If no: write nothing, and report the missing sections by name.
|
||||
5. If yes:
|
||||
- For **Status**: ask the user — "What is the current status of this decision?"
|
||||
Options: "Proposed", "Accepted", "Deprecated", "Superseded by ADR-XXXX"
|
||||
An `Accepted` answer — a decision already in force — is not written as
|
||||
given: write `Proposed`, add the other missing sections, then run
|
||||
acceptance mode (below) on this ADR. Its dependency check, confirmation and
|
||||
story unblocking apply here too; it stays the only path that sets `Accepted`.
|
||||
- For **ADR Dependencies**: ask — "Does this decision depend on any other ADR?
|
||||
Does it enable or block any other ADR or epic?" Accept "None" for each field.
|
||||
- For **Engine Compatibility**: read the engine reference docs (same as Step 1 below)
|
||||
and ask the user to confirm the domain. Then generate the table with verified data.
|
||||
- For **GDD Requirements Addressed**: ask — "Which GDD systems motivated this decision?
|
||||
What specific requirement in each GDD does this ADR address?"
|
||||
- Append each missing section to the ADR file using the Edit tool.
|
||||
- For **Date** (counted only when there is no `## Last Verified`): append
|
||||
`## Date` with today's date — even when it is the only missing section, the
|
||||
case `/dev-story` sends you here for — and say that it records the retrofit,
|
||||
not when the decision was made.
|
||||
- **Never modify any existing section.** Only append or fill absent sections.
|
||||
6. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
|
||||
has its Status and Dependencies fields."
|
||||
**Read `references/0-retrofit.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
**If the argument starts with `accept` followed by an ADR id**
|
||||
(e.g., `/architecture-decision accept ADR-0005`):
|
||||
|
||||
Enter **acceptance mode**. This is the *only* path in the framework that moves an
|
||||
ADR from `Proposed` to `Accepted`. Authoring always produces `Proposed`
|
||||
(Step 5), while
|
||||
`/create-control-manifest`, `/create-epics`, `/create-stories` and `/gate-check`
|
||||
all require `Accepted` — so without this mode the pipeline had a state it could
|
||||
enter and never leave.
|
||||
|
||||
1. **Resolve the id to a file, then read it.** Glob
|
||||
`docs/architecture/adr-NNNN-*.md` for the given number. If **no** file matches,
|
||||
or **more than one** does, stop and say which — do not pick one. If the file
|
||||
has no `## Status` section, stop and say so; a missing Status is exactly what
|
||||
retrofit mode is for.
|
||||
2. **Check the current status.** If it is already `Accepted`, say so and stop.
|
||||
If it is `Deprecated` or `Superseded`, refuse: reviving a superseded decision
|
||||
is a new ADR, not a status edit.
|
||||
3. **Check its dependencies first.** Read `## ADR Dependencies`.
|
||||
|
||||
**If that section is absent, empty, or reads `UNKNOWN`, do not read it as
|
||||
"no dependencies" — refuse and say which:**
|
||||
> "ADR-0005's dependency section is [absent / UNKNOWN], so I cannot tell what
|
||||
> this decision rests on. An empty dependency list and an unexamined one look
|
||||
> identical here, and only one of them is safe to accept. Run
|
||||
> `/architecture-decision retrofit <path>` to establish it."
|
||||
|
||||
A dependency check reading a field that defaults to empty is the vacuous-pass
|
||||
shape this gate exists to prevent — the check would examine nothing and report
|
||||
clean.
|
||||
|
||||
If it depends on any ADR that is not itself `Accepted`, **refuse and name them**:
|
||||
> "ADR-0005 depends on ADR-0002, which is still Proposed. Accept ADR-0002
|
||||
> first — an accepted decision resting on an unaccepted one is not a decision,
|
||||
> it is a deferral with a different label."
|
||||
This is the same dependency rule `/architecture-review` already flags; here it
|
||||
is enforced rather than reported.
|
||||
4. **Confirm with the user, always.** Per `CONTRACT.md`, acceptance authority is
|
||||
**the user, or `technical-director` on the user's explicit confirmation — no
|
||||
other agent, and never this skill on its own.** Use `AskUserQuestion`:
|
||||
- Prompt: "Accept ADR-NNNN — [title]? This is what unblocks stories and epics
|
||||
that depend on it."
|
||||
- Options: `[A] Yes — accept it` / `[B] Not yet — leave it Proposed`
|
||||
**This prompt fires regardless of `modes.automation`, including `autonomous`.**
|
||||
Acceptance is the decision the whole architecture pipeline gates on; it is not
|
||||
a step to be inferred.
|
||||
5. **Find the stories this will unblock, BEFORE the prompt in step 4.** Grep
|
||||
every story for a Blocked Status line —
|
||||
`Grep pattern="Status\**:\**\s*Blocked" path="production/epics" glob="**/story-*.md" output_mode="files_with_matches"`,
|
||||
which matches `> **Status**: Blocked` (the form `/create-stories` writes),
|
||||
`**Status:** Blocked` and `Status: Blocked` — and keep the files that name
|
||||
this ADR's id as the reason they are blocked. That pairing is what "blocked
|
||||
pending this ADR" means — a story blocked for an unrelated reason will not
|
||||
name it. Leave out a story that names this ADR only as the successor to point
|
||||
at (`point the story at ADR-NNNN`, the note for a `Deprecated` or
|
||||
`Superseded` ADR): it is still governed by the old ADR, and accepting the
|
||||
successor does not re-point it.
|
||||
> **Stories live only under `production/epics/`.** A flat top-level stories
|
||||
> directory does not exist and no skill creates one — never write or match a
|
||||
> path outside `production/epics/`. `/dev-story` matches entries *by file
|
||||
> path*, so a story recorded under any other path silently fails to match and
|
||||
> never gets picked up.
|
||||
|
||||
Feed the count into step 4's prompt so it reads *"3 stories become Ready"*
|
||||
rather than a generic claim: **the user is being asked to authorise an effect, and should be
|
||||
shown the effect.** If none match, say "no stories are waiting on this" — that
|
||||
is useful information, not an empty result to omit.
|
||||
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Leave an existing
|
||||
`## Date` as it is: it records when the ADR was written, and `/create-stories`
|
||||
stamps stories with it (or `## Last Verified`), so rewriting it on acceptance
|
||||
would make every story drafted against the Proposed ADR look out of date to
|
||||
`/dev-story`. **If that section is absent, add it** with today's date — retrofit
|
||||
mode already owns this shape, and acceptance must not fail on a template that
|
||||
predates the field.
|
||||
7. Then set each story found in step 5 from `Blocked` to `Ready`. Unblocking is a
|
||||
consequence of acceptance, never of authoring — see Step 6's note below.
|
||||
8. Report what moved: the ADR (and its `## Date`, if one was added), and every
|
||||
story that became Ready.
|
||||
**Read `references/0-accept.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
If NOT in retrofit or acceptance mode, proceed to Step 1 below (normal ADR authoring).
|
||||
|
||||
@@ -190,47 +66,7 @@ Use the user's response as the title, then proceed to Step 1.
|
||||
|
||||
## 1. Load Engine Context (ALWAYS FIRST)
|
||||
|
||||
Before doing anything else, establish the engine environment:
|
||||
|
||||
1. Read `docs/engine-reference/[engine]/VERSION.md` to get:
|
||||
- Engine name and version
|
||||
- LLM knowledge cutoff date
|
||||
- Post-cutoff version risk levels (LOW / MEDIUM / HIGH)
|
||||
|
||||
2. Identify the **domain** of this architecture decision from the title or
|
||||
user description. Common domains: Physics, Rendering, UI, Audio, Navigation,
|
||||
Animation, Networking, Core, Input, Scripting.
|
||||
|
||||
3. Read the corresponding module reference if it exists:
|
||||
`docs/engine-reference/[engine]/modules/[domain].md`
|
||||
|
||||
4. Read `docs/engine-reference/[engine]/breaking-changes.md` — flag any
|
||||
changes in the relevant domain that post-date the LLM's training cutoff.
|
||||
|
||||
5. Read `docs/engine-reference/[engine]/deprecated-apis.md` — flag any APIs
|
||||
in the relevant domain that should not be used.
|
||||
|
||||
6. **Display a knowledge gap warning** before proceeding if the domain carries
|
||||
MEDIUM or HIGH risk:
|
||||
|
||||
```
|
||||
⚠️ ENGINE KNOWLEDGE GAP WARNING
|
||||
Engine: [name + version]
|
||||
Domain: [domain]
|
||||
Risk Level: HIGH — This version is post-LLM-cutoff.
|
||||
|
||||
Key changes verified from engine-reference docs:
|
||||
- [Change 1 relevant to this domain]
|
||||
- [Change 2]
|
||||
|
||||
This ADR will be cross-referenced against the engine reference library.
|
||||
Proceed with verified information only — do NOT rely solely on training data.
|
||||
```
|
||||
|
||||
If no engine has been configured yet, prompt: "No engine is configured.
|
||||
Run `/setup-engine` first, or tell me which engine you are using."
|
||||
|
||||
---
|
||||
**Read `references/1-engine-context.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## 2. Determine the next ADR number
|
||||
|
||||
@@ -240,379 +76,15 @@ Scan `docs/architecture/` for existing ADRs to find the next number.
|
||||
|
||||
## 3. Gather context
|
||||
|
||||
### 3a: Architecture Registry Check (BLOCKING gate) — do this FIRST
|
||||
|
||||
Read `docs/registry/architecture.yaml`. Extract entries relevant to this ADR's
|
||||
domain and decision (grep by system name, domain keyword, or state being touched).
|
||||
Run this before reading any existing ADR — the registry exists specifically so a
|
||||
new ADR's author does not need to open prior ADRs to learn their binding facts
|
||||
(state ownership, interface contracts, forbidden patterns).
|
||||
|
||||
Present any relevant stances to the user **before** the collaborative design
|
||||
begins, as locked constraints:
|
||||
|
||||
```
|
||||
## Existing Architectural Stances (must not contradict)
|
||||
|
||||
State Ownership:
|
||||
player_health → owned by health-system (ADR-0001)
|
||||
Interface: HealthComponent.current_health (read-only float)
|
||||
→ If this ADR reads or writes player health, it must use this interface.
|
||||
|
||||
Interface Contracts:
|
||||
damage_delivery → signal pattern (ADR-0003)
|
||||
Signal: damage_dealt(amount, target, is_crit)
|
||||
→ If this ADR delivers or receives damage events, it must use this signal.
|
||||
|
||||
Forbidden Patterns:
|
||||
✗ autoload_singleton_coupling (ADR-0001)
|
||||
✗ direct_cross_system_state_write (ADR-0000)
|
||||
→ The proposed approach must not use these patterns.
|
||||
```
|
||||
|
||||
If the user's proposed decision would contradict any registered stance, surface
|
||||
the conflict immediately:
|
||||
|
||||
> "⚠️ Conflict: This ADR proposes [X], but ADR-[NNNN] established that [Y] is
|
||||
> the accepted pattern for this purpose. Proceeding without resolving this will
|
||||
> produce contradictory ADRs and inconsistent stories.
|
||||
> Options: (1) Align with the existing stance, (2) Supersede ADR-[NNNN] with
|
||||
> an explicit replacement, (3) Explain why this case is an exception."
|
||||
|
||||
Do not proceed to Step 4 (collaborative design) until any conflict is resolved
|
||||
or explicitly accepted as an intentional exception.
|
||||
|
||||
### 3b: Existing ADRs and Related GDDs — registry-scoped, never unbounded
|
||||
|
||||
The registry (3a) covers *what* prior decisions bind — not always *why*. If the
|
||||
registry surfaced a directly relevant ADR and its reasoning matters here (not
|
||||
just its stated facts), read that specific ADR — never glob-and-read every
|
||||
ADR in `docs/architecture/` on the chance one is relevant:
|
||||
|
||||
1. **Map its headings first** (cheap):
|
||||
```
|
||||
Grep pattern="^## " path="docs/architecture/[adr-file].md" output_mode="content" -n
|
||||
```
|
||||
2. **Under ~50KB** (`Bash: wc -c "docs/architecture/[adr-file].md"`) — one full
|
||||
`Read` is fine; per-call overhead exceeds the savings from bounded reads at
|
||||
this size.
|
||||
3. **~50KB or larger** — bounded-read only `## Context`, `## Decision`, and
|
||||
`## Consequences` (the sections that carry reasoning, not just facts) via
|
||||
`Read(offset, limit)` from the heading map.
|
||||
|
||||
Read GDDs the same way `/design-system` Step 2b does: only GDDs the registry
|
||||
or the ADR list names as directly relevant, and only their `## Dependencies`,
|
||||
`## Formulas`, and `## Edge Cases` sections
|
||||
(`Grep pattern="^## (Dependencies|Formulas|Edge Cases)" ... -A 40`) — never a
|
||||
speculative full read of `design/gdd/*.md` looking for anything that might
|
||||
relate.
|
||||
|
||||
Skip 3b entirely if the registry already answers everything this decision
|
||||
needs — most ADRs will.
|
||||
|
||||
---
|
||||
**Read `references/3-gather-context.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## 4. Guide the decision collaboratively
|
||||
|
||||
Before asking anything, derive the skill's best guesses from the context already
|
||||
gathered (GDDs read, engine reference loaded, existing ADRs scanned). Then present
|
||||
a **confirm/adjust** prompt using `AskUserQuestion` — not open-ended questions.
|
||||
|
||||
**Derive assumptions first:**
|
||||
- **Problem**: Infer from the title + GDD context what decision needs to be made
|
||||
- **Alternatives**: Propose 2-3 concrete options from engine reference + GDD requirements
|
||||
- **Dependencies**: Scan existing ADRs for upstream dependencies. **If the scan is
|
||||
inconclusive, present `UNKNOWN — scan inconclusive, please confirm`, never
|
||||
`None`.** The two are not interchangeable: `None` asserts that nothing upstream
|
||||
constrains this decision, and a user confirming a prefilled list cannot tell an
|
||||
assertion from a guess. This field is load-bearing — `/architecture-review`
|
||||
flags unaccepted dependencies, `/dev-story` reads it, and the acceptance route
|
||||
in Phase 0 **refuses to accept an ADR whose dependencies are not themselves
|
||||
Accepted**. A dependency list that defaulted to empty makes that check pass
|
||||
while examining nothing. `UNKNOWN` must be resolved during the confirm/adjust
|
||||
prompt; it is a prompt state, never a value written to the file
|
||||
- **GDD linkage**: Extract which GDD systems the title directly relates to
|
||||
- **Status**: Always `Proposed` for new ADRs — never ask the user what the status is
|
||||
|
||||
**Scope of assumptions tab**: Assumptions cover only: problem framing, alternative approaches, upstream dependencies, GDD linkage, and status. Schema design questions (e.g., "How should spawn timing work?", "Should data be inline or external?") are NOT assumptions — they are design decisions belonging to a separate step after the assumptions are confirmed. Do not include schema design questions in the assumptions AskUserQuestion widget.
|
||||
|
||||
**After assumptions are confirmed**, if the ADR involves schema or data design choices, use a separate multi-tab `AskUserQuestion` to ask each design question independently before drafting.
|
||||
|
||||
**Present assumptions with `AskUserQuestion`:**
|
||||
|
||||
```
|
||||
Here's what I'm assuming before drafting:
|
||||
|
||||
Problem: [one-sentence problem statement derived from context]
|
||||
Alternatives I'll consider:
|
||||
A) [option derived from engine reference]
|
||||
B) [option derived from GDD requirements]
|
||||
C) [option from common patterns]
|
||||
GDD systems driving this: [list derived from context]
|
||||
Dependencies: [upstream ADRs if any, otherwise "None"]
|
||||
Status: Proposed
|
||||
|
||||
[A] Proceed — draft with these assumptions
|
||||
[B] Change the alternatives list
|
||||
[C] Adjust the GDD linkage
|
||||
[D] Add a performance budget constraint
|
||||
[E] Something else needs changing first
|
||||
```
|
||||
|
||||
Do not generate the ADR until the user confirms assumptions or provides corrections.
|
||||
|
||||
**After engine specialist and TD reviews return** (Step 5.5/5.6), if unresolved
|
||||
decisions remain, present each one as a separate `AskUserQuestion` with the proposed
|
||||
options as choices plus a free-text escape:
|
||||
|
||||
```
|
||||
Decision: [specific unresolved point]
|
||||
[A] [option from specialist review]
|
||||
[B] [alternative option]
|
||||
[C] Different approach — I'll describe it
|
||||
```
|
||||
|
||||
**ADR Dependencies** — derive from existing ADRs, then confirm:
|
||||
- Does this decision depend on any other ADR not yet Accepted?
|
||||
- Does it unlock or unblock any other ADR or epic?
|
||||
- Does it block any specific epic from starting?
|
||||
|
||||
Record answers in the **ADR Dependencies** section. Write "None" for each field if no constraints apply.
|
||||
|
||||
---
|
||||
**Read `references/4-decide.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## 5. Generate the ADR
|
||||
|
||||
Following this format:
|
||||
|
||||
```markdown
|
||||
# ADR-[NNNN]: [Title]
|
||||
|
||||
## Status
|
||||
[Proposed | Accepted | Deprecated | Superseded by ADR-XXXX]
|
||||
|
||||
## Date
|
||||
[Date of decision]
|
||||
|
||||
## Last Verified
|
||||
[YYYY-MM-DD — when this ADR was last confirmed accurate against the current
|
||||
engine version and design. Update this date when you re-read and confirm it is
|
||||
still correct, even if nothing changed.]
|
||||
|
||||
## Decision Makers
|
||||
[Who was involved in this decision]
|
||||
|
||||
## Summary
|
||||
[2 sentences: what problem this ADR solves, and what was decided. Written for
|
||||
tiered context loading — a skill scanning 20 ADRs uses this to decide whether to
|
||||
read the full decision. Be specific: name the system, the problem, and the
|
||||
chosen approach.]
|
||||
|
||||
## Engine Compatibility
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Engine** | [e.g. Godot 4.6] |
|
||||
| **Domain** | [Physics / Rendering / UI / Audio / Navigation / Animation / Networking / Core / Input] |
|
||||
| **Knowledge Risk** | [LOW / MEDIUM / HIGH — from VERSION.md] |
|
||||
| **References Consulted** | [List engine-reference docs read, e.g. `docs/engine-reference/godot/modules/physics.md`] |
|
||||
| **Post-Cutoff APIs Used** | [Any APIs from post-LLM-cutoff versions this decision depends on, or "None"] |
|
||||
| **Verification Required** | [Specific behaviours to test before shipping, or "None"] |
|
||||
|
||||
## ADR Dependencies
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Depends On** | [ADR-NNNN (must be Accepted before this can be implemented), or "None"] |
|
||||
| **Enables** | [ADR-NNNN (this ADR unlocks that decision), or "None"] |
|
||||
| **Blocks** | [Epic/Story name — cannot start until this ADR is Accepted, or "None"] |
|
||||
| **Ordering Note** | [Any sequencing constraint that isn't captured above] |
|
||||
|
||||
## Context
|
||||
|
||||
### Problem Statement
|
||||
[What problem are we solving? Why does this decision need to be made now?]
|
||||
|
||||
### Constraints
|
||||
- [Technical constraints]
|
||||
- [Timeline constraints]
|
||||
- [Resource constraints]
|
||||
- [Compatibility requirements]
|
||||
|
||||
### Requirements
|
||||
- [Must support X]
|
||||
- [Must perform within Y budget]
|
||||
- [Must integrate with Z]
|
||||
|
||||
## Decision
|
||||
|
||||
[The specific technical decision made, described in enough detail for someone
|
||||
to implement it.]
|
||||
|
||||
### Architecture Diagram
|
||||
[ASCII diagram or description of the system architecture this creates]
|
||||
|
||||
### Key Interfaces
|
||||
[API contracts or interface definitions this decision creates]
|
||||
|
||||
### Implementation Guidelines
|
||||
[Specific guidance for the programmer implementing this decision — the rules a
|
||||
`/create-control-manifest` or `/dev-story` run should follow. State mandates as
|
||||
"must / must never" so they extract cleanly.]
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: [Name]
|
||||
- **Description**: [How this would work]
|
||||
- **Pros**: [Advantages]
|
||||
- **Cons**: [Disadvantages]
|
||||
- **Rejection Reason**: [Why this was not chosen]
|
||||
|
||||
### Alternative 2: [Name]
|
||||
- **Description**: [How this would work]
|
||||
- **Pros**: [Advantages]
|
||||
- **Cons**: [Disadvantages]
|
||||
- **Rejection Reason**: [Why this was not chosen]
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- [Good outcomes of this decision]
|
||||
|
||||
### Negative
|
||||
- [Trade-offs and costs accepted]
|
||||
|
||||
## Risks
|
||||
- [Things that could go wrong]
|
||||
- [Mitigation for each risk]
|
||||
|
||||
## GDD Requirements Addressed
|
||||
|
||||
| GDD System | Requirement | How This ADR Addresses It |
|
||||
|------------|-------------|--------------------------|
|
||||
| [system-name].md | [specific rule, formula, or performance constraint from that GDD] | [how this decision satisfies it] |
|
||||
|
||||
## Performance Implications
|
||||
- **CPU**: [Expected impact]
|
||||
- **Memory**: [Expected impact]
|
||||
- **Load Time**: [Expected impact]
|
||||
- **Network**: [Expected impact, if applicable]
|
||||
|
||||
## Migration Plan
|
||||
[If this changes existing code, how do we get from here to there?]
|
||||
|
||||
## Validation Criteria
|
||||
[How will we know this decision was correct? What metrics or tests?]
|
||||
|
||||
## Related
|
||||
- [Links to related ADRs — note if supersedes, contradicts, or depends on]
|
||||
- [Links to related design documents]
|
||||
```
|
||||
|
||||
5.5. **Engine Specialist Validation** — Before saving, spawn the **primary engine specialist** via `Agent` to validate the drafted ADR:
|
||||
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
|
||||
- If no engine is configured (neither source yields an engine), skip this step **Record ``Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)`` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
|
||||
- Spawn `subagent_type: [primary specialist]` with: the ADR's Engine Compatibility section, Decision section, Key Interfaces, and the engine reference docs path. Ask them to:
|
||||
1. Confirm the proposed approach is idiomatic for the pinned engine version
|
||||
2. Flag any APIs or patterns that are deprecated or changed post-training-cutoff
|
||||
3. Identify engine-specific risks or gotchas not captured in the current ADR draft
|
||||
- If the specialist identifies a **blocking issue** (wrong API, deprecated approach, engine version incompatibility): revise the Decision and Engine Compatibility sections accordingly, then confirm the changes with the user before proceeding
|
||||
- If the specialist finds **minor notes** only: incorporate them into the ADR's Risks subsection
|
||||
|
||||
**Review mode check** — apply before spawning TD-ADR:
|
||||
- `solo` → skip. Note: "TD-ADR skipped — Solo mode." Proceed to Step 5.7 (GDD sync check).
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "TD-ADR skipped — Lean mode." Proceed to Step 5.7 (GDD sync check).
|
||||
- `full` → spawn as normal.
|
||||
|
||||
5.6. **Technical Director Strategic Review** — After the engine specialist validation, spawn `technical-director` via `Agent` using gate **TD-ADR** (`.claude/docs/director-gates/td-adr.md`):
|
||||
- Pass: the ADR file path (or draft content), engine version, domain, any existing ADRs in the same domain
|
||||
- The TD validates architectural coherence (is this decision consistent with the whole system?) — distinct from the engine specialist's API-level check
|
||||
- On CONCERNS: show them to the user verbatim and ask with the standard options from `director-gates.md` — `Revise flagged items` / `Accept and proceed` / `Discuss further`. Revise the flagged Decision or Alternatives sections only on `Revise flagged items`.
|
||||
- On REJECT: show the blockers verbatim and revise the Decision or Alternatives sections before proceeding.
|
||||
- A revised draft still reaches the user through the write approval below; nothing is written before it. A `NOT ASSESSED` answer is not an approval — name the missing input (`director-gates.md`).
|
||||
|
||||
5.7. **GDD Sync Check** — Before presenting the write approval, scan all GDDs
|
||||
referenced in the "GDD Requirements Addressed" section for naming inconsistencies
|
||||
with the ADR's Key Interfaces and Decision sections (renamed signals, API methods,
|
||||
or data types). If any are found, surface them as a **prominent warning block**
|
||||
immediately before the write approval — not as a footnote:
|
||||
|
||||
```
|
||||
⚠️ GDD SYNC REQUIRED
|
||||
[gdd-filename].md uses names this ADR has renamed:
|
||||
[old_name] → [new_name_from_adr]
|
||||
[old_name_2] → [new_name_2_from_adr]
|
||||
The GDD must be updated before or alongside writing this ADR to prevent
|
||||
developers reading the GDD from implementing the wrong interface.
|
||||
```
|
||||
|
||||
**This check has three outcomes, not two.** The two above are "found" and "none
|
||||
found"; the third is **could not check**, and until now it fell through the
|
||||
silent branch and rendered exactly like a clean result.
|
||||
|
||||
- **None found** — print one line, do not stay silent:
|
||||
`GDD sync: checked [N] referenced GDD(s), no naming inconsistencies.`
|
||||
A silent pass is indistinguishable from a check that never ran, and this one
|
||||
guards against developers implementing the wrong interface from a stale GDD.
|
||||
- **Could not check** — the ADR has no `GDD Requirements Addressed` section, it
|
||||
names no GDDs, or a named GDD does not exist on disk. Print:
|
||||
`GDD sync: NOT ASSESSED — [which reason, and which files]`
|
||||
Do **not** treat an ADR that references no GDDs as one whose GDDs are
|
||||
consistent. Nothing was compared.
|
||||
|
||||
Only the warning block itself is conditional; the check always reports.
|
||||
|
||||
5. **Write approval** — Use `AskUserQuestion`:
|
||||
|
||||
If GDD sync issues were found:
|
||||
- "ADR draft is complete. How would you like to proceed?"
|
||||
- [A] Write ADR + update GDD in the same pass
|
||||
- [B] Write ADR only — I'll update the GDD manually
|
||||
- [C] Not yet — I need to review further
|
||||
|
||||
If no GDD sync issues:
|
||||
- "ADR draft is complete. May I write it?"
|
||||
- [A] Write ADR to `docs/architecture/adr-[NNNN]-[slug].md`
|
||||
- [B] Not yet — I need to review further
|
||||
|
||||
If yes to any write option, write the file, creating the directory if needed.
|
||||
For option [A] with GDD update: also update the GDD file(s) to use the new names.
|
||||
|
||||
6. **Update Architecture Registry**
|
||||
|
||||
Scan the written ADR for new architectural stances that should be registered:
|
||||
- State it claims ownership of
|
||||
- Interface contracts it defines (signal signatures, method APIs)
|
||||
- Performance budget it claims
|
||||
- API choices it makes explicitly
|
||||
- Patterns it bans (Consequences → Negative or explicit "do not use X")
|
||||
|
||||
Present candidates:
|
||||
```
|
||||
Registry candidates from this ADR:
|
||||
NEW state ownership: player_stamina → stamina-system
|
||||
NEW interface contract: stamina_depleted signal
|
||||
NEW performance budget: stamina-system: 0.5ms/frame
|
||||
NEW forbidden pattern: polling stamina each frame (use signal instead)
|
||||
EXISTING (referenced_by update only): player_health → already registered ✅
|
||||
```
|
||||
|
||||
**Registry append logic**: When writing to `docs/registry/architecture.yaml`, do NOT assume sections are empty. The file may already have entries from previous ADRs written in this session. Before each Edit call:
|
||||
1. Read the current state of `docs/registry/architecture.yaml`
|
||||
2. Find the correct section (state_ownership, interfaces, forbidden_patterns, api_decisions)
|
||||
3. Append the new entry AFTER the last existing entry in that section — do not try to replace a `[]` placeholder that may no longer exist
|
||||
4. If the section has entries already, use the closing content of the last entry as the `old_string` anchor, and append the new entry after it
|
||||
|
||||
**BLOCKING — do not write to `docs/registry/architecture.yaml` without explicit user approval.**
|
||||
|
||||
Ask using `AskUserQuestion`:
|
||||
- "May I update `docs/registry/architecture.yaml` with these [N] new stances?"
|
||||
- Options: "Yes — update the registry", "Not yet — I want to review the candidates", "Skip registry update"
|
||||
|
||||
Only proceed if the user selects yes. If yes: append new entries. Never modify existing entries — if a stance is
|
||||
changing, set the old entry to `status: superseded_by: ADR-[NNNN]` and add the new entry.
|
||||
|
||||
---
|
||||
**Read `references/5-generate.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## 6. Closing Next Steps
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# /architecture-decision — Acceptance Mode
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
**If the argument starts with `accept` followed by an ADR id**
|
||||
|
||||
(e.g., `/architecture-decision accept ADR-0005`):
|
||||
|
||||
Enter **acceptance mode**. This is the *only* path in the framework that moves an
|
||||
ADR from `Proposed` to `Accepted`. Authoring always produces `Proposed`
|
||||
(Step 5), while
|
||||
`/create-control-manifest`, `/create-epics`, `/create-stories` and `/gate-check`
|
||||
all require `Accepted` — so without this mode the pipeline had a state it could
|
||||
enter and never leave.
|
||||
|
||||
1. **Resolve the id to a file, then read it.** Glob
|
||||
`docs/architecture/adr-NNNN-*.md` for the given number. If **no** file matches,
|
||||
or **more than one** does, stop and say which — do not pick one. If the file
|
||||
has no `## Status` section, stop and say so; a missing Status is exactly what
|
||||
retrofit mode is for.
|
||||
2. **Check the current status.** If it is already `Accepted`, say so and stop.
|
||||
If it is `Deprecated` or `Superseded`, refuse: reviving a superseded decision
|
||||
is a new ADR, not a status edit.
|
||||
3. **Check its dependencies first.** Read `## ADR Dependencies`.
|
||||
|
||||
**If that section is absent, empty, or reads `UNKNOWN`, do not read it as
|
||||
"no dependencies" — refuse and say which:**
|
||||
> "ADR-0005's dependency section is [absent / UNKNOWN], so I cannot tell what
|
||||
> this decision rests on. An empty dependency list and an unexamined one look
|
||||
> identical here, and only one of them is safe to accept. Run
|
||||
> `/architecture-decision retrofit <path>` to establish it."
|
||||
|
||||
A dependency check reading a field that defaults to empty is the vacuous-pass
|
||||
shape this gate exists to prevent — the check would examine nothing and report
|
||||
clean.
|
||||
|
||||
If it depends on any ADR that is not itself `Accepted`, **refuse and name them**:
|
||||
> "ADR-0005 depends on ADR-0002, which is still Proposed. Accept ADR-0002
|
||||
> first — an accepted decision resting on an unaccepted one is not a decision,
|
||||
> it is a deferral with a different label."
|
||||
This is the same dependency rule `/architecture-review` already flags; here it
|
||||
is enforced rather than reported.
|
||||
4. **Confirm with the user, always.** Per `CONTRACT.md`, acceptance authority is
|
||||
**the user, or `technical-director` on the user's explicit confirmation — no
|
||||
other agent, and never this skill on its own.** Use `AskUserQuestion`:
|
||||
- Prompt: "Accept ADR-NNNN — [title]? This is what unblocks stories and epics
|
||||
that depend on it."
|
||||
- Options: `[A] Yes — accept it` / `[B] Not yet — leave it Proposed`
|
||||
**This prompt fires regardless of `modes.automation`, including `autonomous`.**
|
||||
Acceptance is the decision the whole architecture pipeline gates on; it is not
|
||||
a step to be inferred.
|
||||
5. **Find the stories this will unblock, BEFORE the prompt in step 4.** Grep
|
||||
every story for a Blocked Status line —
|
||||
`Grep pattern="Status\**:\**\s*Blocked" path="production/epics" glob="**/story-*.md" output_mode="files_with_matches"`,
|
||||
which matches `> **Status**: Blocked` (the form `/create-stories` writes),
|
||||
`**Status:** Blocked` and `Status: Blocked` — and keep the files that name
|
||||
this ADR's id as the reason they are blocked. That pairing is what "blocked
|
||||
pending this ADR" means — a story blocked for an unrelated reason will not
|
||||
name it. Leave out a story that names this ADR only as the successor to point
|
||||
at (`point the story at ADR-NNNN`, the note for a `Deprecated` or
|
||||
`Superseded` ADR): it is still governed by the old ADR, and accepting the
|
||||
successor does not re-point it.
|
||||
> **Stories live only under `production/epics/`.** A flat top-level stories
|
||||
> directory does not exist and no skill creates one — never write or match a
|
||||
> path outside `production/epics/`. `/dev-story` matches entries *by file
|
||||
> path*, so a story recorded under any other path silently fails to match and
|
||||
> never gets picked up.
|
||||
|
||||
Feed the count into step 4's prompt so it reads *"3 stories become Ready"*
|
||||
rather than a generic claim: **the user is being asked to authorise an effect, and should be
|
||||
shown the effect.** If none match, say "no stories are waiting on this" — that
|
||||
is useful information, not an empty result to omit.
|
||||
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Leave an existing
|
||||
`## Date` as it is: it records when the ADR was written, and `/create-stories`
|
||||
stamps stories with it (or `## Last Verified`), so rewriting it on acceptance
|
||||
would make every story drafted against the Proposed ADR look out of date to
|
||||
`/dev-story`. **If that section is absent, add it** with today's date — retrofit
|
||||
mode already owns this shape, and acceptance must not fail on a template that
|
||||
predates the field.
|
||||
7. Then set each story found in step 5 from `Blocked` to `Ready`. Unblocking is a
|
||||
consequence of acceptance, never of authoring — see Step 6's note below.
|
||||
8. Report what moved: the ADR (and its `## Date`, if one was added), and every
|
||||
story that became Ready.
|
||||
@@ -0,0 +1,57 @@
|
||||
# /architecture-decision — Retrofit Mode
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
**If the argument starts with `retrofit` followed by a file path**
|
||||
|
||||
(e.g., `/architecture-decision retrofit docs/architecture/adr-0001-event-system.md`):
|
||||
|
||||
Enter **retrofit mode**:
|
||||
|
||||
1. Read the existing ADR file completely.
|
||||
2. Identify which template sections are present by scanning headings:
|
||||
- `## Status` — **BLOCKING if missing**: `/story-readiness` cannot check ADR acceptance
|
||||
- `## ADR Dependencies` — HIGH if missing: dependency ordering breaks
|
||||
- `## Engine Compatibility` — HIGH if missing: post-cutoff risk unknown
|
||||
- `## GDD Requirements Addressed` — MEDIUM if missing: traceability lost
|
||||
- `## Date` — MEDIUM if missing, and no `## Last Verified` either: `/create-stories`
|
||||
stamps stories with it and `/dev-story` compares against it, so without it a
|
||||
story can never tell whether the ADR changed
|
||||
3. Present to the user:
|
||||
```
|
||||
## Retrofit: [ADR title]
|
||||
File: [path]
|
||||
|
||||
Sections already present (will not be touched):
|
||||
✓ Status: [current value, or "MISSING — will add"]
|
||||
✓ [section]
|
||||
|
||||
Missing sections to add:
|
||||
✗ Status — BLOCKING (stories cannot validate ADR acceptance without this)
|
||||
✗ ADR Dependencies — HIGH
|
||||
✗ Engine Compatibility — HIGH
|
||||
```
|
||||
4. Ask: "Shall I add the [N] missing sections? I will not modify any existing content."
|
||||
If no: write nothing, and report the missing sections by name.
|
||||
5. If yes:
|
||||
- For **Status**: ask the user — "What is the current status of this decision?"
|
||||
Options: "Proposed", "Accepted", "Deprecated", "Superseded by ADR-XXXX"
|
||||
An `Accepted` answer — a decision already in force — is not written as
|
||||
given: write `Proposed`, add the other missing sections, then run
|
||||
acceptance mode (below) on this ADR. Its dependency check, confirmation and
|
||||
story unblocking apply here too; it stays the only path that sets `Accepted`.
|
||||
- For **ADR Dependencies**: ask — "Does this decision depend on any other ADR?
|
||||
Does it enable or block any other ADR or epic?" Accept "None" for each field.
|
||||
- For **Engine Compatibility**: read the engine reference docs (same as Step 1 below)
|
||||
and ask the user to confirm the domain. Then generate the table with verified data.
|
||||
- For **GDD Requirements Addressed**: ask — "Which GDD systems motivated this decision?
|
||||
What specific requirement in each GDD does this ADR address?"
|
||||
- Append each missing section to the ADR file using the Edit tool.
|
||||
- For **Date** (counted only when there is no `## Last Verified`): append
|
||||
`## Date` with today's date — even when it is the only missing section, the
|
||||
case `/dev-story` sends you here for — and say that it records the retrofit,
|
||||
not when the decision was made.
|
||||
- **Never modify any existing section.** Only append or fill absent sections.
|
||||
6. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
|
||||
has its Status and Dependencies fields."
|
||||
@@ -0,0 +1,48 @@
|
||||
# /architecture-decision — Step 1: Load Engine Context
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## 1. Load Engine Context (ALWAYS FIRST)
|
||||
|
||||
Before doing anything else, establish the engine environment:
|
||||
|
||||
1. Read `docs/engine-reference/[engine]/VERSION.md` to get:
|
||||
- Engine name and version
|
||||
- LLM knowledge cutoff date
|
||||
- Post-cutoff version risk levels (LOW / MEDIUM / HIGH)
|
||||
|
||||
2. Identify the **domain** of this architecture decision from the title or
|
||||
user description. Common domains: Physics, Rendering, UI, Audio, Navigation,
|
||||
Animation, Networking, Core, Input, Scripting.
|
||||
|
||||
3. Read the corresponding module reference if it exists:
|
||||
`docs/engine-reference/[engine]/modules/[domain].md`
|
||||
|
||||
4. Read `docs/engine-reference/[engine]/breaking-changes.md` — flag any
|
||||
changes in the relevant domain that post-date the LLM's training cutoff.
|
||||
|
||||
5. Read `docs/engine-reference/[engine]/deprecated-apis.md` — flag any APIs
|
||||
in the relevant domain that should not be used.
|
||||
|
||||
6. **Display a knowledge gap warning** before proceeding if the domain carries
|
||||
MEDIUM or HIGH risk:
|
||||
|
||||
```
|
||||
⚠️ ENGINE KNOWLEDGE GAP WARNING
|
||||
Engine: [name + version]
|
||||
Domain: [domain]
|
||||
Risk Level: HIGH — This version is post-LLM-cutoff.
|
||||
|
||||
Key changes verified from engine-reference docs:
|
||||
- [Change 1 relevant to this domain]
|
||||
- [Change 2]
|
||||
|
||||
This ADR will be cross-referenced against the engine reference library.
|
||||
Proceed with verified information only — do NOT rely solely on training data.
|
||||
```
|
||||
|
||||
If no engine has been configured yet, prompt: "No engine is configured.
|
||||
Run `/setup-engine` first, or tell me which engine you are using."
|
||||
|
||||
---
|
||||
@@ -0,0 +1,78 @@
|
||||
# /architecture-decision — Steps 3a and 3b: Gather Context
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## 3. Gather context
|
||||
|
||||
### 3a: Architecture Registry Check (BLOCKING gate) — do this FIRST
|
||||
|
||||
Read `docs/registry/architecture.yaml`. Extract entries relevant to this ADR's
|
||||
domain and decision (grep by system name, domain keyword, or state being touched).
|
||||
Run this before reading any existing ADR — the registry exists specifically so a
|
||||
new ADR's author does not need to open prior ADRs to learn their binding facts
|
||||
(state ownership, interface contracts, forbidden patterns).
|
||||
|
||||
Present any relevant stances to the user **before** the collaborative design
|
||||
begins, as locked constraints:
|
||||
|
||||
```
|
||||
## Existing Architectural Stances (must not contradict)
|
||||
|
||||
State Ownership:
|
||||
player_health → owned by health-system (ADR-0001)
|
||||
Interface: HealthComponent.current_health (read-only float)
|
||||
→ If this ADR reads or writes player health, it must use this interface.
|
||||
|
||||
Interface Contracts:
|
||||
damage_delivery → signal pattern (ADR-0003)
|
||||
Signal: damage_dealt(amount, target, is_crit)
|
||||
→ If this ADR delivers or receives damage events, it must use this signal.
|
||||
|
||||
Forbidden Patterns:
|
||||
✗ autoload_singleton_coupling (ADR-0001)
|
||||
✗ direct_cross_system_state_write (ADR-0000)
|
||||
→ The proposed approach must not use these patterns.
|
||||
```
|
||||
|
||||
If the user's proposed decision would contradict any registered stance, surface
|
||||
the conflict immediately:
|
||||
|
||||
> "⚠️ Conflict: This ADR proposes [X], but ADR-[NNNN] established that [Y] is
|
||||
> the accepted pattern for this purpose. Proceeding without resolving this will
|
||||
> produce contradictory ADRs and inconsistent stories.
|
||||
> Options: (1) Align with the existing stance, (2) Supersede ADR-[NNNN] with
|
||||
> an explicit replacement, (3) Explain why this case is an exception."
|
||||
|
||||
Do not proceed to Step 4 (collaborative design) until any conflict is resolved
|
||||
or explicitly accepted as an intentional exception.
|
||||
|
||||
### 3b: Existing ADRs and Related GDDs — registry-scoped, never unbounded
|
||||
|
||||
The registry (3a) covers *what* prior decisions bind — not always *why*. If the
|
||||
registry surfaced a directly relevant ADR and its reasoning matters here (not
|
||||
just its stated facts), read that specific ADR — never glob-and-read every
|
||||
ADR in `docs/architecture/` on the chance one is relevant:
|
||||
|
||||
1. **Map its headings first** (cheap):
|
||||
```
|
||||
Grep pattern="^## " path="docs/architecture/[adr-file].md" output_mode="content" -n
|
||||
```
|
||||
2. **Under ~50KB** (`Bash: wc -c "docs/architecture/[adr-file].md"`) — one full
|
||||
`Read` is fine; per-call overhead exceeds the savings from bounded reads at
|
||||
this size.
|
||||
3. **~50KB or larger** — bounded-read only `## Context`, `## Decision`, and
|
||||
`## Consequences` (the sections that carry reasoning, not just facts) via
|
||||
`Read(offset, limit)` from the heading map.
|
||||
|
||||
Read GDDs the same way `/design-system` Step 2b does: only GDDs the registry
|
||||
or the ADR list names as directly relevant, and only their `## Dependencies`,
|
||||
`## Formulas`, and `## Edge Cases` sections
|
||||
(`Grep pattern="^## (Dependencies|Formulas|Edge Cases)" ... -A 40`) — never a
|
||||
speculative full read of `design/gdd/*.md` looking for anything that might
|
||||
relate.
|
||||
|
||||
Skip 3b entirely if the registry already answers everything this decision
|
||||
needs — most ADRs will.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,73 @@
|
||||
# /architecture-decision — Step 4: Guide the Decision Collaboratively
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## 4. Guide the decision collaboratively
|
||||
|
||||
Before asking anything, derive the skill's best guesses from the context already
|
||||
gathered (GDDs read, engine reference loaded, existing ADRs scanned). Then present
|
||||
a **confirm/adjust** prompt using `AskUserQuestion` — not open-ended questions.
|
||||
|
||||
**Derive assumptions first:**
|
||||
- **Problem**: Infer from the title + GDD context what decision needs to be made
|
||||
- **Alternatives**: Propose 2-3 concrete options from engine reference + GDD requirements
|
||||
- **Dependencies**: Scan existing ADRs for upstream dependencies. **If the scan is
|
||||
inconclusive, present `UNKNOWN — scan inconclusive, please confirm`, never
|
||||
`None`.** The two are not interchangeable: `None` asserts that nothing upstream
|
||||
constrains this decision, and a user confirming a prefilled list cannot tell an
|
||||
assertion from a guess. This field is load-bearing — `/architecture-review`
|
||||
flags unaccepted dependencies, `/dev-story` reads it, and the acceptance route
|
||||
in Phase 0 **refuses to accept an ADR whose dependencies are not themselves
|
||||
Accepted**. A dependency list that defaulted to empty makes that check pass
|
||||
while examining nothing. `UNKNOWN` must be resolved during the confirm/adjust
|
||||
prompt; it is a prompt state, never a value written to the file
|
||||
- **GDD linkage**: Extract which GDD systems the title directly relates to
|
||||
- **Status**: Always `Proposed` for new ADRs — never ask the user what the status is
|
||||
|
||||
**Scope of assumptions tab**: Assumptions cover only: problem framing, alternative approaches, upstream dependencies, GDD linkage, and status. Schema design questions (e.g., "How should spawn timing work?", "Should data be inline or external?") are NOT assumptions — they are design decisions belonging to a separate step after the assumptions are confirmed. Do not include schema design questions in the assumptions AskUserQuestion widget.
|
||||
|
||||
**After assumptions are confirmed**, if the ADR involves schema or data design choices, use a separate multi-tab `AskUserQuestion` to ask each design question independently before drafting.
|
||||
|
||||
**Present assumptions with `AskUserQuestion`:**
|
||||
|
||||
```
|
||||
Here's what I'm assuming before drafting:
|
||||
|
||||
Problem: [one-sentence problem statement derived from context]
|
||||
Alternatives I'll consider:
|
||||
A) [option derived from engine reference]
|
||||
B) [option derived from GDD requirements]
|
||||
C) [option from common patterns]
|
||||
GDD systems driving this: [list derived from context]
|
||||
Dependencies: [upstream ADRs if any, otherwise "None"]
|
||||
Status: Proposed
|
||||
|
||||
[A] Proceed — draft with these assumptions
|
||||
[B] Change the alternatives list
|
||||
[C] Adjust the GDD linkage
|
||||
[D] Add a performance budget constraint
|
||||
[E] Something else needs changing first
|
||||
```
|
||||
|
||||
Do not generate the ADR until the user confirms assumptions or provides corrections.
|
||||
|
||||
**After engine specialist and TD reviews return** (Step 5.5/5.6), if unresolved
|
||||
decisions remain, present each one as a separate `AskUserQuestion` with the proposed
|
||||
options as choices plus a free-text escape:
|
||||
|
||||
```
|
||||
Decision: [specific unresolved point]
|
||||
[A] [option from specialist review]
|
||||
[B] [alternative option]
|
||||
[C] Different approach — I'll describe it
|
||||
```
|
||||
|
||||
**ADR Dependencies** — derive from existing ADRs, then confirm:
|
||||
- Does this decision depend on any other ADR not yet Accepted?
|
||||
- Does it unlock or unblock any other ADR or epic?
|
||||
- Does it block any specific epic from starting?
|
||||
|
||||
Record answers in the **ADR Dependencies** section. Write "None" for each field if no constraints apply.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,246 @@
|
||||
# /architecture-decision — Step 5: Generate the ADR
|
||||
|
||||
> Part of `/architecture-decision`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## 5. Generate the ADR
|
||||
|
||||
**In this file:**
|
||||
|
||||
- The ADR template
|
||||
- 5.5 Engine Specialist Validation
|
||||
- 5.6 Technical Director Strategic Review, with the review mode check
|
||||
- 5.7 GDD Sync Check: found, none found, could not check
|
||||
- Write approval
|
||||
- Update Architecture Registry, and the registry append logic
|
||||
|
||||
Following this format:
|
||||
|
||||
```markdown
|
||||
# ADR-[NNNN]: [Title]
|
||||
|
||||
## Status
|
||||
[Proposed | Accepted | Deprecated | Superseded by ADR-XXXX]
|
||||
|
||||
## Date
|
||||
[Date of decision]
|
||||
|
||||
## Last Verified
|
||||
[YYYY-MM-DD — when this ADR was last confirmed accurate against the current
|
||||
engine version and design. Update this date when you re-read and confirm it is
|
||||
still correct, even if nothing changed.]
|
||||
|
||||
## Decision Makers
|
||||
[Who was involved in this decision]
|
||||
|
||||
## Summary
|
||||
[2 sentences: what problem this ADR solves, and what was decided. Written for
|
||||
tiered context loading — a skill scanning 20 ADRs uses this to decide whether to
|
||||
read the full decision. Be specific: name the system, the problem, and the
|
||||
chosen approach.]
|
||||
|
||||
## Engine Compatibility
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Engine** | [e.g. Godot 4.6] |
|
||||
| **Domain** | [Physics / Rendering / UI / Audio / Navigation / Animation / Networking / Core / Input] |
|
||||
| **Knowledge Risk** | [LOW / MEDIUM / HIGH — from VERSION.md] |
|
||||
| **References Consulted** | [List engine-reference docs read, e.g. `docs/engine-reference/godot/modules/physics.md`] |
|
||||
| **Post-Cutoff APIs Used** | [Any APIs from post-LLM-cutoff versions this decision depends on, or "None"] |
|
||||
| **Verification Required** | [Specific behaviours to test before shipping, or "None"] |
|
||||
|
||||
## ADR Dependencies
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Depends On** | [ADR-NNNN (must be Accepted before this can be implemented), or "None"] |
|
||||
| **Enables** | [ADR-NNNN (this ADR unlocks that decision), or "None"] |
|
||||
| **Blocks** | [Epic/Story name — cannot start until this ADR is Accepted, or "None"] |
|
||||
| **Ordering Note** | [Any sequencing constraint that isn't captured above] |
|
||||
|
||||
## Context
|
||||
|
||||
### Problem Statement
|
||||
[What problem are we solving? Why does this decision need to be made now?]
|
||||
|
||||
### Constraints
|
||||
- [Technical constraints]
|
||||
- [Timeline constraints]
|
||||
- [Resource constraints]
|
||||
- [Compatibility requirements]
|
||||
|
||||
### Requirements
|
||||
- [Must support X]
|
||||
- [Must perform within Y budget]
|
||||
- [Must integrate with Z]
|
||||
|
||||
## Decision
|
||||
|
||||
[The specific technical decision made, described in enough detail for someone
|
||||
to implement it.]
|
||||
|
||||
### Architecture Diagram
|
||||
[ASCII diagram or description of the system architecture this creates]
|
||||
|
||||
### Key Interfaces
|
||||
[API contracts or interface definitions this decision creates]
|
||||
|
||||
### Implementation Guidelines
|
||||
[Specific guidance for the programmer implementing this decision — the rules a
|
||||
`/create-control-manifest` or `/dev-story` run should follow. State mandates as
|
||||
"must / must never" so they extract cleanly.]
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: [Name]
|
||||
- **Description**: [How this would work]
|
||||
- **Pros**: [Advantages]
|
||||
- **Cons**: [Disadvantages]
|
||||
- **Rejection Reason**: [Why this was not chosen]
|
||||
|
||||
### Alternative 2: [Name]
|
||||
- **Description**: [How this would work]
|
||||
- **Pros**: [Advantages]
|
||||
- **Cons**: [Disadvantages]
|
||||
- **Rejection Reason**: [Why this was not chosen]
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- [Good outcomes of this decision]
|
||||
|
||||
### Negative
|
||||
- [Trade-offs and costs accepted]
|
||||
|
||||
## Risks
|
||||
- [Things that could go wrong]
|
||||
- [Mitigation for each risk]
|
||||
|
||||
## GDD Requirements Addressed
|
||||
|
||||
| GDD System | Requirement | How This ADR Addresses It |
|
||||
|------------|-------------|--------------------------|
|
||||
| [system-name].md | [specific rule, formula, or performance constraint from that GDD] | [how this decision satisfies it] |
|
||||
|
||||
## Performance Implications
|
||||
- **CPU**: [Expected impact]
|
||||
- **Memory**: [Expected impact]
|
||||
- **Load Time**: [Expected impact]
|
||||
- **Network**: [Expected impact, if applicable]
|
||||
|
||||
## Migration Plan
|
||||
[If this changes existing code, how do we get from here to there?]
|
||||
|
||||
## Validation Criteria
|
||||
[How will we know this decision was correct? What metrics or tests?]
|
||||
|
||||
## Related
|
||||
- [Links to related ADRs — note if supersedes, contradicts, or depends on]
|
||||
- [Links to related design documents]
|
||||
```
|
||||
|
||||
5.5. **Engine Specialist Validation** — Before saving, spawn the **primary engine specialist** via `Agent` to validate the drafted ADR:
|
||||
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
|
||||
- If no engine is configured (neither source yields an engine), skip this step **Record ``Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)`` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
|
||||
- Spawn `subagent_type: [primary specialist]` with: the ADR's Engine Compatibility section, Decision section, Key Interfaces, and the engine reference docs path. Ask them to:
|
||||
1. Confirm the proposed approach is idiomatic for the pinned engine version
|
||||
2. Flag any APIs or patterns that are deprecated or changed post-training-cutoff
|
||||
3. Identify engine-specific risks or gotchas not captured in the current ADR draft
|
||||
- If the specialist identifies a **blocking issue** (wrong API, deprecated approach, engine version incompatibility): revise the Decision and Engine Compatibility sections accordingly, then confirm the changes with the user before proceeding
|
||||
- If the specialist finds **minor notes** only: incorporate them into the ADR's Risks subsection
|
||||
|
||||
**Review mode check** — apply before spawning TD-ADR:
|
||||
- `solo` → skip. Note: "TD-ADR skipped — Solo mode." Proceed to Step 5.7 (GDD sync check).
|
||||
- `lean` → skip (not a PHASE-GATE). Note: "TD-ADR skipped — Lean mode." Proceed to Step 5.7 (GDD sync check).
|
||||
- `full` → spawn as normal.
|
||||
|
||||
5.6. **Technical Director Strategic Review** — After the engine specialist validation, spawn `technical-director` via `Agent` using gate **TD-ADR** (`.claude/docs/director-gates/td-adr.md`):
|
||||
- Pass: the ADR file path (or draft content), engine version, domain, any existing ADRs in the same domain
|
||||
- The TD validates architectural coherence (is this decision consistent with the whole system?) — distinct from the engine specialist's API-level check
|
||||
- On CONCERNS: show them to the user verbatim and ask with the standard options from `director-gates.md` — `Revise flagged items` / `Accept and proceed` / `Discuss further`. Revise the flagged Decision or Alternatives sections only on `Revise flagged items`.
|
||||
- On REJECT: show the blockers verbatim and revise the Decision or Alternatives sections before proceeding.
|
||||
- A revised draft still reaches the user through the write approval below; nothing is written before it. A `NOT ASSESSED` answer is not an approval — name the missing input (`director-gates.md`).
|
||||
|
||||
5.7. **GDD Sync Check** — Before presenting the write approval, scan all GDDs
|
||||
referenced in the "GDD Requirements Addressed" section for naming inconsistencies
|
||||
with the ADR's Key Interfaces and Decision sections (renamed signals, API methods,
|
||||
or data types). If any are found, surface them as a **prominent warning block**
|
||||
immediately before the write approval — not as a footnote:
|
||||
|
||||
```
|
||||
⚠️ GDD SYNC REQUIRED
|
||||
[gdd-filename].md uses names this ADR has renamed:
|
||||
[old_name] → [new_name_from_adr]
|
||||
[old_name_2] → [new_name_2_from_adr]
|
||||
The GDD must be updated before or alongside writing this ADR to prevent
|
||||
developers reading the GDD from implementing the wrong interface.
|
||||
```
|
||||
|
||||
**This check has three outcomes, not two.** The two above are "found" and "none
|
||||
found"; the third is **could not check**, and until now it fell through the
|
||||
silent branch and rendered exactly like a clean result.
|
||||
|
||||
- **None found** — print one line, do not stay silent:
|
||||
`GDD sync: checked [N] referenced GDD(s), no naming inconsistencies.`
|
||||
A silent pass is indistinguishable from a check that never ran, and this one
|
||||
guards against developers implementing the wrong interface from a stale GDD.
|
||||
- **Could not check** — the ADR has no `GDD Requirements Addressed` section, it
|
||||
names no GDDs, or a named GDD does not exist on disk. Print:
|
||||
`GDD sync: NOT ASSESSED — [which reason, and which files]`
|
||||
Do **not** treat an ADR that references no GDDs as one whose GDDs are
|
||||
consistent. Nothing was compared.
|
||||
|
||||
Only the warning block itself is conditional; the check always reports.
|
||||
|
||||
5. **Write approval** — Use `AskUserQuestion`:
|
||||
|
||||
If GDD sync issues were found:
|
||||
- "ADR draft is complete. How would you like to proceed?"
|
||||
- [A] Write ADR + update GDD in the same pass
|
||||
- [B] Write ADR only — I'll update the GDD manually
|
||||
- [C] Not yet — I need to review further
|
||||
|
||||
If no GDD sync issues:
|
||||
- "ADR draft is complete. May I write it?"
|
||||
- [A] Write ADR to `docs/architecture/adr-[NNNN]-[slug].md`
|
||||
- [B] Not yet — I need to review further
|
||||
|
||||
If yes to any write option, write the file, creating the directory if needed.
|
||||
For option [A] with GDD update: also update the GDD file(s) to use the new names.
|
||||
|
||||
6. **Update Architecture Registry**
|
||||
|
||||
Scan the written ADR for new architectural stances that should be registered:
|
||||
- State it claims ownership of
|
||||
- Interface contracts it defines (signal signatures, method APIs)
|
||||
- Performance budget it claims
|
||||
- API choices it makes explicitly
|
||||
- Patterns it bans (Consequences → Negative or explicit "do not use X")
|
||||
|
||||
Present candidates:
|
||||
```
|
||||
Registry candidates from this ADR:
|
||||
NEW state ownership: player_stamina → stamina-system
|
||||
NEW interface contract: stamina_depleted signal
|
||||
NEW performance budget: stamina-system: 0.5ms/frame
|
||||
NEW forbidden pattern: polling stamina each frame (use signal instead)
|
||||
EXISTING (referenced_by update only): player_health → already registered ✅
|
||||
```
|
||||
|
||||
**Registry append logic**: When writing to `docs/registry/architecture.yaml`, do NOT assume sections are empty. The file may already have entries from previous ADRs written in this session. Before each Edit call:
|
||||
1. Read the current state of `docs/registry/architecture.yaml`
|
||||
2. Find the correct section (state_ownership, interfaces, forbidden_patterns, api_decisions)
|
||||
3. Append the new entry AFTER the last existing entry in that section — do not try to replace a `[]` placeholder that may no longer exist
|
||||
4. If the section has entries already, use the closing content of the last entry as the `old_string` anchor, and append the new entry after it
|
||||
|
||||
**BLOCKING — do not write to `docs/registry/architecture.yaml` without explicit user approval.**
|
||||
|
||||
Ask using `AskUserQuestion`:
|
||||
- "May I update `docs/registry/architecture.yaml` with these [N] new stances?"
|
||||
- Options: "Yes — update the registry", "Not yet — I want to review the candidates", "Skip registry update"
|
||||
|
||||
Only proceed if the user selects yes. If yes: append new entries. Never modify existing entries — if a stance is
|
||||
changing, set the old entry to `status: superseded_by: ADR-[NNNN]` and add the new entry.
|
||||
|
||||
---
|
||||
@@ -9,8 +9,6 @@ model: opus
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow`
|
||||
|
||||
|
||||
|
||||
# Architecture Review
|
||||
|
||||
The architecture review validates that the complete body of architectural decisions
|
||||
@@ -43,791 +41,39 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
|
||||
## Phase 1: Load Everything
|
||||
|
||||
### Phase 1a — L0: Summary Scan (fast, low tokens)
|
||||
|
||||
**Freshness check before any scan.** Locate the latest prior report — Glob
|
||||
`docs/architecture/architecture-review-*.md` and take the newest — then:
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/review-receipts.sh check "[latest-report]" docs/architecture/adr-*.md design/gdd/*.md
|
||||
```
|
||||
|
||||
- **Any `UNRESOLVED`** — check this FIRST; it disqualifies every option
|
||||
below. One of the two globs matched no file, so that whole document class
|
||||
was never examined and the comparison covered less than it appears to.
|
||||
Say which pattern came back unresolved and stop: an ADR or GDD directory
|
||||
that is empty, renamed or misspelled is a finding about the project, not a
|
||||
reason to stand on a prior report. Never read a set of `UNCHANGED` lines as
|
||||
"everything is current" while an `UNRESOLVED` line is present — the set
|
||||
compared was not the set requested.
|
||||
- **Everything `UNCHANGED`** (and no `UNRESOLVED`) — nothing this review
|
||||
reads has changed since that report; re-running reproduces it. Surface the
|
||||
prior report's date and verdict and offer via `AskUserQuestion`: `[A] Stand
|
||||
on the prior report (Recommended)` / `[B] Re-run the full review anyway` —
|
||||
`guided` proceeds with [A] and notes it; `autonomous` logs via
|
||||
`log_decision` and stands on the prior report.
|
||||
- **Some `CHANGED`/`NEW`** — name them, then scope instead of re-running
|
||||
everything: recommend `/architecture-review [system]` (single-system mode)
|
||||
for just the changed systems. A full re-run stays available on request,
|
||||
and structural changes (a `NEW` ADR, a deleted file) warrant one.
|
||||
- **`RECEIPT: NONE`** — no prior report, or one written before receipts
|
||||
existed. Proceed with the full review; this run's report will carry the
|
||||
first stamps.
|
||||
|
||||
Before reading any full document, use Grep to extract `## Summary` sections
|
||||
from all GDDs and ADRs:
|
||||
|
||||
```
|
||||
Grep pattern="## Summary" glob="design/gdd/*.md" output_mode="content" -A 4
|
||||
Grep pattern="## Summary" glob="docs/architecture/adr-*.md" output_mode="content" -A 3
|
||||
```
|
||||
|
||||
**Fail open on a missing Summary.** Establish the denominator: glob
|
||||
`design/gdd/*.md` and count **N**. A scan matching fewer than N means those GDDs
|
||||
predate `## Summary` (`/design-system` emits it, but older GDDs lack it) — never
|
||||
treat an absent Summary as a system out of scope. A zero-match scan means "no GDD
|
||||
carries a Summary yet", not "nothing to review": full-read the unmatched set.
|
||||
|
||||
For `single-gdd [path]` mode: use the target GDD's summary to identify which
|
||||
ADRs reference the same system (Grep ADRs for the system name), then load only
|
||||
those ADRs' sections per Phase 1b. Skip unrelated GDDs entirely.
|
||||
|
||||
For `engine` mode: load ADR sections only — GDDs are not needed for engine checks.
|
||||
In practice this is the `## Engine Compatibility` scan alone.
|
||||
|
||||
For `coverage` or `full` mode: proceed to Phase 1b for the full in-scope set.
|
||||
**This is a section load, not a full-file load** — see below for why, and for the
|
||||
narrow cases that still justify escalating to a whole document.
|
||||
|
||||
### Phase 1b — L1/L2: Targeted Section Load
|
||||
|
||||
Load the sections the later phases actually consume — **not whole files**. This
|
||||
skill reads the two largest document sets in the project (every GDD *and* every
|
||||
ADR); at realistic sizes a full load of both exhausts the context window before
|
||||
Phase 2 starts, and most of what it loads is narrative this skill never uses.
|
||||
|
||||
**Establish the denominator first.** Glob `design/gdd/*.md` and count **N_gdd**;
|
||||
glob `docs/architecture/adr-*.md` and count **N_adr**. Report both. A section
|
||||
scan matching fewer than the denominator means those documents lack the section —
|
||||
**never treat an absent section as an absent document.** The scan narrows the
|
||||
*read* set; it never shrinks the *in-scope* set.
|
||||
|
||||
### Design Documents
|
||||
|
||||
Phase 2 extracts *technical requirements* — data structures, performance
|
||||
constraints, engine capabilities, cross-system communication, persistence,
|
||||
threading, platform needs. Those live in a known set of sections; Overview and
|
||||
Player Fantasy are narrative and yield none.
|
||||
|
||||
```
|
||||
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
|
||||
```
|
||||
|
||||
Accept **either** `## Detailed Rules` or `## Detailed Design` — the design
|
||||
standard and the GDD template disagree on the name and they denote the same
|
||||
required section. Full-read a single GDD only when a scanned section
|
||||
cross-references material outside itself, or when a GDD matched zero sections
|
||||
(it predates the template — read it whole and say so).
|
||||
|
||||
- `design/gdd/systems-index.md` — the authoritative list of systems; read whole (small, and it is an index)
|
||||
|
||||
### Architecture Documents
|
||||
|
||||
Phases 3–5 need the traceability table, the decision itself, engine claims, and
|
||||
the dependency edges — not Context, Consequences, Alternatives, Migration Plan or
|
||||
Validation Criteria, which explain *why* a decision was made.
|
||||
|
||||
```
|
||||
Grep pattern="^## (Status|Decision|GDD Requirements Addressed|Engine Compatibility|ADR Dependencies|Performance Implications)" glob="docs/architecture/adr-*.md" output_mode="content" -A 30
|
||||
```
|
||||
|
||||
Interpret against **N_adr**, and distinguish the two zero-match cases — they are
|
||||
not the same finding:
|
||||
|
||||
| Result | Meaning | Action |
|
||||
|---|---|---|
|
||||
| N_adr matches | Normal. | Proceed on the scanned sections. |
|
||||
| Some ADRs match, some do not | Those ADRs are missing sections. | Record each as a **structural gap** in the Phase 7 report — a missing `## GDD Requirements Addressed` is itself a traceability finding. |
|
||||
| **0 matches, N_adr > 0** | **Malformed ADRs**, not "no architecture". | "[N_adr] ADRs found, none carries a scannable section — run `/architecture-decision retrofit [file]` on each." Do **not** report zero coverage; that would read as a design failure when it is a format failure. |
|
||||
|
||||
Escalate to a full read of one ADR only when judging a conflict needs its
|
||||
reasoning (Phase 4) — that is a per-ADR decision, not a blanket load.
|
||||
|
||||
- `docs/architecture/architecture.md` if it exists
|
||||
|
||||
### Engine Reference
|
||||
- `docs/engine-reference/[engine]/VERSION.md`
|
||||
- `docs/engine-reference/[engine]/breaking-changes.md`
|
||||
- `docs/engine-reference/[engine]/deprecated-apis.md`
|
||||
- **Only the module docs the in-scope ADRs actually name** — take the union of
|
||||
each ADR's `References Consulted` and `Post-Cutoff APIs Used` fields (already
|
||||
captured by the `## Engine Compatibility` scan above) and read those files.
|
||||
Reading the whole `modules/` directory loads engine subsystems the project may
|
||||
not use at all. If no ADR names any module, read none and note it: Phase 5
|
||||
cannot cross-check engine claims that were never made.
|
||||
|
||||
### Project Standards
|
||||
- `project.yaml` — `naming.*` and `performance.*`; plus `.claude/docs/technical-preferences.md` for those keys when absent and for forbidden patterns / allowed libraries
|
||||
|
||||
Report a count: "Loaded [N] GDDs, [M] ADRs, engine: [name + version]."
|
||||
|
||||
**Also read `docs/consistency-failures.md`** if it exists. Extract entries with
|
||||
Domain matching the systems under review (Architecture, Engine, or any GDD domain
|
||||
being covered). Surface recurring patterns as a "Known conflict-prone areas" note
|
||||
at the top of the Phase 4 conflict detection output.
|
||||
|
||||
---
|
||||
**Read `references/1-load.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 2: Extract Technical Requirements from Every GDD
|
||||
|
||||
### Pre-load the TR Registry
|
||||
|
||||
Before extracting any requirements, read `docs/architecture/tr-registry.yaml`
|
||||
if it exists. Index existing entries by `id` and by normalized `requirement`
|
||||
text (lowercase, trimmed). This prevents ID renumbering across review runs.
|
||||
|
||||
For each requirement you extract, the matching rule is:
|
||||
1. **Exact/near match** to an existing registry entry for the same system →
|
||||
reuse that entry's TR-ID unchanged. Update the `requirement` text in the
|
||||
registry only if the GDD wording changed (same intent, clearer phrasing) —
|
||||
add a `revised: [date]` field.
|
||||
2. **No match** → assign a new ID: next available `TR-[system]-NNN` for that
|
||||
system, starting from the highest existing sequence + 1.
|
||||
3. **Ambiguous** (partial match, intent unclear) → ask the user:
|
||||
> "Does '[new requirement text]' refer to the same requirement as
|
||||
> `TR-[system]-NNN: [existing text]'`, or is it a new requirement?"
|
||||
User answers: "Same requirement" (reuse ID) or "New requirement" (new ID).
|
||||
|
||||
For any requirement with `status: deprecated` in the registry — skip it.
|
||||
It was removed from the GDD intentionally.
|
||||
|
||||
For each GDD, read it and extract all **technical requirements** — things the
|
||||
architecture must provide for the system to work. A technical requirement is any
|
||||
statement that implies a specific architectural decision.
|
||||
|
||||
Categories to extract:
|
||||
|
||||
| Category | Example |
|
||||
|----------|---------|
|
||||
| **Data structures** | "Each entity has health, max health, status effects" → needs a component/data schema |
|
||||
| **Performance constraints** | "Collision detection must run at 60fps with 200 entities" → physics budget ADR |
|
||||
| **Engine capability** | "Inverse kinematics for character animation" → IK system ADR |
|
||||
| **Cross-system communication** | "Damage system notifies UI and audio simultaneously" → event/signal architecture ADR |
|
||||
| **State persistence** | "Player progress persists between sessions" → save system ADR |
|
||||
| **Threading/timing** | "AI decisions happen off the main thread" → concurrency ADR |
|
||||
| **Platform requirements** | "Supports keyboard, gamepad, touch" → input system ADR |
|
||||
|
||||
For each GDD, produce a structured list:
|
||||
|
||||
```
|
||||
GDD: [filename]
|
||||
System: [system name]
|
||||
Technical Requirements:
|
||||
TR-[GDD]-001: [requirement text] → Domain: [Physics/Rendering/etc]
|
||||
TR-[GDD]-002: [requirement text] → Domain: [...]
|
||||
```
|
||||
|
||||
This becomes the **requirements baseline** — the complete set of what the
|
||||
architecture must cover.
|
||||
|
||||
---
|
||||
**Read `references/2-extract-requirements.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 3: Build the Traceability Matrix
|
||||
|
||||
For each technical requirement extracted in Phase 2, search the ADRs:
|
||||
|
||||
1. Use the ADRs **already loaded in Phase 1b** — do not re-read them. Extract each
|
||||
ADR's "GDD Requirements Addressed" section from what is already in context.
|
||||
(If Phase 1b ran in a mode that did not load every ADR, `Grep pattern="## GDD
|
||||
Requirements Addressed" glob="docs/architecture/adr-*.md" output_mode="content"
|
||||
-A 15` fills the gap without a full re-read.)
|
||||
2. Check if it explicitly references the requirement or its GDD
|
||||
3. Check if the ADR's decision text implicitly covers the requirement
|
||||
4. Mark coverage status:
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| ✅ **Covered** | An **Accepted** ADR explicitly addresses this requirement |
|
||||
| 🟡 **Covered (Proposed)** | An ADR addresses it, but that ADR is still `Proposed` |
|
||||
| ⚠️ **Partial** | An ADR partially covers this, or coverage is ambiguous |
|
||||
| ❌ **Gap** | No ADR addresses this requirement |
|
||||
| ❓ **Not assessed** | The ADR is unreadable, or has no `## Status` section |
|
||||
|
||||
> **Read each ADR's `## Status` before marking coverage — an unaccepted decision
|
||||
> is not coverage.** If `✅` meant only that *an ADR addresses this*, with no
|
||||
> status qualification, a requirement covered entirely by `Proposed` ADRs would
|
||||
> count as covered and this review could return **PASS: All requirements
|
||||
> covered** over an architecture nobody had accepted. Four skills downstream
|
||||
> (`create-control-manifest`, `create-epics`, `create-stories`, `gate-check`)
|
||||
> require `Accepted`, so a PASS on that basis sends work forward that every one
|
||||
> of them will refuse.
|
||||
>
|
||||
> `🟡` is **not** a pass state: it caps the verdict at **CONCERNS**, and names the
|
||||
> route out — `/architecture-decision accept ADR-NNNN`. That route is the only
|
||||
> thing that moves an ADR to `Accepted`; without it, grading `Proposed` as
|
||||
> covered would be the only option, which is why it must never be graded so.
|
||||
|
||||
Build the full matrix:
|
||||
|
||||
```
|
||||
## Traceability Matrix
|
||||
|
||||
| Requirement ID | GDD | System | Requirement | ADR Coverage | Status |
|
||||
|---------------|-----|--------|-------------|--------------|--------|
|
||||
| TR-combat-001 | combat.md | Combat | Hitbox detection < 1 frame | ADR-0003 | ✅ |
|
||||
| TR-combat-002 | combat.md | Combat | Combo window timing | — | ❌ GAP |
|
||||
| TR-inventory-001 | inventory.md | Inventory | Persistent item storage | ADR-0005 | ✅ |
|
||||
```
|
||||
|
||||
Count the totals: X covered, Y partial, Z gaps.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3b: Story and Test Linkage (RTM mode only)
|
||||
|
||||
*Skip this phase unless the argument is `rtm` or `full` with stories present.*
|
||||
|
||||
This phase extends the Phase 3 matrix to include the story that implements
|
||||
each requirement and the test that verifies it — producing the full
|
||||
Requirements Traceability Matrix (RTM).
|
||||
|
||||
### Step 3b-1 — Load stories
|
||||
|
||||
Glob `production/epics/**/*.md` (excluding EPIC.md index files) to establish the
|
||||
denominator. Then collect the fields with **targeted section greps, not a full
|
||||
read of each story** — the same two-grep form `/test-evidence-review` uses for
|
||||
this identical extraction:
|
||||
|
||||
```
|
||||
Grep pattern="## Test Evidence" glob="production/epics/**/story-*.md" output_mode="content" -A 8
|
||||
Grep pattern="TR-" glob="production/epics/**/story-*.md" output_mode="content"
|
||||
```
|
||||
|
||||
- **TR-ID** — from the second grep.
|
||||
- **Test file path** — under `## Test Evidence`, captured by the first grep's `-A 8`.
|
||||
- **Status** — from the story header; add `Grep pattern="^> \*\*Status\*\*"` if not already captured.
|
||||
- **Story path and title** — from the file name and path; no read at all.
|
||||
|
||||
Full-read a story only when its Test Evidence section is missing or ambiguous.
|
||||
|
||||
### Step 3b-2 — Load test files
|
||||
|
||||
Glob the engine's test root (`.claude/docs/directory-structure.md`): Godot
|
||||
`tests/unit/**/*_test.*` and `tests/integration/**/*_test.*`; Unity
|
||||
`Assets/Tests/**/*Tests.cs`; Unreal `Source/*/Private/Tests/**/*.cpp`. With no
|
||||
engine configured, say the test index could not be built rather than reading an
|
||||
empty glob as "no tests". Build an index: system → [test file paths].
|
||||
|
||||
For each test file path from Step 3b-1, confirm via Glob whether the file
|
||||
actually exists. Note MISSING if the stated path does not exist.
|
||||
|
||||
### Step 3b-3 — Build the extended RTM
|
||||
|
||||
For each TR-ID in the Phase 3 matrix, add:
|
||||
- **Story**: the story file path(s) that reference this TR-ID (may be multiple)
|
||||
- **Test File**: the test file path stated in the story's Test Evidence section
|
||||
- **Test Status**: COVERED (test file exists) / MISSING (path stated but not
|
||||
found) / NONE (no test path stated, story type may be Visual/Feel/UI) /
|
||||
NO STORY (requirement has no story yet — pre-production gap)
|
||||
|
||||
Extended matrix format:
|
||||
|
||||
```
|
||||
## Requirements Traceability Matrix (RTM)
|
||||
|
||||
| TR-ID | GDD | Requirement | ADR | Story | Test File | Test Status |
|
||||
|-------|-----|-------------|-----|-------|-----------|-------------|
|
||||
| TR-combat-001 | combat.md | Hitbox < 1 frame | ADR-0003 | story-001-hitbox.md | tests/unit/combat/hitbox_test.gd | COVERED |
|
||||
| TR-combat-002 | combat.md | Combo window | — | story-002-combo.md | — | NONE (Visual/Feel) |
|
||||
| TR-inventory-001 | inventory.md | Persistent storage | ADR-0005 | — | — | NO STORY |
|
||||
```
|
||||
|
||||
RTM coverage summary:
|
||||
- COVERED: [N] — requirements with ADR + story + passing test
|
||||
- MISSING test: [N] — story exists but test file not found
|
||||
- NO STORY: [N] — requirements with ADR but no story yet
|
||||
- NO ADR: [N] — requirements without architectural coverage (from Phase 3 gaps)
|
||||
- Full chain complete (COVERED): [N/total] ([%])
|
||||
|
||||
---
|
||||
**Read `references/3-traceability.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 4: Cross-ADR Conflict Detection
|
||||
|
||||
Compare every ADR against every other ADR to detect contradictions. A conflict
|
||||
exists when:
|
||||
|
||||
- **Data ownership conflict**: Two ADRs claim exclusive ownership of the same data
|
||||
- **Integration contract conflict**: ADR-A assumes System X has interface Y, but
|
||||
ADR-B defines System X with a different interface
|
||||
- **Performance budget conflict**: ADR-A allocates N ms to physics, ADR-B allocates
|
||||
N ms to AI, together they exceed the total frame budget
|
||||
- **Dependency cycle**: ADR-A says System X initialises before Y; ADR-B says Y
|
||||
initialises before X
|
||||
- **Architecture pattern conflict**: ADR-A uses event-driven communication for a
|
||||
subsystem; ADR-B uses direct function calls to the same subsystem
|
||||
- **State management conflict**: Two ADRs define authority over the same game state
|
||||
(e.g. both Combat ADR and Character ADR claim to own the health value)
|
||||
|
||||
For each conflict found:
|
||||
|
||||
```
|
||||
## Conflict: [ADR-NNNN] vs [ADR-MMMM]
|
||||
Type: [Data ownership / Integration / Performance / Dependency / Pattern / State]
|
||||
ADR-NNNN claims: [...]
|
||||
ADR-MMMM claims: [...]
|
||||
Impact: [What breaks if both are implemented as written]
|
||||
Resolution options:
|
||||
1. [Option A]
|
||||
2. [Option B]
|
||||
```
|
||||
|
||||
### ADR Dependency Ordering
|
||||
|
||||
After conflict detection, analyse the dependency graph across all ADRs.
|
||||
|
||||
**Build the graph deterministically — do not trace it by hand:**
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/adr-dep-graph.sh
|
||||
```
|
||||
|
||||
It collects every `Depends On` edge, runs Kahn's algorithm, and emits
|
||||
`ADRS:` / `EDGES:` / `NO_DEPS_SECTION:` / `CYCLE:`. A model tracing A→B→C→A across
|
||||
a dozen ADRs eventually misses an edge; the algorithm cannot. It reports
|
||||
observations, not a verdict — you apply the meaning below.
|
||||
|
||||
**`NO_DEPS_SECTION` is load-bearing**: it makes "no cycles because the graph is
|
||||
clean" distinguishable from "no cycles because half the ADRs declare no
|
||||
dependencies". Report the second case as a structural gap, never as a clean graph.
|
||||
|
||||
Then interpret:
|
||||
|
||||
1. **Topological sort**: the emitted order — ADRs with no
|
||||
dependencies come first (Foundation), ADRs that depend on those come next, etc.
|
||||
2. **Flag unresolved dependencies**: cross the `EDGES:` list against the `## Status`
|
||||
values already scanned in Phase 1b. If ADR-A depends on an ADR that is still
|
||||
`Proposed` or does not exist, flag it:
|
||||
```
|
||||
⚠️ ADR-0005 depends on ADR-0002 — but ADR-0002 is still Proposed.
|
||||
ADR-0005 cannot be safely implemented until ADR-0002 is Accepted.
|
||||
```
|
||||
3. **Cycle detection**: every `CYCLE:` line the script emitted is a
|
||||
`DEPENDENCY CYCLE` — report each one. Do not re-derive them by hand:
|
||||
```
|
||||
🔴 DEPENDENCY CYCLE: ADR-0003 → ADR-0006 → ADR-0003
|
||||
This cycle must be broken before either can be implemented.
|
||||
```
|
||||
4. **Output recommended implementation order**:
|
||||
```
|
||||
### Recommended ADR Implementation Order (topologically sorted)
|
||||
Foundation (no dependencies):
|
||||
1. ADR-0001: [title]
|
||||
2. ADR-0003: [title]
|
||||
Depends on Foundation:
|
||||
3. ADR-0002: [title] (requires ADR-0001)
|
||||
4. ADR-0005: [title] (requires ADR-0003)
|
||||
Feature layer:
|
||||
5. ADR-0004: [title] (requires ADR-0002, ADR-0005)
|
||||
```
|
||||
|
||||
---
|
||||
**Read `references/4-conflicts.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 5: Engine Compatibility Cross-Check
|
||||
|
||||
Across all ADRs, check for engine consistency:
|
||||
|
||||
### Version Consistency
|
||||
- Do all ADRs that mention an engine version agree on the same version?
|
||||
- If any ADR was written for an older engine version, flag it as potentially stale
|
||||
|
||||
### Post-Cutoff API Consistency
|
||||
- Collect all "Post-Cutoff APIs Used" fields from all ADRs
|
||||
- For each, verify against the relevant module reference doc
|
||||
- Check that no two ADRs make contradictory assumptions about the same post-cutoff API
|
||||
|
||||
### Deprecated API Check
|
||||
- Grep all ADRs for API names listed in `deprecated-apis.md`
|
||||
- Flag any ADR referencing a deprecated API
|
||||
|
||||
### Missing Engine Compatibility Sections
|
||||
- List all ADRs that are missing the Engine Compatibility section entirely
|
||||
- These are blind spots — their engine assumptions are unknown
|
||||
|
||||
Output format:
|
||||
```
|
||||
### Engine Audit Results
|
||||
Engine: [name + version]
|
||||
ADRs with Engine Compatibility section: X / Y total
|
||||
|
||||
Deprecated API References:
|
||||
- ADR-0002: uses [deprecated API] — deprecated since [version]
|
||||
|
||||
Stale Version References:
|
||||
- ADR-0001: written for [older version] — current project version is [version]
|
||||
|
||||
Post-Cutoff API Conflicts:
|
||||
- ADR-0004 and ADR-0007 both use [API] with incompatible assumptions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Engine Specialist Consultation
|
||||
|
||||
After completing the engine audit above, spawn the **primary engine specialist** via `Agent` for a domain-expert second opinion:
|
||||
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
|
||||
- If no engine is configured (neither source yields an engine), skip this consultation **Record ``Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)`` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
|
||||
- Spawn `subagent_type: [primary specialist]` with: all ADRs that contain engine-specific decisions or `Post-Cutoff APIs Used` fields, the engine reference docs, and the Phase 5 audit findings. Ask them to:
|
||||
1. Confirm or challenge each audit finding — specialists may know of engine nuances not captured in the reference docs
|
||||
2. Identify engine-specific anti-patterns in the ADRs that the audit may have missed (e.g., using the wrong Godot node type, Unity component coupling, Unreal subsystem misuse)
|
||||
3. Flag ADRs that make assumptions about engine behaviour that differ from the actual pinned version
|
||||
|
||||
Incorporate additional findings under `### Engine Specialist Findings` in the Phase 5 output. These feed into the final verdict — specialist-identified issues carry the same weight as audit-identified issues.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5b: Design Revision Flags (Architecture → GDD Feedback)
|
||||
|
||||
For each **HIGH RISK engine finding** from Phase 5, check whether any GDD makes an
|
||||
assumption that the verified engine reality contradicts.
|
||||
|
||||
Specific cases to check:
|
||||
|
||||
1. **Post-cutoff API behaviour differs from training-data assumptions**: If an ADR
|
||||
records a verified API behaviour that differs from the default LLM assumption,
|
||||
check all GDDs that reference the related system. Look for design rules written
|
||||
around the old (assumed) behaviour.
|
||||
|
||||
2. **Known engine limitations in ADRs**: If an ADR records a known engine limitation
|
||||
(e.g. "Jolt ignores HingeJoint3D damp", "D3D12 is now the default backend"), check
|
||||
GDDs that design mechanics around the affected feature.
|
||||
|
||||
3. **Deprecated API conflicts**: If Phase 5 flagged a deprecated API used in an ADR,
|
||||
check whether any GDD contains mechanics that assume the deprecated API's behaviour.
|
||||
|
||||
For each conflict found, record it in the GDD Revision Flags table:
|
||||
|
||||
```
|
||||
### GDD Revision Flags (Architecture → Design Feedback)
|
||||
These GDD assumptions conflict with verified engine behaviour or accepted ADRs.
|
||||
The GDD should be revised before its system enters implementation.
|
||||
|
||||
| GDD | Assumption | Reality (from ADR/engine-reference) | Action |
|
||||
|-----|-----------|--------------------------------------|--------|
|
||||
| combat.md | "Use HingeJoint3D damp for weapon recoil" | Jolt ignores damp — ADR-0003 | Revise GDD |
|
||||
```
|
||||
|
||||
If no revision flags are found, write: "No GDD revision flags — all GDD assumptions
|
||||
are consistent with verified engine behaviour."
|
||||
|
||||
Before asking, display the proposed change inline — show the current systems-index row for each flagged GDD and the proposed updated row side by side so the user can see exactly what will change.
|
||||
|
||||
Then use `AskUserQuestion`:
|
||||
- "I found [N] GDD revision flag(s). May I update the systems index?"
|
||||
- [A] Yes — apply all [N] updates to the systems index now
|
||||
- [B] Show me the full diff first, then ask again
|
||||
- [C] No — leave the systems index unchanged for now
|
||||
|
||||
If [A]: apply the updates. Status field must be exactly `Needs Revision` — no parentheticals
|
||||
(other skills match that exact string and parentheticals break the match).
|
||||
If [B]: display the complete proposed systems-index section, then re-ask with `AskUserQuestion`.
|
||||
|
||||
---
|
||||
**Read `references/5-engine.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 6: Architecture Document Coverage
|
||||
|
||||
**If `docs/architecture/architecture.md` does not exist, say so in the report** —
|
||||
`Architecture document coverage: NOT ASSESSED — no docs/architecture/architecture.md`
|
||||
— and carry it into the Phase 7 verdict per the trigger list below. Phase 5
|
||||
already models this for the engine consultation (*"A skipped check that says
|
||||
nothing is indistinguishable from a check that passed"*); this phase is the one
|
||||
that did not. Silently producing no Phase 6 findings reads as an architecture
|
||||
document that was checked and found clean, which is the opposite of what
|
||||
happened.
|
||||
|
||||
If it exists, validate it against GDDs:
|
||||
|
||||
- Does every system from `systems-index.md` appear in the architecture layers?
|
||||
- Does the data flow section cover all cross-system communication defined in GDDs?
|
||||
- Do the API boundaries support all integration requirements from GDDs?
|
||||
- Are there systems in the architecture doc that have no corresponding GDD
|
||||
(orphaned architecture)?
|
||||
|
||||
---
|
||||
**Read `references/6-document-coverage.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 7: Output the Review Report
|
||||
|
||||
```
|
||||
## Architecture Review Report
|
||||
Date: [date]
|
||||
Engine: [name + version]
|
||||
GDDs Reviewed: [N]
|
||||
ADRs Reviewed: [M]
|
||||
|
||||
[output of: Bash: bash .claude/scripts/review-receipts.sh hash docs/architecture/adr-*.md design/gdd/*.md
|
||||
— one Reviewed-Content-Hash line per file reviewed; Phase 1a's freshness
|
||||
check reads these on the next run to skip or scope an unchanged re-review]
|
||||
|
||||
---
|
||||
|
||||
### Traceability Summary
|
||||
Total requirements: [N]
|
||||
✅ Covered: [X]
|
||||
⚠️ Partial: [Y]
|
||||
❌ Gaps: [Z]
|
||||
|
||||
### Coverage Gaps (no ADR exists)
|
||||
For each gap:
|
||||
❌ TR-[id]: [GDD] → [system] → [requirement]
|
||||
Suggested ADR: "/architecture-decision [suggested title]"
|
||||
Domain: [Physics/Rendering/etc]
|
||||
Engine Risk: [LOW/MEDIUM/HIGH]
|
||||
|
||||
### Cross-ADR Conflicts
|
||||
[List all conflicts from Phase 4]
|
||||
|
||||
### ADR Dependency Order
|
||||
[Topologically sorted implementation order from Phase 4 — dependency ordering section]
|
||||
[Unresolved dependencies and cycles if any]
|
||||
|
||||
### GDD Revision Flags
|
||||
[GDD assumptions that conflict with verified engine behaviour — from Phase 5b]
|
||||
[Or: "None — all GDD assumptions consistent with verified engine behaviour"]
|
||||
|
||||
### Engine Compatibility Issues
|
||||
[List all engine issues from Phase 5]
|
||||
|
||||
### Architecture Document Coverage
|
||||
[List missing systems and orphaned architecture from Phase 6]
|
||||
|
||||
---
|
||||
|
||||
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
|
||||
PASS: All requirements covered by **Accepted** ADRs, no conflicts, engine consistent
|
||||
NOT ASSESSED: The review could not be performed over its stated scope — name why
|
||||
CONCERNS: Some gaps, partial coverage, or coverage resting on `Proposed` ADRs,
|
||||
but no blocking conflicts
|
||||
FAIL: Critical gaps (Foundation/Core layer requirements uncovered),
|
||||
or blocking cross-ADR conflicts detected
|
||||
|
||||
**`NOT ASSESSED` ranks above PASS and below CONCERNS and FAIL.** Emit it when:
|
||||
|
||||
- **No ADRs exist, or none could be read.** Zero requirements traced is not full
|
||||
coverage — it is an untraced architecture, and a matrix of `❌ Gap` rows at
|
||||
least says so while an empty matrix says nothing.
|
||||
- **The requirement source is missing** — no `tr-registry.yaml` and no GDD
|
||||
requirements to trace *from*. A review with no left-hand column cannot report
|
||||
coverage; it can only report that it had nothing to compare.
|
||||
- **An ADR is unreadable or has no `## Status`**, so its rows are `❓` and their
|
||||
coverage is unknown rather than absent.
|
||||
- **Phase 6 could not run** — no `docs/architecture/architecture.md`. It must
|
||||
appear as a named `NOT ASSESSED` **line item** in the report rather than as
|
||||
absent findings. ADR traceability can still be complete, so a CONCERNS or FAIL
|
||||
finding elsewhere still stands; but in `full` mode, whose scope includes
|
||||
Phase 6, the verdict cannot be PASS — a review that could not look at part of
|
||||
its scope has not shown that part is sound, so it is NOT ASSESSED.
|
||||
- **No engine is configured** (`full` and `engine` modes) — Phase 5 has no pinned
|
||||
engine reference to audit the ADRs against, and the specialist consultation was
|
||||
skipped. Record the `Engine validation: NOT ASSESSED` line item; like Phase 6
|
||||
above, it keeps the verdict from PASS.
|
||||
|
||||
Do not resolve any of these to PASS on the grounds that no gap was *found*. No
|
||||
gap was looked for.
|
||||
|
||||
### Blocking Issues (must resolve before PASS)
|
||||
[List items that must be resolved — FAIL verdict only]
|
||||
|
||||
### Required ADRs
|
||||
[Prioritised list of ADRs to create, most foundational first]
|
||||
```
|
||||
|
||||
---
|
||||
**Read `references/7-report.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 8: Write and Update Traceability Index
|
||||
|
||||
Use `AskUserQuestion` for the write approval:
|
||||
- "Review complete. What would you like to write?"
|
||||
- [A] Write all three files — review report (`docs/architecture/architecture-review-[date].md`), traceability index (`docs/architecture/requirements-traceability.md`), TR registry (`docs/architecture/tr-registry.yaml`)
|
||||
- [B] Write review report only — `docs/architecture/architecture-review-[date].md`
|
||||
- [C] Don't write anything yet — I need to review the findings first
|
||||
|
||||
When Phase 4 found a 🔴 conflict and `docs/consistency-failures.md` exists, name
|
||||
that file in option [A] as well — "…and append [N] conflict entr(y/ies) to
|
||||
`docs/consistency-failures.md`". Only [A] appends there (see Reflexion Log
|
||||
Update); [B] writes the report and nothing else.
|
||||
|
||||
### RTM Output (rtm mode only)
|
||||
|
||||
For `rtm` mode, use `AskUserQuestion`:
|
||||
- "May I write the full Requirements Traceability Matrix?"
|
||||
- [A] Yes — write to `docs/architecture/requirements-traceability.md`
|
||||
- [B] Not yet — show me the full RTM data first, then ask again
|
||||
|
||||
RTM file format:
|
||||
|
||||
```markdown
|
||||
# Requirements Traceability Matrix (RTM)
|
||||
|
||||
> Last Updated: [date]
|
||||
> Mode: /architecture-review rtm
|
||||
> Coverage: [N]% full chain complete (GDD → ADR → Story → Test)
|
||||
|
||||
## How to read this matrix
|
||||
|
||||
| Column | Meaning |
|
||||
|--------|---------|
|
||||
| TR-ID | Stable requirement ID from tr-registry.yaml |
|
||||
| GDD | Source design document |
|
||||
| ADR | Architectural decision governing implementation |
|
||||
| Story | Story file that implements this requirement |
|
||||
| Test File | Automated test file path |
|
||||
| Test Status | COVERED / MISSING / NONE / NO STORY |
|
||||
|
||||
## Full Traceability Matrix
|
||||
|
||||
| TR-ID | GDD | Requirement | ADR | Story | Test File | Status |
|
||||
|-------|-----|-------------|-----|-------|-----------|--------|
|
||||
[Full matrix rows from Phase 3b]
|
||||
|
||||
## Coverage Summary
|
||||
|
||||
| Status | Count | % |
|
||||
|--------|-------|---|
|
||||
| COVERED — full chain complete | [N] | [%] |
|
||||
| MISSING test — story exists, no test | [N] | [%] |
|
||||
| NO STORY — ADR exists, not yet implemented | [N] | [%] |
|
||||
| NO ADR — architectural gap | [N] | [%] |
|
||||
| **Total requirements** | **[N]** | **100%** |
|
||||
|
||||
## Uncovered Requirements (Priority Fix List)
|
||||
|
||||
Requirements where the full chain is broken, prioritised by layer:
|
||||
|
||||
### Foundation layer gaps
|
||||
[list with suggested action per gap]
|
||||
|
||||
### Core layer gaps
|
||||
[list]
|
||||
|
||||
### Feature / Presentation layer gaps
|
||||
[list — lower priority]
|
||||
|
||||
## History
|
||||
|
||||
| Date | Full Chain % | Notes |
|
||||
|------|-------------|-------|
|
||||
| [date] | [%] | Initial RTM |
|
||||
```
|
||||
|
||||
### TR Registry Update
|
||||
|
||||
Also ask: "May I update `docs/architecture/tr-registry.yaml` with new requirement
|
||||
IDs from this review?"
|
||||
|
||||
If yes:
|
||||
- **Append** any new TR-IDs that weren't in the registry before this review
|
||||
- **Update** `requirement` text and `revised` date for any entries whose GDD
|
||||
wording changed (ID stays the same)
|
||||
- **Mark** `status: deprecated` for any registry entries whose GDD requirement
|
||||
no longer exists (confirm with user before marking deprecated)
|
||||
- **Never** renumber or delete existing entries
|
||||
- Update the `last_updated` and `version` fields at the top
|
||||
|
||||
This ensures all future story files can reference stable TR-IDs that persist
|
||||
across every subsequent architecture review.
|
||||
|
||||
### Reflexion Log Update
|
||||
|
||||
When the user chose Phase 8's [A] — the option that named this file — append
|
||||
any 🔴 CONFLICT entries found in Phase 4 to `docs/consistency-failures.md` (if
|
||||
the file exists), after writing the review report:
|
||||
|
||||
```markdown
|
||||
### [YYYY-MM-DD] — /architecture-review — 🔴 CONFLICT
|
||||
**Domain**: Architecture / [specific domain e.g. State Ownership, Performance]
|
||||
**Documents involved**: [ADR-NNNN] vs [ADR-MMMM]
|
||||
**What happened**: [specific conflict — what each ADR claims]
|
||||
**Resolution**: [how it was or should be resolved]
|
||||
**Pattern**: [generalised lesson for future ADR authors in this domain]
|
||||
```
|
||||
|
||||
Only append CONFLICT entries — do not log GAP entries (missing ADRs are expected
|
||||
before the architecture is complete). Do not create the file if missing — only
|
||||
append when it already exists.
|
||||
|
||||
### Session State Update
|
||||
|
||||
After writing all approved files, silently append to
|
||||
`production/session-state/active.md`:
|
||||
|
||||
## Session Extract — /architecture-review [date]
|
||||
- Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
- Requirements: [N] total — [X] covered, [Y] partial, [Z] gaps
|
||||
- New TR-IDs registered: [N, or "None"]
|
||||
- GDD revision flags: [comma-separated GDD names, or "None"]
|
||||
- Top ADR gaps: [top 3 gap titles from the report, or "None"]
|
||||
- Report: docs/architecture/architecture-review-[date].md
|
||||
|
||||
If `active.md` does not exist, create it with this block as the initial content.
|
||||
Confirm in conversation: "Session state updated."
|
||||
|
||||
The traceability index — written to `docs/architecture/requirements-traceability.md`,
|
||||
the path `/propagate-design-change` and the Pre-Production gate read; `rtm` mode
|
||||
later extends the same file with story and test columns — uses this format:
|
||||
|
||||
```markdown
|
||||
# Architecture Traceability Index
|
||||
Last Updated: [date]
|
||||
Engine: [name + version]
|
||||
|
||||
## Coverage Summary
|
||||
- Total requirements: [N]
|
||||
- Covered: [X] ([%])
|
||||
- Partial: [Y]
|
||||
- Gaps: [Z]
|
||||
|
||||
## Full Matrix
|
||||
[Complete traceability matrix from Phase 3]
|
||||
|
||||
## Known Gaps
|
||||
[All ❌ items with suggested ADRs]
|
||||
|
||||
## Superseded Requirements
|
||||
[Requirements whose GDD was changed after the ADR was written]
|
||||
```
|
||||
|
||||
---
|
||||
**Read `references/8-write.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 9: Handoff
|
||||
|
||||
After completing the review and writing approved files, present:
|
||||
|
||||
1. **Immediate actions**: List the top 3 ADRs to create (highest-impact gaps first,
|
||||
Foundation layer before Feature layer)
|
||||
2. **Pre-gate checklist**: Check whether these exist via Glob and mark each ✅ or ❌:
|
||||
- the engine's test root — `tests/unit/` and `tests/integration/` (Godot), `Assets/Tests/EditMode/` and `Assets/Tests/PlayMode/` (Unity), `Source/<Module>/Private/Tests/` (Unreal) — if ❌: run `/test-setup`
|
||||
- `.github/workflows/tests.yml` — if ❌: run `/test-setup`
|
||||
- `design/accessibility-requirements.md` — if ❌: run `/ux-design`
|
||||
- `design/ux/interaction-patterns.md` — if ❌: run `/ux-design`
|
||||
Present ❌ items as required steps before gate-check. Do not offer `/gate-check`
|
||||
as an option if any item is ❌ — offer the missing skill to run instead.
|
||||
3. **Rerun trigger**: "Re-run `/architecture-review` after each new ADR is written
|
||||
to verify coverage improves"
|
||||
|
||||
Then close with `AskUserQuestion` tailored to the pre-gate checklist state:
|
||||
- If ADR gaps remain or any pre-gate item is ❌:
|
||||
- "Architecture review complete. What would you like to do next?"
|
||||
- [A] Write a missing ADR — open a fresh session and run `/architecture-decision [system]`
|
||||
- [B] Run `/test-setup` — required before gate-check (only show if test infrastructure is ❌)
|
||||
- [C] Run `/ux-design` — required before gate-check (only show if UX/accessibility files are ❌)
|
||||
- [D] Stop here for this session
|
||||
- If all pre-gate checklist items are ✅ and no blocking ADR gaps remain:
|
||||
- "Architecture review complete. All pre-gate items confirmed. What would you like to do next?"
|
||||
- [A] Run `/gate-check pre-production`
|
||||
- [B] Write a missing ADR — open a fresh session and run `/architecture-decision [system]`
|
||||
- [C] Stop here for this session
|
||||
|
||||
---
|
||||
**Read `references/9-handoff.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Error Recovery Protocol
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
# /architecture-review — Phase 1: Load Everything
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 1: Load Everything
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Phase 1a — L0: Summary Scan (fast, low tokens)
|
||||
- Phase 1b — L1/L2: Targeted Section Load
|
||||
- Design Documents
|
||||
- Architecture Documents
|
||||
- Engine Reference
|
||||
- Project Standards
|
||||
|
||||
### Phase 1a — L0: Summary Scan (fast, low tokens)
|
||||
|
||||
**Freshness check before any scan.** Locate the latest prior report — Glob
|
||||
`docs/architecture/architecture-review-*.md` and take the newest — then:
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/review-receipts.sh check "[latest-report]" docs/architecture/adr-*.md design/gdd/*.md
|
||||
```
|
||||
|
||||
- **Any `UNRESOLVED`** — check this FIRST; it disqualifies every option
|
||||
below. One of the two globs matched no file, so that whole document class
|
||||
was never examined and the comparison covered less than it appears to.
|
||||
Say which pattern came back unresolved and stop: an ADR or GDD directory
|
||||
that is empty, renamed or misspelled is a finding about the project, not a
|
||||
reason to stand on a prior report. Never read a set of `UNCHANGED` lines as
|
||||
"everything is current" while an `UNRESOLVED` line is present — the set
|
||||
compared was not the set requested.
|
||||
- **Everything `UNCHANGED`** (and no `UNRESOLVED`) — nothing this review
|
||||
reads has changed since that report; re-running reproduces it. Surface the
|
||||
prior report's date and verdict and offer via `AskUserQuestion`: `[A] Stand
|
||||
on the prior report (Recommended)` / `[B] Re-run the full review anyway` —
|
||||
`guided` proceeds with [A] and notes it; `autonomous` logs via
|
||||
`log_decision` and stands on the prior report.
|
||||
- **Some `CHANGED`/`NEW`** — name them, then scope instead of re-running
|
||||
everything: recommend `/architecture-review [system]` (single-system mode)
|
||||
for just the changed systems. A full re-run stays available on request,
|
||||
and structural changes (a `NEW` ADR, a deleted file) warrant one.
|
||||
- **`RECEIPT: NONE`** — no prior report, or one written before receipts
|
||||
existed. Proceed with the full review; this run's report will carry the
|
||||
first stamps.
|
||||
|
||||
Before reading any full document, use Grep to extract `## Summary` sections
|
||||
from all GDDs and ADRs:
|
||||
|
||||
```
|
||||
Grep pattern="## Summary" glob="design/gdd/*.md" output_mode="content" -A 4
|
||||
Grep pattern="## Summary" glob="docs/architecture/adr-*.md" output_mode="content" -A 3
|
||||
```
|
||||
|
||||
**Fail open on a missing Summary.** Establish the denominator: glob
|
||||
`design/gdd/*.md` and count **N**. A scan matching fewer than N means those GDDs
|
||||
predate `## Summary` (`/design-system` emits it, but older GDDs lack it) — never
|
||||
treat an absent Summary as a system out of scope. A zero-match scan means "no GDD
|
||||
carries a Summary yet", not "nothing to review": full-read the unmatched set.
|
||||
|
||||
For `single-gdd [path]` mode: use the target GDD's summary to identify which
|
||||
ADRs reference the same system (Grep ADRs for the system name), then load only
|
||||
those ADRs' sections per Phase 1b. Skip unrelated GDDs entirely.
|
||||
|
||||
For `engine` mode: load ADR sections only — GDDs are not needed for engine checks.
|
||||
In practice this is the `## Engine Compatibility` scan alone.
|
||||
|
||||
For `coverage` or `full` mode: proceed to Phase 1b for the full in-scope set.
|
||||
**This is a section load, not a full-file load** — see below for why, and for the
|
||||
narrow cases that still justify escalating to a whole document.
|
||||
|
||||
### Phase 1b — L1/L2: Targeted Section Load
|
||||
|
||||
Load the sections the later phases actually consume — **not whole files**. This
|
||||
skill reads the two largest document sets in the project (every GDD *and* every
|
||||
ADR); at realistic sizes a full load of both exhausts the context window before
|
||||
Phase 2 starts, and most of what it loads is narrative this skill never uses.
|
||||
|
||||
**Establish the denominator first.** Glob `design/gdd/*.md` and count **N_gdd**;
|
||||
glob `docs/architecture/adr-*.md` and count **N_adr**. Report both. A section
|
||||
scan matching fewer than the denominator means those documents lack the section —
|
||||
**never treat an absent section as an absent document.** The scan narrows the
|
||||
*read* set; it never shrinks the *in-scope* set.
|
||||
|
||||
### Design Documents
|
||||
|
||||
Phase 2 extracts *technical requirements* — data structures, performance
|
||||
constraints, engine capabilities, cross-system communication, persistence,
|
||||
threading, platform needs. Those live in a known set of sections; Overview and
|
||||
Player Fantasy are narrative and yield none.
|
||||
|
||||
```
|
||||
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
|
||||
```
|
||||
|
||||
Accept **either** `## Detailed Rules` or `## Detailed Design` — the design
|
||||
standard and the GDD template disagree on the name and they denote the same
|
||||
required section. Full-read a single GDD only when a scanned section
|
||||
cross-references material outside itself, or when a GDD matched zero sections
|
||||
(it predates the template — read it whole and say so).
|
||||
|
||||
- `design/gdd/systems-index.md` — the authoritative list of systems; read whole (small, and it is an index)
|
||||
|
||||
### Architecture Documents
|
||||
|
||||
Phases 3–5 need the traceability table, the decision itself, engine claims, and
|
||||
the dependency edges — not Context, Consequences, Alternatives, Migration Plan or
|
||||
Validation Criteria, which explain *why* a decision was made.
|
||||
|
||||
```
|
||||
Grep pattern="^## (Status|Decision|GDD Requirements Addressed|Engine Compatibility|ADR Dependencies|Performance Implications)" glob="docs/architecture/adr-*.md" output_mode="content" -A 30
|
||||
```
|
||||
|
||||
Interpret against **N_adr**, and distinguish the two zero-match cases — they are
|
||||
not the same finding:
|
||||
|
||||
| Result | Meaning | Action |
|
||||
|---|---|---|
|
||||
| N_adr matches | Normal. | Proceed on the scanned sections. |
|
||||
| Some ADRs match, some do not | Those ADRs are missing sections. | Record each as a **structural gap** in the Phase 7 report — a missing `## GDD Requirements Addressed` is itself a traceability finding. |
|
||||
| **0 matches, N_adr > 0** | **Malformed ADRs**, not "no architecture". | "[N_adr] ADRs found, none carries a scannable section — run `/architecture-decision retrofit [file]` on each." Do **not** report zero coverage; that would read as a design failure when it is a format failure. |
|
||||
|
||||
Escalate to a full read of one ADR only when judging a conflict needs its
|
||||
reasoning (Phase 4) — that is a per-ADR decision, not a blanket load.
|
||||
|
||||
- `docs/architecture/architecture.md` if it exists
|
||||
|
||||
### Engine Reference
|
||||
- `docs/engine-reference/[engine]/VERSION.md`
|
||||
- `docs/engine-reference/[engine]/breaking-changes.md`
|
||||
- `docs/engine-reference/[engine]/deprecated-apis.md`
|
||||
- **Only the module docs the in-scope ADRs actually name** — take the union of
|
||||
each ADR's `References Consulted` and `Post-Cutoff APIs Used` fields (already
|
||||
captured by the `## Engine Compatibility` scan above) and read those files.
|
||||
Reading the whole `modules/` directory loads engine subsystems the project may
|
||||
not use at all. If no ADR names any module, read none and note it: Phase 5
|
||||
cannot cross-check engine claims that were never made.
|
||||
|
||||
### Project Standards
|
||||
- `project.yaml` — `naming.*` and `performance.*`; plus `.claude/docs/technical-preferences.md` for those keys when absent and for forbidden patterns / allowed libraries
|
||||
|
||||
Report a count: "Loaded [N] GDDs, [M] ADRs, engine: [name + version]."
|
||||
|
||||
**Also read `docs/consistency-failures.md`** if it exists. Extract entries with
|
||||
Domain matching the systems under review (Architecture, Engine, or any GDD domain
|
||||
being covered). Surface recurring patterns as a "Known conflict-prone areas" note
|
||||
at the top of the Phase 4 conflict detection output.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,58 @@
|
||||
# /architecture-review — Phase 2: Extract Technical Requirements
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 2: Extract Technical Requirements from Every GDD
|
||||
|
||||
### Pre-load the TR Registry
|
||||
|
||||
Before extracting any requirements, read `docs/architecture/tr-registry.yaml`
|
||||
if it exists. Index existing entries by `id` and by normalized `requirement`
|
||||
text (lowercase, trimmed). This prevents ID renumbering across review runs.
|
||||
|
||||
For each requirement you extract, the matching rule is:
|
||||
1. **Exact/near match** to an existing registry entry for the same system →
|
||||
reuse that entry's TR-ID unchanged. Update the `requirement` text in the
|
||||
registry only if the GDD wording changed (same intent, clearer phrasing) —
|
||||
add a `revised: [date]` field.
|
||||
2. **No match** → assign a new ID: next available `TR-[system]-NNN` for that
|
||||
system, starting from the highest existing sequence + 1.
|
||||
3. **Ambiguous** (partial match, intent unclear) → ask the user:
|
||||
> "Does '[new requirement text]' refer to the same requirement as
|
||||
> `TR-[system]-NNN: [existing text]'`, or is it a new requirement?"
|
||||
User answers: "Same requirement" (reuse ID) or "New requirement" (new ID).
|
||||
|
||||
For any requirement with `status: deprecated` in the registry — skip it.
|
||||
It was removed from the GDD intentionally.
|
||||
|
||||
For each GDD, read it and extract all **technical requirements** — things the
|
||||
architecture must provide for the system to work. A technical requirement is any
|
||||
statement that implies a specific architectural decision.
|
||||
|
||||
Categories to extract:
|
||||
|
||||
| Category | Example |
|
||||
|----------|---------|
|
||||
| **Data structures** | "Each entity has health, max health, status effects" → needs a component/data schema |
|
||||
| **Performance constraints** | "Collision detection must run at 60fps with 200 entities" → physics budget ADR |
|
||||
| **Engine capability** | "Inverse kinematics for character animation" → IK system ADR |
|
||||
| **Cross-system communication** | "Damage system notifies UI and audio simultaneously" → event/signal architecture ADR |
|
||||
| **State persistence** | "Player progress persists between sessions" → save system ADR |
|
||||
| **Threading/timing** | "AI decisions happen off the main thread" → concurrency ADR |
|
||||
| **Platform requirements** | "Supports keyboard, gamepad, touch" → input system ADR |
|
||||
|
||||
For each GDD, produce a structured list:
|
||||
|
||||
```
|
||||
GDD: [filename]
|
||||
System: [system name]
|
||||
Technical Requirements:
|
||||
TR-[GDD]-001: [requirement text] → Domain: [Physics/Rendering/etc]
|
||||
TR-[GDD]-002: [requirement text] → Domain: [...]
|
||||
```
|
||||
|
||||
This becomes the **requirements baseline** — the complete set of what the
|
||||
architecture must cover.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,129 @@
|
||||
# /architecture-review — Phases 3 and 3b: Traceability Matrix and Story Linkage
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 3: Build the Traceability Matrix
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Step 3b-1 — Load stories
|
||||
- Step 3b-2 — Load test files
|
||||
- Step 3b-3 — Build the extended RTM
|
||||
|
||||
For each technical requirement extracted in Phase 2, search the ADRs:
|
||||
|
||||
1. Use the ADRs **already loaded in Phase 1b** — do not re-read them. Extract each
|
||||
ADR's "GDD Requirements Addressed" section from what is already in context.
|
||||
(If Phase 1b ran in a mode that did not load every ADR, `Grep pattern="## GDD
|
||||
Requirements Addressed" glob="docs/architecture/adr-*.md" output_mode="content"
|
||||
-A 15` fills the gap without a full re-read.)
|
||||
2. Check if it explicitly references the requirement or its GDD
|
||||
3. Check if the ADR's decision text implicitly covers the requirement
|
||||
4. Mark coverage status:
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| ✅ **Covered** | An **Accepted** ADR explicitly addresses this requirement |
|
||||
| 🟡 **Covered (Proposed)** | An ADR addresses it, but that ADR is still `Proposed` |
|
||||
| ⚠️ **Partial** | An ADR partially covers this, or coverage is ambiguous |
|
||||
| ❌ **Gap** | No ADR addresses this requirement |
|
||||
| ❓ **Not assessed** | The ADR is unreadable, or has no `## Status` section |
|
||||
|
||||
> **Read each ADR's `## Status` before marking coverage — an unaccepted decision
|
||||
> is not coverage.** If `✅` meant only that *an ADR addresses this*, with no
|
||||
> status qualification, a requirement covered entirely by `Proposed` ADRs would
|
||||
> count as covered and this review could return **PASS: All requirements
|
||||
> covered** over an architecture nobody had accepted. Four skills downstream
|
||||
> (`create-control-manifest`, `create-epics`, `create-stories`, `gate-check`)
|
||||
> require `Accepted`, so a PASS on that basis sends work forward that every one
|
||||
> of them will refuse.
|
||||
>
|
||||
> `🟡` is **not** a pass state: it caps the verdict at **CONCERNS**, and names the
|
||||
> route out — `/architecture-decision accept ADR-NNNN`. That route is the only
|
||||
> thing that moves an ADR to `Accepted`; without it, grading `Proposed` as
|
||||
> covered would be the only option, which is why it must never be graded so.
|
||||
|
||||
Build the full matrix:
|
||||
|
||||
```
|
||||
## Traceability Matrix
|
||||
|
||||
| Requirement ID | GDD | System | Requirement | ADR Coverage | Status |
|
||||
|---------------|-----|--------|-------------|--------------|--------|
|
||||
| TR-combat-001 | combat.md | Combat | Hitbox detection < 1 frame | ADR-0003 | ✅ |
|
||||
| TR-combat-002 | combat.md | Combat | Combo window timing | — | ❌ GAP |
|
||||
| TR-inventory-001 | inventory.md | Inventory | Persistent item storage | ADR-0005 | ✅ |
|
||||
```
|
||||
|
||||
Count the totals: X covered, Y partial, Z gaps.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3b: Story and Test Linkage (RTM mode only)
|
||||
|
||||
*Skip this phase unless the argument is `rtm` or `full` with stories present.*
|
||||
|
||||
This phase extends the Phase 3 matrix to include the story that implements
|
||||
each requirement and the test that verifies it — producing the full
|
||||
Requirements Traceability Matrix (RTM).
|
||||
|
||||
### Step 3b-1 — Load stories
|
||||
|
||||
Glob `production/epics/**/*.md` (excluding EPIC.md index files) to establish the
|
||||
denominator. Then collect the fields with **targeted section greps, not a full
|
||||
read of each story** — the same two-grep form `/test-evidence-review` uses for
|
||||
this identical extraction:
|
||||
|
||||
```
|
||||
Grep pattern="## Test Evidence" glob="production/epics/**/story-*.md" output_mode="content" -A 8
|
||||
Grep pattern="TR-" glob="production/epics/**/story-*.md" output_mode="content"
|
||||
```
|
||||
|
||||
- **TR-ID** — from the second grep.
|
||||
- **Test file path** — under `## Test Evidence`, captured by the first grep's `-A 8`.
|
||||
- **Status** — from the story header; add `Grep pattern="^> \*\*Status\*\*"` if not already captured.
|
||||
- **Story path and title** — from the file name and path; no read at all.
|
||||
|
||||
Full-read a story only when its Test Evidence section is missing or ambiguous.
|
||||
|
||||
### Step 3b-2 — Load test files
|
||||
|
||||
Glob the engine's test root (`.claude/docs/directory-structure.md`): Godot
|
||||
`tests/unit/**/*_test.*` and `tests/integration/**/*_test.*`; Unity
|
||||
`Assets/Tests/**/*Tests.cs`; Unreal `Source/*/Private/Tests/**/*.cpp`. With no
|
||||
engine configured, say the test index could not be built rather than reading an
|
||||
empty glob as "no tests". Build an index: system → [test file paths].
|
||||
|
||||
For each test file path from Step 3b-1, confirm via Glob whether the file
|
||||
actually exists. Note MISSING if the stated path does not exist.
|
||||
|
||||
### Step 3b-3 — Build the extended RTM
|
||||
|
||||
For each TR-ID in the Phase 3 matrix, add:
|
||||
- **Story**: the story file path(s) that reference this TR-ID (may be multiple)
|
||||
- **Test File**: the test file path stated in the story's Test Evidence section
|
||||
- **Test Status**: COVERED (test file exists) / MISSING (path stated but not
|
||||
found) / NONE (no test path stated, story type may be Visual/Feel/UI) /
|
||||
NO STORY (requirement has no story yet — pre-production gap)
|
||||
|
||||
Extended matrix format:
|
||||
|
||||
```
|
||||
## Requirements Traceability Matrix (RTM)
|
||||
|
||||
| TR-ID | GDD | Requirement | ADR | Story | Test File | Test Status |
|
||||
|-------|-----|-------------|-----|-------|-----------|-------------|
|
||||
| TR-combat-001 | combat.md | Hitbox < 1 frame | ADR-0003 | story-001-hitbox.md | tests/unit/combat/hitbox_test.gd | COVERED |
|
||||
| TR-combat-002 | combat.md | Combo window | — | story-002-combo.md | — | NONE (Visual/Feel) |
|
||||
| TR-inventory-001 | inventory.md | Persistent storage | ADR-0005 | — | — | NO STORY |
|
||||
```
|
||||
|
||||
RTM coverage summary:
|
||||
- COVERED: [N] — requirements with ADR + story + passing test
|
||||
- MISSING test: [N] — story exists but test file not found
|
||||
- NO STORY: [N] — requirements with ADR but no story yet
|
||||
- NO ADR: [N] — requirements without architectural coverage (from Phase 3 gaps)
|
||||
- Full chain complete (COVERED): [N/total] ([%])
|
||||
|
||||
---
|
||||
@@ -0,0 +1,85 @@
|
||||
# /architecture-review — Phase 4: Cross-ADR Conflict Detection
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 4: Cross-ADR Conflict Detection
|
||||
|
||||
Compare every ADR against every other ADR to detect contradictions. A conflict
|
||||
exists when:
|
||||
|
||||
- **Data ownership conflict**: Two ADRs claim exclusive ownership of the same data
|
||||
- **Integration contract conflict**: ADR-A assumes System X has interface Y, but
|
||||
ADR-B defines System X with a different interface
|
||||
- **Performance budget conflict**: ADR-A allocates N ms to physics, ADR-B allocates
|
||||
N ms to AI, together they exceed the total frame budget
|
||||
- **Dependency cycle**: ADR-A says System X initialises before Y; ADR-B says Y
|
||||
initialises before X
|
||||
- **Architecture pattern conflict**: ADR-A uses event-driven communication for a
|
||||
subsystem; ADR-B uses direct function calls to the same subsystem
|
||||
- **State management conflict**: Two ADRs define authority over the same game state
|
||||
(e.g. both Combat ADR and Character ADR claim to own the health value)
|
||||
|
||||
For each conflict found:
|
||||
|
||||
```
|
||||
## Conflict: [ADR-NNNN] vs [ADR-MMMM]
|
||||
Type: [Data ownership / Integration / Performance / Dependency / Pattern / State]
|
||||
ADR-NNNN claims: [...]
|
||||
ADR-MMMM claims: [...]
|
||||
Impact: [What breaks if both are implemented as written]
|
||||
Resolution options:
|
||||
1. [Option A]
|
||||
2. [Option B]
|
||||
```
|
||||
|
||||
### ADR Dependency Ordering
|
||||
|
||||
After conflict detection, analyse the dependency graph across all ADRs.
|
||||
|
||||
**Build the graph deterministically — do not trace it by hand:**
|
||||
|
||||
```
|
||||
Bash: bash .claude/scripts/adr-dep-graph.sh
|
||||
```
|
||||
|
||||
It collects every `Depends On` edge, runs Kahn's algorithm, and emits
|
||||
`ADRS:` / `EDGES:` / `NO_DEPS_SECTION:` / `CYCLE:`. A model tracing A→B→C→A across
|
||||
a dozen ADRs eventually misses an edge; the algorithm cannot. It reports
|
||||
observations, not a verdict — you apply the meaning below.
|
||||
|
||||
**`NO_DEPS_SECTION` is load-bearing**: it makes "no cycles because the graph is
|
||||
clean" distinguishable from "no cycles because half the ADRs declare no
|
||||
dependencies". Report the second case as a structural gap, never as a clean graph.
|
||||
|
||||
Then interpret:
|
||||
|
||||
1. **Topological sort**: the emitted order — ADRs with no
|
||||
dependencies come first (Foundation), ADRs that depend on those come next, etc.
|
||||
2. **Flag unresolved dependencies**: cross the `EDGES:` list against the `## Status`
|
||||
values already scanned in Phase 1b. If ADR-A depends on an ADR that is still
|
||||
`Proposed` or does not exist, flag it:
|
||||
```
|
||||
⚠️ ADR-0005 depends on ADR-0002 — but ADR-0002 is still Proposed.
|
||||
ADR-0005 cannot be safely implemented until ADR-0002 is Accepted.
|
||||
```
|
||||
3. **Cycle detection**: every `CYCLE:` line the script emitted is a
|
||||
`DEPENDENCY CYCLE` — report each one. Do not re-derive them by hand:
|
||||
```
|
||||
🔴 DEPENDENCY CYCLE: ADR-0003 → ADR-0006 → ADR-0003
|
||||
This cycle must be broken before either can be implemented.
|
||||
```
|
||||
4. **Output recommended implementation order**:
|
||||
```
|
||||
### Recommended ADR Implementation Order (topologically sorted)
|
||||
Foundation (no dependencies):
|
||||
1. ADR-0001: [title]
|
||||
2. ADR-0003: [title]
|
||||
Depends on Foundation:
|
||||
3. ADR-0002: [title] (requires ADR-0001)
|
||||
4. ADR-0005: [title] (requires ADR-0003)
|
||||
Feature layer:
|
||||
5. ADR-0004: [title] (requires ADR-0002, ADR-0005)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -0,0 +1,113 @@
|
||||
# /architecture-review — Phases 5 and 5b: Engine Cross-Check and Design Revision Flags
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 5: Engine Compatibility Cross-Check
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Version Consistency
|
||||
- Post-Cutoff API Consistency
|
||||
- Deprecated API Check
|
||||
- Missing Engine Compatibility Sections
|
||||
- Engine Specialist Consultation
|
||||
|
||||
Across all ADRs, check for engine consistency:
|
||||
|
||||
### Version Consistency
|
||||
- Do all ADRs that mention an engine version agree on the same version?
|
||||
- If any ADR was written for an older engine version, flag it as potentially stale
|
||||
|
||||
### Post-Cutoff API Consistency
|
||||
- Collect all "Post-Cutoff APIs Used" fields from all ADRs
|
||||
- For each, verify against the relevant module reference doc
|
||||
- Check that no two ADRs make contradictory assumptions about the same post-cutoff API
|
||||
|
||||
### Deprecated API Check
|
||||
- Grep all ADRs for API names listed in `deprecated-apis.md`
|
||||
- Flag any ADR referencing a deprecated API
|
||||
|
||||
### Missing Engine Compatibility Sections
|
||||
- List all ADRs that are missing the Engine Compatibility section entirely
|
||||
- These are blind spots — their engine assumptions are unknown
|
||||
|
||||
Output format:
|
||||
```
|
||||
### Engine Audit Results
|
||||
Engine: [name + version]
|
||||
ADRs with Engine Compatibility section: X / Y total
|
||||
|
||||
Deprecated API References:
|
||||
- ADR-0002: uses [deprecated API] — deprecated since [version]
|
||||
|
||||
Stale Version References:
|
||||
- ADR-0001: written for [older version] — current project version is [version]
|
||||
|
||||
Post-Cutoff API Conflicts:
|
||||
- ADR-0004 and ADR-0007 both use [API] with incompatible assumptions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Engine Specialist Consultation
|
||||
|
||||
After completing the engine audit above, spawn the **primary engine specialist** via `Agent` for a domain-expert second opinion:
|
||||
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
|
||||
- If no engine is configured (neither source yields an engine), skip this consultation **Record ``Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)`` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
|
||||
- Spawn `subagent_type: [primary specialist]` with: all ADRs that contain engine-specific decisions or `Post-Cutoff APIs Used` fields, the engine reference docs, and the Phase 5 audit findings. Ask them to:
|
||||
1. Confirm or challenge each audit finding — specialists may know of engine nuances not captured in the reference docs
|
||||
2. Identify engine-specific anti-patterns in the ADRs that the audit may have missed (e.g., using the wrong Godot node type, Unity component coupling, Unreal subsystem misuse)
|
||||
3. Flag ADRs that make assumptions about engine behaviour that differ from the actual pinned version
|
||||
|
||||
Incorporate additional findings under `### Engine Specialist Findings` in the Phase 5 output. These feed into the final verdict — specialist-identified issues carry the same weight as audit-identified issues.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5b: Design Revision Flags (Architecture → GDD Feedback)
|
||||
|
||||
For each **HIGH RISK engine finding** from Phase 5, check whether any GDD makes an
|
||||
assumption that the verified engine reality contradicts.
|
||||
|
||||
Specific cases to check:
|
||||
|
||||
1. **Post-cutoff API behaviour differs from training-data assumptions**: If an ADR
|
||||
records a verified API behaviour that differs from the default LLM assumption,
|
||||
check all GDDs that reference the related system. Look for design rules written
|
||||
around the old (assumed) behaviour.
|
||||
|
||||
2. **Known engine limitations in ADRs**: If an ADR records a known engine limitation
|
||||
(e.g. "Jolt ignores HingeJoint3D damp", "D3D12 is now the default backend"), check
|
||||
GDDs that design mechanics around the affected feature.
|
||||
|
||||
3. **Deprecated API conflicts**: If Phase 5 flagged a deprecated API used in an ADR,
|
||||
check whether any GDD contains mechanics that assume the deprecated API's behaviour.
|
||||
|
||||
For each conflict found, record it in the GDD Revision Flags table:
|
||||
|
||||
```
|
||||
### GDD Revision Flags (Architecture → Design Feedback)
|
||||
These GDD assumptions conflict with verified engine behaviour or accepted ADRs.
|
||||
The GDD should be revised before its system enters implementation.
|
||||
|
||||
| GDD | Assumption | Reality (from ADR/engine-reference) | Action |
|
||||
|-----|-----------|--------------------------------------|--------|
|
||||
| combat.md | "Use HingeJoint3D damp for weapon recoil" | Jolt ignores damp — ADR-0003 | Revise GDD |
|
||||
```
|
||||
|
||||
If no revision flags are found, write: "No GDD revision flags — all GDD assumptions
|
||||
are consistent with verified engine behaviour."
|
||||
|
||||
Before asking, display the proposed change inline — show the current systems-index row for each flagged GDD and the proposed updated row side by side so the user can see exactly what will change.
|
||||
|
||||
Then use `AskUserQuestion`:
|
||||
- "I found [N] GDD revision flag(s). May I update the systems index?"
|
||||
- [A] Yes — apply all [N] updates to the systems index now
|
||||
- [B] Show me the full diff first, then ask again
|
||||
- [C] No — leave the systems index unchanged for now
|
||||
|
||||
If [A]: apply the updates. Status field must be exactly `Needs Revision` — no parentheticals
|
||||
(other skills match that exact string and parentheticals break the match).
|
||||
If [B]: display the complete proposed systems-index section, then re-ask with `AskUserQuestion`.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,25 @@
|
||||
# /architecture-review — Phase 6: Architecture Document Coverage
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 6: Architecture Document Coverage
|
||||
|
||||
**If `docs/architecture/architecture.md` does not exist, say so in the report** —
|
||||
`Architecture document coverage: NOT ASSESSED — no docs/architecture/architecture.md`
|
||||
— and carry it into the Phase 7 verdict per the trigger list below. Phase 5
|
||||
already models this for the engine consultation (*"A skipped check that says
|
||||
nothing is indistinguishable from a check that passed"*); this phase is the one
|
||||
that did not. Silently producing no Phase 6 findings reads as an architecture
|
||||
document that was checked and found clean, which is the opposite of what
|
||||
happened.
|
||||
|
||||
If it exists, validate it against GDDs:
|
||||
|
||||
- Does every system from `systems-index.md` appear in the architecture layers?
|
||||
- Does the data flow section cover all cross-system communication defined in GDDs?
|
||||
- Do the API boundaries support all integration requirements from GDDs?
|
||||
- Are there systems in the architecture doc that have no corresponding GDD
|
||||
(orphaned architecture)?
|
||||
|
||||
---
|
||||
@@ -0,0 +1,93 @@
|
||||
# /architecture-review — Phase 7: Output the Review Report
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 7: Output the Review Report
|
||||
|
||||
```
|
||||
## Architecture Review Report
|
||||
Date: [date]
|
||||
Engine: [name + version]
|
||||
GDDs Reviewed: [N]
|
||||
ADRs Reviewed: [M]
|
||||
|
||||
[output of: Bash: bash .claude/scripts/review-receipts.sh hash docs/architecture/adr-*.md design/gdd/*.md
|
||||
— one Reviewed-Content-Hash line per file reviewed; Phase 1a's freshness
|
||||
check reads these on the next run to skip or scope an unchanged re-review]
|
||||
|
||||
---
|
||||
|
||||
### Traceability Summary
|
||||
Total requirements: [N]
|
||||
✅ Covered: [X]
|
||||
⚠️ Partial: [Y]
|
||||
❌ Gaps: [Z]
|
||||
|
||||
### Coverage Gaps (no ADR exists)
|
||||
For each gap:
|
||||
❌ TR-[id]: [GDD] → [system] → [requirement]
|
||||
Suggested ADR: "/architecture-decision [suggested title]"
|
||||
Domain: [Physics/Rendering/etc]
|
||||
Engine Risk: [LOW/MEDIUM/HIGH]
|
||||
|
||||
### Cross-ADR Conflicts
|
||||
[List all conflicts from Phase 4]
|
||||
|
||||
### ADR Dependency Order
|
||||
[Topologically sorted implementation order from Phase 4 — dependency ordering section]
|
||||
[Unresolved dependencies and cycles if any]
|
||||
|
||||
### GDD Revision Flags
|
||||
[GDD assumptions that conflict with verified engine behaviour — from Phase 5b]
|
||||
[Or: "None — all GDD assumptions consistent with verified engine behaviour"]
|
||||
|
||||
### Engine Compatibility Issues
|
||||
[List all engine issues from Phase 5]
|
||||
|
||||
### Architecture Document Coverage
|
||||
[List missing systems and orphaned architecture from Phase 6]
|
||||
|
||||
---
|
||||
|
||||
### Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
|
||||
PASS: All requirements covered by **Accepted** ADRs, no conflicts, engine consistent
|
||||
NOT ASSESSED: The review could not be performed over its stated scope — name why
|
||||
CONCERNS: Some gaps, partial coverage, or coverage resting on `Proposed` ADRs,
|
||||
but no blocking conflicts
|
||||
FAIL: Critical gaps (Foundation/Core layer requirements uncovered),
|
||||
or blocking cross-ADR conflicts detected
|
||||
|
||||
**`NOT ASSESSED` ranks above PASS and below CONCERNS and FAIL.** Emit it when:
|
||||
|
||||
- **No ADRs exist, or none could be read.** Zero requirements traced is not full
|
||||
coverage — it is an untraced architecture, and a matrix of `❌ Gap` rows at
|
||||
least says so while an empty matrix says nothing.
|
||||
- **The requirement source is missing** — no `tr-registry.yaml` and no GDD
|
||||
requirements to trace *from*. A review with no left-hand column cannot report
|
||||
coverage; it can only report that it had nothing to compare.
|
||||
- **An ADR is unreadable or has no `## Status`**, so its rows are `❓` and their
|
||||
coverage is unknown rather than absent.
|
||||
- **Phase 6 could not run** — no `docs/architecture/architecture.md`. It must
|
||||
appear as a named `NOT ASSESSED` **line item** in the report rather than as
|
||||
absent findings. ADR traceability can still be complete, so a CONCERNS or FAIL
|
||||
finding elsewhere still stands; but in `full` mode, whose scope includes
|
||||
Phase 6, the verdict cannot be PASS — a review that could not look at part of
|
||||
its scope has not shown that part is sound, so it is NOT ASSESSED.
|
||||
- **No engine is configured** (`full` and `engine` modes) — Phase 5 has no pinned
|
||||
engine reference to audit the ADRs against, and the specialist consultation was
|
||||
skipped. Record the `Engine validation: NOT ASSESSED` line item; like Phase 6
|
||||
above, it keeps the verdict from PASS.
|
||||
|
||||
Do not resolve any of these to PASS on the grounds that no gap was *found*. No
|
||||
gap was looked for.
|
||||
|
||||
### Blocking Issues (must resolve before PASS)
|
||||
[List items that must be resolved — FAIL verdict only]
|
||||
|
||||
### Required ADRs
|
||||
[Prioritised list of ADRs to create, most foundational first]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -0,0 +1,172 @@
|
||||
# /architecture-review — Phase 8: Write and Update Traceability Index
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 8: Write and Update Traceability Index
|
||||
|
||||
**In this file:**
|
||||
|
||||
- RTM Output (rtm mode only)
|
||||
- TR Registry Update
|
||||
- Reflexion Log Update
|
||||
- Session State Update
|
||||
|
||||
Use `AskUserQuestion` for the write approval:
|
||||
- "Review complete. What would you like to write?"
|
||||
- [A] Write all three files — review report (`docs/architecture/architecture-review-[date].md`), traceability index (`docs/architecture/requirements-traceability.md`), TR registry (`docs/architecture/tr-registry.yaml`)
|
||||
- [B] Write review report only — `docs/architecture/architecture-review-[date].md`
|
||||
- [C] Don't write anything yet — I need to review the findings first
|
||||
|
||||
When Phase 4 found a 🔴 conflict and `docs/consistency-failures.md` exists, name
|
||||
that file in option [A] as well — "…and append [N] conflict entr(y/ies) to
|
||||
`docs/consistency-failures.md`". Only [A] appends there (see Reflexion Log
|
||||
Update); [B] writes the report and nothing else.
|
||||
|
||||
### RTM Output (rtm mode only)
|
||||
|
||||
For `rtm` mode, use `AskUserQuestion`:
|
||||
- "May I write the full Requirements Traceability Matrix?"
|
||||
- [A] Yes — write to `docs/architecture/requirements-traceability.md`
|
||||
- [B] Not yet — show me the full RTM data first, then ask again
|
||||
|
||||
RTM file format:
|
||||
|
||||
```markdown
|
||||
# Requirements Traceability Matrix (RTM)
|
||||
|
||||
> Last Updated: [date]
|
||||
> Mode: /architecture-review rtm
|
||||
> Coverage: [N]% full chain complete (GDD → ADR → Story → Test)
|
||||
|
||||
## How to read this matrix
|
||||
|
||||
| Column | Meaning |
|
||||
|--------|---------|
|
||||
| TR-ID | Stable requirement ID from tr-registry.yaml |
|
||||
| GDD | Source design document |
|
||||
| ADR | Architectural decision governing implementation |
|
||||
| Story | Story file that implements this requirement |
|
||||
| Test File | Automated test file path |
|
||||
| Test Status | COVERED / MISSING / NONE / NO STORY |
|
||||
|
||||
## Full Traceability Matrix
|
||||
|
||||
| TR-ID | GDD | Requirement | ADR | Story | Test File | Status |
|
||||
|-------|-----|-------------|-----|-------|-----------|--------|
|
||||
[Full matrix rows from Phase 3b]
|
||||
|
||||
## Coverage Summary
|
||||
|
||||
| Status | Count | % |
|
||||
|--------|-------|---|
|
||||
| COVERED — full chain complete | [N] | [%] |
|
||||
| MISSING test — story exists, no test | [N] | [%] |
|
||||
| NO STORY — ADR exists, not yet implemented | [N] | [%] |
|
||||
| NO ADR — architectural gap | [N] | [%] |
|
||||
| **Total requirements** | **[N]** | **100%** |
|
||||
|
||||
## Uncovered Requirements (Priority Fix List)
|
||||
|
||||
Requirements where the full chain is broken, prioritised by layer:
|
||||
|
||||
### Foundation layer gaps
|
||||
[list with suggested action per gap]
|
||||
|
||||
### Core layer gaps
|
||||
[list]
|
||||
|
||||
### Feature / Presentation layer gaps
|
||||
[list — lower priority]
|
||||
|
||||
## History
|
||||
|
||||
| Date | Full Chain % | Notes |
|
||||
|------|-------------|-------|
|
||||
| [date] | [%] | Initial RTM |
|
||||
```
|
||||
|
||||
### TR Registry Update
|
||||
|
||||
Also ask: "May I update `docs/architecture/tr-registry.yaml` with new requirement
|
||||
IDs from this review?"
|
||||
|
||||
If yes, read the current `docs/architecture/tr-registry.yaml` again first:
|
||||
the review read it at the start, and another skill or session may have changed
|
||||
it since. Build the update from that fresh read, never from the earlier copy,
|
||||
and keep every entry already in it. Then:
|
||||
- **Append** any new TR-IDs that weren't in the registry before this review
|
||||
- **Update** `requirement` text and `revised` date for any entries whose GDD
|
||||
wording changed (ID stays the same)
|
||||
- **Mark** `status: deprecated` for any registry entries whose GDD requirement
|
||||
no longer exists (confirm with user before marking deprecated)
|
||||
- **Mark** `status: "superseded-by: TR-[system]-NNN"` for an entry whose
|
||||
requirement was split or replaced, naming the new TR-ID(s). Keep the quotes:
|
||||
unquoted, the second colon makes the file invalid YAML
|
||||
- **Never** renumber or delete existing entries
|
||||
- Update the `last_updated` and `version` fields at the top
|
||||
|
||||
This ensures all future story files can reference stable TR-IDs that persist
|
||||
across every subsequent architecture review.
|
||||
|
||||
### Reflexion Log Update
|
||||
|
||||
When the user chose Phase 8's [A] — the option that named this file — append
|
||||
any 🔴 CONFLICT entries found in Phase 4 to `docs/consistency-failures.md` (if
|
||||
the file exists), after writing the review report:
|
||||
|
||||
```markdown
|
||||
### [YYYY-MM-DD] — /architecture-review — 🔴 CONFLICT
|
||||
**Domain**: Architecture / [specific domain e.g. State Ownership, Performance]
|
||||
**Documents involved**: [ADR-NNNN] vs [ADR-MMMM]
|
||||
**What happened**: [specific conflict — what each ADR claims]
|
||||
**Resolution**: [how it was or should be resolved]
|
||||
**Pattern**: [generalised lesson for future ADR authors in this domain]
|
||||
```
|
||||
|
||||
Only append CONFLICT entries — do not log GAP entries (missing ADRs are expected
|
||||
before the architecture is complete). Do not create the file if missing — only
|
||||
append when it already exists.
|
||||
|
||||
### Session State Update
|
||||
|
||||
After writing all approved files, silently append to
|
||||
`production/session-state/active.md`:
|
||||
|
||||
## Session Extract — /architecture-review [date]
|
||||
- Verdict: [PASS / NOT ASSESSED / CONCERNS / FAIL]
|
||||
- Requirements: [N] total — [X] covered, [Y] partial, [Z] gaps
|
||||
- New TR-IDs registered: [N, or "None"]
|
||||
- GDD revision flags: [comma-separated GDD names, or "None"]
|
||||
- Top ADR gaps: [top 3 gap titles from the report, or "None"]
|
||||
- Report: docs/architecture/architecture-review-[date].md
|
||||
|
||||
If `active.md` does not exist, create it with this block as the initial content.
|
||||
Confirm in conversation: "Session state updated."
|
||||
|
||||
The traceability index — written to `docs/architecture/requirements-traceability.md`,
|
||||
the path `/propagate-design-change` and the Pre-Production gate read; `rtm` mode
|
||||
later extends the same file with story and test columns — uses this format:
|
||||
|
||||
```markdown
|
||||
# Architecture Traceability Index
|
||||
Last Updated: [date]
|
||||
Engine: [name + version]
|
||||
|
||||
## Coverage Summary
|
||||
- Total requirements: [N]
|
||||
- Covered: [X] ([%])
|
||||
- Partial: [Y]
|
||||
- Gaps: [Z]
|
||||
|
||||
## Full Matrix
|
||||
[Complete traceability matrix from Phase 3]
|
||||
|
||||
## Known Gaps
|
||||
[All ❌ items with suggested ADRs]
|
||||
|
||||
## Superseded Requirements
|
||||
[Requirements whose GDD was changed after the ADR was written]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -0,0 +1,35 @@
|
||||
# /architecture-review — Phase 9: Handoff
|
||||
|
||||
> Part of `/architecture-review`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 9: Handoff
|
||||
|
||||
After completing the review and writing approved files, present:
|
||||
|
||||
1. **Immediate actions**: List the top 3 ADRs to create (highest-impact gaps first,
|
||||
Foundation layer before Feature layer)
|
||||
2. **Pre-gate checklist**: Check whether these exist via Glob and mark each ✅ or ❌:
|
||||
- the engine's test root — `tests/unit/` and `tests/integration/` (Godot), `Assets/Tests/EditMode/` and `Assets/Tests/PlayMode/` (Unity), `Source/<Module>/Private/Tests/` (Unreal) — if ❌: run `/test-setup`
|
||||
- `.github/workflows/tests.yml` — if ❌: run `/test-setup`
|
||||
- `design/accessibility-requirements.md` — if ❌: run `/ux-design`
|
||||
- `design/ux/interaction-patterns.md` — if ❌: run `/ux-design`
|
||||
Present ❌ items as required steps before gate-check. Do not offer `/gate-check`
|
||||
as an option if any item is ❌ — offer the missing skill to run instead.
|
||||
3. **Rerun trigger**: "Re-run `/architecture-review` after each new ADR is written
|
||||
to verify coverage improves"
|
||||
|
||||
Then close with `AskUserQuestion` tailored to the pre-gate checklist state:
|
||||
- If ADR gaps remain or any pre-gate item is ❌:
|
||||
- "Architecture review complete. What would you like to do next?"
|
||||
- [A] Write a missing ADR — open a fresh session and run `/architecture-decision [system]`
|
||||
- [B] Run `/test-setup` — required before gate-check (only show if test infrastructure is ❌)
|
||||
- [C] Run `/ux-design` — required before gate-check (only show if UX/accessibility files are ❌)
|
||||
- [D] Stop here for this session
|
||||
- If all pre-gate checklist items are ✅ and no blocking ADR gaps remain:
|
||||
- "Architecture review complete. All pre-gate items confirmed. What would you like to do next?"
|
||||
- [A] Run `/gate-check pre-production`
|
||||
- [B] Write a missing ADR — open a fresh session and run `/architecture-decision [system]`
|
||||
- [C] Stop here for this session
|
||||
|
||||
---
|
||||
@@ -12,6 +12,8 @@ model: sonnet
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
|
||||
defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
# Art Bible
|
||||
|
||||
|
||||
## Phase 0: Parse Arguments and Context Check
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ model: sonnet
|
||||
# Read-only diagnostic skill — no specialist agent delegation needed
|
||||
---
|
||||
|
||||
# Asset Audit
|
||||
|
||||
## Measuring file sizes and formats requires Bash
|
||||
|
||||
This skill's report asks for **file sizes against budgets**, **texture dimensions**
|
||||
@@ -43,11 +45,10 @@ not a filled-in report.** Check first, and stop if the check fails.
|
||||
|
||||
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
|
||||
"what does the data say?" when there is no data. The failure mode this prevents is
|
||||
specific and has been observed in practice: report templates whose verdict
|
||||
enum had no "could not run" state produced **false clean passes** — an asset audit
|
||||
returning COMPLIANT on a project with no assets and no standards, and a
|
||||
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
|
||||
profiler data and no budget ever set.
|
||||
specific: a report whose verdict enum has no "could not run" state produces
|
||||
**false clean passes** — an asset audit returning COMPLIANT on a project with no
|
||||
assets and no standards, or a performance profile reporting ">99% headroom against
|
||||
a 16.67ms budget" with zero profiler data and no budget ever set.
|
||||
|
||||
**Absence of evidence is never evidence of absence.** A scan that finds no
|
||||
matches because there are no files to scan has not verified anything. Say which of
|
||||
|
||||
@@ -9,6 +9,8 @@ model: sonnet
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys review_mode,automation`
|
||||
|
||||
# Asset Spec
|
||||
|
||||
|
||||
|
||||
If no argument is provided, check whether `design/assets/entity-inventory.md` exists:
|
||||
|
||||
@@ -9,6 +9,8 @@ model: sonnet
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
|
||||
# Balance Check
|
||||
|
||||
|
||||
|
||||
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
@@ -33,11 +35,10 @@ not a filled-in report.** Check first, and stop if the check fails.
|
||||
|
||||
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
|
||||
"what does the data say?" when there is no data. The failure mode this prevents is
|
||||
specific and has been observed in practice: report templates whose verdict
|
||||
enum had no "could not run" state produced **false clean passes** — an asset audit
|
||||
returning COMPLIANT on a project with no assets and no standards, and a
|
||||
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
|
||||
profiler data and no budget ever set.
|
||||
specific: a report whose verdict enum has no "could not run" state produces
|
||||
**false clean passes** — an asset audit returning COMPLIANT on a project with no
|
||||
assets and no standards, or a performance profile reporting ">99% headroom against
|
||||
a 16.67ms budget" with zero profiler data and no budget ever set.
|
||||
|
||||
**Absence of evidence is never evidence of absence.** A scan that finds no
|
||||
matches because there are no files to scan has not verified anything. Say which of
|
||||
|
||||
@@ -12,6 +12,8 @@ model: sonnet
|
||||
Resolved above — use as-is. No block → defaults in
|
||||
`.claude/docs/config-resolution.md`.
|
||||
|
||||
# Brainstorm
|
||||
|
||||
|
||||
`--review` overrides `review_mode`; store it for all gate spawns this run. See
|
||||
`.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
|
||||
|
||||
@@ -15,6 +15,8 @@ every file write follows `.claude/docs/automation-modes.md`
|
||||
(collaborative asks always · guided major-only · autonomous logs and proceeds;
|
||||
`automation_always_ask` categories always prompt).
|
||||
|
||||
# Bug Report
|
||||
|
||||
## Phase 1: Parse Arguments
|
||||
|
||||
Determine the mode from the argument:
|
||||
|
||||
@@ -7,7 +7,7 @@ allowed-tools: Read, Glob, Grep, Write, Edit, Bash(bash "*/.claude/skills/bug-tr
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation,workflow`
|
||||
|
||||
**Automation mode**: Resolve `modes.automation` (`project.local.yaml` →
|
||||
`project.yaml` → default `collaborative`). Every `AskUserQuestion` call and
|
||||
@@ -77,7 +77,7 @@ Read the most recently modified file in `production/sprints/` to understand:
|
||||
- Stories in scope (for assignment target)
|
||||
- Sprint capacity constraints (if noted)
|
||||
|
||||
If no sprint file exists: note "No sprint plan found — assigning to backlog only."
|
||||
If no sprint file exists: note "No sprint plan found — assigning to backlog only." At `workflow: minimal` there are no sprints by design — say that instead, and name the P1 bugs as the next fixes, ahead of the next story in the brief's build order.
|
||||
|
||||
### Step 2c — Load severity reference
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ every file write follows `.claude/docs/automation-modes.md`
|
||||
(collaborative asks always · guided major-only · autonomous logs and proceeds;
|
||||
`automation_always_ask` categories always prompt).
|
||||
|
||||
# Changelog
|
||||
|
||||
## Recent History
|
||||
|
||||
Recent commits:
|
||||
|
||||
@@ -9,6 +9,8 @@ model: sonnet
|
||||
|
||||
!`bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys automation`
|
||||
|
||||
# Code Review
|
||||
|
||||
|
||||
|
||||
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
@@ -33,11 +35,10 @@ not a filled-in report.** Check first, and stop if the check fails.
|
||||
|
||||
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
|
||||
"what does the data say?" when there is no data. The failure mode this prevents is
|
||||
specific and has been observed in practice: report templates whose verdict
|
||||
enum had no "could not run" state produced **false clean passes** — an asset audit
|
||||
returning COMPLIANT on a project with no assets and no standards, and a
|
||||
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
|
||||
profiler data and no budget ever set.
|
||||
specific: a report whose verdict enum has no "could not run" state produces
|
||||
**false clean passes** — an asset audit returning COMPLIANT on a project with no
|
||||
assets and no standards, or a performance profile reporting ">99% headroom against
|
||||
a 16.67ms budget" with zero profiler data and no budget ever set.
|
||||
|
||||
**Absence of evidence is never evidence of absence.** A scan that finds no
|
||||
matches because there are no files to scan has not verified anything. Say which of
|
||||
|
||||
@@ -271,6 +271,12 @@ Verdict: PASS | CONFLICTS FOUND | NOT ASSESSED
|
||||
|
||||
## Phase 6: Registry Corrections
|
||||
|
||||
**Re-read before you write.** Phase 1 read the registry before the scans, and
|
||||
another skill or session may have changed it since. Before each Edit, read the
|
||||
current `design/registry/entities.yaml`, find the entry in its section, and
|
||||
anchor the Edit on the entry's current text, never on what Phase 1 saw. Append
|
||||
a new entry after the last existing entry of its section.
|
||||
|
||||
If stale registry entries were found, ask:
|
||||
> "May I update `design/registry/entities.yaml` to fix the [N] stale entries?"
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ every file write follows `.claude/docs/automation-modes.md`
|
||||
|
||||
Resolved above — use as-is. No block → defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
# Content Audit
|
||||
|
||||
> This skill declares tier-dependent behaviour ("audit only specs in the required
|
||||
> sections"), which is unreachable unless the tier is actually resolved — without
|
||||
> it the skill applies whatever tier it assumed. Resolve `modes.workflow` before
|
||||
@@ -59,11 +61,10 @@ not a filled-in report.** Check first, and stop if the check fails.
|
||||
|
||||
**A verdict of `NOT ASSESSED` is a success.** It is the correct, useful answer to
|
||||
"what does the data say?" when there is no data. The failure mode this prevents is
|
||||
specific and has been observed in practice: report templates whose verdict
|
||||
enum had no "could not run" state produced **false clean passes** — an asset audit
|
||||
returning COMPLIANT on a project with no assets and no standards, and a
|
||||
performance profile reporting ">99% headroom against a 16.67ms budget" with zero
|
||||
profiler data and no budget ever set.
|
||||
specific: a report whose verdict enum has no "could not run" state produces
|
||||
**false clean passes** — an asset audit returning COMPLIANT on a project with no
|
||||
assets and no standards, or a performance profile reporting ">99% headroom against
|
||||
a 16.67ms budget" with zero profiler data and no budget ever set.
|
||||
|
||||
**Absence of evidence is never evidence of absence.** A scan that finds no
|
||||
matches because there are no files to scan has not verified anything. Say which of
|
||||
|
||||
@@ -12,7 +12,6 @@ model: sonnet
|
||||
Resolved above — use as-is; `--review` overrides `review_mode`. No block →
|
||||
defaults in `.claude/docs/config-resolution.md`.
|
||||
|
||||
|
||||
# Create Architecture
|
||||
|
||||
This skill produces `docs/architecture/architecture.md` — the master architecture
|
||||
@@ -22,10 +21,8 @@ It sits between design and implementation, and must exist before sprint planning
|
||||
**Distinct from `/architecture-decision`**: ADRs record individual point decisions.
|
||||
This skill creates the whole-system blueprint that gives ADRs their context.
|
||||
|
||||
|
||||
See `.claude/docs/director-gates.md` for the full check pattern. Individual gate definitions live in `.claude/docs/director-gates/[gate-id].md` — the spawned agent reads its own gate file; do not read it in the parent session.
|
||||
|
||||
|
||||
Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
|
||||
(collaborative asks always · guided major-only · autonomous logs and proceeds;
|
||||
`automation_always_ask` categories always prompt).
|
||||
@@ -54,505 +51,39 @@ considered per layer. Apply it to every section you author.
|
||||
|
||||
## Phase 0: Load All Context
|
||||
|
||||
Before anything else, load the full project context in this order:
|
||||
|
||||
### 0a. Engine Context (Critical)
|
||||
|
||||
Read the four project-wide engine documents in full — they are small, and every
|
||||
part of each is used:
|
||||
|
||||
1. `docs/engine-reference/[engine]/VERSION.md`
|
||||
→ Extract: engine name, version, LLM cutoff, post-cutoff risk levels
|
||||
2. `docs/engine-reference/[engine]/breaking-changes.md`
|
||||
→ Extract: all HIGH and MEDIUM risk changes
|
||||
3. `docs/engine-reference/[engine]/deprecated-apis.md`
|
||||
→ Extract: APIs to avoid
|
||||
4. `docs/engine-reference/[engine]/current-best-practices.md`
|
||||
→ Extract: post-cutoff best practices that differ from training data
|
||||
|
||||
Then read **only the module docs whose domain this game actually uses** —
|
||||
not the whole `modules/` directory:
|
||||
|
||||
5. `docs/engine-reference/[engine]/modules/` — glob it to establish what exists,
|
||||
then match against the domains present in `design/gdd/systems-index.md`
|
||||
(the same domain vocabulary the ADR template uses: Physics, Rendering, UI,
|
||||
Audio, Navigation, Animation, Networking, Core, Input). Read the matching
|
||||
modules; skip the rest.
|
||||
→ Extract: current API patterns per domain
|
||||
|
||||
A game with no multiplayer system does not need the networking module loaded
|
||||
to write its architecture, and loading it costs the same as one that does.
|
||||
**If the domain match is ambiguous, read the module** — a missed engine
|
||||
constraint is far more expensive here than a redundant read, because this
|
||||
phase is where those constraints get baked into the architecture.
|
||||
|
||||
If no engine is configured, stop and prompt:
|
||||
> "No engine is configured. Run `/setup-engine` first. Architecture cannot be
|
||||
> written without knowing which engine and version you are targeting."
|
||||
|
||||
### 0b. Design Context + Technical Requirements Extraction
|
||||
|
||||
Load the approved design documents and extract technical requirements from each:
|
||||
|
||||
1. `design/gdd/game-concept.md` — game pillars, genre, core loop
|
||||
2. `design/gdd/systems-index.md` — all systems, dependencies, priority tiers
|
||||
|
||||
**Check both exist before reading either. Neither is optional here, and both
|
||||
need an absence branch** — §0a stops for an unconfigured engine, and these two
|
||||
matter just as much:
|
||||
|
||||
- **`systems-index.md` absent** — stop:
|
||||
> "No systems index found. Run `/map-systems` first. An architecture written
|
||||
> without it invents layers for systems nobody mapped, and every ADR, epic and
|
||||
> story downstream inherits that invention."
|
||||
At `minimal` the index is not required (§ tier note above) — say so and proceed
|
||||
from the brief instead.
|
||||
- **`game-concept.md` absent** — at `standard`/`full`, stop and point at
|
||||
`/brainstorm`. At `minimal`, read `design/game-brief.md` in its place; if that
|
||||
is absent too, stop — there is no design record to architect against.
|
||||
- **Either present but empty or still template placeholders** — treat as absent.
|
||||
Present-but-empty is the case that most looks like present.
|
||||
|
||||
Do not proceed on a partial read and note it later. This phase is where design
|
||||
assumptions get baked into ADRs, and an assumption made here is re-derived by
|
||||
everything downstream rather than re-checked.
|
||||
3. Project config — `naming.*` and `performance.*` from `project.yaml` (for any
|
||||
key absent or empty, fall back to `.claude/docs/technical-preferences.md`);
|
||||
allowed libraries and forbidden patterns from
|
||||
`.claude/docs/technical-preferences.md` (not migrated to project.yaml)
|
||||
4. **Every GDD in `design/gdd/`** — extract technical requirements from the
|
||||
sections that carry them, **not from whole files**. Establish the denominator
|
||||
first (glob `design/gdd/*.md`, count **N**), then:
|
||||
```
|
||||
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
|
||||
```
|
||||
Overview and Player Fantasy are narrative and imply no architecture; the
|
||||
scanned set is where rules, numbers, and cross-system contracts live. Accept
|
||||
either `## Detailed Rules` or `## Detailed Design` — the design standard and
|
||||
the GDD template disagree on the name and they denote the same section.
|
||||
|
||||
Full-read a GDD when it matched **zero** sections (it predates the template —
|
||||
a zero-match means "unstructured", never "no requirements") or when a scanned
|
||||
section refers to material outside itself. **Never treat an absent section as
|
||||
an absent requirement**: report any GDD that contributed nothing, rather than
|
||||
letting it drop silently out of the baseline below.
|
||||
|
||||
For each, extract:
|
||||
- Data structures implied by the game rules
|
||||
- Performance constraints stated or implied
|
||||
- Engine capabilities the system requires
|
||||
- Cross-system communication patterns (what talks to what, how)
|
||||
- State that must persist (save/load implications)
|
||||
- Threading or timing requirements
|
||||
|
||||
Build a **Technical Requirements Baseline** — a flat list of all extracted
|
||||
requirements across all GDDs, numbered `TR-[gdd-slug]-[NNN]`. This is the
|
||||
complete set of what the architecture must cover. Present it as:
|
||||
|
||||
```
|
||||
## Technical Requirements Baseline
|
||||
Extracted from [N] GDDs | [X] total requirements
|
||||
|
||||
| Req ID | GDD | System | Requirement | Domain |
|
||||
|--------|-----|--------|-------------|--------|
|
||||
| TR-combat-001 | combat.md | Combat | Hitbox detection per-frame | Physics |
|
||||
| TR-combat-002 | combat.md | Combat | Combo state machine | Core |
|
||||
| TR-inventory-001 | inventory.md | Inventory | Item persistence | Save/Load |
|
||||
```
|
||||
|
||||
This baseline feeds into every subsequent phase. No GDD requirement should be
|
||||
left without an architectural decision to support it by the end of this session.
|
||||
|
||||
### 0c. Existing Architecture Decisions
|
||||
|
||||
To learn **what has already been decided and in which domain**, scan the ADR
|
||||
headers — do not full-read every ADR to produce a list of numbers and domains:
|
||||
```
|
||||
Grep pattern="^## (Status|Summary)" glob="docs/architecture/adr-*.md" output_mode="content" -A 4
|
||||
Grep pattern="\*\*Domain\*\*" glob="docs/architecture/adr-*.md" output_mode="content"
|
||||
```
|
||||
`## Summary` (a 2-sentence what-and-why) plus `## Status` and the Engine
|
||||
Compatibility `Domain` field are exactly "what was decided and its domain". List
|
||||
the ADRs found, their status, and their domains from the scan. Full-read a
|
||||
specific ADR only when a new decision this session would collide with it and you
|
||||
need its reasoning — not to build the inventory.
|
||||
|
||||
### 0d. Generate Knowledge Gap Inventory
|
||||
|
||||
Before proceeding, display a structured summary:
|
||||
|
||||
```
|
||||
## Engine Knowledge Gap Inventory
|
||||
Engine: [name + version]
|
||||
LLM Training Covers: up to approximately [version]
|
||||
Post-Cutoff Versions: [list]
|
||||
|
||||
### HIGH RISK Domains (must verify against engine reference before deciding)
|
||||
- [Domain]: [Key changes]
|
||||
|
||||
### MEDIUM RISK Domains (verify key APIs)
|
||||
- [Domain]: [Key changes]
|
||||
|
||||
### LOW RISK Domains (in training data, likely reliable)
|
||||
- [Domain]: [no significant post-cutoff changes]
|
||||
|
||||
### Systems from GDD that touch HIGH/MEDIUM risk domains:
|
||||
- [GDD system name] → [domain] → [risk level]
|
||||
```
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "One or more engine domains are HIGH RISK — the LLM's knowledge may be unreliable for these areas. Architectural recommendations in these domains should be cross-referenced with the engine docs before being acted on. How would you like to proceed?"
|
||||
- Options:
|
||||
- `[A] Proceed — flag HIGH RISK domains throughout the output`
|
||||
- `[B] Let me check the engine reference first — pause here`
|
||||
- `[C] Show me which domains are HIGH RISK and why`
|
||||
|
||||
### 0e. Existing Architecture Document
|
||||
|
||||
Glob `docs/architecture/architecture.md`. If it exists, this run updates it —
|
||||
it never replaces it unasked. Read its `## Document Status` block and its `##`
|
||||
headings, then use `AskUserQuestion`:
|
||||
- Prompt: "An architecture document already exists (v[N], [last updated]). What should this run do?"
|
||||
- Options: `[A] Update chosen sections in place` / `[B] Rewrite the whole document — replaces the existing file` / `[C] Stop`
|
||||
|
||||
On `[A]`, ask which sections. Phases 1–6 author only those and say which they
|
||||
skipped; Phase 7 replaces just those sections and raises `Version` to N+1,
|
||||
leaving every other section as it is. `[B]` runs the full walkthrough, and
|
||||
Phase 7's ask says it replaces the existing file.
|
||||
|
||||
A focus-area argument (`layers`, `data-flow`, `api-boundaries`, `adr-audit`)
|
||||
is `[A]` with that one section chosen: it runs only its phase (1, 3, 4 or 5),
|
||||
and Phase 7 writes that section. Phase 7b still runs on the updated document —
|
||||
an update is reviewed like a first draft, at the review modes that review one. With no existing document there is nothing to
|
||||
update — say so, and offer the full walkthrough instead.
|
||||
|
||||
---
|
||||
**Read `references/0-load-context.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 1: System Layer Mapping
|
||||
|
||||
Map every system from `systems-index.md` into an architecture layer. The standard
|
||||
game architecture layers are:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ PRESENTATION LAYER │ ← UI, HUD, menus, VFX, audio
|
||||
├─────────────────────────────────────────────┤
|
||||
│ FEATURE LAYER │ ← gameplay systems, AI, quests
|
||||
├─────────────────────────────────────────────┤
|
||||
│ CORE LAYER │ ← physics, input, combat, movement
|
||||
├─────────────────────────────────────────────┤
|
||||
│ FOUNDATION LAYER │ ← engine integration, save/load,
|
||||
│ │ scene management, event bus
|
||||
├─────────────────────────────────────────────┤
|
||||
│ PLATFORM LAYER │ ← OS, hardware, engine API surface
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
For each GDD system, ask:
|
||||
- Which layer does it belong to?
|
||||
- What are its module boundaries?
|
||||
- What does it own exclusively? (data, state, behaviour)
|
||||
|
||||
Present the proposed layer assignment and ask for approval before proceeding to
|
||||
the next section. Record the approved layer map in
|
||||
`production/session-state/active.md`; it goes into the document at Phase 7.
|
||||
|
||||
**Engine awareness check**: For each system assigned to the Core and Foundation
|
||||
layers, flag if it touches a HIGH or MEDIUM risk engine domain. Show the relevant
|
||||
engine reference excerpt inline.
|
||||
|
||||
---
|
||||
**Read `references/1-layers.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 2: Module Ownership Map
|
||||
|
||||
For each module defined in Phase 1, define ownership:
|
||||
|
||||
- **Owns**: what data and state this module is solely responsible for
|
||||
- **Exposes**: what other modules may read or call
|
||||
- **Consumes**: what it reads from other modules
|
||||
- **Engine APIs used**: which specific engine classes/nodes/signals this module
|
||||
calls directly (with version and risk level noted)
|
||||
|
||||
Format as a table per layer, then as an ASCII dependency diagram.
|
||||
|
||||
**Engine awareness check**: For every engine API listed, verify against the
|
||||
relevant module reference doc. If an API is post-cutoff, flag it:
|
||||
|
||||
```
|
||||
⚠️ [ClassName.method()] — Godot 4.6 (post-cutoff, HIGH risk)
|
||||
Verified against: docs/engine-reference/godot/modules/[domain].md
|
||||
Behaviour confirmed: [yes / NEEDS VERIFICATION]
|
||||
```
|
||||
|
||||
Get user approval on the ownership map, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
**Read `references/2-module-ownership.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 3: Data Flow
|
||||
|
||||
Define how data moves between modules during key game scenarios. Cover at minimum:
|
||||
|
||||
1. **Frame update path**: Input → Core systems → State → Rendering
|
||||
2. **Event/signal path**: How systems communicate without tight coupling
|
||||
3. **Save/load path**: What state is serialised, which module owns serialisation
|
||||
4. **Initialisation order**: Which modules must boot before others
|
||||
|
||||
Use ASCII sequence diagrams where helpful. For each data flow:
|
||||
- Name the data being transferred
|
||||
- Identify the producer and consumer
|
||||
- State whether this is synchronous call, signal/event, or shared state
|
||||
- Flag any data flows that cross thread boundaries
|
||||
|
||||
Get user approval on each scenario, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
**Read `references/3-data-flow.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 4: API Boundaries
|
||||
|
||||
Define the public contracts between modules. For each boundary:
|
||||
|
||||
- What is the interface a module exposes to the rest of the system?
|
||||
- What are the entry points (functions/signals/properties)?
|
||||
- What invariants must callers respect?
|
||||
- What must the module guarantee to callers?
|
||||
|
||||
Write in pseudocode or the project's actual language (from technical preferences).
|
||||
These become the contracts programmers implement against.
|
||||
|
||||
**Engine awareness check**: If any interface uses engine-specific types (e.g.
|
||||
`Node`, `Resource`, `Signal` in Godot), flag the version and verify the type
|
||||
exists and has not changed signature in the target engine version.
|
||||
|
||||
Get user approval on the API boundaries, then record them in
|
||||
`production/session-state/active.md`; they are written at Phase 7.
|
||||
|
||||
---
|
||||
**Read `references/4-api-boundaries.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 5: ADR Audit + Traceability Check
|
||||
|
||||
Review all existing ADRs from Phase 0c against both the architecture built in
|
||||
Phases 1-4 AND the Technical Requirements Baseline from Phase 0b.
|
||||
|
||||
### ADR Quality Check
|
||||
|
||||
For each ADR:
|
||||
- [ ] Does it have an Engine Compatibility section?
|
||||
- [ ] Is the engine version recorded?
|
||||
- [ ] Are post-cutoff APIs flagged?
|
||||
- [ ] Does it have a "GDD Requirements Addressed" section?
|
||||
- [ ] Does it conflict with the layer/ownership decisions made in this session?
|
||||
- [ ] Is it still valid for the pinned engine version?
|
||||
|
||||
| ADR | Engine Compat | Version | GDD Linkage | Conflicts | Valid |
|
||||
|-----|--------------|---------|-------------|-----------|-------|
|
||||
| ADR-0001: [title] | ✅/❌ | ✅/❌ | ✅/❌ | None/[conflict] | ✅/⚠️ |
|
||||
|
||||
### Traceability Coverage Check
|
||||
|
||||
Map every requirement from the Technical Requirements Baseline to existing ADRs.
|
||||
For each requirement, check if any ADR's "GDD Requirements Addressed" section
|
||||
or decision text covers it:
|
||||
|
||||
| Req ID | Requirement | ADR Coverage | Status |
|
||||
|--------|-------------|--------------|--------|
|
||||
| TR-combat-001 | Hitbox detection per-frame | ADR-0003 | ✅ |
|
||||
| TR-combat-002 | Combo state machine | — | ❌ GAP |
|
||||
|
||||
Count: X covered, Y gaps. For each gap, it becomes a **Required New ADR**.
|
||||
|
||||
### Required New ADRs
|
||||
|
||||
List all decisions made during this architecture session (Phases 1-4) that do
|
||||
not yet have a corresponding ADR, PLUS all uncovered Technical Requirements.
|
||||
Group by layer — Foundation first:
|
||||
|
||||
**Foundation Layer (must create before any coding):**
|
||||
- `/architecture-decision [title]` → covers: TR-[id], TR-[id]
|
||||
|
||||
**Core Layer:**
|
||||
- `/architecture-decision [title]` → covers: TR-[id]
|
||||
|
||||
---
|
||||
**Read `references/5-adr-audit.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 6: Missing ADR List
|
||||
|
||||
Based on the full architecture, produce a complete list of ADRs that should exist
|
||||
but don't yet. Group by priority:
|
||||
|
||||
**Must have before coding starts (Foundation & Core decisions):**
|
||||
- [e.g. "Scene management and scene loading strategy"]
|
||||
- [e.g. "Event bus vs direct signal architecture"]
|
||||
|
||||
**Should have before the relevant system is built:**
|
||||
- [e.g. "Inventory serialisation format"]
|
||||
|
||||
**Can defer to implementation:**
|
||||
- [e.g. "Specific shader technique for water"]
|
||||
|
||||
---
|
||||
**Read `references/6-missing-adrs.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 7: Write the Master Architecture Document
|
||||
|
||||
Once all sections are approved, write the complete document to
|
||||
`docs/architecture/architecture.md`.
|
||||
|
||||
In an update (Phase 0e `[A]`, or a focus-area argument), write only the chosen
|
||||
sections instead, replacing each in place with `Edit`, and raise `Version`; the
|
||||
ask below then names those sections and the version change.
|
||||
|
||||
Display a one-paragraph summary of what the document will contain (layers, modules, data flows, ADR gaps). Then use `AskUserQuestion`:
|
||||
- "All sections approved. May I write the master architecture document?"
|
||||
- [A] Yes — write to `docs/architecture/architecture.md` now
|
||||
- [B] Show me the full draft inline first, then ask again
|
||||
- [C] Not yet — I have more changes to discuss
|
||||
|
||||
The document structure:
|
||||
|
||||
```markdown
|
||||
# [Game Name] — Master Architecture
|
||||
|
||||
## Document Status
|
||||
- Version: [N]
|
||||
- Last Updated: [date]
|
||||
- Engine: [name + version]
|
||||
- GDDs Covered: [list]
|
||||
- ADRs Referenced: [list]
|
||||
|
||||
## Engine Knowledge Gap Summary
|
||||
[Condensed from Phase 0d inventory — HIGH/MEDIUM risk domains and their implications]
|
||||
|
||||
## System Layer Map
|
||||
[From Phase 1]
|
||||
|
||||
## Module Ownership
|
||||
[From Phase 2]
|
||||
|
||||
## Data Flow
|
||||
[From Phase 3]
|
||||
|
||||
## API Boundaries
|
||||
[From Phase 4]
|
||||
|
||||
## ADR Audit
|
||||
[From Phase 5]
|
||||
|
||||
## Required ADRs
|
||||
[From Phase 6]
|
||||
|
||||
## Architecture Principles
|
||||
[3-5 key principles that govern all technical decisions for this project,
|
||||
derived from the game concept, GDDs, and technical preferences]
|
||||
|
||||
## Open Questions
|
||||
[Decisions deferred — must be resolved before the relevant layer is built]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7b: Technical Director Sign-Off + Lead Programmer Feasibility Review
|
||||
|
||||
After writing the master architecture document, perform an explicit sign-off before handoff.
|
||||
|
||||
**Review mode check** — apply before spawning either gate:
|
||||
- `solo` → skip both. Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Solo mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `lean` → skip both (neither is a PHASE-GATE). Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Lean mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `full` → spawn both, in parallel.
|
||||
|
||||
**Step 1 — Spawn `technical-director` via `Agent` using gate TD-ARCHITECTURE (`.claude/docs/director-gates/td-architecture.md`):**
|
||||
|
||||
Pass: the architecture document path (`docs/architecture/architecture.md`), the Technical Requirements Baseline (TR-IDs and count), the ADR list with statuses, and the Engine Knowledge Gap Inventory from Phase 0d. Issue this call and Step 2's before waiting for either result.
|
||||
|
||||
**Step 2 — Spawn `lead-programmer` via `Agent` using gate LP-FEASIBILITY (`.claude/docs/director-gates/lp-feasibility.md`):**
|
||||
|
||||
Pass: architecture document path, technical requirements baseline summary, ADR list.
|
||||
|
||||
**Step 3 — Present both assessments to the user:**
|
||||
|
||||
Show the TD-ARCHITECTURE verdict (APPROVE / CONCERNS / REJECT) and the LP-FEASIBILITY verdict (FEASIBLE / CONCERNS / INFEASIBLE) side by side.
|
||||
|
||||
Use `AskUserQuestion` — "Technical Director and Lead Programmer have reviewed the architecture. How would you like to proceed?"
|
||||
Options: `Accept — proceed to handoff` / `Revise flagged items first` / `Discuss specific concerns`.
|
||||
If either verdict is REJECT or INFEASIBLE, do not offer `Accept` — the blockers are revised (or discussed) first.
|
||||
`Revise flagged items first` re-drafts each flagged section and shows it for approval as in Phases 1–4; the revised document is then written once, through Phase 7's ask, and Step 4 records `REVISED after [verdict]`.
|
||||
A `NOT ASSESSED` answer is never recorded as `APPROVE` or `FEASIBLE`: Step 4 records it with the input that was missing (`director-gates.md`).
|
||||
|
||||
**Step 4 — Record sign-off in the architecture document:**
|
||||
|
||||
Update the Document Status section:
|
||||
```
|
||||
- TD-ARCHITECTURE: [date] — APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
- LP-FEASIBILITY: [date] — FEASIBLE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after INFEASIBLE / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
```
|
||||
|
||||
Show the proposed Document Status block inline, then use `AskUserQuestion`:
|
||||
- "May I update the Document Status section with the sign-off results?"
|
||||
- [A] Yes — apply to `docs/architecture/architecture.md`
|
||||
- [B] Not yet — I want to revisit the concerns first
|
||||
|
||||
---
|
||||
**Read `references/7-write.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Phase 8: Handoff
|
||||
|
||||
**Step 1 — Update session state**: Write a summary to `production/session-state/active.md` covering: artifact written, TD/LP sign-off verdicts, any blockers, required ADRs remaining, and next step.
|
||||
|
||||
**Step 2 — Output the handoff** using exactly this template (no freeform prose, no rephrasing of section titles):
|
||||
|
||||
---
|
||||
|
||||
## Architecture Complete
|
||||
|
||||
`docs/architecture/architecture.md` v[N] — [TD-ARCHITECTURE: APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED / skipped — [mode] mode]. [One sentence on what the architecture covers.]
|
||||
|
||||
---
|
||||
|
||||
## Run These ADRs Next
|
||||
|
||||
**1. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence: what it defines and what it unblocks.]
|
||||
|
||||
**2. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence.]
|
||||
|
||||
**3. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence.]
|
||||
|
||||
**Then:** `/architecture-review`, and `/create-control-manifest` once it passes and those ADRs are Accepted — it turns them into the layer rules manifest.
|
||||
|
||||
List top 3 from Phase 6 in priority order. If fewer than 3 remain, list only what's outstanding.
|
||||
|
||||
---
|
||||
|
||||
## Gate-Check Readiness
|
||||
|
||||
> **Required before `/gate-check pre-production`:**
|
||||
> - [ ] Accept ADRs: [list Proposed ADR IDs that must be Accepted]
|
||||
> - [ ] Write ADRs: [list ADR IDs that must still be written]
|
||||
> - [ ] Run `/architecture-review` — writes the review report and the traceability index (`docs/architecture/requirements-traceability.md`) the gate reads
|
||||
> - [ ] Run `/test-setup` — scaffolds `tests/unit/`, `tests/integration/`, CI workflow, and an example test file
|
||||
> - [ ] Run `/ux-design` — creates `design/ux/interaction-patterns.md` and `design/accessibility-requirements.md`
|
||||
>
|
||||
> Run `/gate-check pre-production` when all boxes are checked.
|
||||
|
||||
If nothing is blocking, write instead:
|
||||
> No blockers — run `/gate-check pre-production` now.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions to Watch
|
||||
|
||||
| ID | Summary | Priority | Resolution Path |
|
||||
|----|---------|----------|-----------------|
|
||||
| QQ-XX | [short description] | High / Medium / Low | [ADR or system that resolves it] |
|
||||
|
||||
Omit this section entirely if there are no open QQs.
|
||||
|
||||
---
|
||||
|
||||
(End of handoff. Do not add trailing commentary after the closing rule.)
|
||||
|
||||
---
|
||||
**Read `references/8-handoff.md` now and follow it** — this phase's steps are in that file, not here. Read it again if the conversation was compacted or resumed during this phase.
|
||||
|
||||
## Collaborative Protocol
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
# /create-architecture — Phase 0: Load All Context
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 0: Load All Context
|
||||
|
||||
**In this file:**
|
||||
|
||||
- 0a. Engine Context (Critical)
|
||||
- 0b. Design Context + Technical Requirements Extraction
|
||||
- 0c. Existing Architecture Decisions
|
||||
- 0d. Generate Knowledge Gap Inventory
|
||||
- 0e. Existing Architecture Document
|
||||
|
||||
Before anything else, load the full project context in this order:
|
||||
|
||||
### 0a. Engine Context (Critical)
|
||||
|
||||
Read the four project-wide engine documents in full — they are small, and every
|
||||
part of each is used:
|
||||
|
||||
1. `docs/engine-reference/[engine]/VERSION.md`
|
||||
→ Extract: engine name, version, LLM cutoff, post-cutoff risk levels
|
||||
2. `docs/engine-reference/[engine]/breaking-changes.md`
|
||||
→ Extract: all HIGH and MEDIUM risk changes
|
||||
3. `docs/engine-reference/[engine]/deprecated-apis.md`
|
||||
→ Extract: APIs to avoid
|
||||
4. `docs/engine-reference/[engine]/current-best-practices.md`
|
||||
→ Extract: post-cutoff best practices that differ from training data
|
||||
|
||||
Then read **only the module docs whose domain this game actually uses** —
|
||||
not the whole `modules/` directory:
|
||||
|
||||
5. `docs/engine-reference/[engine]/modules/` — glob it to establish what exists,
|
||||
then match against the domains present in `design/gdd/systems-index.md`
|
||||
(the same domain vocabulary the ADR template uses: Physics, Rendering, UI,
|
||||
Audio, Navigation, Animation, Networking, Core, Input). Read the matching
|
||||
modules; skip the rest.
|
||||
→ Extract: current API patterns per domain
|
||||
|
||||
A game with no multiplayer system does not need the networking module loaded
|
||||
to write its architecture, and loading it costs the same as one that does.
|
||||
**If the domain match is ambiguous, read the module** — a missed engine
|
||||
constraint is far more expensive here than a redundant read, because this
|
||||
phase is where those constraints get baked into the architecture.
|
||||
|
||||
If no engine is configured, stop and prompt:
|
||||
> "No engine is configured. Run `/setup-engine` first. Architecture cannot be
|
||||
> written without knowing which engine and version you are targeting."
|
||||
|
||||
### 0b. Design Context + Technical Requirements Extraction
|
||||
|
||||
Load the approved design documents and extract technical requirements from each:
|
||||
|
||||
1. `design/gdd/game-concept.md` — game pillars, genre, core loop
|
||||
2. `design/gdd/systems-index.md` — all systems, dependencies, priority tiers
|
||||
|
||||
**Check both exist before reading either. Neither is optional here, and both
|
||||
need an absence branch** — §0a stops for an unconfigured engine, and these two
|
||||
matter just as much:
|
||||
|
||||
- **`systems-index.md` absent** — stop:
|
||||
> "No systems index found. Run `/map-systems` first. An architecture written
|
||||
> without it invents layers for systems nobody mapped, and every ADR, epic and
|
||||
> story downstream inherits that invention."
|
||||
At `minimal` the index is not required (§ tier note above) — say so and proceed
|
||||
from the brief instead.
|
||||
- **`game-concept.md` absent** — at `standard`/`full`, stop and point at
|
||||
`/brainstorm`. At `minimal`, read `design/game-brief.md` in its place; if that
|
||||
is absent too, stop — there is no design record to architect against.
|
||||
- **Either present but empty or still template placeholders** — treat as absent.
|
||||
Present-but-empty is the case that most looks like present.
|
||||
|
||||
Do not proceed on a partial read and note it later. This phase is where design
|
||||
assumptions get baked into ADRs, and an assumption made here is re-derived by
|
||||
everything downstream rather than re-checked.
|
||||
3. Project config — `naming.*` and `performance.*` from `project.yaml` (for any
|
||||
key absent or empty, fall back to `.claude/docs/technical-preferences.md`);
|
||||
allowed libraries and forbidden patterns from
|
||||
`.claude/docs/technical-preferences.md` (not migrated to project.yaml)
|
||||
4. **Every GDD in `design/gdd/`** — extract technical requirements from the
|
||||
sections that carry them, **not from whole files**. Establish the denominator
|
||||
first (glob `design/gdd/*.md`, count **N**), then:
|
||||
```
|
||||
Grep pattern="^## (Detailed Rules|Detailed Design|Formulas|Dependencies|Tuning Knobs|Acceptance Criteria)" glob="design/gdd/*.md" output_mode="content" -A 40
|
||||
```
|
||||
Overview and Player Fantasy are narrative and imply no architecture; the
|
||||
scanned set is where rules, numbers, and cross-system contracts live. Accept
|
||||
either `## Detailed Rules` or `## Detailed Design` — the design standard and
|
||||
the GDD template disagree on the name and they denote the same section.
|
||||
|
||||
Full-read a GDD when it matched **zero** sections (it predates the template —
|
||||
a zero-match means "unstructured", never "no requirements") or when a scanned
|
||||
section refers to material outside itself. **Never treat an absent section as
|
||||
an absent requirement**: report any GDD that contributed nothing, rather than
|
||||
letting it drop silently out of the baseline below.
|
||||
|
||||
For each, extract:
|
||||
- Data structures implied by the game rules
|
||||
- Performance constraints stated or implied
|
||||
- Engine capabilities the system requires
|
||||
- Cross-system communication patterns (what talks to what, how)
|
||||
- State that must persist (save/load implications)
|
||||
- Threading or timing requirements
|
||||
|
||||
Build a **Technical Requirements Baseline** — a flat list of all extracted
|
||||
requirements across all GDDs, numbered `TR-[system]-[NNN]`, the TR registry's
|
||||
ID format. This is the
|
||||
complete set of what the architecture must cover. Present it as:
|
||||
|
||||
```
|
||||
## Technical Requirements Baseline
|
||||
Extracted from [N] GDDs | [X] total requirements
|
||||
|
||||
| Req ID | GDD | System | Requirement | Domain |
|
||||
|--------|-----|--------|-------------|--------|
|
||||
| TR-combat-001 | combat.md | Combat | Hitbox detection per-frame | Physics |
|
||||
| TR-combat-002 | combat.md | Combat | Combo state machine | Core |
|
||||
| TR-inventory-001 | inventory.md | Inventory | Item persistence | Save/Load |
|
||||
```
|
||||
|
||||
This baseline feeds into every subsequent phase. No GDD requirement should be
|
||||
left without an architectural decision to support it by the end of this session.
|
||||
|
||||
### 0c. Existing Architecture Decisions
|
||||
|
||||
To learn **what has already been decided and in which domain**, scan the ADR
|
||||
headers — do not full-read every ADR to produce a list of numbers and domains:
|
||||
```
|
||||
Grep pattern="^## (Status|Summary)" glob="docs/architecture/adr-*.md" output_mode="content" -A 4
|
||||
Grep pattern="\*\*Domain\*\*" glob="docs/architecture/adr-*.md" output_mode="content"
|
||||
```
|
||||
`## Summary` (a 2-sentence what-and-why) plus `## Status` and the Engine
|
||||
Compatibility `Domain` field are exactly "what was decided and its domain". List
|
||||
the ADRs found, their status, and their domains from the scan. Full-read a
|
||||
specific ADR only when a new decision this session would collide with it and you
|
||||
need its reasoning — not to build the inventory.
|
||||
|
||||
### 0d. Generate Knowledge Gap Inventory
|
||||
|
||||
Before proceeding, display a structured summary:
|
||||
|
||||
```
|
||||
## Engine Knowledge Gap Inventory
|
||||
Engine: [name + version]
|
||||
LLM Training Covers: up to approximately [version]
|
||||
Post-Cutoff Versions: [list]
|
||||
|
||||
### HIGH RISK Domains (must verify against engine reference before deciding)
|
||||
- [Domain]: [Key changes]
|
||||
|
||||
### MEDIUM RISK Domains (verify key APIs)
|
||||
- [Domain]: [Key changes]
|
||||
|
||||
### LOW RISK Domains (in training data, likely reliable)
|
||||
- [Domain]: [no significant post-cutoff changes]
|
||||
|
||||
### Systems from GDD that touch HIGH/MEDIUM risk domains:
|
||||
- [GDD system name] → [domain] → [risk level]
|
||||
```
|
||||
|
||||
Use `AskUserQuestion`:
|
||||
- Prompt: "One or more engine domains are HIGH RISK — the LLM's knowledge may be unreliable for these areas. Architectural recommendations in these domains should be cross-referenced with the engine docs before being acted on. How would you like to proceed?"
|
||||
- Options:
|
||||
- `[A] Proceed — flag HIGH RISK domains throughout the output`
|
||||
- `[B] Let me check the engine reference first — pause here`
|
||||
- `[C] Show me which domains are HIGH RISK and why`
|
||||
|
||||
### 0e. Existing Architecture Document
|
||||
|
||||
Glob `docs/architecture/architecture.md`. If it exists, this run updates it —
|
||||
it never replaces it unasked. Read its `## Document Status` block and its `##`
|
||||
headings, then use `AskUserQuestion`:
|
||||
- Prompt: "An architecture document already exists (v[N], [last updated]). What should this run do?"
|
||||
- Options: `[A] Update chosen sections in place` / `[B] Rewrite the whole document — replaces the existing file` / `[C] Stop`
|
||||
|
||||
On `[A]`, ask which sections. Phases 1–6 author only those and say which they
|
||||
skipped; Phase 7 replaces just those sections and raises `Version` to N+1,
|
||||
leaving every other section as it is. `[B]` runs the full walkthrough, and
|
||||
Phase 7's ask says it replaces the existing file.
|
||||
|
||||
A focus-area argument (`layers`, `data-flow`, `api-boundaries`, `adr-audit`)
|
||||
is `[A]` with that one section chosen: it runs only its phase (1, 3, 4 or 5),
|
||||
and Phase 7 writes that section. Phase 7b still runs on the updated document —
|
||||
an update is reviewed like a first draft, at the review modes that review one. With no existing document there is nothing to
|
||||
update — say so, and offer the full walkthrough instead.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,39 @@
|
||||
# /create-architecture — Phase 1: System Layer Mapping
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 1: System Layer Mapping
|
||||
|
||||
Map every system from `systems-index.md` into an architecture layer. The standard
|
||||
game architecture layers are:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ PRESENTATION LAYER │ ← UI, HUD, menus, VFX, audio
|
||||
├─────────────────────────────────────────────┤
|
||||
│ FEATURE LAYER │ ← gameplay systems, AI, quests
|
||||
├─────────────────────────────────────────────┤
|
||||
│ CORE LAYER │ ← physics, input, combat, movement
|
||||
├─────────────────────────────────────────────┤
|
||||
│ FOUNDATION LAYER │ ← engine integration, save/load,
|
||||
│ │ scene management, event bus
|
||||
├─────────────────────────────────────────────┤
|
||||
│ PLATFORM LAYER │ ← OS, hardware, engine API surface
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
For each GDD system, ask:
|
||||
- Which layer does it belong to?
|
||||
- What are its module boundaries?
|
||||
- What does it own exclusively? (data, state, behaviour)
|
||||
|
||||
Present the proposed layer assignment and ask for approval before proceeding to
|
||||
the next section. Record the approved layer map in
|
||||
`production/session-state/active.md`; it goes into the document at Phase 7.
|
||||
|
||||
**Engine awareness check**: For each system assigned to the Core and Foundation
|
||||
layers, flag if it touches a HIGH or MEDIUM risk engine domain. Show the relevant
|
||||
engine reference excerpt inline.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,30 @@
|
||||
# /create-architecture — Phase 2: Module Ownership Map
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 2: Module Ownership Map
|
||||
|
||||
For each module defined in Phase 1, define ownership:
|
||||
|
||||
- **Owns**: what data and state this module is solely responsible for
|
||||
- **Exposes**: what other modules may read or call
|
||||
- **Consumes**: what it reads from other modules
|
||||
- **Engine APIs used**: which specific engine classes/nodes/signals this module
|
||||
calls directly (with version and risk level noted)
|
||||
|
||||
Format as a table per layer, then as an ASCII dependency diagram.
|
||||
|
||||
**Engine awareness check**: For every engine API listed, verify against the
|
||||
relevant module reference doc. If an API is post-cutoff, flag it:
|
||||
|
||||
```
|
||||
⚠️ [ClassName.method()] — Godot 4.6 (post-cutoff, HIGH risk)
|
||||
Verified against: docs/engine-reference/godot/modules/[domain].md
|
||||
Behaviour confirmed: [yes / NEEDS VERIFICATION]
|
||||
```
|
||||
|
||||
Get user approval on the ownership map, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,24 @@
|
||||
# /create-architecture — Phase 3: Data Flow
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 3: Data Flow
|
||||
|
||||
Define how data moves between modules during key game scenarios. Cover at minimum:
|
||||
|
||||
1. **Frame update path**: Input → Core systems → State → Rendering
|
||||
2. **Event/signal path**: How systems communicate without tight coupling
|
||||
3. **Save/load path**: What state is serialised, which module owns serialisation
|
||||
4. **Initialisation order**: Which modules must boot before others
|
||||
|
||||
Use ASCII sequence diagrams where helpful. For each data flow:
|
||||
- Name the data being transferred
|
||||
- Identify the producer and consumer
|
||||
- State whether this is synchronous call, signal/event, or shared state
|
||||
- Flag any data flows that cross thread boundaries
|
||||
|
||||
Get user approval on each scenario, then record it in
|
||||
`production/session-state/active.md`; it is written at Phase 7.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,25 @@
|
||||
# /create-architecture — Phase 4: API Boundaries
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 4: API Boundaries
|
||||
|
||||
Define the public contracts between modules. For each boundary:
|
||||
|
||||
- What is the interface a module exposes to the rest of the system?
|
||||
- What are the entry points (functions/signals/properties)?
|
||||
- What invariants must callers respect?
|
||||
- What must the module guarantee to callers?
|
||||
|
||||
Write in pseudocode or the project's actual language (from technical preferences).
|
||||
These become the contracts programmers implement against.
|
||||
|
||||
**Engine awareness check**: If any interface uses engine-specific types (e.g.
|
||||
`Node`, `Resource`, `Signal` in Godot), flag the version and verify the type
|
||||
exists and has not changed signature in the target engine version.
|
||||
|
||||
Get user approval on the API boundaries, then record them in
|
||||
`production/session-state/active.md`; they are written at Phase 7.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,50 @@
|
||||
# /create-architecture — Phase 5: ADR Audit and Traceability Check
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 5: ADR Audit + Traceability Check
|
||||
|
||||
Review all existing ADRs from Phase 0c against both the architecture built in
|
||||
Phases 1-4 AND the Technical Requirements Baseline from Phase 0b.
|
||||
|
||||
### ADR Quality Check
|
||||
|
||||
For each ADR:
|
||||
- [ ] Does it have an Engine Compatibility section?
|
||||
- [ ] Is the engine version recorded?
|
||||
- [ ] Are post-cutoff APIs flagged?
|
||||
- [ ] Does it have a "GDD Requirements Addressed" section?
|
||||
- [ ] Does it conflict with the layer/ownership decisions made in this session?
|
||||
- [ ] Is it still valid for the pinned engine version?
|
||||
|
||||
| ADR | Engine Compat | Version | GDD Linkage | Conflicts | Valid |
|
||||
|-----|--------------|---------|-------------|-----------|-------|
|
||||
| ADR-0001: [title] | ✅/❌ | ✅/❌ | ✅/❌ | None/[conflict] | ✅/⚠️ |
|
||||
|
||||
### Traceability Coverage Check
|
||||
|
||||
Map every requirement from the Technical Requirements Baseline to existing ADRs.
|
||||
For each requirement, check if any ADR's "GDD Requirements Addressed" section
|
||||
or decision text covers it:
|
||||
|
||||
| Req ID | Requirement | ADR Coverage | Status |
|
||||
|--------|-------------|--------------|--------|
|
||||
| TR-combat-001 | Hitbox detection per-frame | ADR-0003 | ✅ |
|
||||
| TR-combat-002 | Combo state machine | — | ❌ GAP |
|
||||
|
||||
Count: X covered, Y gaps. For each gap, it becomes a **Required New ADR**.
|
||||
|
||||
### Required New ADRs
|
||||
|
||||
List all decisions made during this architecture session (Phases 1-4) that do
|
||||
not yet have a corresponding ADR, PLUS all uncovered Technical Requirements.
|
||||
Group by layer — Foundation first:
|
||||
|
||||
**Foundation Layer (must create before any coding):**
|
||||
- `/architecture-decision [title]` → covers: TR-[id], TR-[id]
|
||||
|
||||
**Core Layer:**
|
||||
- `/architecture-decision [title]` → covers: TR-[id]
|
||||
|
||||
---
|
||||
@@ -0,0 +1,21 @@
|
||||
# /create-architecture — Phase 6: Missing ADR List
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 6: Missing ADR List
|
||||
|
||||
Based on the full architecture, produce a complete list of ADRs that should exist
|
||||
but don't yet. Group by priority:
|
||||
|
||||
**Must have before coding starts (Foundation & Core decisions):**
|
||||
- [e.g. "Scene management and scene loading strategy"]
|
||||
- [e.g. "Event bus vs direct signal architecture"]
|
||||
|
||||
**Should have before the relevant system is built:**
|
||||
- [e.g. "Inventory serialisation format"]
|
||||
|
||||
**Can defer to implementation:**
|
||||
- [e.g. "Specific shader technique for water"]
|
||||
|
||||
---
|
||||
@@ -0,0 +1,109 @@
|
||||
# /create-architecture — Phases 7 and 7b: Write and Sign-Off
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 7: Write the Master Architecture Document
|
||||
|
||||
**In this file:**
|
||||
|
||||
- Phase 7: the master architecture document template, then the write
|
||||
- Phase 7b: Technical Director Sign-Off + Lead Programmer Feasibility Review: review mode check, presenting both assessments, recording the sign-off
|
||||
|
||||
Once all sections are approved, write the complete document to
|
||||
`docs/architecture/architecture.md`.
|
||||
|
||||
In an update (Phase 0e `[A]`, or a focus-area argument), write only the chosen
|
||||
sections instead, replacing each in place with `Edit`, and raise `Version`; the
|
||||
ask below then names those sections and the version change.
|
||||
|
||||
Display a one-paragraph summary of what the document will contain (layers, modules, data flows, ADR gaps). Then use `AskUserQuestion`:
|
||||
- "All sections approved. May I write the master architecture document?"
|
||||
- [A] Yes — write to `docs/architecture/architecture.md` now
|
||||
- [B] Show me the full draft inline first, then ask again
|
||||
- [C] Not yet — I have more changes to discuss
|
||||
|
||||
The document structure:
|
||||
|
||||
```markdown
|
||||
# [Game Name] — Master Architecture
|
||||
|
||||
## Document Status
|
||||
- Version: [N]
|
||||
- Last Updated: [date]
|
||||
- Engine: [name + version]
|
||||
- GDDs Covered: [list]
|
||||
- ADRs Referenced: [list]
|
||||
|
||||
## Engine Knowledge Gap Summary
|
||||
[Condensed from Phase 0d inventory — HIGH/MEDIUM risk domains and their implications]
|
||||
|
||||
## System Layer Map
|
||||
[From Phase 1]
|
||||
|
||||
## Module Ownership
|
||||
[From Phase 2]
|
||||
|
||||
## Data Flow
|
||||
[From Phase 3]
|
||||
|
||||
## API Boundaries
|
||||
[From Phase 4]
|
||||
|
||||
## ADR Audit
|
||||
[From Phase 5]
|
||||
|
||||
## Required ADRs
|
||||
[From Phase 6]
|
||||
|
||||
## Architecture Principles
|
||||
[3-5 key principles that govern all technical decisions for this project,
|
||||
derived from the game concept, GDDs, and technical preferences]
|
||||
|
||||
## Open Questions
|
||||
[Decisions deferred — must be resolved before the relevant layer is built]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 7b: Technical Director Sign-Off + Lead Programmer Feasibility Review
|
||||
|
||||
After writing the master architecture document, perform an explicit sign-off before handoff.
|
||||
|
||||
**Review mode check** — apply before spawning either gate:
|
||||
- `solo` → skip both. Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Solo mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `lean` → skip both (neither is a PHASE-GATE). Note: "TD-ARCHITECTURE and LP-FEASIBILITY skipped — Lean mode." Go to Step 4 and record both as skipped, then Phase 8.
|
||||
- `full` → spawn both, in parallel.
|
||||
|
||||
**Step 1 — Spawn `technical-director` via `Agent` using gate TD-ARCHITECTURE (`.claude/docs/director-gates/td-architecture.md`):**
|
||||
|
||||
Pass: the architecture document path (`docs/architecture/architecture.md`), the Technical Requirements Baseline (TR-IDs and count), the ADR list with statuses, and the Engine Knowledge Gap Inventory from Phase 0d. Issue this call and Step 2's before waiting for either result.
|
||||
|
||||
**Step 2 — Spawn `lead-programmer` via `Agent` using gate LP-FEASIBILITY (`.claude/docs/director-gates/lp-feasibility.md`):**
|
||||
|
||||
Pass: architecture document path, technical requirements baseline summary, ADR list.
|
||||
|
||||
**Step 3 — Present both assessments to the user:**
|
||||
|
||||
Show the TD-ARCHITECTURE verdict (APPROVE / CONCERNS / REJECT) and the LP-FEASIBILITY verdict (FEASIBLE / CONCERNS / INFEASIBLE) side by side.
|
||||
|
||||
Use `AskUserQuestion` — "Technical Director and Lead Programmer have reviewed the architecture. How would you like to proceed?"
|
||||
Options: `Accept — proceed to handoff` / `Revise flagged items first` / `Discuss specific concerns`.
|
||||
If either verdict is REJECT or INFEASIBLE, do not offer `Accept` — the blockers are revised (or discussed) first.
|
||||
`Revise flagged items first` re-drafts each flagged section and shows it for approval as in Phases 1–4; the revised document is then written once, through Phase 7's ask, and Step 4 records `REVISED after [verdict]`.
|
||||
A `NOT ASSESSED` answer is never recorded as `APPROVE` or `FEASIBLE`: Step 4 records it with the input that was missing (`director-gates.md`).
|
||||
|
||||
**Step 4 — Record sign-off in the architecture document:**
|
||||
|
||||
Update the Document Status section:
|
||||
```
|
||||
- TD-ARCHITECTURE: [date] — APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
- LP-FEASIBILITY: [date] — FEASIBLE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after INFEASIBLE / NOT ASSESSED — [missing input] / skipped — [mode] mode
|
||||
```
|
||||
|
||||
Show the proposed Document Status block inline, then use `AskUserQuestion`:
|
||||
- "May I update the Document Status section with the sign-off results?"
|
||||
- [A] Yes — apply to `docs/architecture/architecture.md`
|
||||
- [B] Not yet — I want to revisit the concerns first
|
||||
|
||||
---
|
||||
@@ -0,0 +1,65 @@
|
||||
# /create-architecture — Phase 8: Handoff
|
||||
|
||||
> Part of `/create-architecture`. `SKILL.md` names when to read this file; the settings it
|
||||
> resolved and the rules under its later headings still apply here.
|
||||
|
||||
## Phase 8: Handoff
|
||||
|
||||
**Step 1 — Update session state**: Write a summary to `production/session-state/active.md` covering: artifact written, TD/LP sign-off verdicts, any blockers, required ADRs remaining, and next step.
|
||||
|
||||
**Step 2 — Output the handoff** using exactly this template (no freeform prose, no rephrasing of section titles):
|
||||
|
||||
---
|
||||
|
||||
## Architecture Complete
|
||||
|
||||
`docs/architecture/architecture.md` v[N] — [TD-ARCHITECTURE: APPROVE / CONCERNS (accepted) / REVISED after CONCERNS / REVISED after REJECT / NOT ASSESSED / skipped — [mode] mode]. [One sentence on what the architecture covers.]
|
||||
|
||||
---
|
||||
|
||||
## Run These ADRs Next
|
||||
|
||||
**1. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence: what it defines and what it unblocks.]
|
||||
|
||||
**2. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence.]
|
||||
|
||||
**3. `/architecture-decision "[Title]"` → ADR-[XXXX]**
|
||||
[One sentence.]
|
||||
|
||||
**Then:** `/architecture-review`, and `/create-control-manifest` once it passes and those ADRs are Accepted — it turns them into the layer rules manifest.
|
||||
|
||||
List top 3 from Phase 6 in priority order. If fewer than 3 remain, list only what's outstanding.
|
||||
|
||||
---
|
||||
|
||||
## Gate-Check Readiness
|
||||
|
||||
> **Required before `/gate-check pre-production`:**
|
||||
> - [ ] Accept ADRs: [list Proposed ADR IDs that must be Accepted]
|
||||
> - [ ] Write ADRs: [list ADR IDs that must still be written]
|
||||
> - [ ] Run `/architecture-review` — writes the review report and the traceability index (`docs/architecture/requirements-traceability.md`) the gate reads
|
||||
> - [ ] Run `/test-setup` — scaffolds `tests/unit/`, `tests/integration/`, CI workflow, and an example test file
|
||||
> - [ ] Run `/ux-design` — creates `design/ux/interaction-patterns.md` and `design/accessibility-requirements.md`
|
||||
>
|
||||
> Run `/gate-check pre-production` when all boxes are checked.
|
||||
|
||||
If nothing is blocking, write instead:
|
||||
> No blockers — run `/gate-check pre-production` now.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions to Watch
|
||||
|
||||
| ID | Summary | Priority | Resolution Path |
|
||||
|----|---------|----------|-----------------|
|
||||
| QQ-XX | [short description] | High / Medium / Low | [ADR or system that resolves it] |
|
||||
|
||||
Omit this section entirely if there are no open QQs.
|
||||
|
||||
---
|
||||
|
||||
(End of handoff. Do not add trailing commentary after the closing rule.)
|
||||
|
||||
---
|
||||
@@ -130,7 +130,7 @@ For `standard`/`full` (a `/create-epics` epic exists), read in full (these are s
|
||||
- `production/epics/[epic-slug]/EPIC.md` — epic overview, governing ADRs, GDD requirements table
|
||||
- The epic's GDD (`design/gdd/[filename].md`) — at `full` read all 8 sections; at `standard` the 5 required sections (+ conditional Formulas); at `minimal` the GDD may not exist — work from the epic brief + acceptance criteria. Always prioritise Acceptance Criteria, Formulas, and Edge Cases where present.
|
||||
- `docs/architecture/control-manifest.md` — grep only this epic's layer (`Grep pattern="^## <layer> Layer Rules" path="docs/architecture/control-manifest.md" output_mode="content" -A 40`) plus the header Manifest Version date, not a full read of all layers
|
||||
- `docs/architecture/tr-registry.yaml` — grep only this system's entries (`Grep pattern="system: <slug>" path="docs/architecture/tr-registry.yaml" output_mode="content" -B1 -A5`, or `id: TR-<slug>-`), not the whole cross-system registry
|
||||
- `docs/architecture/tr-registry.yaml` — grep only this system's entries (`Grep pattern="system: <slug>\s*$" path="docs/architecture/tr-registry.yaml" output_mode="content" -B1 -A5`, or `id: TR-<slug>-[0-9]`; the anchors keep `combat` from matching `combat-ai`), not the whole cross-system registry
|
||||
|
||||
**Load each governing ADR by section — never with an unbounded full read.** A
|
||||
substantial ADR exceeds the 25k-token `Read` cap, and a capped read's only
|
||||
|
||||
@@ -261,4 +261,5 @@ Use `AskUserQuestion`:
|
||||
- **Rollback plan first, always** — a patch without a rollback plan is irresponsible
|
||||
- **Deferred is not forgotten** — every deferred bug is listed in the record's
|
||||
"Deferred to 1.1" table; run `/bug-triage` afterwards to schedule them into the 1.1 sprint
|
||||
(if the project has no sprint plan, as on the default minimal workflow, into the brief's build order)
|
||||
- **Player communication is part of the patch** — `/patch-notes` is a required output, not optional
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user