Release 1.1.2 — the default path works end to end

Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
This commit is contained in:
Donchitos
2026-09-29 21:32:19 +10:00
co-authored by Claude Opus 5.5
parent 7ed2c3e9c4
commit b21fa0f7f2
383 changed files with 22888 additions and 10618 deletions
@@ -1,7 +1,7 @@
# /architecture-decision — Handoff Contract
## Role in Pipeline
Authors a new Architecture Decision Record (ADR) by guiding a collaborative design session, cross-referencing the engine reference library and existing architectural stances, and writing a fully-structured ADR file to `docs/architecture/` — which then unblocks stories and epics that depend on the decision.
Authors a new Architecture Decision Record (ADR) by guiding a collaborative design session, cross-referencing the engine reference library and existing architectural stances, and writing a fully-structured ADR file to `docs/architecture/` as `Proposed`. Its `accept` mode is the only route to `Accepted`, and acceptance is what unblocks the stories and epics that depend on the decision.
Two checks inside the run emit `NOT ASSESSED` rather than passing silently, and
a reader of the resulting ADR should expect them: **engine validation** when no
@@ -21,30 +21,30 @@ nothing is indistinguishable from a check that passed.
| `docs/registry/architecture.yaml` | All existing architectural stances (state ownership, interface contracts, forbidden patterns, performance budgets) — checked for conflicts before the design begins | Yes |
| `docs/architecture/` (existing ADRs) | Scanned to determine the next sequential ADR number | Yes |
| `design/gdd/[system].md` (GDDs relevant to the decision) | Specific rules, formulas, performance constraints, or integration points that motivate the decision | Yes |
| `project.yaml` | `engine.name` — derives the primary specialist (`<engine>-specialist`) to spawn for validation (Step 4.5) | Yes |
| `project.yaml` | `engine.name` — derives the primary specialist (`<engine>-specialist`) to spawn for validation (Step 5.5) | Yes |
| `.claude/docs/technical-preferences.md` | `Engine Specialists` section — legacy fallback, used only when `engine.name` is absent or empty in `project.yaml` | Yes — required only when `engine.name` is absent |
### Preconditions
- An engine must be configured (`docs/engine-reference/[engine]/VERSION.md` must exist) — if not, the skill prompts to run `/setup-engine` first
- The title or subject of the decision must be provided by the user before Step 0 proceeds (if no argument is given, the skill asks)
- If in **retrofit mode** (`retrofit [path]` argument), the target ADR file must already exist on disk
- Any conflict with a registered architectural stance in `docs/registry/architecture.yaml` must be resolved or explicitly accepted as an exception before the ADR is drafted (Step 2a is a BLOCKING gate)
- Any conflict with a registered architectural stance in `docs/registry/architecture.yaml` must be resolved or explicitly accepted as an exception before the ADR is drafted (Step 3a is a BLOCKING gate)
## Outputs Produced
### Files Written
| File | Guaranteed Fields / Sections | Notes |
|------|------------------------------|-------|
| `docs/architecture/adr-NNNN-[slug].md` | `## Status`, `## Date`, `## Engine Compatibility` (table with engine, domain, knowledge risk, post-cutoff APIs, verification required), `## ADR Dependencies` (table with depends-on, enables, blocks, ordering note), `## Context` (problem statement, constraints, requirements), `## Decision` (+ architecture diagram + key interfaces), `## Alternatives Considered`, `## Consequences` (positive, negative, risks), `## GDD Requirements Addressed` (table), `## Performance Implications`, `## Migration Plan`, `## Validation Criteria`, `## Related Decisions` | created after user approves ("May I write this ADR to docs/architecture/adr-NNNN-[slug].md?") |
| `docs/architecture/adr-NNNN-[slug].md` | `## Status`, `## Date`, `## Engine Compatibility` (table with engine, domain, knowledge risk, post-cutoff APIs, verification required), `## ADR Dependencies` (table with depends-on, enables, blocks, ordering note), `## Context` (problem statement, constraints, requirements), `## Decision` (+ architecture diagram + key interfaces), `## Alternatives Considered`, `## Consequences` (positive, negative), `## Risks`, `## GDD Requirements Addressed` (table), `## Performance Implications`, `## Migration Plan`, `## Validation Criteria`, `## Related` | created after user approves ("May I write this ADR to docs/architecture/adr-NNNN-[slug].md?") |
| `docs/registry/architecture.yaml` | New stance entries (state ownership, interface contracts, performance budgets, forbidden patterns) derived from the ADR; existing entries marked `status: superseded_by` if overridden | appended after separate user approval ("May I update docs/registry/architecture.yaml with these N new stances?") |
### Output Guarantees
- The ADR number is the next sequential integer after the highest existing `adr-NNNN-*` filename in `docs/architecture/`
- `## Status` is always present and set to `Proposed` unless the user explicitly confirms `Accepted` during the session
- `## Status` is always present. Authoring writes `Proposed`; retrofit writes the status the user gives, except that an `Accepted` answer is written as `Proposed` and handed to acceptance mode. Only acceptance mode writes `Accepted`, after its dependency check and the user's confirmation
- `## Engine Compatibility` is always populated using verified data from the engine reference docs — never from training data alone when the domain carries MEDIUM or HIGH risk
- `## GDD Requirements Addressed` is always present (if no GDD motivated the decision, it documents which GDDs the decision will constrain or enable)
- `## ADR Dependencies` is always present (fields set to "None" if no ordering constraints exist)
- Engine specialist validation (Step 4.5) runs before the file is written if an engine specialist is configured; blocking issues found by the specialist cause the Decision section to be revised before saving
- Engine specialist validation (Step 5.5) runs before the file is written if an engine specialist is configured; blocking issues found by the specialist cause the Decision section to be revised before saving
## Immutability Rules
- READS but does NOT modify: all existing ADR files in `docs/architecture/` (including in retrofit mode — existing sections are never touched), all GDD files in `design/gdd/`, `docs/engine-reference/**`, `project.yaml`, `.claude/docs/technical-preferences.md` (legacy fallback)
@@ -53,10 +53,10 @@ nothing is indistinguishable from a check that passed.
## Hard Constraints (Never Violate)
- Never sets `Status: Accepted` without explicit user confirmation — the default on creation is always `Status: Proposed`
- **Acceptance route: `/architecture-decision accept ADR-NNNN`** — the only path that sets `Accepted`. It refuses when a dependency is still Proposed, and prompts for confirmation regardless of `modes.automation`. Without this route acceptance would be enforced by ten skills, owned per the authority below, and reachable by nobody.
- **Acceptance route: `/architecture-decision accept ADR-NNNN`** — the only path that sets `Accepted`. It refuses when a dependency is still Proposed, and prompts for confirmation regardless of `modes.automation`. Retrofit mode's `Accepted` answer, for a decision already in force, is written as `Proposed` and handed to this route. Without this route acceptance would be enforced by ten skills, owned per the authority below, and reachable by nobody.
- **Acceptance authority: the user, or `technical-director` on the user's explicit confirmation — no other agent, and not this skill on its own.** Recorded here because every consumer enforces the consequences of acceptance, and without this line nothing would say who can produce it. This narrows *who* may set the field; it does not relax the confirmation rule above.
- Never assigns an ADR number that is already in use — always scan `docs/architecture/` first and use the next sequential number
- Never proceeds past the architectural stance conflict check (Step 2a) if a conflict exists — surface the conflict and require resolution or explicit exception acknowledgment before drafting
- Never proceeds past the architectural stance conflict check (Step 3a) if a conflict exists — surface the conflict and require resolution or explicit exception acknowledgment before drafting
- Never references APIs listed in `docs/engine-reference/[engine]/deprecated-apis.md` in the Decision or Key Interfaces sections
- Never writes the ADR file without asking: "May I write this ADR to docs/architecture/adr-NNNN-[slug].md?"
- Never writes to `docs/registry/architecture.yaml` without a separate ask: "May I update docs/registry/architecture.yaml with these N new stances?"
@@ -71,12 +71,12 @@ nothing is indistinguishable from a check that passed.
- `## Engine Compatibility` section — checked during the Technical Setup → Pre-Production gate
### `/create-stories` reads ADRs expecting:
- `## Implementation Guidelines` section — provides the concrete patterns programmer agents must follow (note: this section is generated during `/create-stories`, not by `/architecture-decision` itself; the ADR must have a Decision section detailed enough to derive these guidelines)
- `### Implementation Guidelines` (under `## Decision`) — the concrete "must / must never" patterns programmer agents follow; the ADR template carries this subsection
- `## ADR Dependencies` table — stories referencing a `Depends On` ADR that is still `Proposed` are automatically set `Status: Blocked`
### `/dev-story` reads ADRs expecting:
- `## Decision` (full text, verbatim — not summarized)
- `## Implementation Guidelines` (verbatim)
- `### Implementation Guidelines` (under `## Decision`, verbatim)
- `## Engine Compatibility` (post-cutoff API risks, verification required)
- `## ADR Dependencies` (to detect if this ADR's dependencies are unresolved)
@@ -87,8 +87,8 @@ nothing is indistinguishable from a check that passed.
## Known Fragile Points
- If the ADR number scan misses a file (e.g., a file in a subdirectory of `docs/architecture/` or with a non-standard naming pattern), a duplicate number can be assigned — all ADR files must follow the `adr-NNNN-[slug].md` naming convention at the top level of `docs/architecture/`
- Stories that were `Status: Blocked` pending this ADR must be manually updated to `Status: Ready` after the ADR reaches `Accepted` — the skill surfaces a reminder but does not automatically update story files
- Acceptance mode moves a story from `Blocked` to `Ready` only when the story file, under `production/epics/`, contains a Blocked Status line in any of the forms `/create-stories` writes (`> **Status**: Blocked`, `**Status:** Blocked`, `Status: Blocked`) and this ADR's id. A story blocked pending this ADR that never names its id is not found, and stays `Blocked` until it is updated by hand
- The `## GDD Requirements Addressed` table is populated based on what the user tells the skill during the collaborative session; if the user does not know which GDDs motivated the decision, this table may be incomplete — `/create-epics` and `/gate-check` both rely on this linkage for traceability
- Engine specialist validation (Step 4.5) is skipped only when **both** sources are unset — `engine.name` absent or empty in `project.yaml` **and** `.claude/docs/technical-preferences.md` still reading `[TO BE CONFIGURED]`. A project configured solely via `project.yaml` **does** get specialist validation. When both are unset, post-cutoff engine API risks are not caught before the ADR is written
- Engine specialist validation (Step 5.5) is skipped only when **both** sources are unset — `engine.name` absent or empty in `project.yaml` **and** `.claude/docs/technical-preferences.md` still reading `[TO BE CONFIGURED]`. A project configured solely via `project.yaml` **does** get specialist validation. When both are unset, post-cutoff engine API risks are not caught before the ADR is written
- `docs/registry/architecture.yaml` is append-only by design; if a stance entry becomes permanently invalid (not superseded by another ADR), it must be manually removed — there is no cleanup mechanism
- In retrofit mode, if the existing ADR has sections present but empty (e.g., a `## Status` heading with no value), the skill treats the section as present and does not fill it — an empty Status is effectively invisible to downstream skills like `/story-readiness`
+46 -22
View File
@@ -3,7 +3,7 @@ name: architecture-decision
description: "Create an ADR documenting a technical decision: context, alternatives considered, consequences."
argument-hint: "[title | retrofit <path> | accept <ADR-id>] [--review full|lean|solo]"
user-invocable: true
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, Bash(bash "*/.claude/skills/architecture-decision/../../hooks/yaml-helper.sh" resolve_config *)
allowed-tools: Read, Glob, Grep, Write, Edit, Agent, AskUserQuestion, Bash(wc -c *), Bash(bash "*/.claude/skills/architecture-decision/../../hooks/yaml-helper.sh" resolve_config *)
model: sonnet
---
@@ -26,16 +26,15 @@ Every `AskUserQuestion` call follows `.claude/docs/automation-modes.md`
`automation_always_ask` categories always prompt).
**`team.size`**: which agents validate this ADR (orthogonal to review_mode/workflow).
- **`individual`** (default): `technical-director` + `lead-programmer` + the engine-specialist.
- **`small`**: + an engine sub-specialist where applicable.
- **`studio`**: + an adversarial review by an alternate engine-specialist.
Any non-core agent needed at `individual` routes through the nearest active core agent with a note.
- **`individual`** (default): `technical-director` (TD-ADR) + the engine-specialist.
- **`small`** and **`studio`**: the same two. This skill spawns no engine
sub-specialist and no adversarial reviewer at any size.
**`docs.density`** — it controls the *depth* of the ADR's prose sections, not
which sections the skeleton emits (that is fixed). `modes.rigor` sets it
alongside `workflow`; set `docs.density` explicitly to vary ADR verbosity alone:
`terse` = decision + alternatives as bullets, one line of rationale each;
`balanced` = paragraph per section with light rationale (default); `thorough` =
`terse` (the default, via `rigor: minimal`) = decision + alternatives as bullets, one line of rationale each;
`balanced` = paragraph per section with light rationale (`rigor: standard`); `thorough` =
full prose with trade-offs and worked rationale in Decision, Alternatives, and
Consequences. Apply it to the prose sections; the Engine Compatibility, ADR
Dependencies, and GDD Requirements tables are structural and stay whole at every
@@ -57,6 +56,9 @@ Enter **retrofit mode**:
- `## ADR Dependencies` — HIGH if missing: dependency ordering breaks
- `## Engine Compatibility` — HIGH if missing: post-cutoff risk unknown
- `## GDD Requirements Addressed` — MEDIUM if missing: traceability lost
- `## Date` — MEDIUM if missing, and no `## Last Verified` either: `/create-stories`
stamps stories with it and `/dev-story` compares against it, so without it a
story can never tell whether the ADR changed
3. Present to the user:
```
## Retrofit: [ADR title]
@@ -72,9 +74,14 @@ Enter **retrofit mode**:
✗ Engine Compatibility — HIGH
```
4. Ask: "Shall I add the [N] missing sections? I will not modify any existing content."
If no: write nothing, and report the missing sections by name.
5. If yes:
- For **Status**: ask the user — "What is the current status of this decision?"
Options: "Proposed", "Accepted", "Deprecated", "Superseded by ADR-XXXX"
An `Accepted` answer — a decision already in force — is not written as
given: write `Proposed`, add the other missing sections, then run
acceptance mode (below) on this ADR. Its dependency check, confirmation and
story unblocking apply here too; it stays the only path that sets `Accepted`.
- For **ADR Dependencies**: ask — "Does this decision depend on any other ADR?
Does it enable or block any other ADR or epic?" Accept "None" for each field.
- For **Engine Compatibility**: read the engine reference docs (same as Step 1 below)
@@ -82,9 +89,12 @@ Enter **retrofit mode**:
- For **GDD Requirements Addressed**: ask — "Which GDD systems motivated this decision?
What specific requirement in each GDD does this ADR address?"
- Append each missing section to the ADR file using the Edit tool.
- For **Date** (counted only when there is no `## Last Verified`): append
`## Date` with today's date — even when it is the only missing section, the
case `/dev-story` sends you here for — and say that it records the retrofit,
not when the decision was made.
- **Never modify any existing section.** Only append or fill absent sections.
6. After adding all missing sections, update the ADR's `## Date` field if it is absent.
7. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
6. Suggest: "Run `/architecture-review` to re-validate coverage now that this ADR
has its Status and Dependencies fields."
**If the argument starts with `accept` followed by an ADR id**
@@ -134,25 +144,37 @@ enter and never leave.
Acceptance is the decision the whole architecture pipeline gates on; it is not
a step to be inferred.
5. **Find the stories this will unblock, BEFORE the prompt in step 4.** Grep
`production/epics/[epic-slug]/story-*.md` — the one place stories live — for
files containing **both** `Status: Blocked` and this ADR's id.
every story for a Blocked Status line —
`Grep pattern="Status\**:\**\s*Blocked" path="production/epics" glob="**/story-*.md" output_mode="files_with_matches"`,
which matches `> **Status**: Blocked` (the form `/create-stories` writes),
`**Status:** Blocked` and `Status: Blocked` — and keep the files that name
this ADR's id as the reason they are blocked. That pairing is what "blocked
pending this ADR" means — a story blocked for an unrelated reason will not
name it. Leave out a story that names this ADR only as the successor to point
at (`point the story at ADR-NNNN`, the note for a `Deprecated` or
`Superseded` ADR): it is still governed by the old ADR, and accepting the
successor does not re-point it.
> **Stories live only under `production/epics/`.** A flat top-level stories
> directory does not exist and no skill creates one — never write or match a
> path outside `production/epics/`. `/dev-story` matches entries *by file
> path*, so a story recorded under any other path silently fails to match and
> never gets picked up. That pairing is what "blocked pending this
ADR" means — a story blocked for an unrelated reason will not name it. Feed the
count into step 4's prompt so it reads *"3 stories become Ready"* rather than a
generic claim: **the user is being asked to authorise an effect, and should be
> never gets picked up.
Feed the count into step 4's prompt so it reads *"3 stories become Ready"*
rather than a generic claim: **the user is being asked to authorise an effect, and should be
shown the effect.** If none match, say "no stories are waiting on this" — that
is useful information, not an empty result to omit.
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Set the date in the
ADR's `## Date` section; **if that section is absent, add it** — retrofit mode
already owns this shape, and acceptance must not fail on a template that
6. On confirmation, `Edit` the `## Status` line to `Accepted`. Leave an existing
`## Date` as it is: it records when the ADR was written, and `/create-stories`
stamps stories with it (or `## Last Verified`), so rewriting it on acceptance
would make every story drafted against the Proposed ADR look out of date to
`/dev-story`. **If that section is absent, add it** with today's date — retrofit
mode already owns this shape, and acceptance must not fail on a template that
predates the field.
7. Then set each story found in step 5 from `Blocked` to `Ready`. Unblocking is a
consequence of acceptance, never of authoring — see Step 6's note below.
8. Report what moved: the ADR, its new date, and every story that became Ready.
8. Report what moved: the ADR (and its `## Date`, if one was added), and every
story that became Ready.
If NOT in retrofit or acceptance mode, proceed to Step 1 below (normal ADR authoring).
@@ -273,7 +295,7 @@ ADR in `docs/architecture/` on the chance one is relevant:
```
2. **Under ~50KB** (`Bash: wc -c "docs/architecture/[adr-file].md"`) — one full
`Read` is fine; per-call overhead exceeds the savings from bounded reads at
this size (measured elsewhere in this project).
this size.
3. **~50KB or larger** — bounded-read only `## Context`, `## Decision`, and
`## Consequences` (the sections that carry reasoning, not just facts) via
`Read(offset, limit)` from the heading map.
@@ -489,7 +511,7 @@ to implement it.]
5.5. **Engine Specialist Validation** — Before saving, spawn the **primary engine specialist** via `Agent` to validate the drafted ADR:
- Resolve the primary specialist: `<engine>-specialist` derived from `engine.name` in `project.yaml` (Godot→`godot-specialist`, Unity→`unity-specialist`, Unreal→`unreal-specialist`); if `engine.name` is absent or empty, read the Primary line of the `## Engine Specialists` section in `.claude/docs/technical-preferences.md`
- If no engine is configured (neither source yields an engine), skip this step **Record `Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
- If no engine is configured (neither source yields an engine), skip this step **Record ``Engine validation: NOT ASSESSED — no engine configured (`engine.name` unset in `project.yaml`)`` in this run's output.** A skipped check that says nothing is indistinguishable from a check that passed; the reader cannot tell engine guidance was never sought.
- Spawn `subagent_type: [primary specialist]` with: the ADR's Engine Compatibility section, Decision section, Key Interfaces, and the engine reference docs path. Ask them to:
1. Confirm the proposed approach is idiomatic for the pinned engine version
2. Flag any APIs or patterns that are deprecated or changed post-training-cutoff
@@ -505,7 +527,9 @@ to implement it.]
5.6. **Technical Director Strategic Review** — After the engine specialist validation, spawn `technical-director` via `Agent` using gate **TD-ADR** (`.claude/docs/director-gates/td-adr.md`):
- Pass: the ADR file path (or draft content), engine version, domain, any existing ADRs in the same domain
- The TD validates architectural coherence (is this decision consistent with the whole system?) — distinct from the engine specialist's API-level check
- If CONCERNS or REJECT: revise the Decision or Alternatives sections accordingly before proceeding
- On CONCERNS: show them to the user verbatim and ask with the standard options from `director-gates.md` — `Revise flagged items` / `Accept and proceed` / `Discuss further`. Revise the flagged Decision or Alternatives sections only on `Revise flagged items`.
- On REJECT: show the blockers verbatim and revise the Decision or Alternatives sections before proceeding.
- A revised draft still reaches the user through the write approval below; nothing is written before it. A `NOT ASSESSED` answer is not an approval — name the missing input (`director-gates.md`).
5.7. **GDD Sync Check** — Before presenting the write approval, scan all GDDs
referenced in the "GDD Requirements Addressed" section for naming inconsistencies