Phase spec — phase plan from an ADR
The ADR says WHAT was decided and WHY. The spec says in what order, in which files,
with which acceptance criteria — and nothing else. Every phase of the spec must trace
back to an ADR section; anything that does not is either the session's own call
(flag it to the user) or does not belong. Where this skill and the project's CLAUDE.md
disagree on a convention (test runner, file layout, doc rules), the project wins — the
spec is written for that project's implementer.
Inputs — all three, or don't start
- ADR with no decision left PENDING — each DECIDED or DROPPED — and its review closed (produced by
/adr). Open decisions → back to the
ADR, not into the spec. The spec never re-decides; where they disagree the ADR wins
and the spec is fixed. If writing the spec exposes a contradiction inside the ADR,
stop and ask — the ADR is corrected first, then the spec.
- Issue, or the ADR's problem statement when the feature came from a conversation — the 30-second "why" for the spec preamble.
- Agent roster — who implements (Lyutik / Geralt / …), to size phases for their context.
Language
The spec is always English, whatever language the conversation runs in. It is read by
the implementing agent, not the user: English costs fewer tokens and the model reads it
better. The ~400-line budget below is an English budget — Cyrillic at the same length is
a different size and token count. The ADR's language is the user's choice (they read it);
the spec quotes its section numbers, not its prose.
Before writing — verify against the code, not memory
Every file, export, constant, line count and "used nowhere" claim in the spec must be
checked with grep/wc/ls first. A spec that names Sidebar.tsx when the file is
LeftSidebar.tsx, or says a store field is unused when two components read it, costs the
implementer a phase. Concretely, before the first line:
- locate every file the ADR names; note size (
wc -l) — the cut depends on it;
- grep the identifiers the phases will rename/delete — who imports them;
- check what test/lint/build tooling exists (
package.json scripts, pytest.ini) — the
verification rule must name real commands;
- read the project's
CLAUDE.md lines that describe the behaviour being changed — each
phase that changes them must update them.
Cutting phases
- One phase = one reviewable diff = one commit. A reviewer must be able to hold the
whole diff; a phase that needs a summary to be reviewed is two phases.
- Explicit dependencies in a phase map table (
#, phase, ADR refs, depends on).
New artifacts have a single owning phase; later phases reference, never re-declare.
- Scope fits the implementer's context — roughly 30% of its window per phase.
Big new component + deletion of two old ones + page wiring is the ceiling, not the norm.
- No non-working intermediate states across phases unless the branch is not deployed
between them — then say so explicitly in the phase.
- Order by risk and reuse: foundations (stores, state) first, surfaces that consume
them after, mobile/responsive after the desktop surface exists, cosmetic sweeps last.
- Tests ride with the logic they test, in the same phase; tooling (test runner,
config) lands in the first phase that has something worth testing.
Who writes what
- The session writes every phase from the ADR: scope, files, edge cases, acceptance,
verification. The implementer never sets its own scope or criteria — the same rule as
"doesn't review its own code", one step earlier.
- A profile agent (Jobs, Lauda, Gilfoyle, …) writes a phase only when a different agent
implements it (Jobs → Lyutik). Otherwise it is the executor scoping itself.
- The implementer reviews the cut once (Review step 2) — as a reviewer of the plan,
not its author. It never writes or amends a phase.
Phase template — WHAT, never HOW
## Phase N — <name> (<ADR refs>)
**Goal.** Why this phase exists; what is true after it that was not before. 2–3 lines.
**Scope.** Bullets of behaviour and boundaries. Name the files/identifiers touched,
say what moves/dies/appears. Leave component boundaries and internal decomposition to
the implementer — write "implementer's call" where the ADR left it open.
**Files.** New / modified / deleted, plus the CLAUDE.md lines this phase must update.
**Edge cases.** The non-obvious ones the implementer would miss: SSR, hydration, two
mounts, stale storage, degraded responses, breakpoints, focus/Escape.
**Acceptance.** Verifiable results, not commands. A one-line `grep … → empty` is fine;
a bash block is a runbook — cut it.
**Verify.** An executable checklist the SESSION runs as written — one line per Acceptance
criterion: **layer** → concrete call/input → expected value. Layers, cheapest that proves
the claim: `unit` (pytest/vitest, no stack) → `api` (curl/SQL against the stack) →
`browser` (playwright, only for what is visual or click-driven; name viewport + theme +
what the frame must show). "Test in the browser" is not a scenario; "browser 400px dark:
expired card greyed, no Download button" is. Test data the scenario needs (a seeded row,
a user state) is named here too — the session must not invent it mid-phase. A criterion
that has no runnable local check says `not testable locally` explicitly.
**Rollback.** `Revert.` unless something lives outside code (storage keys, GTM tags,
migrations) — then say what stays behind and whether it is harmless.
Preamble before the phases: source ADR + "the ADR wins", issue/branch/wireframe links,
Ground rules (implementer, gate — the session's check of the diff against each phase's Acceptance, run by /implement — design source, verification commands, test policy,
doc-update rule, rollback default, "no backend changes" or the opposite, and the line
"phases are run with /implement: briefing to the user first, then the agent"), then the
phase map table. Close with After the phases — PR, changelog, manual steps outside code
(GTM tags, cron), follow-ups the ADR deferred.
Format — the skill decides, no question to the user
- One file up to ~400 English lines →
<topic>-spec.md next to the ADR.
- Beyond that, or 8+ phases → a directory
<topic>-spec/ with README.md (preamble +
map) and NN-<phase>.md per phase, 60–120 lines each.
- Estimate from ADR size × phase count before writing; do not write 600 lines and split
afterwards.
- Placement: next to the ADR — project root for a single-file ADR, inside its
docs/adr/<domain>/ directory for a split one — listed in .git/info/exclude (never
.gitignore, never staged). Check with git check-ignore -v after adding.
Review — three steps, in this order, none optional
- Self-review against the ADR — every DECIDED section maps to at least one phase;
every phase cites its sections; no phase contains a decision the ADR did not make.
- Implementer review of the cut — send each implementer (Geralt, Lyutik, …) its own
phases + the ADR + the spec preamble (the file itself, or the directory README), read-only, in parallel. Ask five things: cut
(split/merge), order/dependencies, wrong facts (files, lines, "only caller" claims,
commands), missing edge cases, feasibility. "Phase N: clean" is a valid answer and
must be offered as one. Implementation-level findings the session verifies and applies
itself; only findings that touch ADR logic go to the user, in plain language. Record
the outcome in the preamble ("Implementer review of the cut: , ").
- Present to the user: the phase map table plus a short list of the calls that are
the session's own. The boundary: how to cut, in what order, how to verify — those are
the spec's calls and belong on this list; what the product does or how it is built is
the ADR's, and a gap there goes back to
/adr, never onto this list. Wait for the user's explicit yes.
Do not start the next step on silence.
External review (Agatha/Arthur/Dash, twix, precogs) only on the user's command.
Reviewers push toward runbooks and toward re-deciding — hold the line; verify BLOCKING
claims against the files before applying.
Anti-patterns
| Avoid |
Instead |
| Spec in the conversation's language |
English, always |
| Re-deciding an ADR point "because it's cleaner" |
Stop, fix the ADR with the user, then the spec |
| Implementation code or bash blocks in acceptance |
Result criteria + one-line hints |
| Naming files/exports from memory |
grep/ls first; the spec is a contract |
| Implementer writes its own phase |
Session writes; implementer reviews the cut (Review 2) |
| Skipping Review 2 to save time |
One parallel agent round; skipping it has cost ~20 corrections found mid-phase instead |
| Component tests / snapshot tests in a frontend phase |
Logic tests only; markup via playwright by the session |
| A 600-line single file |
Estimate first; directory when over ~400 |
| "Update docs at the end" |
Each phase names the CLAUDE.md lines it changes |
| Spec committed to the repo |
Root + .git/info/exclude; the code is the artifact |
Example
examples/phase-example.md — one real phase (quota store extraction): the
template filled in with verified file names, five named test scenarios, and the
CLAUDE.md lines it owns.
1---2name: spec3description: Turns a closed ADR into a phase spec an LLM implementer executes phase by phase: cuts, orders and describes — decides nothing (the ADR did), implements nothing (the implementer agents do). Triggers: "/spec", "спека", "напиши спеку", "спека фаз", "нарізка фаз", "write the spec", "phase spec". Requires an ADR with no decision left PENDING (each DECIDED or DROPPED) and its review closed — without one, stop and point at /adr. Running the phases (briefing, gate, review, commit) is /implement, not this skill.4---56# Phase spec — phase plan from an ADR78The ADR says WHAT was decided and WHY. The spec says in what order, in which files,9with which acceptance criteria — and nothing else. Every phase of the spec must trace10back to an ADR section; anything that does not is either the session's own call11(flag it to the user) or does not belong. Where this skill and the project's `CLAUDE.md`12disagree on a convention (test runner, file layout, doc rules), the project wins — the13spec is written for that project's implementer.1415## Inputs — all three, or don't start16171. **ADR** with no decision left PENDING — each DECIDED or DROPPED — and its review closed (produced by `/adr`). Open decisions → back to the18 ADR, not into the spec. The spec never re-decides; where they disagree the ADR wins19 and the spec is fixed. If writing the spec exposes a contradiction inside the ADR,20 stop and ask — the ADR is corrected first, then the spec.212. **Issue, or the ADR's problem statement** when the feature came from a conversation — the 30-second "why" for the spec preamble.223. **Agent roster** — who implements (Lyutik / Geralt / …), to size phases for their context.2324## Language2526**The spec is always English**, whatever language the conversation runs in. It is read by27the implementing agent, not the user: English costs fewer tokens and the model reads it28better. The ~400-line budget below is an English budget — Cyrillic at the same length is29a different size and token count. The ADR's language is the user's choice (they read it);30the spec quotes its section numbers, not its prose.3132## Before writing — verify against the code, not memory3334Every file, export, constant, line count and "used nowhere" claim in the spec must be35checked with `grep`/`wc`/`ls` first. A spec that names `Sidebar.tsx` when the file is36`LeftSidebar.tsx`, or says a store field is unused when two components read it, costs the37implementer a phase. Concretely, before the first line:3839- locate every file the ADR names; note size (`wc -l`) — the cut depends on it;40- grep the identifiers the phases will rename/delete — who imports them;41- check what test/lint/build tooling exists (`package.json` scripts, `pytest.ini`) — the42 verification rule must name real commands;43- read the project's `CLAUDE.md` lines that describe the behaviour being changed — each44 phase that changes them must update them.4546## Cutting phases4748- **One phase = one reviewable diff = one commit.** A reviewer must be able to hold the49 whole diff; a phase that needs a summary to be reviewed is two phases.50- **Explicit dependencies** in a phase map table (`#`, phase, ADR refs, depends on).51 New artifacts have a single owning phase; later phases reference, never re-declare.52- **Scope fits the implementer's context** — roughly 30% of its window per phase.53 Big new component + deletion of two old ones + page wiring is the ceiling, not the norm.54- **No non-working intermediate states across phases** unless the branch is not deployed55 between them — then say so explicitly in the phase.56- **Order by risk and reuse:** foundations (stores, state) first, surfaces that consume57 them after, mobile/responsive after the desktop surface exists, cosmetic sweeps last.58- **Tests ride with the logic they test**, in the same phase; tooling (test runner,59 config) lands in the first phase that has something worth testing.6061## Who writes what6263- **The session writes every phase** from the ADR: scope, files, edge cases, acceptance,64 verification. The implementer never sets its own scope or criteria — the same rule as65 "doesn't review its own code", one step earlier.66- **A profile agent (Jobs, Lauda, Gilfoyle, …) writes a phase only when a different agent67 implements it** (Jobs → Lyutik). Otherwise it is the executor scoping itself.68- **The implementer reviews the cut once** (Review step 2) — as a reviewer of the plan,69 not its author. It never writes or amends a phase.7071## Phase template — WHAT, never HOW7273```74## Phase N — <name> (<ADR refs>)7576**Goal.** Why this phase exists; what is true after it that was not before. 2–3 lines.7778**Scope.** Bullets of behaviour and boundaries. Name the files/identifiers touched,79say what moves/dies/appears. Leave component boundaries and internal decomposition to80the implementer — write "implementer's call" where the ADR left it open.8182**Files.** New / modified / deleted, plus the CLAUDE.md lines this phase must update.8384**Edge cases.** The non-obvious ones the implementer would miss: SSR, hydration, two85mounts, stale storage, degraded responses, breakpoints, focus/Escape.8687**Acceptance.** Verifiable results, not commands. A one-line `grep … → empty` is fine;88a bash block is a runbook — cut it.8990**Verify.** An executable checklist the SESSION runs as written — one line per Acceptance91criterion: **layer** → concrete call/input → expected value. Layers, cheapest that proves92the claim: `unit` (pytest/vitest, no stack) → `api` (curl/SQL against the stack) →93`browser` (playwright, only for what is visual or click-driven; name viewport + theme +94what the frame must show). "Test in the browser" is not a scenario; "browser 400px dark:95expired card greyed, no Download button" is. Test data the scenario needs (a seeded row,96a user state) is named here too — the session must not invent it mid-phase. A criterion97that has no runnable local check says `not testable locally` explicitly.9899**Rollback.** `Revert.` unless something lives outside code (storage keys, GTM tags,100migrations) — then say what stays behind and whether it is harmless.101```102103Preamble before the phases: source ADR + "the ADR wins", issue/branch/wireframe links,104**Ground rules** (implementer, gate — the session's check of the diff against each phase's Acceptance, run by `/implement` — design source, verification commands, test policy,105doc-update rule, rollback default, "no backend changes" or the opposite, and the line106"phases are run with /implement: briefing to the user first, then the agent"), then the107phase map table. Close with **After the phases** — PR, changelog, manual steps outside code108(GTM tags, cron), follow-ups the ADR deferred.109110## Format — the skill decides, no question to the user111112- One file up to **~400 English lines** → `<topic>-spec.md` next to the ADR.113- Beyond that, or 8+ phases → a directory `<topic>-spec/` with `README.md` (preamble +114 map) and `NN-<phase>.md` per phase, 60–120 lines each.115- Estimate from ADR size × phase count before writing; do not write 600 lines and split116 afterwards.117- **Placement:** next to the ADR — project root for a single-file ADR, inside its118 `docs/adr/<domain>/` directory for a split one — listed in `.git/info/exclude` (never119 `.gitignore`, never staged). Check with `git check-ignore -v` after adding.120121## Review — three steps, in this order, none optional1221231. **Self-review against the ADR** — every DECIDED section maps to at least one phase;124 every phase cites its sections; no phase contains a decision the ADR did not make.1252. **Implementer review of the cut** — send each implementer (Geralt, Lyutik, …) its own126 phases + the ADR + the spec preamble (the file itself, or the directory README), read-only, in parallel. Ask five things: cut127 (split/merge), order/dependencies, wrong facts (files, lines, "only caller" claims,128 commands), missing edge cases, feasibility. "Phase N: clean" is a valid answer and129 must be offered as one. Implementation-level findings the session verifies and applies130 itself; only findings that touch ADR logic go to the user, in plain language. Record131 the outcome in the preamble ("Implementer review of the cut: <date>, <what changed>").1323. **Present to the user:** the phase map table plus a short list of the calls that are133 the session's own. The boundary: how to cut, in what order, how to verify — those are134 the spec's calls and belong on this list; what the product does or how it is built is135 the ADR's, and a gap there goes back to `/adr`, never onto this list. Wait for the user's explicit yes.136 Do not start the next step on silence.137138External review (Agatha/Arthur/Dash, `twix`, precogs) only on the user's command.139Reviewers push toward runbooks and toward re-deciding — hold the line; verify BLOCKING140claims against the files before applying.141142## Anti-patterns143144| Avoid | Instead |145|---|---|146| Spec in the conversation's language | English, always |147| Re-deciding an ADR point "because it's cleaner" | Stop, fix the ADR with the user, then the spec |148| Implementation code or bash blocks in acceptance | Result criteria + one-line hints |149| Naming files/exports from memory | `grep`/`ls` first; the spec is a contract |150| Implementer writes its own phase | Session writes; implementer reviews the cut (Review 2) |151| Skipping Review 2 to save time | One parallel agent round; skipping it has cost ~20 corrections found mid-phase instead |152| Component tests / snapshot tests in a frontend phase | Logic tests only; markup via playwright by the session |153| A 600-line single file | Estimate first; directory when over ~400 |154| "Update docs at the end" | Each phase names the CLAUDE.md lines it changes |155| Spec committed to the repo | Root + `.git/info/exclude`; the code is the artifact |156157## Example158159[`examples/phase-example.md`](examples/phase-example.md) — one real phase (quota store extraction): the160template filled in with verified file names, five named test scenarios, and the161CLAUDE.md lines it owns.