diff --git a/README.md b/README.md
index b52e37d..802b1b1 100644
--- a/README.md
+++ b/README.md
@@ -18,12 +18,13 @@ The pipeline skills, each with the agents it primarily dispatches:
| Skill | Trigger | Output | Mandatory? |
|-------|---------|--------|------------|
-| `brainstorm` | New cycle starting | spec under the configured spec dir | Hard-gate before plan |
+| `brainstorm` | New cycle with an open design | ratified design handed to `specify` (writes no spec itself) | Optional discovery front-end |
+| `specify` | Design settled in sources, or handed over by `brainstorm` | spec under the configured spec dir | Hard-gate before plan |
| `planner` | New iteration within an open cycle | plan under the configured plan dir | Hard-gate before implement |
| `implement` | Plan exists | code + tests, uncommitted in working tree | Standard iteration path |
| `audit` | Cycle closing OR baseline drift suspected | drift report + regression report | Mandatory at cycle close |
| `debug` | Bug observed | RED test in working tree + cause analysis | Mandatory RED-first for any bug |
-| `tdd` | Test-specifiable feature / issue (alternative to `brainstorm`) | RED executable-spec in working tree → `implement` mini-mode | Opt-in entry path; bounces to `brainstorm` on a design fork |
+| `tdd` | Test-specifiable feature / issue (third entry path, alongside `brainstorm` and `specify`) | RED executable-spec in working tree → `implement` mini-mode | Opt-in entry path; bounces to `brainstorm` on a design fork |
| `fieldtest` | Orchestrator-dispatched post-audit | example fixtures + friction spec | Per-cycle optional; milestone fieldtest is the closing gate for a surface-touching milestone |
| `docwriter` | API surface stable across N cycles | rustdoc / docstring sweep | Optional |
| `boss` | User types `/boss` | autonomous-orchestrator session — dispatches the other skills until done-state or bounce-back | User-invoked, never auto-dispatched |
diff --git a/boss/SKILL.md b/boss/SKILL.md
index bb4effd..d81d3b1 100644
--- a/boss/SKILL.md
+++ b/boss/SKILL.md
@@ -93,7 +93,8 @@ back to the user.
Pipeline:
```
-brainstorm → planner → implement → audit → fieldtest
+brainstorm → specify → planner → implement → audit → fieldtest
+ specify → planner (design settled in sources, no discovery)
+
debug (bug-triggered)
+
@@ -109,52 +110,56 @@ new feature work with no spec or plan yet, run the **Entry-path
reflection** below before dispatching anything. Read each skill's
`SKILL.md` trigger section if unsure.
-**Entry-path reflection (feature work).** When the profile enables
-the `tdd` phase, `brainstorm` and `tdd` are two **co-equal** entry
-paths for new feature work — neither is the default, and the choice
-is made by reflection every time, not by habit. Before dispatching
-either, decide which fits the item in hand and record the one-line
-verdict ("test-specifiable → `tdd`" / "design fork → `brainstorm`")
-in the loop. The discriminator is the **design line**, not a
-preference:
+**Entry-path reflection (feature work).** When the profile enables the
+`tdd` phase, there are **three** entry paths for new feature work, and
+the choice is made by reflection every time, not by habit. Before
+dispatching, decide which fits the item in hand and record the one-line
+verdict ("test-specifiable → `tdd`" / "design settled → `specify`" /
+"design fork → `brainstorm`") in the loop. The discriminator is the
+**design line**:
- The item's desired behaviour can be pinned by one honest minimal
- assertion — "calling X with Y returns Z", a backlog `feature`
- issue whose body fixes one observable behaviour — then it is
- **test-specifiable** and `tdd` owns it. Dispatch `tdd`
- autonomously, the same way a bug issue is dispatched to `debug`:
- it authors a RED executable-spec and hands the GREEN side to
- `implement` mini-mode. This is **not** a new-cycle bounce-back —
- the test is the spec; no `brainstorm` runs to begin.
-- Writing that one assertion would force a choice between two or
- three plausible behaviours with real trade-offs — a genuine design
- fork — then the work needs a prose spec the user approves, and
- `brainstorm` owns it. Starting a new cycle through `brainstorm` is
- itself a bounce-back per §"Direction freedom" trigger 4: green-light
- the cycle (and the session shape) with the user first; only then
- does `brainstorm` get dispatched.
+ assertion — "calling X with Y returns Z" — then it is
+ **test-specifiable** and `tdd` owns it. Dispatch `tdd` autonomously,
+ the same way a bug issue is dispatched to `debug`.
+- The sources resolve every load-bearing design decision — an
+ exhaustive issue body, a long in-context discussion — then the design
+ is **settled** and `specify` owns it. Dispatch `specify`
+ autonomously: it is bounded (no interview), produces the spec through
+ all the gates, and pauses only at its own user-review gate (a
+ problem-state notify, not a pre-dispatch checkpoint).
+- Writing the spec would force a choice between two or three plausible
+ designs with real trade-offs — a genuine design fork — then discovery
+ must resolve it first, and `brainstorm` owns it. Starting a fresh
+ `brainstorm` cycle is itself a bounce-back per §"Direction freedom"
+ trigger 4: green-light the cycle (and the session shape) with the
+ user first; only then does `brainstorm` get dispatched.
-The asymmetry in autonomy — a `tdd` dispatch proceeds, a fresh
-`brainstorm` cycle bounces back — is **not** a ranking of the two
-skills. It is a consequence of context budget: a fresh `brainstorm`
-is high-context work the orchestrator cannot compact on its own (see
-trigger 4), whereas a test-specifiable item is bounded. Do not let
-that asymmetry harden into a reflex of routing borderline items to
-`brainstorm` "to be safe" — that is the exact bias this reflection
-exists to break; apply the design-line test honestly each time. The
-one principled tilt is two-sided and lives *inside* the test, not
-above it: genuine doubt about whether one assertion can pin the
-behaviour *is itself* the design-fork signal, so it resolves to
-`brainstorm` — not because `brainstorm` is preferred, but because
-unresolved ambiguity is a fork by definition. A `tdd` bounce-back
-also fires reactively: if `tdd` later reports the behaviour was not
-test-specifiable after all, that escalation routes to `brainstorm`
-and — being a new cycle that needs a fresh spec — is a bounce-back
-to the user per the same trigger 4.
+The asymmetry in autonomy — `tdd` and `specify` dispatch proceed, a
+fresh `brainstorm` cycle bounces back — is **not** a ranking of the
+skills. It is a consequence of context budget: `tdd` and `specify` are
+both bounded (no open Q&A), whereas a fresh `brainstorm` is high-context
+discovery the orchestrator cannot compact on its own (see trigger 4).
+`specify` dispatched in `/boss` still pauses at its own Step-6
+user-review gate to take sign-off — that is a final-sign-off notify, not
+a pre-dispatch checkpoint. Do not let the asymmetry harden into a reflex
+of routing borderline items to `brainstorm` "to be safe" — that is the
+exact bias this reflection exists to break; apply the design-line test
+honestly each time. The one principled tilt is two-sided and lives
+*inside* the test: genuine doubt about whether the sources (or one
+assertion) can pin the design *is itself* the design-fork signal, so it
+resolves to `brainstorm` — not because `brainstorm` is preferred, but
+because unresolved ambiguity is a fork by definition. A `specify` or
+`tdd` bounce-back also fires reactively: if either later reports the
+design was not settled / not test-specifiable after all, that escalation
+routes to `brainstorm` and — being a new cycle needing a fresh
+discovery — is a bounce-back to the user per the same trigger 4.
-If the profile does **not** enable the `tdd` phase, `brainstorm` is
-the only design entry path and the reflection collapses to it; a new
-feature cycle with no spec always bounces back first.
+If the profile does **not** enable the `tdd` phase, the reflection is
+two-way — `specify` for a settled design, `brainstorm` for an open one.
+`specify` is a core node (never profile-gated), so the settled-design
+path is always available; only the `tdd` test-specifiable branch is
+opt-in.
If the working tree is mid-flight (uncommitted changes left over
from a previous session): inspect first, then resume the right
@@ -327,7 +332,8 @@ actionable ask, not a wrap-up summary.
| "Notify can name the iteration code — user will figure out what it means" | No. The notify text is for the user-as-reader who did not watch the orchestrator work. Iteration codes, crate names, function identifiers, type names — all internal, all banned. |
| "The previous cycle closed cleanly and the next backlog item is obvious — just dispatch `brainstorm` and keep going" | No. Starting a new cycle is itself a bounce-back. A fresh `brainstorm` is high-context work, and the orchestrator cannot compact its own context — only the user can decide whether the next cycle wants a fresh session or a continuation of this one. The "obviousness" of the candidate is irrelevant; the *cross-cycle hop* is the checkpoint, not the topic choice. |
| "It's the same broad area as the cycle I just closed, that's not really a new cycle" | If there is no spec file for it yet and it would route through `brainstorm` to get one, it IS a new cycle for this rule's purposes. The rule keys on "needs a fresh spec", not on subjective continuity. |
-| "Feature work, so route it to `brainstorm` — that's the safe default" | `brainstorm` and `tdd` are co-equal entry paths on a tdd-enabled profile; neither is the default. Routing a test-specifiable item to `brainstorm` "to be safe" is the exact bias to break — run the Entry-path reflection and pick by the design line. The only tilt toward `brainstorm` is when one honest assertion genuinely cannot pin the behaviour, and that is a design fork, not a default. |
+| "Feature work, so route it to `brainstorm` — that's the safe default" | `brainstorm`, `specify`, and `tdd` are co-equal entry paths; none is the default. Routing a settled design to `brainstorm` re-litigates decided choices; routing a test-specifiable item there wastes the test path. Run the Entry-path reflection and pick by the design line. The only tilt toward `brainstorm` is a genuinely unresolved fork — and that is a fork, not a default. |
+| "The issue is exhaustive but it's a new cycle, so bounce to the user before `specify`" | `specify` direct-entry is bounded and autonomously dispatchable — it is NOT the high-context `brainstorm` cycle that trigger 4 reserves for the user. Dispatch it; it will pause at its own user-review gate for sign-off. The pre-dispatch bounce is for an *open* design that needs discovery, not for a settled one that needs only production. |
| "`tdd` is opt-in / profile-gated, so it's the secondary skill" | Profile-gating is about whether the path is *available*, not about rank. Once enabled, the choice between the two is decided by fit per item, reflected on each time — not by treating `brainstorm` as primary and `tdd` as the exception. |
## Red Flags — STOP
@@ -338,7 +344,7 @@ actionable ask, not a wrap-up summary.
- About to send a notify that names a crate, an iteration code, or an agent.
- About to bounce back at every iteration boundary "just to be safe" — that's reactive deference, not direction freedom.
- About to dispatch `brainstorm` on a backlog issue that does not yet have a spec file, without first bouncing back to the user. New cycles never start autonomously.
-- About to route feature work to `brainstorm` without running the Entry-path reflection — defaulting to it because it "feels safer" than `tdd`, rather than applying the design-line test. On a tdd-enabled profile the two are co-equal; the choice is reflected on each time.
+- About to route feature work to `brainstorm` without running the Entry-path reflection — defaulting to it because it "feels safer" than `specify` or `tdd`, rather than applying the design-line test. The three are co-equal; the choice is reflected on each time. Routing a *settled* design to `brainstorm` (re-litigating decided choices) is as much a failure as skipping discovery on an open one.
## Cross-references
@@ -356,6 +362,8 @@ actionable ask, not a wrap-up summary.
- **Glossary write-rule:** `../docs/glossary-convention.md` —
record-reality discipline for the only autonomous glossary writer.
- **Downstream skills dispatched:** `../brainstorm`,
- `../planner`, `../implement`, `../audit`, `../fieldtest`,
- `../debug`, `../tdd` (test-specifiable feature, profile-gated;
- autonomously dispatchable like `../debug`), `../docwriter`.
+ `../specify` (spec-production core; autonomously dispatchable for a
+ settled design), `../planner`, `../implement`, `../audit`,
+ `../fieldtest`, `../debug`, `../tdd` (test-specifiable feature,
+ profile-gated; autonomously dispatchable like `../debug`),
+ `../docwriter`.
diff --git a/brainstorm/SKILL.md b/brainstorm/SKILL.md
index 40460e1..540c72b 100644
--- a/brainstorm/SKILL.md
+++ b/brainstorm/SKILL.md
@@ -1,6 +1,6 @@
---
name: brainstorm
-description: Use when a new cycle is starting — gathers requirements, explores 2-3 approaches with trade-offs, presents a sectioned design with user approval, writes the spec under paths.spec_dir. Hard-gate before any plan or code work; applies even when the user says they have a clear vision.
+description: Use when a new cycle is starting and the design is NOT yet settled — gathers requirements, explores 2-3 approaches with trade-offs, presents a sectioned design with user approval, then hands the ratified design to the specify skill to produce the spec. The optional discovery front-end; when the design is already settled in the sources, skip to specify directly. Applies even when the user says they have a clear vision.
---
# brainstorm — cycle spec generator
@@ -9,14 +9,20 @@ description: Use when a new cycle is starting — gathers requirements, explores
## Overview
-The spec is where the orchestrator does the design work. It
-is the artefact that future iterations, the architect agent,
-and any future reader read to understand WHAT the cycle
-delivers and WHY. Skipping the spec means shipping the user's
-intuition unfiltered, which is exactly the reactive-deference
-failure mode the orchestrator discipline exists to prevent.
+Discovery is where the orchestrator does the *deciding* work —
+surfacing requirements, exploring approaches, and ratifying a design
+with the user. It is the front-end that resolves a genuine design fork
+before any spec is written. Skipping it when the design is genuinely
+open means shipping the user's intuition unfiltered, which is exactly
+the reactive-deference failure mode the orchestrator discipline exists
+to prevent.
-It produces specs under the project's `paths.spec_dir`.
+`brainstorm` does not write the spec. Its terminal state is handing the
+ratified design to `specify` (the spec-production core), which applies
+the acceptance criterion, writes the spec under `paths.spec_dir`, runs
+the gates, and takes user sign-off. When the design is *already*
+settled in the sources, `brainstorm` is skipped entirely and the work
+enters through `specify` directly.
## When to Use / Skipping
@@ -28,37 +34,28 @@ Triggers:
- A cycle-scope spec is missing for an existing line of
work and one is needed retroactively.
-**Skipping is permitted only** for:
+**Skip `brainstorm` (enter through the named alternative) for:**
-- A bug-fix iteration (use `debug` directly).
-- A test-specifiable feature, on a project whose profile
- enables the `tdd` phase (use `tdd` directly — the RED
- executable-spec is the spec, no prose spec needed). The
- boundary is the design line: the moment one honest minimal
- assertion cannot pin the behaviour without choosing between
- plausible designs, `tdd` bounces back here.
-- A tidy iteration (use `audit` directly).
-- A trivial mechanical edit (per the project's CLAUDE.md
- "trivial mechanical edits" carve-out).
+- A design already settled in the sources — an exhaustive issue, a
+ long in-context discussion, settled design docs. Use `specify`
+ directly: discovery would only re-litigate decisions the sources
+ already made.
+- A test-specifiable feature, on a profile that enables `tdd` — use
+ `tdd` directly.
+- A bug-fix iteration — use `debug` directly.
+- A tidy iteration — use `audit` directly.
+- A trivial mechanical edit — per the project's CLAUDE.md carve-out.
-**Skipping is not permitted** for:
+**Do not skip `brainstorm`** when the design is genuinely open:
-- A user request framed as "I have a clear vision, just plan
- it".
-- A cycle described as "small, only two iterations".
-- A cycle where you are confident you know what to build.
+- A user request framed as "I have a clear vision, just plan it" whose
+ vision still hides an unresolved fork.
+- A cycle where a load-bearing decision is not yet made.
-## The Hard-Gate
-
-```
-NO IMPLEMENTATION, SCAFFOLDING, OR DOWNSTREAM SKILL INVOCATION
-UNTIL A SPEC HAS BEEN PRESENTED AND THE USER HAS APPROVED IT.
-```
-
-The hard-gate applies regardless of perceived simplicity.
-The spec can be short for a small cycle (a few sections),
-but it MUST exist and be approved before any plan or code
-work begins.
+The discriminator is the design line: if the sources resolve every
+load-bearing decision, the work belongs to `specify`; if writing the
+spec would force you to *pick* one, discovery is what resolves it, and
+that is `brainstorm`.
## The Process
@@ -76,7 +73,7 @@ Before asking any clarifying questions:
`validated-against` frontmatter if present: `status:
aspirational` means its code is a target, not verified fact.
Track which content you may lift from such a source — it is
- flagged for lift-time validation (Step 4).
+ flagged for lift-time validation when `specify` writes the spec.
- `git log --oneline -20` for the chronological scan.
- Identify scope: is this one cycle, or does it need to be
decomposed into sub-cycles first? If multi-subsystem,
@@ -117,54 +114,7 @@ approach gets:
Wait for user choice before proceeding.
-### Step 4 — Apply the project's feature-acceptance criterion
-
-The project's `CLAUDE.md` declares the criterion a feature
-must satisfy to ship. Apply it now, prospectively. The
-typical shape is some combination of:
-
-- the project's intended audience naturally reaches for the
- feature,
-- the feature measurably improves correctness or removes
- redundancy,
-- the feature reintroduces no class of failure the project's
- core constraint exists to eliminate.
-
-If the project does not declare a criterion, the default is
-"the feature solves a real user-facing problem and does not
-contradict a stated design commitment". The orchestrator
-applies the criterion; do not delegate it to the user.
-
-**The criterion is unjudgeable without concrete code.** For
-any cycle with authoring or consumer surface, the spec MUST
-contain the actual program / invocation / configuration a
-user would write — and that example *is* the criterion's
-empirical evidence. A prose assertion ("a user naturally
-reaches for X") with no shown code is exactly the
-unfalsifiable hand-wave the criterion exists to prevent:
-write the code the user would write, then judge whether it
-is in fact what the criterion demands. For an infrastructure
-cycle with **no** user surface there is still concrete code:
-show the actual code the cycle *delivers* — frequently a
-test fixture whose correct behaviour is rejection (wrong
-code must fail the relevant check) — plus a *minimal,
-honest* slice of the north-star program the infrastructure
-exists to serve. "This cycle has no surface so there's no
-code to show" is the rationalisation to refuse: an infra
-cycle that cannot be tied to concrete code is speculative
-infra.
-
-**Code lifted from an aspirational source is a hypothesis, not
-evidence.** If the concrete code here is lifted from a
-`design_models` file (or any source marked `status: aspirational`,
-per Step 1), it carries no validation by default — the marker
-exists precisely because no one has run it through the live tool.
-Its `design/` location is not ratification. Treat it as the spec's
-most suspect bytes: it must clear the Step-7 parse-every-block
-gate before PASS. The marker tells you *which* blocks to distrust
-first.
-
-### Step 5 — Present design in sections
+### Step 4 — Present design in sections
Scale each section to its complexity (a few sentences if
straightforward, up to 200-300 words if nuanced). Cover:
@@ -175,202 +125,43 @@ straightforward, up to 200-300 words if nuanced). Cover:
- Error handling
- Testing strategy
-**Concrete code is the headline; the implementation shape is
-supporting.** The `## Concrete code shapes` section leads
-with the user-facing program (the Step-4 empirical evidence),
-or — for an infra cycle — the delivered fixture and a
-north-star slice. The before → after implementation shape
-(struct / signature / match-arm) follows as a clearly
-secondary subsection — "also useful, not the point" — never
-first, never a substitute for the user-facing code. Prose may
-*explain* code, never *replace* it. Exact bytes / line-
-numbers remain the planner's job (planner Iron Law) — the
-spec owns the *shape*, shown, with the user-facing program
-foremost.
+The design you present here is conceptual — the architecture,
+components, data flow, error handling, and testing strategy the cycle
+commits to. The concrete user-facing code and the before → after
+implementation shapes are produced downstream, when `specify`
+materialises this ratified design into the spec (and applies the
+acceptance criterion against that worked code). Your job here is to get
+the *design decision* right and ratified, not to write the artefact.
Ask after each section whether it looks right. Be ready to
revisit earlier sections if a later one surfaces a
contradiction.
-### Step 6 — Write the spec
+### Step 5 — Hand off to `specify`
-Path: under `paths.spec_dir`, with a name per the project's
-`naming.policy` (see profile schema). Determine the next
-slot per the policy (e.g. for `stable_per_directory_4digit`:
-look at the latest counter and add 1).
+The terminal state of `brainstorm` is invoking `specify`. NO spec file
+is written here; NO other skill is invoked; NO direct jump to `planner`
+or `implement`.
-Structure:
+Hand off carries the **ratified design narrative**, in-context (same
+orchestrator context — no intermediate artefact):
-```markdown
-#
— Design Spec
+- the approach chosen and why
+- the constraints and invariants surfaced in Q&A
+- the design sections the user ratified (Step 4)
+- the iteration scope ("the first iteration covers section X+Y")
-**Date:** YYYY-MM-DD
-**Status:** Draft — awaiting user spec review
-**Authors:** orchestrator + Claude
-
-## Goal
-## Architecture
-## Concrete code shapes
-## Components
-## Data flow
-## Error handling
-## Testing strategy
-## Acceptance criteria
-```
-
-`## Concrete code shapes` is mandatory and **leads with the
-user-facing program**: the worked author example for a
-surface cycle (= the Step-4 empirical evidence), or — for a
-no-surface infra cycle — the code the cycle *delivers* (often
-a must-fail fixture) plus a minimal honest north-star slice
-(Step 4). The before → after implementation shape for each
-load-bearing change follows as an explicitly secondary
-subsection, never first.
-
-### Step 7 — Self-review
-
-Inline checklist (not a subagent dispatch):
-
-1. **Placeholder scan:** any "TBD", "TODO", incomplete
- sections, vague requirements? Fix.
-2. **Internal consistency:** sections must not contradict.
- Architecture must match component descriptions.
-3. **Scope check:** focused enough for one plan, or does it
- need sub-cycle decomposition?
-4. **Ambiguity check:** could any requirement be interpreted
- two ways? If so, pick one and make it explicit.
-5. **Concrete-code check:** does `## Concrete code shapes`
- exist and carry before → after code for every load-bearing
- change (plus the worked user-facing example for a surface
- cycle)? A load-bearing change described only in prose is
- a self-review failure to fix, exactly like a placeholder.
-6. **Parse-every-block gate.** Extract every fenced code block
- from the spec and run it through the `spec_validation` gate
- defined in `docs/profile-schema.md` (which owns the
- parser-invocation protocol, the noted no-parser skip, the
- malformed-entry failure, and the no-op when the profile
- declares no `spec_validation`). A parse failure here is a
- self-review failure — the spec inlines code that does not
- parse against the live tool — fix the spec before proceeding;
- do not pass the unparsed bytes downstream. Paste the
- parse-trace into the brainstorm chat: a visible trace attests
- the gate fired; its absence means it was skipped.
-
-Fix issues inline. No need to re-review — fix and commit.
-
-### Step 7.5 — Grounding-check (hard-gate)
-
-Dispatch the read-only `grounding-check` agent. The agent
-reads the just-written spec with fresh context, extracts its
-load-bearing assumptions about *current* behaviour of the
-codebase (compiler, type-checker, runtime, schema, API,
-whatever the project owns), and for each one searches the
-workspace for a currently-green test that ratifies it.
-
-Dispatch carrier — the fields `spec_path` and `iteration_scope`,
-defined authoritatively under **Carrier contract** in
-`agents/grounding-check.md` (note `spec_path` is an *absolute*
-path). That table is the single source for those fields; it is
-deliberately not restated here, so the two files cannot drift.
-
-The agent returns a `PASS` / `BLOCK` / `INFRA_ERROR` report.
-Orchestrator interpretation:
-
-| Agent status | Orchestrator action |
-|--------------|---------------------|
-| `PASS` | Proceed to Step 8. The report goes into the brainstorm chat for the record. |
-| `BLOCK` | Present the report to the user. User either: (a) accepts discard → execute the failure-mode procedure below; or (b) overrides in free chat ("Test `::` ratifies that") → log the override note in the brainstorm chat and proceed to Step 8. |
-| `INFRA_ERROR` | Abort the brainstorm. The spec stays as-is on disk; debug the workspace out-of-band and re-dispatch the agent. |
-
-**Failure-mode procedure (no-override `BLOCK`):**
-
-1. Delete the just-written spec file from the working tree
- (`rm ` — a shell delete on the working tree,
- NOT `git rm`; the file was never committed).
-2. Open a backlog issue (via the project's issue-tracker
- create command — `tea issues create` for Gitea,
- `gh issue create` for GitHub, analogous for Linear /
- Jira / etc.) pointing forward to a future re-brainstorm.
- Include in the issue:
-
- - **Title:** one-line identity of the deferred work
- - **Label:** matching the project's vocabulary (often
- `feature` / `bug` / `idea`; promote to `BLOCKER` if
- the unratified mechanism is on a core-functionality
- path)
- - **Body:** short description, plus two structured
- lines:
- - `depends on: `
- - `context: `
-
- If the deferred work is large enough to need its own
- spec on resumption — multi-iteration scope, cross-
- subsystem — file it as a **milestone container**
- instead (Gitea milestones, GitHub milestones, Linear
- projects, whatever the project's tracker calls a
- long-running work scope), not as a single issue.
-
-3. Tell the user the spec was retired and which backlog
- entry was filed (include the issue or milestone number).
- No commit is needed for the backlog entry — the issue
- tracker is the live store.
-
-After the failure-mode procedure runs, the brainstorm
-session ENDS. There is no Step 8, no Step 9. The idea is
-parked until the dependency ships, at which point a fresh
-brainstorm session re-derives the spec from scratch.
-
-**Re-dispatch on any post-PASS edit.** The grounding-check
-PASS report is bound to the exact bytes of the spec at
-dispatch time. Any subsequent edit to the spec file —
-orchestrator-side polish, a user-requested change in free
-chat, a wording tighten, anything — invalidates the PASS
-report and requires a fresh dispatch of `grounding-check`
-before Step 8 commit. Step 7.5 is the *last* step that
-touches the spec file; nothing slips between it and the
-commit.
-
-### Step 8 — User-review gate
-
-The spec sits in the working tree as an unstaged file. Tell
-the user:
-
-> Spec written to `` (uncommitted). Please review it
-> and let me know if you want changes before we start the
-> implementation plan. The orchestrator will commit it once
-> you approve.
-
-Wait for the user's response. If they request changes, edit
-the file in place (still uncommitted), **re-run Step 7 AND
-re-dispatch Step 7.5** (the previous PASS report no longer
-covers the edited bytes), then return here. Only proceed to
-the next step after approval AND a fresh Step 7.5 PASS.
-
-The orchestrator commits the approved spec after the user
-signs off (suggested commit subject: `spec:
-`). The brainstorm skill does not perform the commit
-itself.
-
-### Step 9 — Hand off to `planner`
-
-The terminal state of `brainstorm` is invoking `planner`. NO
-other skill is invoked from `brainstorm`. NO direct jump to
-`implement`.
-
-Hand off carries:
-
-- path to the spec under `paths.spec_dir`
-- iteration scope ("the first iteration covers section X+Y
- of the spec")
+`specify` reads this narrative as its source, applies the
+acceptance criterion, writes the spec, runs the parse and
+grounding-check gates, takes user sign-off, and hands off to `planner`.
+The production gates live there, not here.
## Handoff Contract
| Direction | Carrier |
|-----------|---------|
-| user → `brainstorm` | new cycle request |
-| `brainstorm` → `grounding-check` (Step 7.5) | `spec_path` + `iteration_scope` |
-| `brainstorm` → `planner` (Step 9, on PASS or overridden BLOCK) | path to spec + iteration scope |
-| `brainstorm` → issue backlog (Step 7.5, on no-override BLOCK) | new issue opened via the project's issue-tracker create command naming the unratified dependency; spec file deleted from the working tree (no commit needed) |
+| user → `brainstorm` | new cycle request with a genuinely open design |
+| `brainstorm` → `specify` (Step 5) | ratified design narrative (approach, constraints, ratified sections, iteration scope) — in-context; no spec file written |
## Common Rationalisations
@@ -382,10 +173,6 @@ Hand off carries:
| "User is busy, present my own design without Q&A" | Reactive deference disguised as decisiveness. The Q&A surfaces constraints the user hasn't articulated; skipping it means shipping the user's defaults, not their intent. |
| "Spec exists from previous cycle, append to it" | New cycle = new spec file. The architect agent reads spec files per cycle; mixing scopes makes drift review unreadable. |
| "Approaches A, B, C are all bad — proceed with A" | This is exactly the moment to surface "the problem is mis-framed" rather than ratify a known-bad shape into the design ledger. Escalate to the user. |
-| "Just polishing a wording after PASS, no need to re-dispatch" | The grounding-check report attests to specific bytes. A polish edit changes the bytes; the previous attestation no longer covers them. Re-dispatch is cheap; the alternative is a commit with an attestation that doesn't match the file. |
-| "The shape is clear from the prose, I don't need to paste the code" | If it's clear, pasting it is free; if pasting it is hard, it wasn't clear. The feature-acceptance criterion is unjudgeable without the worked code; "a user reaches for it" with no shown code is the exact hand-wave the criterion exists to kill. |
-| "The block obviously parses — I wrote it carefully" | Careful authoring is not a parse. A spec's code blocks are hypotheses until the live tool accepts them; treating them as truth is the compound-hallucination failure the parse-every-block gate exists to kill. If a parser is configured for the block's fence label, run it and paste the trace. |
-| "It's in a model doc / the design ledger, so it's canonical" | A `models` / RFC / proposal doc holds aspirational code — a target, not verified fact; its `design/` location is not ratification. Code lifted from a `status: aspirational` source must clear the Step-7 parse gate like any other block, and is in fact the most suspect bytes in the spec. |
## Red Flags — STOP
@@ -393,42 +180,24 @@ Hand off carries:
- "One paragraph is enough"
- "User said it's clear, who am I to push back"
- "The 2-3 approaches all suck, just pick one"
-- Skipping Step 7 self-review because "I wrote it carefully"
-- A load-bearing change described in prose with no
- before → after code block; a surface cycle with no worked
- user-facing example
-- A spec carrying a code block whose fence label has a
- configured `spec_validation` parser, committed without a
- parse-trace in the brainstorm chat
-- Lifting code verbatim from a `status: aspirational` source (a
- `models` / RFC / proposal file) into the spec without flagging
- it for the Step-7 parse gate
-- Editing the spec file after a Step 7.5 PASS without
- re-dispatching
-- Jumping straight from spec to `implement` (must go via
- `planner`)
- Inventing a design rationale that's actually about effort,
not semantics
## Cross-references
-- **Output target:** `../planner/SKILL.md` — only valid next
- skill.
-- **Alternative entry path / bounce-back source:**
- `../tdd/SKILL.md` — on profiles that enable it, a
- test-specifiable feature enters through `tdd` instead of
- here; `tdd` bounces the work back to `brainstorm` the moment
- the behaviour stops being test-specifiable (a genuine design
- fork). Such a bounce-back arrives as a normal cycle request.
-- **Agent dispatched:** `agents/grounding-check.md` —
- dispatched in Step 7.5 as a hard-gate. The agent reads the
- spec with fresh context and reports PASS / BLOCK /
- INFRA_ERROR.
-- **Ad-hoc dispatch.** The orchestrator MAY also ad-hoc
- dispatch `../planner/agents/plan-recon.md` during Step 1
- when the cycle enters code territory the orchestrator has
- not recently read; this is opt-in and not part of the
+- **Output target:** `../specify/SKILL.md` — the only valid next
+ skill. `brainstorm` hands the ratified design to `specify`, which
+ produces the spec and gates `planner`. There is no direct
+ `brainstorm → planner` edge any more.
+- **Alternative entry path / bounce-back source:** `../tdd/SKILL.md` —
+ a test-specifiable feature enters through `tdd` instead of here;
+ `tdd` bounces back the moment the behaviour stops being
+ test-specifiable. `../specify/SKILL.md` likewise bounces back here
+ when the sources do not resolve a design fork.
+- **Ad-hoc dispatch.** The orchestrator MAY ad-hoc dispatch
+ `../planner/agents/plan-recon.md` during Step 1 when the cycle
+ enters code territory not recently read; opt-in, not part of the
standard process.
-- **Project feature-acceptance criterion:** declared in the
- project's `CLAUDE.md` (or a contract the CLAUDE.md
- points to). Applied prospectively in Step 4.
+- **Project feature-acceptance criterion:** declared in the project's
+ `CLAUDE.md` — applied prospectively by `specify` (its Step 2), not
+ here.
diff --git a/docs/migration.md b/docs/migration.md
index 163103a..586833f 100644
--- a/docs/migration.md
+++ b/docs/migration.md
@@ -25,6 +25,8 @@ seven skills follow once the pattern is approved.
├── boss/ (pilot: landed)
│ └── SKILL.md
├── brainstorm/
+│ └── SKILL.md
+├── specify/
│ ├── SKILL.md
│ └── agents/
│ └── grounding-check.md
diff --git a/docs/pipeline.md b/docs/pipeline.md
index dd64172..f40c16a 100644
--- a/docs/pipeline.md
+++ b/docs/pipeline.md
@@ -4,10 +4,11 @@
[new cycle] [test-specifiable feature] [bug observed]
| | |
v v v
- brainstorm -> plan -> implement debug -> implement (mini)
- ^ |
- | tdd -> implement (mini)
- +----(design fork)----------/ (RED executable-spec -> GREEN, like a bug fix)
+ brainstorm -> specify -> plan -> implement debug -> implement (mini)
+ ^ ^ |
+ | | tdd -> implement (mini)
+ | specify -> plan (design settled in sources)
+ +----(design fork)----------/ (specify/tdd bounce here; RED executable-spec -> GREEN)
(per iteration loop)
|
[cycle close — a loop step, not a milestone close]
@@ -37,7 +38,7 @@
These are two distinct axes, and conflating them is a bug.
- A **cycle** is one round in the pipeline graph above
- (`brainstorm → planner → implement → audit → [fieldtest]`).
+ (`brainstorm → specify → planner → implement → audit → [fieldtest]`).
A cycle close is an internal loop step.
- A **milestone** is a tracker container (Gitea milestone,
GitHub milestone, Linear project — whatever the project's
@@ -85,9 +86,23 @@ close`); no skill performs it automatically.
### brainstorm
-Hard-gate before plan. Gathers requirements, explores 2-3
-approaches with trade-offs, presents a sectioned design with
-user approval, writes the spec to the configured `spec_dir`.
+Optional discovery front-end. Gathers requirements, explores 2-3
+approaches with trade-offs, presents a sectioned design with user
+approval, then hands the ratified design to `specify` (it writes no
+spec itself). Skipped when the design is already settled in the
+sources — that work enters through `specify` directly.
+
+### specify
+
+Hard-gate before plan — the spec-production core and the carrier of the
+"no plan without an approved spec" invariant. Takes a settled design
+(directly from sources, or a ratified design handed over by
+`brainstorm`), applies the feature-acceptance criterion, writes the
+spec to the configured `spec_dir`, runs the parse-every-block and
+`grounding-check` gates, and takes user sign-off — with review but no
+interview. Bounces to `brainstorm` the moment the sources do not
+resolve a load-bearing design decision. A core node, not opt-in
+(unlike `tdd`).
### planner
@@ -119,7 +134,7 @@ the GREEN side to the implement skill in mini mode.
### tdd
-Opt-in alternative to the `brainstorm → planner` design entry,
+Opt-in alternative to the `brainstorm → specify → planner` design entry,
for work whose desired behaviour is test-specifiable — expressible
as one failing test. RED-first: the `tdd-author` agent turns a
description or issue into a single minimal, autonomous RED
@@ -172,7 +187,11 @@ Reviewer agents have role-specific states:
Skipping is codified per skill, not ad hoc. Each `SKILL.md`
documents what the skill skips and under what conditions:
-- `brainstorm` is never skipped at cycle start.
+- `specify` is never skipped at cycle start — it is the spec-production
+ gate before `planner`. `brainstorm` is the *optional* discovery stage
+ before it: skipped when the design is already settled in the sources
+ (the work enters through `specify` directly), run when a load-bearing
+ decision is still open.
- `planner` is never skipped at iteration start, except for
the bug-driven `debug → implement (mini)` side path.
- `implement` is the iteration body; not skippable.
diff --git a/docs/profile-schema.md b/docs/profile-schema.md
index f415483..35aaade 100644
--- a/docs/profile-schema.md
+++ b/docs/profile-schema.md
@@ -9,7 +9,7 @@ lowercase snake_case. Lists are YAML sequences.
| Key | Type | Default | Description |
|---------------------|--------|------------------------|-------------|
-| `spec_dir` | string | `docs/specs` | Where the brainstorm skill writes specs. |
+| `spec_dir` | string | `docs/specs` | Where the specify skill writes specs. |
| `plan_dir` | string | `docs/plans` | Where the planner skill writes plans. |
| `glossary` | string | (unset) | Canonical-nomenclature file (optional). If set, it is standing reading for every role — no separate `standing_reading.always` entry is needed; unset is a documented no-op. See `glossary-convention.md`. |
| `design_ledger` | string | `docs/design/INDEX.md` | Canonical specification index (optional — projects without a design ledger can omit). |
@@ -188,7 +188,10 @@ Per-phase configuration. Each phase has its own sub-map.
```yaml
pipeline:
brainstorm:
- gates: [planner] # planner cannot start until this has run
+ gates: [specify] # optional discovery; hands ratified design to specify
+ optional: true # skipped when the design is settled in the sources
+ specify:
+ gates: [planner] # core node — planner cannot start until the spec is approved
planner:
gates: [implement]
implement: {} # standard
@@ -207,6 +210,7 @@ pipeline:
debug:
trigger: bug # observable misbehaviour
red_first: true # RED test before any fix
+ # specify above is a CORE node (always present); tdd below is opt-in.
tdd: # opt-in: omit the key to disable the entry path
trigger: test_specifiable_feature # behaviour expressible as one failing test
red_first: true # RED executable-spec before any implementation
@@ -217,8 +221,12 @@ pipeline:
Phases not listed are disabled for the project. A project that
does not want a `fieldtest` phase simply omits the key. `tdd` is
-opt-in the same way: a profile that omits it keeps
-`brainstorm → planner` as the only design entry path.
+opt-in the same way. `specify`, by contrast, is a **core** node — it
+is the spec-production gate before `planner` on every design path,
+reachable directly from settled sources or via the optional
+`brainstorm` discovery stage. `tdd` opt-in only adds the
+test-specifiable bypass; with `tdd` omitted, the design entry paths
+are `brainstorm → specify → planner` and `specify → planner`.
## Example: minimal profile
@@ -247,7 +255,8 @@ git:
close_marker: "closes #N"
pipeline:
- brainstorm: { gates: [planner] }
+ brainstorm: { gates: [specify], optional: true }
+ specify: { gates: [planner] }
planner: { gates: [implement] }
implement: {}
audit: { mandatory_at: cycle_close }
diff --git a/specify/SKILL.md b/specify/SKILL.md
new file mode 100644
index 0000000..0b348c6
--- /dev/null
+++ b/specify/SKILL.md
@@ -0,0 +1,380 @@
+---
+name: specify
+description: Use when the design is already settled — a long in-context design discussion, an exhaustive tracker issue, or a ratified design handed over by brainstorm — and a spec must be produced from those sources with review but without an interview. The spec-production core: applies the feature-acceptance criterion, writes the spec under paths.spec_dir, runs the parse and grounding-check gates, takes user sign-off, hands off to planner. Bounces to brainstorm the moment the sources do not resolve a load-bearing design decision. Co-equal third entry path alongside brainstorm and tdd.
+---
+
+# specify — spec-production entry path
+
+> **Violating the letter of these rules is violating the spirit.**
+
+## Overview
+
+`specify` is where a settled design becomes an approved spec. It
+takes **given sources** — a long in-context design discussion, an
+exhaustive tracker issue, settled design docs, or a ratified design
+narrative handed over by `brainstorm` — and produces the spec the
+planner consumes: with review, but **without an interview**.
+
+It is the **sole home of the spec-production gates**: the
+feature-acceptance criterion, the write-spec step, the
+parse-every-block self-review, the `grounding-check` hard-gate, and
+the user-review gate. Whichever way design work enters — fresh
+through `brainstorm`'s discovery, or directly from sources that
+already resolve the design — it passes through `specify` to become a
+spec. `specify` carries the universal invariant **no plan without an
+approved spec**.
+
+`specify` is the *producing* half of a deliberate split. `brainstorm`
+owns *deciding* — interview, approaches, ratification. `specify` owns
+*producing* — rendering that decision into the canonical artefact and
+clearing the gates. The split is the toolchain's deepest discipline
+applied one level up: `tdd → implement` and `debug → implement` split
+RED from GREEN across two dispatches so the spec stays honest;
+`specify` splits deciding from producing so the producing phase reads
+the decision as a *source* rather than making it inline.
+
+This skill is **not** opt-in. Unlike `tdd` (a profile-gated bypass),
+`specify` is a core pipeline node: it is the gate before `planner` on
+every design path that is not a bug fix or a test-specifiable feature.
+
+## When to Use / Skipping
+
+Triggers:
+
+- The design is settled in the sources and a spec must be written:
+ an exhaustive issue body, a long in-context design discussion, or
+ a ratified design `brainstorm` just handed over.
+- A cycle-scope spec is missing for settled work and one is needed.
+
+**Use the named alternative instead for:**
+
+- A genuine design fork — the sources do **not** resolve a
+ load-bearing decision. Use `brainstorm` (its discovery is what
+ resolves the fork). `specify` itself bounces here the moment it
+ detects this (see The Iron Law and Step 1.5).
+- A test-specifiable feature, on a profile that enables `tdd` — the
+ RED executable-spec is the spec. Use `tdd` directly.
+- An observed bug — use `debug` directly (RED-first).
+- A tidy iteration — use `audit` directly.
+- A trivial mechanical edit — per the project's CLAUDE.md carve-out.
+
+**Skipping a gate is never permitted.** The interview is `brainstorm`'s,
+and its absence here is the whole point — but the *production gates*
+(criterion, parse-every-block, grounding-check, user-review) are
+non-negotiable regardless of how the work entered. "The issue looks
+exhaustive, skip the grounding-check" is the reactive-deference failure
+this skill must not reintroduce.
+
+## The Iron Law
+
+```
+THE SOURCES MUST RESOLVE EVERY LOAD-BEARING DESIGN DECISION BEFORE THE SPEC IS WRITTEN.
+IF WRITING THE SPEC FORCES A CHOICE BETWEEN PLAUSIBLE DESIGNS THE SOURCES DO NOT RESOLVE,
+ STOP AND BOUNCE TO brainstorm. DO NOT SILENTLY PICK ONE.
+THE PRODUCTION GATES — ACCEPTANCE CRITERION, PARSE-EVERY-BLOCK, GROUNDING-CHECK, USER-REVIEW —
+ ARE NON-NEGOTIABLE REGARDLESS OF ENTRY PATH.
+NO PLAN, SCAFFOLDING, OR DOWNSTREAM SKILL UNTIL THE SPEC HAS BEEN PRESENTED AND THE USER HAS APPROVED IT.
+```
+
+Every clause is non-negotiable. The precondition gate is what makes
+the no-interview path legitimate rather than merely convenient: it is
+the honest fork-check that `tdd`'s "is this test-specifiable?" is for
+test work.
+
+## The Process
+
+### Step 1 — Explore / re-ground context
+
+Before producing anything, establish what the sources actually say:
+
+- **Direct entry** (from sources): read the sources in full — the
+ tracker issue body, the in-context design discussion, any settled
+ design docs. This IS the design input. Then `git log -5
+ --format=full` for the current state of the project.
+- **Chain entry** (from `brainstorm`): the ratified design narrative
+ is already in-context. Re-ground lightly — fresh `git log`, the
+ files the design touches — rather than re-deriving it.
+- If the project has a design ledger under `paths.design_ledger`,
+ walk to the contracts the work touches. Note any `status:
+ aspirational` source: its code is a target, not verified fact —
+ track it for the Step-4 parse gate.
+
+### Step 1.5 — Precondition gate (bounce-back)
+
+Enumerate the **load-bearing design decisions** the spec must encode
+— the choices that, decided differently, would change what ships.
+For each, ask the honest question:
+
+> Do the sources **resolve** this, or am I about to **pick** it
+> myself?
+
+If every load-bearing decision is resolved by the sources, proceed to
+Step 2. If even one is unresolved — the sources leave a genuine fork
+between plausible designs with real trade-offs — **STOP and bounce to
+`brainstorm`** (see Error handling / The Bounce-Back). Do not silently
+pick one and bake it into the spec; a guessed design ratified into a
+spec is harder to dislodge than an open question, and it is exactly
+the reactive-deference failure the gate exists to prevent.
+
+Genuine doubt about whether the sources resolve a decision *is itself*
+the fork signal — it resolves to a bounce, not to a guess.
+
+### Step 2 — Apply the project's feature-acceptance criterion
+
+The project's `CLAUDE.md` declares the criterion a feature must
+satisfy to ship. Apply it now, prospectively. The typical shape is
+some combination of:
+
+- the project's intended audience naturally reaches for the feature,
+- the feature measurably improves correctness or removes redundancy,
+- the feature reintroduces no class of failure the project's core
+ constraint exists to eliminate.
+
+If the project declares no criterion, the default is "the feature
+solves a real user-facing problem and does not contradict a stated
+design commitment". The orchestrator applies the criterion; do not
+delegate it to the user.
+
+**The criterion is unjudgeable without concrete code.** For any cycle
+with authoring or consumer surface, the spec MUST contain the actual
+program / invocation / configuration a user would write — and that
+example *is* the criterion's empirical evidence. A prose assertion
+("a user naturally reaches for X") with no shown code is the
+unfalsifiable hand-wave the criterion exists to prevent: write the
+code the user would write, then judge whether it is what the criterion
+demands. For an infrastructure cycle with **no** user surface there is
+still concrete code: show the code the cycle *delivers* — frequently a
+test fixture whose correct behaviour is rejection — plus a *minimal,
+honest* slice of the north-star program the infrastructure serves. "No
+surface so no code to show" is the rationalisation to refuse.
+
+**Code lifted from an aspirational source is a hypothesis, not
+evidence.** If the concrete code here is lifted from a `design_models`
+file (or any `status: aspirational` source, per Step 1), it carries no
+validation by default. Treat it as the spec's most suspect bytes: it
+must clear the Step-4 parse-every-block gate before PASS.
+
+### Step 3 — Write the spec
+
+Path: under `paths.spec_dir`, with a name per the project's
+`naming.policy` (see profile schema). Determine the next slot per the
+policy.
+
+Structure:
+
+```markdown
+# — Design Spec
+
+**Date:** YYYY-MM-DD
+**Status:** Draft — awaiting user spec review
+**Authors:** orchestrator + Claude
+
+## Goal
+## Architecture
+## Concrete code shapes
+## Components
+## Data flow
+## Error handling
+## Testing strategy
+## Acceptance criteria
+```
+
+`## Concrete code shapes` is mandatory and **leads with the
+user-facing program**: the worked author example for a surface cycle
+(= the Step-2 empirical evidence), or — for a no-surface infra cycle —
+the code the cycle *delivers* (often a must-fail fixture) plus a
+minimal honest north-star slice. The before → after implementation
+shape (struct / signature / match-arm) for each load-bearing change
+follows as an explicitly secondary subsection, never first. Prose may
+*explain* code, never *replace* it. Exact bytes / line-numbers remain
+the planner's job — the spec owns the *shape*, shown.
+
+### Step 4 — Self-review
+
+Inline checklist (not a subagent dispatch):
+
+1. **Placeholder scan:** any "TBD", "TODO", incomplete sections,
+ vague requirements? Fix.
+2. **Internal consistency:** sections must not contradict.
+ Architecture must match component descriptions.
+3. **Scope check:** focused enough for one plan, or does it need
+ sub-cycle decomposition?
+4. **Ambiguity check:** could any requirement be read two ways? Pick
+ one and make it explicit.
+5. **Concrete-code check:** does `## Concrete code shapes` exist and
+ carry before → after code for every load-bearing change (plus the
+ worked user-facing example for a surface cycle)? A load-bearing
+ change described only in prose is a self-review failure to fix.
+6. **Parse-every-block gate.** Extract every fenced code block and run
+ it through the `spec_validation` gate defined in
+ `docs/profile-schema.md` (which owns the parser-invocation
+ protocol, the no-parser skip, the malformed-entry failure, and the
+ no-op when the profile declares no `spec_validation`). A parse
+ failure is a self-review failure — fix the spec; do not pass
+ unparsed bytes downstream. Paste the parse-trace into the chat: a
+ visible trace attests the gate fired; its absence means it was
+ skipped.
+
+Fix issues inline.
+
+### Step 5 — Grounding-check (hard-gate)
+
+Dispatch the read-only `grounding-check` agent. The agent reads the
+just-written spec with fresh context, extracts its load-bearing
+assumptions about *current* behaviour of the codebase, and for each
+searches the workspace for a currently-green test that ratifies it.
+
+Dispatch carrier — the fields `spec_path` and `iteration_scope`,
+defined authoritatively under **Carrier contract** in
+`agents/grounding-check.md` (note `spec_path` is an *absolute* path).
+That table is the single source for those fields; it is deliberately
+not restated here, so the two files cannot drift.
+
+The agent returns `PASS` / `BLOCK` / `INFRA_ERROR`. Interpretation:
+
+| Agent status | Orchestrator action |
+|--------------|---------------------|
+| `PASS` | Proceed to Step 6. The report goes into the chat for the record. |
+| `BLOCK` | Present the report to the user. User either: (a) accepts discard → execute the failure-mode procedure below; or (b) overrides in free chat ("Test `::` ratifies that") → log the override note and proceed to Step 6. |
+| `INFRA_ERROR` | Abort. The spec stays as-is on disk; debug the workspace out-of-band and re-dispatch the agent. |
+
+**Failure-mode procedure (no-override `BLOCK`):**
+
+1. Delete the just-written spec file from the working tree
+ (`rm ` — a shell delete, NOT `git rm`; never committed).
+2. Open a backlog issue (via the project's issue-tracker create
+ command) pointing forward to a future re-design. Include:
+ - **Title:** one-line identity of the deferred work
+ - **Label:** matching the project's vocabulary (`feature` / `bug`
+ / `idea`; promote to `BLOCKER` if the unratified mechanism is on
+ a core-functionality path)
+ - **Body:** short description plus two structured lines:
+ - `depends on: `
+ - `context: `
+
+ If the deferred work needs its own spec on resumption
+ (multi-iteration, cross-subsystem), file it as a **milestone
+ container** instead of a single issue.
+3. Tell the user the spec was retired and which backlog entry was
+ filed. No commit is needed — the issue tracker is the live store.
+
+After the failure-mode procedure runs, the session ENDS. There is no
+Step 6, no Step 7. The idea is parked until the dependency ships.
+
+**Re-dispatch on any post-PASS edit.** The PASS report is bound to the
+exact bytes of the spec at dispatch time. Any subsequent edit — polish,
+a user-requested change, a wording tighten — invalidates the PASS
+report and requires a fresh dispatch of `grounding-check` before the
+Step-6 sign-off and commit. Step 5 is the *last* step that touches the
+spec file; nothing slips between it and the commit.
+
+### Step 6 — User-review gate
+
+The spec sits in the working tree as an unstaged file. Tell the user:
+
+> Spec written to `` (uncommitted). Please review it and let me
+> know if you want changes before we start the implementation plan.
+> The orchestrator will commit it once you approve.
+
+Wait for the user's response. If they request changes, edit the file
+in place (still uncommitted), **re-run Step 4 AND re-dispatch Step 5**
+(the previous PASS report no longer covers the edited bytes), then
+return here. Only proceed after approval AND a fresh Step 5 PASS.
+
+The orchestrator commits the approved spec after sign-off (suggested
+commit subject: `spec: `). The skill does not perform
+the commit itself.
+
+**In `/boss` (autonomous):** `specify` is dispatched autonomously —
+it is bounded (no interview). It runs the criterion, parse, and
+grounding-check gates without a checkpoint, then **pauses here** as a
+problem-state notify ("spec X ready, please sign off"). This is the
+final sign-off pause, not a pre-dispatch checkpoint — the distinction
+from `brainstorm`, which `/boss` bounces *before* dispatch.
+
+### Step 7 — Hand off to `planner`
+
+The terminal state of `specify` is invoking `planner`. NO other skill
+is invoked from `specify`. NO direct jump to `implement`.
+
+Hand off carries:
+
+- path to the spec under `paths.spec_dir`
+- iteration scope ("the first iteration covers section X+Y of the
+ spec")
+
+## The Bounce-Back
+
+`specify` returns to `brainstorm` whenever the precondition fails — the
+sources do not resolve a load-bearing design decision (Step 1.5), or a
+`grounding-check` `BLOCK` reveals an unratified mechanism the user does
+not override (Step 5 failure-mode routes to a re-design). On a
+precondition bounce:
+
+1. Nothing was written yet (the gate fires *before* Step 3), so there
+ is no working-tree artefact to discard.
+2. Invoke `brainstorm` with the unresolved design question as the
+ cycle request. From there the normal `brainstorm → specify →
+ planner` path runs.
+
+The bounce-back is not a failure of this skill; it is the skill
+correctly refusing to ratify an un-chosen design into a spec — the same
+discipline `tdd` applies when behaviour is not test-specifiable.
+
+## Handoff Contract
+
+| Direction | Carrier |
+|-----------|---------|
+| user / issue (design settled) → `specify` | the sources: issue body, in-context design discussion, design docs |
+| `brainstorm` → `specify` | ratified design narrative (approaches chosen, constraints, sections approved) — in-context; brainstorm writes no spec file |
+| `specify` → `grounding-check` (Step 5) | `spec_path` (absolute) + `iteration_scope` |
+| `specify` → `planner` (Step 7, on PASS or overridden BLOCK) | path to spec + iteration scope |
+| `specify` → `brainstorm` (precondition bounce) | the unresolved design question as a cycle request; no spec written |
+| `specify` → issue backlog (Step 5, no-override BLOCK) | new issue naming the unratified dependency; spec file deleted from the working tree |
+
+## Common Rationalisations
+
+| Excuse | Reality |
+|--------|---------|
+| "The issue looks exhaustive — skip the grounding-check / criterion too" | The interview is what `specify` skips, by design. The production gates are not the interview; they are what keeps the spec honest no matter how it entered. Skipping a gate because the sources look thorough is the exact reactive-deference failure this skill must not reintroduce. |
+| "There's a small open fork but the sources mostly decide it — I'll pick the rest" | "Mostly decided" with one real fork left is an unresolved design, and a guessed design baked into a spec is harder to dislodge than an open question. That is the bounce-back trigger — stop and go to `brainstorm`. |
+| "Genuine doubt whether the sources resolve this — but bouncing feels like overkill" | Doubt about whether the sources resolve a decision *is* the fork signal. It resolves to a bounce, not a guess. The bounce is cheap (nothing is written yet); a wrong guess in a ratified spec is not. |
+| "The shape is clear from the prose, I don't need to paste the code" | If it's clear, pasting it is free; if pasting it is hard, it wasn't clear. The acceptance criterion is unjudgeable without the worked code. |
+| "The block obviously parses — I wrote it carefully" | Careful authoring is not a parse. A spec's code blocks are hypotheses until the live tool accepts them. If a parser is configured for the fence label, run it and paste the trace. |
+| "Just polishing a wording after PASS, no need to re-dispatch" | The grounding-check report attests to specific bytes. A polish edit changes the bytes; the attestation no longer covers them. Re-dispatch is cheap. |
+| "It's in a model doc / the design ledger, so it's canonical" | A `models` / RFC / proposal doc holds aspirational code — a target, not verified fact. Code lifted from a `status: aspirational` source must clear the Step-4 parse gate like any other block. |
+
+## Red Flags — STOP
+
+- An unresolved design fork silently picked instead of bounced (any flavour)
+- "The sources are thorough, skip a gate" thoughts (any flavour)
+- A load-bearing change described in prose with no before → after code
+ block; a surface cycle with no worked user-facing example
+- A spec carrying a code block whose fence label has a configured
+ `spec_validation` parser, committed without a parse-trace in the chat
+- Lifting code verbatim from a `status: aspirational` source without
+ flagging it for the Step-4 parse gate
+- Editing the spec file after a Step 5 PASS without re-dispatching
+- Jumping straight from spec to `implement` (must go via `planner`)
+- Running an interview here (that is `brainstorm`'s job — if the work
+ needs one, bounce)
+
+## Cross-references
+
+- **Output target:** `../planner/SKILL.md` — only valid next skill.
+- **Discovery front-end / bounce-back target:** `../brainstorm/SKILL.md`
+ — produces the ratified design `specify` consumes on the chain path,
+ and reclaims the work when the sources do not resolve a design fork.
+- **Sibling fast path:** `../tdd/SKILL.md` — the same
+ bounce-to-`brainstorm`-on-fork discipline, for test-specifiable work;
+ its RED executable-spec is the spec, so it skips both `specify` and
+ `planner`.
+- **Agent dispatched:** `agents/grounding-check.md` — dispatched in
+ Step 5 as a hard-gate. Reads the spec with fresh context and reports
+ PASS / BLOCK / INFRA_ERROR.
+- **Ad-hoc dispatch.** The orchestrator MAY also ad-hoc dispatch
+ `../planner/agents/plan-recon.md` during Step 1 when the work enters
+ code territory not recently read; opt-in, not part of the standard
+ process.
+- **Project feature-acceptance criterion:** declared in the project's
+ `CLAUDE.md`. Applied prospectively in Step 2.
diff --git a/brainstorm/agents/grounding-check.md b/specify/agents/grounding-check.md
similarity index 93%
rename from brainstorm/agents/grounding-check.md
rename to specify/agents/grounding-check.md
index 53e1bc5..72ad004 100644
--- a/brainstorm/agents/grounding-check.md
+++ b/specify/agents/grounding-check.md
@@ -1,6 +1,6 @@
---
name: grounding-check
-description: Read-only grounding-check reviewer for spec drafts. Dispatched by the brainstorm skill in Step 7.5, between linguistic self-review and user-approval. Reads the draft with fresh context, extracts its load-bearing assumptions about current codebase behaviour, and for each one searches the workspace for a currently-green test that ratifies it; also validates the spec's own fenced code blocks against the project's configured parsers. Reports PASS or BLOCK. Does NOT propose fixes, does NOT edit files.
+description: Read-only grounding-check reviewer for spec drafts. Dispatched by the specify skill in Step 5, between linguistic self-review and user-approval. Reads the draft with fresh context, extracts its load-bearing assumptions about current codebase behaviour, and for each one searches the workspace for a currently-green test that ratifies it; also validates the spec's own fenced code blocks against the project's configured parsers. Reports PASS or BLOCK. Does NOT propose fixes, does NOT edit files.
tools: Read, Glob, Grep, Bash
---
@@ -18,9 +18,9 @@ recover from — multiple prep-iter band-aids before someone
demands that the spec — not the plan — be corrected at the
root.
-This agent is dispatched between the brainstorm's linguistic
+This agent is dispatched between specify's linguistic
self-review (Step 7) and user-approval (Step 8). The
-brainstorm-driven orchestrator has spent 30+ minutes building
+specify-driven orchestrator has spent its budget building
the spec and is biased toward shipping it. You, by contrast,
arrive fresh: no sunk-cost, no investment in the framing.
Your only loyalty is to the question "does the codebase,
@@ -60,9 +60,9 @@ the dispatching skill references it rather than restating it.
| Field | Content |
|-------|---------|
| `spec_path` | absolute path to the spec draft you are checking |
-| `iteration_scope` | which sections of the spec are in scope for the imminent first iteration (verbatim from brainstorm) |
+| `iteration_scope` | which sections of the spec are in scope for the imminent first iteration (verbatim from specify) |
-The controller is the `brainstorm` skill's Step 7.5. You
+The controller is the `specify` skill's Step 5. You
receive the carrier inline in the dispatch prompt; do NOT
open the plan directory or any other spec to "fill in" the
carrier.
@@ -202,9 +202,9 @@ down to one iteration.
| Status | Meaning |
|--------|---------|
-| `PASS` | All extracted load-bearing assumptions ratified. brainstorm proceeds to Step 8. |
-| `BLOCK` | At least one load-bearing assumption is unratified. brainstorm presents the report to the user. |
-| `INFRA_ERROR` | The dispatch cannot complete (spec file missing, type-check broken, etc.). brainstorm aborts; orchestrator debugs out-of-band. |
+| `PASS` | All extracted load-bearing assumptions ratified. specify proceeds to Step 6. |
+| `BLOCK` | At least one load-bearing assumption is unratified. specify presents the report to the user. |
+| `INFRA_ERROR` | The dispatch cannot complete (spec file missing, type-check broken, etc.). specify aborts; orchestrator debugs out-of-band. |
There is no `NEEDS_CONTEXT`. The standing reading list is
the full context you get. If you cannot decide, you flag the
diff --git a/tdd/SKILL.md b/tdd/SKILL.md
index 857e5d8..5f291ca 100644
--- a/tdd/SKILL.md
+++ b/tdd/SKILL.md
@@ -1,6 +1,6 @@
---
name: tdd
-description: Use when a feature description or tracker issue has test-specifiable behaviour — the "how it should work" can be pinned as a single failing test. Authors a minimal RED executable-spec and hands the GREEN side to implement mini-mode, exactly as a bug fix is handled. The alternative entry path to brainstorm→planner for test-specifiable work; bounces back to brainstorm the moment the behaviour is not test-specifiable (genuine design forks). Distinct from the per-task TDD the implementer already practices inside implement.
+description: Use when a feature description or tracker issue has test-specifiable behaviour — the "how it should work" can be pinned as a single failing test. Authors a minimal RED executable-spec and hands the GREEN side to implement mini-mode, exactly as a bug fix is handled. The alternative entry path to brainstorm→specify→planner for test-specifiable work; bounces back to brainstorm the moment the behaviour is not test-specifiable (genuine design forks). Distinct from the per-task TDD the implementer already practices inside implement.
---
# tdd — executable-spec-first entry path
@@ -11,7 +11,7 @@ description: Use when a feature description or tracker issue has test-specifiabl
For work whose desired behaviour is expressible as a test, the
test *is* the spec. This skill is the alternative to the
-`brainstorm → planner` design path: instead of a prose spec the
+`brainstorm → specify → planner` design path: instead of a prose spec the
user approves, it produces a single minimal **RED executable-spec**
that says "this is how it should work", then treats that test
exactly like a bug to be fixed — handing the GREEN side to the
@@ -74,7 +74,7 @@ prevent, and it is no less a failure for being dressed as a test.
This skill is an opt-in entry path. A project enables it by
listing a `tdd` phase in its profile `pipeline:` block (see
`docs/profile-schema.md`); a profile that omits it keeps
-`brainstorm → planner` as the only design entry path.
+`brainstorm → specify → planner` as the only design entry path.
## The Iron Law
@@ -153,7 +153,7 @@ orchestrator:
worse than no test).
2. Invokes `brainstorm` with the design question the agent
surfaced as the cycle request. From there the normal
- `brainstorm → planner → implement` path runs.
+ `brainstorm → specify → planner → implement` path runs.
The bounce-back is not a failure of this skill; it is the skill
correctly refusing to ratify an un-chosen design into a test.
@@ -211,6 +211,11 @@ iteration and gets queued for a separate one.
This is the same mini-mode handoff `../debug/SKILL.md` uses.
- **Bounce-back target:** `../brainstorm/SKILL.md` — reclaims the
work when the behaviour is not test-specifiable.
+- **Sibling fast path:** `../specify/SKILL.md` — the other bounded
+ entry path that shares this skill's bounce-to-`brainstorm`-on-fork
+ discipline. Where `tdd` owns work whose behaviour one assertion can
+ pin, `specify` owns work whose design the sources already resolve;
+ both fall back to `brainstorm` when their precondition fails.
- **Sibling RED-first skill:** `../debug/SKILL.md` — same two-stage
RED→GREEN shape, but triggered by an observed bug rather than a
new-behaviour description.
diff --git a/templates/project-profile.yml b/templates/project-profile.yml
index 94c425c..389d39f 100644
--- a/templates/project-profile.yml
+++ b/templates/project-profile.yml
@@ -67,7 +67,8 @@ notifications:
# command: "" # e.g. "~/.claude/notify.sh"; boss falls back to chat if empty
pipeline:
- brainstorm: { gates: [planner] }
+ brainstorm: { gates: [specify], optional: true } # optional discovery; skipped when design is settled
+ specify: { gates: [planner] } # core node: spec-production gate before planner
planner: { gates: [implement] }
implement: {}
audit: { mandatory_at: cycle_close }