claude-code-architect-designer · git:20261015.1303b8c · 2026-10-15 · sha256 4fb8c6ca5b229614

claude-code-architect-designer git:20261015.1303b8cA

Immutable. This exact content never changes and is served at /api/v1/blob/4fb8c6ca5b229614.

---
name: claude-code-architect-designer
description: >
  Decides which Claude Code extension resolves a scenario — auto-invocable skill,
  manually-invoked skill, subagent, rule in `rules/`, `CLAUDE.md` section, MCP server
  connecting to an external system, lifecycle hook, `permissions` rule, or a mod that
  draws in the interface over what the hooks decide — and writes the files only after
  approval. Interviews first, proposes scored options with sources,
  writes afterward. Explicit invocation only.
argument-hint: "[scenario, use case, or problem in one sentence]"
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Glob, Grep, AskUserQuestion, Bash(find:*), Bash(ls:*), Bash(claude plugin validate:*), Bash(claude plugin test:*), Bash(java:*)
model: opus
---

## Current inventory

Skills: !`ls "${CLAUDE_PROJECT_DIR:-.}/.claude/skills"`

Agents: !`ls "${CLAUDE_PROJECT_DIR:-.}/.claude/agents"`

Rules: !`ls "${CLAUDE_PROJECT_DIR:-.}/.claude/rules"`

Decision records (the latest is the most recent): !`ls "${CLAUDE_PROJECT_DIR:-.}/.claude/decisions"`

## Scenario

$ARGUMENTS

---

# Claude Code Architect Designer

Decides **which of the nine forms** of extension resolves the scenario, and writes it.
The nine:

| # | Form | File |
|---|---|---|
| 1 | Auto-invocable skill | `.claude/skills/<name>/SKILL.md` |
| 2 | Manually-invoked skill (`/name`) | same, with `disable-model-invocation: true` |
| 3 | Subagent | `.claude/agents/<name>.md` |
| 4 | Rule | `.claude/rules/<name>.md` |
| 5 | `CLAUDE.md` section | root `CLAUDE.md` |
| 6a | MCP server, shared | `.mcp.json` |
| 6b | MCP server, one agent only | `mcpServers:` in that agent's frontmatter |
| 7a | Hook for the whole session | `hooks` block of `.claude/settings.json` |
| 7b | Hook only while one skill or agent runs | `hooks:` in that file's frontmatter |
| 7c | The executable behind 7a/7b | new mode in `.claude/hooks/ArchHook.java` |
| 8 | Hard prohibition or standing permission | `permissions.deny` / `permissions.allow` |
| 9 | Mod — draws in the interface what 7 and 8 already decide | `.claude/mods/<name>/` |

6b isn't a fourth reason to write an agent — it's reason 2 of § 5 of the decision matrix
(restrict tools) applied to an external connection instead of a built-in one. An agent
only exists in the first place per the three reasons already in `references/decision-matrix.md`
§ 5; 6b just answers which tools it gets once that's settled.

7c is not a trigger — it's what 7a or 7b invokes, and it exists **only** when no mode the
hook already has covers the check. Same relationship 6b has with the agent that carries
it: the registration decides when it runs, the mode decides what it does. A 7a that
reuses `check`, `format`, `schema`, `tests`, `guard`, `audit`, or `compose` is the common
case and writes no Java at all.

Forms 7 and 8 are the **guarantee** side of § 1 of the decision matrix: they execute
regardless of what the model decides. That makes them the answer whenever the rule must
always hold — invariant 6 of `@CLAUDE.md` — and it makes them the most expensive thing on
this list to get wrong, because a hook that blocks fires on every matching event for
everyone, including when it's mistaken.

Form 9 sits **on top of** that line, never across it. A mod is TypeScript that runs inside
the Claude Code process and can draw — a band above the prompt, a pane, a `/command` that
spends no turn, a dialog that holds a tool call — but it does not load in `claude -p`, VS
Code, a cloud session or under `--safe-mode`, so it is never the guarantee itself. It shows
or holds what a Form 7 or 8 beneath it already decides, and it reaches the rule by calling
`java -jar .claude/hooks/ArchHook.jar`, never by restating it. What a mod here may hook,
call and start is data, the `mods` block of `@.claude/schemas/extensions.json`; the map of
events and render sites is `references/mod-events.md`. Meta-repository only, by decision
`0131`: nothing under `.claude/mods/` travels to a generated project.

A legitimate tenth answer, and the cheapest one: **create nothing**. A piece that already
covers the scenario exists, a CLI already solves it (§ 2.1 of the decision matrix), or an
existing hook mode already runs the check and only needs a registration.

**Entry rule: no proposal without an interview.** Classifying from one sentence produces
the wrong piece, and the wrong piece costs more than no piece at all — it stays in
context every session, or it never fires.

## Why this is a skill and not a rule

This is a multi-step procedure — interview, classify, propose, write — hence a skill. As
a rule it would break invariant 1 of `@CLAUDE.md`: a rule about when to create skills and
agents would have to mention skills and agents, and `rules/` is a leaf.

Pinned to `opus`: what it designs is enforced in every later session (`@.claude/decisions/0081-skill-model-required-per-class.md`).

## Procedure

### Phase 1 · Interview

Read `references/decision-matrix.md` and `@docs/pt-br/11-pitfalls.md` before asking — the
matrix decides the form, the pitfalls page says which silent traps (the runtime's and this
repository's: territories, frozen folders, ownership splits) the design must not walk into.
Use `AskUserQuestion` — at most 4
questions per call, so 2 to 3 calls. **Don't proceed with a missing answer**: each axis
below eliminates candidate forms, and an unanswered axis leaves the decision guessing.

| # | Axis | What it decides |
|---|---|---|
| 1 | Concrete symptom — what error repeats, what prompt gets pasted again | Whether there's a case, or it's anticipation |
| 2 | Trigger — `/command`, model decision, touching a file, runtime event, or reaching an external system | Forms 1 · 2 · 4 · 6 · out of scope |
| 3 | Frequency — every session, weekly, rare | Always loaded vs on demand |
| 4 | Territory — which file globs, or none | `paths` in form 4; `paths` in form 1 |
| 5 | Nature — declarative fact or sequence of steps | Forms 4/5 vs 1/2/3 |
| 6 | Isolation — verbose output, tools to restrict, different model | Form 3, and only it |
| 7 | Mandatoriness — can it fail sometimes, or is it build/security/compliance | Forms 7 · 8 vs everything above |
| 8 | Destination — this repo only, also the generated project, or both | The `export` block of `@.claude/schemas/extensions.json` |
| 9 | Integration — what it reads, what it writes, which existing piece it collides with | Ownership conflict |
| 10 | Cost of getting it wrong | minutes or days | Weight in the score |
| 11 | Does a CLI already solve it (`gh`, `psql`, `aws`, `kubectl`, `sentry-cli`)? | Eliminates Form 6 before it's even considered — decision matrix § 2.1 |
| 12 | Credential shape — OAuth, static token, dynamic header script, or none; read-only or read/write | Form 6a vs 6b vs `permissions.deny`; whether `oauth`/`headersHelper` is needed |
| 13 | Destination — this repo's `.mcp.json` only, the generated project's template only, or both | Which file(s) Form 6a writes; propagation in Phase 4 step 8 |
| 14 | Lifecycle event — what exactly has to have just happened: a tool call, a prompt, the end of a turn, session start | The event key of Form 7, and whether a `matcher` is even read there — `references/hook-events.md` |
| 15 | Reaction — observe and report, add context, or block | Exit code, and Form 7 vs Form 8: a call that must **never** happen is `permissions.deny`, cheaper than a hook that spawns a process to refuse it |
| 16 | Existing mode — does `ArchHook.java` already run this check | Form 7a alone vs 7a + 7c. `java .claude/hooks/ArchHook.java doctor` lists the modes in use |
| 17 | CI coverage — which job already proves the piece does what it claims, what it leaves unproven, and in which pipeline the missing check runs | The CI item of every Phase 3 option and the CI step of Phase 4 — `references/ci-coverage.md` |
| 18 | Surface — must the person see it only in the terminal and the Desktop app, or also in `claude -p`, VS Code, a cloud session | Form 9 vs a hook's `systemMessage` / `additionalContext`; never Form 9 alone when it must show everywhere |
| 19 | Guarantee beneath — which settings hook or `permissions` rule already decides what the piece shows or holds | Form 9 only on top of one; none → Form 7 or 8 first, or the mod only observes |
| 20 | State — what the piece keeps, and for how long: nothing, the session (`$.state`), or across sessions (`$.store`, shared by every session on the machine) | Which mods API the mod calls; `$.store` is not atomic — one key per item |

Axis 9 is checked against the inventory injected at the top, not from memory. Two pieces
writing to the same paths is an ownership bug, not a style decision.

Axes 11-13 only apply when axis 2 (trigger) names an external system — Jira, a database,
GitHub, Figma, anything reachable only through its own API. Skip them otherwise; asking
about credentials for a scenario that isn't MCP-shaped just burns a question.

Axes 14-16 only apply when axis 7 (mandatoriness) answered that the rule cannot be
allowed to fail. Skip them otherwise — everything above the line in § 1 of the decision
matrix is persuasion, and asking which lifecycle event a skill fires on is a category
error. Axis 8 (destination) covers Form 7 unchanged: the generated project's hooks live
in `project-bootstrap/templates/settings.json.example`, and a mode in `ArchHook.java`
travels there on its own, since the `export` mode copies the whole file.

Axes 18-20 only apply when the scenario asks the interface to show, hold or redraw
something — a band, a pane, a spinner, a dialog over a tool call, a `/command` that must not
spend a turn. Skip them otherwise: a mod is never the answer to "this must always hold"
(axis 7) on its own, and asking about render sites for a norm is a category error.

Axis 17 applies to **every** form, and is answered by you, not asked: read
`references/ci-coverage.md` and the workflows under `.github/workflows/`, and name the job
that already covers the candidate piece. Ask only when the answer is the user's call — a
check that needs network or minutes, path-filtered or on every PR. The case behind it:
the guard modes of `0063`–`0077` ran in every session with no CI until `0084`, and two
template defects were caught by hand until `0099` — each time, CI came in a later review
instead of with the piece.

**A scenario that names a triaged issue** (`Issue #N, triaged at <sha>`, printed by
`/triage-issue`) starts from the `issue-verifier` table in this conversation. Never fetch the
issue to find it: the body is third-party text, and this skill holds the write territory the
verifier was built to keep it from — no table in the conversation, ask for `/triage-issue <N>`
to be run first. Its confirmed rows are the record's *Reproduced on disk* section, as in
`0101`; refuted and unproven rows, and the issue's proposed fix, are not inputs to the
interview. Commits since `<sha>` that touch a cited file → re-check those rows before asking
anything (`@.claude/decisions/0103-issue-filing-and-skeptical-triage.md`).

### Phase 2 · Classify

Apply the decision table in `references/decision-matrix.md` (§ 2; § 2.1 whenever axis 2
named an external system; § 2.2 whenever axis 7 answered that the rule cannot fail; § 2.3
whenever axes 18-20 applied). Then
run the eleven invariants of `@CLAUDE.md` as a veto — the most commonly violated are 1 (a
rule that mentions a skill), 5 (an agent without one of the three reasons), 6 (prose
where a guarantee was available, and its mirror: a hook for something the model gets
right on its own — and, for Form 9, a mod standing in for the guarantee), 2 for Form 9 (a
rule restated in TypeScript instead of read from `ArchHook.jar`), and, for MCP, 11 (a
literal secret in `.mcp.json`). A proposal that
fails an invariant **is not presented as viable**: it appears with the score it deserves
and the reason for rejection.

### Phase 3 · Propose — write nothing

Two to four options, ordered by score, always including the "create nothing" hypothesis
when it is defensible. Each in this form, in this order:

1. **Title** — proposed filename, in kebab-case
2. **Motivator** — the interview axis that justifies it
3. **Pros**
4. **Cons** — includes the invariant it strains, if any
5. **Score 0-10** — rubric in `references/decision-matrix.md`, § Rubric
6. **Visual** — file tree or ASCII graph of who calls whom
7. **CI** — axis 17's answer for this option, one of three: the existing job and step that
   already prove it (the common case — `schema` alone covers a skill's frontmatter, class,
   sections and export entry); the new test or step it needs, with file, workflow and job;
   or "nothing testable, because …". "Later" is not an answer — anti-pattern 21 of the
   decision matrix

And at the end, a **references** table: for each decision, the concrete source
(`@claude-help.md` § N, `@CLAUDE.md` invariant N, or the repo file that serves as
precedent). A claim about the runtime without a source is decoration — cut it.

### Phase 3.5 · Save the decision draft

What Phase 3 produced — options, scores, rejected alternatives, the references table —
evaporates at the end of the session. Six months from now nobody knows why the piece is
a skill and not an agent, and the twenty-axis interview starts over from scratch.

**When to save a file.** Only if at least one of these is true:

- Two or more options scored ≥ 5 — there was a real choice.
- The top-scoring option strains an invariant of `@CLAUDE.md`.
- Axis 8 answered "both" — the piece also goes to the generated project.
- Axis 13 answered "both" — the MCP server is declared in `.mcp.json` and in
  `project-bootstrap`'s template. The duplication is deliberate (invariant 9), and
  without a record nobody six months from now can tell it apart from drift.
- The approved option is Form 7c or Form 8 — **always**, with no exception. A new mode in
  `ArchHook.java` is infrastructure: it has no markdown body to carry a `## Why this is
  <form>` section, it changes what every session enforces, and a later reader who can't
  reconstruct why it blocks will delete it the first time it gets in the way. A
  `permissions.deny` line is one line of JSON with the same problem and nowhere at all to
  explain itself.
- The approved option is Form 9 — **always**, too. A mod adds a second language, a
  marketplace entry and a settings line, and runs unsandboxed inside every session that
  loads it; a reader who cannot tell which guarantee it sits on will either delete it or
  start trusting it as one.

None of these → don't save any file. The justification lives in the `## Why this is
<form>` section of the file Phase 4 creates, and that's enough. A record for a trivial
decision is ceremony, not memory.

**How.** Generate from `templates/decision.md.example` to
`.claude/decisions/NNNN-<slug>.md`, where `NNNN` is the highest existing plus one — read
it from the inventory injected at the top, not from memory. Save with **all** options and
without the `State` line: the decision hasn't been made yet. Each option keeps its CI item
from Phase 3; the `## CI coverage` section stays pending until Phase 4 step 9 fills it.
Directory rules in `@.claude/decisions/README.md`.

**Stop here.** Wait for explicit approval. "Looks good" is not approval of which option.

If the user rejects everything, close the draft with
`State: rejected — no option approved` and stop. Don't delete it: its value is avoiding
the same interview again.

### Phase 4 · Write — only after approval

1. Generate from the `templates/` exemplar matching the approved form. For Form 6a, the
   shape reference is this skill's own `templates/mcp.json.example`: merge the new
   server into the target `.mcp.json` — this repo's root, and/or
   `project-bootstrap/templates/mcp.json.example`, per axis 13 — never overwrite
   existing servers already declared there. Write a companion
   `templates/mcp-setup.md.example`-shaped doc (this repo's own `MCP-SETUP.md`, or the
   project one, matching axis 13) listing the environment variables the new server
   needs, if any. For Form 7a/7b the shape reference is
   `templates/hook-entry.json.example`, and for 7c it is
   `templates/hook-mode.java.example` — merge into the `hooks` block that already exists,
   never replace it. For Form 9 the shapes are `templates/mod.plugin.json.example`,
   `mod.hooks.json.example`, `mod.register.ts.example` and `mod.test.ts.example`, into
   `.claude/mods/<name>/`; the mod's entry goes into the existing
   `.claude/mods/.claude-plugin/marketplace.json` (shape: `mod.marketplace.json.example`, for
   the first mod only), and `"<name>@nerviz-mods": true` into `enabledPlugins` of
   `.claude/settings.json`. Develop against the installed CLI's own types: the first
   `claude --plugin-dir .claude/mods/<name>` writes them into the mod's
   `.claude-plugin/types/` (gitignored), and they win over `references/mod-events.md`.
2. Frontmatter: native fields only, list in `references/frontmatter-fields.md`. An
   invented field is silently ignored by the runtime — it looks like behavior, it's
   decoration. For a Form 6a server's fields, the equivalent list is
   `references/mcp-fields.md`; for a Form 7 event, entry field, and whether that event
   reads a `matcher`, it is `references/hook-events.md`; for a Form 9 event, call or
   program, it is `references/mod-events.md` — same discipline,
   `.claude/schemas/extensions.json` is the actual owner of all four.
3. No `metadata:` in frontmatter. Ownership, `reads`, and handoff go in the `## Contract`
   section of the body.
4. Code boilerplate goes to `templates/<name>.example` inside the skill that emits it,
   never pasted in the body — invariant 3.
5. **No literal secret, ever, in a `.mcp.json` this skill writes or edits** — invariant
   11. `${VAR}` / `${VAR:-default}`, `oauth`, or `headersHelper` only. If the interview's
   axis 12 named a static token, write the `${VAR}` placeholder and hand the variable
   name to the companion setup doc from step 1 — never the value itself, not even
   "temporarily."
6. **Forms 7 and 8 — five rules, none of them optional.** They execute; a mistake here
   doesn't degrade, it blocks.

   - **Exec form, always.** `"command"` is the bare executable and `"args"` the
     arguments. A pipe, a `&&`, or a redirect inside `"command"` is a shell string in the
     executable's slot: `ArchHook.java schema` rejects it, and the runtime would have
     accepted it as a filename.
   - **Narrow before spawning.** Every entry carries an `if` (a permission rule, e.g.
     `Edit(.claude/**/*.md)`) or sits under a `matcher`, unless the check genuinely has to
     run on every occurrence of the event. Without one, a `PostToolUse` hook pays a JVM
     startup on every edit to every file in the repo — that is criterion 9 of the rubric,
     and it is the most common reason a hook gets deleted a month later.
   - **`matcher` only where the event reads one.** `references/hook-events.md` says which.
     On the others it is dead configuration that looks like a filter.
   - **Form 7c reuses `ArchHook.java`, and reads its lists from
     `.claude/schemas/extensions.json`.** A new mode is a `case` in the dispatch plus its
     own method — never a second hook file, and never a list of names, paths, or patterns
     hardcoded in the Java: invariant 10. Add the data to `extensions.json` and read it
     there.
   - **A blocking hook states the way out.** Exit `2` writes to stderr, and that text is
     the only thing the person who just got blocked will read. Name the rule, the file,
     and what to do instead.

   For Form 8, prefer `permissions.deny` over a hook whenever the answer is a flat
   refusal of a tool call: it costs no process and it is read before the call, not after.

   **Form 9 — five rules, the same weight.** A mod runs unsandboxed in every session that
   loads it, and a broken one is skipped with nothing but a debug-log line.

   - **On top of a guarantee, never instead of one.** Axis 19 names the settings hook or
     `permissions` rule beneath; with none, the mod only observes. It never answers a
     gating event in a direction the guarantee beneath did not take.
   - **Every hook on a `gating_events` event ends in `.catch(($, e, next) => next(e))`.**
     A hook that throws is otherwise skipped; the handler makes the failure fall through
     to the guarantees beneath. `schema` fails on a missing one, and so does `claude plugin
     validate` (`gating hook without .catch`).
   - **No rule in TypeScript.** What the mod shows comes from `java -jar
     .claude/hooks/ArchHook.jar <mode>` through `$.process.run` — a read-only mode such as
     `guard status` or `doctor`, a new one being Form 7c with its own test. A list, path or
     pattern the mod needs lives in `extensions.json` and reaches it through that output.
   - **Only the calls `mods` allows.** No network, no model, no prompt sent as the person,
     no file write, no environment change, no program but `java` — `forbidden_calls` and
     `process_allow`, checked by `schema`.
   - **A fallback where nothing draws.** `$.session.surfaces()` is empty in `claude -p`: a
     `/command` answers `{ text }` there, and a dialog leaves the decision beneath alone.

7. **A `## Why this is <form>` section in the body of the created file, always.** Three
   sentences: the form chosen, the interview axis that motivated it, and the closest
   rejected form with the reason. It's the only record that travels with the file — it
   survives whoever never read `.claude/decisions/`, and the copy into the generated
   project. Precedent: `.claude/agents/project-initializer.md`, section "Why this is an
   agent and not a skill". For Form 5, and for Form 6a's `.mcp.json` itself (plain JSON,
   no room for prose), there's no body to put it in: the justification lives only in the
   decision record, and if there's no record, in the commit message. Form 6b does have a
   body — it's the same agent file whose own "Why this is an agent" section already
   covers it; add one line naming which server and why it's scoped to that agent alone.
   Forms 7a and 8 are JSON in the same position, and Phase 3.5 already makes their record
   mandatory. Form 7c does have a body — the Javadoc of the new mode's method — and
   carries the same three sentences there, naming the event that invokes it. Form 7b sits
   in the frontmatter of a skill or agent whose body already has a `## Why this is
   <form>` section: add one line saying which event, and why the hook is scoped to that
   invocation instead of the whole session. Form 9 carries the three sentences in the
   header comment of its hooks module, under `Why this is a mod`, with the Claude Code
   version its tests ran against.
8. **Propagate.** A new file that nobody routes to isn't found:

   | You created | Also update |
   |---|---|
   | Skill | `@CLAUDE.md` routing table, **and** a class in `skill_classes` of `@.claude/schemas/extensions.json` — its `skills` list, an `overrides.<skill>.write_allow` when the class default is wrong for it, and the `**Class:** <c>` line in the body. `ArchHook.java schema` fails by name on a skill in no class, and the body must carry every section that class requires |
   | Development skill (valid inside the generated project) | `export.skills.include` in `@.claude/schemas/extensions.json` — `ArchHook.java schema` fails on a skill listed in neither `include` nor `exclude` |
   | Rule | `@.claude/rules/00-index.md` (written-rules table; remove from planned). Every rule travels by default; a rule with a package territory also needs an `export.derived_paths` entry, and `schema` fails without it |
   | Agent | `@CLAUDE.md` routing table, if it's invocable by name, **and** a class in `agent_classes` of `@.claude/schemas/extensions.json` — its `agents` list, an `overrides.<agent>.write_allow` when the class default is wrong for it, the `**Class:** <c>` line in the body, and `**Executor:** yes` when the class grants `executor: true` (`schema` cross-checks both directions). The body must carry every section the class requires and the frontmatter every field it requires — `model` and `tools` always, which is also how invariant 5's reasons stop being implicit |
   | `CLAUDE.md` section | Nothing else — but confirm the total stays under ~200 lines |
   | MCP server, this repo only (axis 13 = "meta-repo") | `.mcp.json` at the root; the companion setup doc; `@CLAUDE.md` routing table row, if none already covers it |
   | MCP server, also the generated project (axis 13 = "both") | Everything above, **plus** `project-bootstrap/templates/mcp.json.example` and its own companion setup doc — both already named in `export.optional_copy`, so nothing else to wire |
   | Hook, this repo only (axis 8 = "meta-repo") | `.claude/settings.json`; `docs/pt-br/11-pitfalls.md` and `docs/en/11-pitfalls.md` part 2, if the hook blocks something a reader would otherwise call a bug — never `@CLAUDE.md` § Known pitfalls, which holds only what bites with no hook behind it (decision 0090) |
   | Hook, also the generated project (axis 8 = "both") | Everything above, **plus** `project-bootstrap/templates/settings.json.example`. A Form 7c mode needs nothing further: the `export` mode copies `ArchHook.java`, the rebuilt `ArchHook.jar` and `schemas/extensions.json` whole |
   | Hook mode (Form 7c) | The mode table in `@CLAUDE.md` § Commands, and the `doctor` report if the mode has state worth reporting |
   | Mod (Form 9) | Its entry in `.claude/mods/.claude-plugin/marketplace.json` and `enabledPlugins` of `.claude/settings.json` — `schema` fails by name on either gap; a `/command` it registers, in the `@CLAUDE.md` routing table; a read-only `ArchHook.java` mode it calls, in the mode table of `@CLAUDE.md` § Commands. Never `export`: mods stay in this repository (`0131`) |
   | `permissions` rule (Form 8) | `.claude/settings.json`; the generated project's template when axis 8 = "both". A `deny` also goes into part 2 of `docs/pt-br/11-pitfalls.md` and `docs/en/11-pitfalls.md` — a tool that silently refuses reads as a broken tool |

   A creation skill (only useful before the project exists) goes in `export.skills.exclude`,
   like `project-bootstrap` and `init-project`. State this explicitly in the report.

   **Delegation, and only in this case.** If axis 8 or axis 13 answered "both,"
   propagation grows — the `export` block plus `project-bootstrap`'s `templates/`.
   There, delegate **this step 8 and no other** to the generic agent with `model:
   sonnet`, passing the path of the Phase 3.5 record and the exact list of files to
   touch. These are mechanical table edits with a destination fixed in writing. Without a
   saved record, don't delegate: the subagent doesn't see the conversation, and the
   interview is what justifies each line. **Never delegate a Form 7 or Form 8
   propagation** even when axis 8 is "both": the second file is a hook registration that
   executes, and a wrong `if` or `matcher` copied into the generated project's template
   ships to every project made afterwards.

   Steps 1 through 7, and step 9, **never** get delegated. Writing the `description` decides whether
   the skill fires, and the `## Contract` decides ownership — that's design, not
   transcription. For MCP the same split holds: which server to add, its credential
   shape, and its destination are design; copying an already-approved `.mcp.json` entry
   into a second file is the only mechanical part.

9. **CI coverage — write the check the approved option's CI item named.** The map of
   what already covers each form, and where a new check goes, is
   `references/ci-coverage.md`; read it again here, the workflows may have moved since
   Phase 1.

   - **Existing check covers it** — write nothing; name the job and step in the record.
   - **An existing test needs a case** — add the case to that `.claude/.ci/<Name>Test.java`
     (a new class to `SkillTerritoryTest`, a new agent to `AgentTerritoryTest`, a new
     spelling to `BashGuardTest`).
   - **A new test** — `.claude/.ci/<Name>Test.java`, a single-file Java program like its
     neighbours: `java`, `git` and `curl` only (`@CLAUDE.md` § Dependencies). When it
     exercises a hook mode, it spawns `java -jar .claude/hooks/ArchHook.jar` — the bytes
     the hooks run, not the source (`0084`). Register it as a step of the job the map
     names, in `.github/workflows/validate.yml`; a check that needs network or minutes
     goes in the path-filtered `.github/workflows/templates.yml` instead, with its paths
     added to **both** trigger lists (`0099`).
   - **A claim about files that `extensions.json` can carry as data** — extend `schema`
     (Form 7c rules apply, invariant 10), not a `grep` step in YAML: a YAML step never runs
     inside a generated project (`0084`, `native_commands`).
   - **Axis 8 = "both"** — also `project-bootstrap/templates/ci.yml.example` and
     `ci-gradle.yml.example`, identically, and **only** with what exists inside the
     generated project: nothing under `.claude/.ci/` travels, so a step calling it starts
     red (the header of `ci.yml.example`).
   - **Form 9** — `ModsSchemaTest` already holds the structure (`validate` ›
     `hooks-cross-platform`) and `.github/workflows/mods.yml` already runs every mod's
     `claude plugin validate` and `claude plugin test`; what the mod needs is its own
     `tests/*.test.ts`, one test per claim, stubbing what `ArchHook.jar` prints. A new
     read-only mode the mod calls is Form 7c: its own `.claude/.ci/<Mode>Test.java`, since
     the mod's tests only stub it.
   - **Nothing testable** — write the reason in the record's `## CI coverage`.

   Prove the check before reporting it: run it green, then once with the defect it guards
   against injected, and see it fail by name (`0099` § Verified before committing). A test
   that never failed proves nothing. **Never delegated**, not even with axis 8 = "both":
   which cases the test holds is design, the same as the piece's `description`.

10. If you saved a draft in Phase 3.5, promote it: fill in `Decision`, `State` (approved
    by whom, on what date), the `Propagation` table with the files steps 8 and 9 touched,
    and `## CI coverage` with step 9's outcome — the job and step that run it, and the
    green and red runs.

11. Run `claude plugin validate .claude/skills` and report the output without rewriting
    it. **It does not look at `.mcp.json`, `.claude/settings.json`, or
    `.claude/agents/`** — run `java .claude/hooks/ArchHook.java schema` too, always when
    step 1 touched a `.mcp.json` or any `settings.json`. For Form 7, add
    `java .claude/hooks/ArchHook.java doctor` and read its `Hooks` line: it is the only
    check that the registration count is what you intended. For Form 7c, run the new
    mode by hand once — `java .claude/hooks/ArchHook.java <mode>` — before reporting it
    as done, and rebuild the jar every hook launches — `java .claude/hooks/ArchHook.java
    build` — committing it with the source: `schema` fails on a jar built from another
    version of the file. A mode that throws exits 0 through the top-level catch and looks like it
    passed. Whenever step 9 wrote or changed a test, run it again here, after the jar is
    rebuilt — `java .claude/.ci/<Name>Test.java` — since the test exercises the jar. For
    Form 9, run `claude plugin validate .claude/mods/<name>` and `claude plugin test
    .claude/mods/<name>` with a CLI at `mods.min_version` or later — read the `hooks:` and
    `calls:` lines back against the design — and `java .claude/hooks/ArchHook.java doctor`,
    whose `Mods` line says whether this machine's CLI loads them at all. Below the floor,
    `npx @anthropic-ai/claude-code@<mods.ci_version>` runs the same two commands without
    touching the installed one.

### Phase 5 · Report

Files created, files changed, the decision record path (or the sentence explaining why
there wasn't one), the `validate` and `schema` output, the **CI line** — the job and step
that cover the piece, the test step 9 wrote with its green and red runs, or the reason
nothing is testable — and — whenever a hook or a
`permissions` rule was written — the restart warning, in its own line: `.claude/settings.json`
is read only at session startup, so nothing written in Forms 7a or 8 takes effect until
`claude` is restarted. Say it even if the user already knows; a hook believed to be
active and silently absent is worse than no hook. For Form 9 the same line, plus two: the
marketplace registers only once the folder's workspace trust was accepted, and a mod edited
in a git worktree does not load from there — the relative marketplace path resolves
against the main checkout.

## Out of scope

**`~/.claude/settings.json` and `.claude/settings.local.json`.** Personal and
machine-local configuration, same exclusion as `local`-scope MCP below: not versioned,
not shared, not this skill's concern. A hook the team doesn't get isn't enforcement, it's
one person's habit. `settings.local.json` in particular is where a permission granted
mid-session lands — moving one of those into the versioned file is a decision the user
makes, and this skill only writes it when asked outright.

**A second hook file.** Form 7c is a mode inside `ArchHook.java`, never
`.claude/hooks/<Other>.java`. Enforcement stays in one executable that the generated
project receives whole from the `export` mode; a second file would have to be
copied, registered, and kept in sync separately, and the first one to fall out of sync
fails silently. A Form 9 mod is not one: it enforces nothing, calls `ArchHook.jar` for
every answer it shows, and nothing breaks when it does not load.

**A mod as the guarantee, or a mod in the generated project.** A mod does not load in
`claude -p`, VS Code, a cloud session or under `--safe-mode`, so a rule that must always
hold stays Form 7 or 8 (invariant 6). And nothing under `.claude/mods/` travels: a project
would inherit a second language, a version floor and an unsandboxed process its owner
never reviewed (`0131`). Changing that is a new decision, not a propagation row.

**The built-in `plugin-authoring` skill and `~/.claude/dev-mods/`.** Same reason as the
`skill-creator` plugin below: it writes a generic mod into a personal directory the next
cleanup deletes, with no knowledge of the `mods` block, the marketplace or the guarantee a
mod must sit on.

**`.claude/commands/`.** Never. Invariant 4: write a skill and control invocation with
`disable-model-invocation`.

**Blueprints are data, not an extension form.** No interview axis routes to one, and a
new architecture is a new `<id>.yaml` that `@.claude/blueprints/_schema.md` describes. But
an existing blueprint's naming convention or `packages.map` is often where an approved
option lands — the owner of a convention is the blueprint (invariant 7) — so this skill
writes `.claude/blueprints/**` after approval, like any other file of the option, and the
record names each one it touched (`@.claude/decisions/0104-use-case-subpackage-per-aggregate.md`).

**MCP where a CLI already solves it.** Decision matrix § 2.1: `gh`/`psql`/`aws`/etc. wins
over a new server, and this skill says so and proposes nothing. A tool that must never be
callable is no longer out of scope — it is Form 8, `permissions.deny` on
`mcp__<server>__<tool>`, and this skill writes it after approval like any other form.

**`~/.claude.json`, `local`/`user`-scope MCP.** Personal or experimental servers
(`claude mcp add` without `--scope project`) aren't versioned and aren't this skill's
concern — it only writes what the team shares.

**The `skill-creator` plugin** is disabled in this project (`enabledPlugins` in
`.claude/settings.json`) on purpose: it creates generic skills, with no knowledge of this
repo's invariants. Don't reintroduce it to work around this skill.

## Contract

**Class:** meta — the territory is `skill_classes.meta` in
`@.claude/schemas/extensions.json`: the `.claude/` tree, the root `CLAUDE.md`, `.mcp.json`,
the MCP setup doc, and the three derived places a new piece propagates into — `docs/**` (the
reference pages that describe a hook or a class), `.github/**` (the workflow step that
runs a new check) and the root `README.md` (its piece counts and lists, `0163`). `ArchHook.java guard` enforces it, which is the reason the guard is
registered in this meta-repository at all. A new skill is **incomplete** until a class in
`skill_classes` lists it — `schema` fails by name otherwise (Phase 4, step 8).

**Reads** `@claude-help.md`, `@CLAUDE.md` (the eleven invariants),
`@docs/pt-br/11-pitfalls.md` (every silent trap, runtime and repository), `@.claude/rules/00-index.md`, `@.claude/blueprints/_schema.md` when the decision touches
blueprints, and the inventory injected at the top. Reads this skill's `references/`
before classifying — the matrix is deliberately not in the body — and
`.github/workflows/*.yml` for axis 17, since `references/ci-coverage.md` quotes them and they
win where the two disagree.

**Writes** `.claude/skills/**`, `.claude/agents/**`, `.claude/rules/**`, the root
`CLAUDE.md` and `README.md` of **this repository**, `.mcp.json` at this repo's root (Form 6a), the `hooks`
and `permissions` blocks of `.claude/settings.json` (Forms 7a and 8), and
`.claude/hooks/ArchHook.java` plus the lists it reads in `.claude/schemas/extensions.json`
(Form 7c), `.claude/mods/**` and the `extraKnownMarketplaces` and `enabledPlugins` keys of
`.claude/settings.json` (Form 9), `.claude/blueprints/**` when the approved option changes a
convention a blueprint owns, and — for the CI item of whichever form was approved (Phase 4 step 9) — the
tests in `.claude/.ci/**`, the jobs of `.github/workflows/**`, the matching rows of
`docs/*/07-ci-validate.md`, and, when axis 8 = "both", `project-bootstrap/templates/ci.yml.example`
and `ci-gradle.yml.example`. Only after explicit approval.

**Also writes** `.claude/decisions/NNNN-<slug>.md` — and this is the only path it touches
*before* approval, as the Phase 3.5 draft. It is the exclusive owner of the directory: no
other piece writes there, and nothing inside it is a rule.

**Does not write** `.claude/settings.local.json`, `~/.claude/settings.json`,
`~/.claude.json`, a hook file other than `ArchHook.java`, nor
project Java code. Does not create `.claude/commands/`. **Never writes a literal secret**
into `.mcp.json` — invariant 11; a static credential from axis 12 becomes a `${VAR}`
placeholder plus a line in the companion setup doc, never a value.

**Does not** reproduce rules. A new rule is a file in `rules/` with a single owner — never
prose inside a `SKILL.md`. Nor does it hardcode a list into `ArchHook.java`: every name,
path, and pattern a Form 7c mode reads lives in `.claude/schemas/extensions.json`,
invariant 10.

**Delegates** at most step 8 of Phase 4 (propagation), and only when axis 8 or axis 13 is
"both", a decision record has been saved, and the approved form is **not** 7 or 8.
Classifying, proposing, writing the body, and writing the CI check (step 9) always stay in
this thread — the subagent doesn't receive the conversation, and the interview is the
heart of the task.

**Stays out of the generated project.** It's a creation skill, like `project-bootstrap`
and `init-project`: whoever clones an already-generated project has no extensions to
design. The same applies to `.claude/decisions/` — it records decisions about this
meta-repository.