Files
claude fe5ca8f8c0 feat(pipeline): consolidate cycle recon, add fieldtest probe tier, enforce assumption economy
Implements the three efficiency findings from the #310 pipeline
measurement (refs #35): ~691k subagent tokens / ~3.5 h for a
deliberately small cycle, with recon duplication as the single
biggest obligatory per-cycle cost.

1. Cycle recon (pipeline.md § Cycle recon; specify, planner,
   brainstorm, boss, plan-recon): recon fan-out is budgeted per
   cycle, not per phase. One full plan-recon dispatch — normally
   specify Step 1, in a new pre-spec sources/recon_scope carrier
   form — serves both the spec's concrete code shapes and the
   plan's file-map. planner Step 2 becomes reuse-first (freshness /
   quotability / coverage conditions) with narrowly-bounded delta
   dispatches (new Delta dispatch contract in plan-recon.md);
   broad Explore-type grounding sweeps are banned in every mode.
   Field evidence: 151k (Explore) + 99k (plan-recon) with ~40 %
   overlap in one bounded cycle.

2. Fieldtest probe tier (fieldtest, fieldtester, pipeline.md,
   agent-template.md § model rule 2): a cycle whose user-visible
   delta is a single narrow axis dispatches the per-cycle
   fieldtest at tier: probe — 1-2 examples on exactly that axis,
   ~200-word report, explicit model:sonnet dispatch override (no
   dispatch-level effort override exists; frontmatter effort
   applies). Probe is a tier, not a skip; the milestone fieldtest
   always runs full tier on the frontmatter model, keeping the
   milestone-close gate's >=2-example floor unconditional.

3. Assumption economy (specify Step 3 + self-review item 6):
   grounding-check cost scales with the spec's assumption count,
   so specs state current-behaviour claims only where the change
   relies on them (the gate's own falsity test), demote
   context-only mentions to ledger citations, and keep iteration
   scope tight — fewer restatements, never fewer reliances. The
   gate itself is unchanged.

Design reviewed pre-implementation (opus plan review); diff
adversarially verified by a 3-lens review workflow (consistency,
operability, cross-reference), confirmed findings folded in.

refs #35
2026-07-25 13:52:04 +02:00

21 KiB

name, description
name description
brainstorm Use when a new cycle is starting and the design is NOT yet settled — enumerates the load-bearing design forks, populates them with a parallel swarm of grounded synthetic-user stances instead of a serial interview, triages the result (forks the swarm settles on a cited ground are decided; forks it splits on are the user's call), then hands the ratified design to specify. 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 discovery front-end

Violating the letter of these rules is violating the spirit.

Overview

Discovery is where the orchestrator does the deciding work — surfacing the load-bearing forks a new cycle forces, resolving the ones it can ground an answer for, and putting the rest to the user. It is the front-end that settles 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 the orchestrator discipline exists to prevent.

What brainstorm no longer does is run a serial interview — one question per message, a per-section ratification gate — to get there. That ceremony spent ~10 blocking round-trips per cycle to catch a divergence from the orchestrator's recommendation that, across a whole project, materialises about once. Instead brainstorm populates the design space in parallel: it enumerates the forks, dispatches a swarm of grounded, genuinely-opposed synthetic-user stances to answer them, and triages the result. Where the stances converge on a cited common ground the fork was derivable — it is decided, and the user only vetoes. Where they genuinely split, no source settles it — it is a direction fork, and that is the user's call. Direction is never delegated downstream; it is set here, by the user, on exactly the forks that turn out to be theirs.

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 docs/specs, runs the gates, and takes sign-off. When the design is already settled in the sources, brainstorm is skipped entirely and the work enters through specify.

When to Use / Skipping

Triggers:

  • A new cycle is starting (a new feature area, a new subsystem, or a major refactor of an existing one) whose design is genuinely open.
  • A cycle-scope spec is missing for an existing line of work and one is needed retroactively, and the design behind it was never settled.

Skip brainstorm (enter through the named alternative) for:

  • 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 — 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.

Do not skip brainstorm when the design is genuinely open:

  • A 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 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 Iron Law

ENUMERATE EVERY LOAD-BEARING DESIGN FORK BEFORE POPULATING ANYTHING — THIS
  ENUMERATION IS ALSO THE ORCHESTRATOR'S OWN INDEPENDENT SIGNAL, USED LATER TO
  CROSS-CHECK THE SWARM.
A FORK THE SWARM SETTLES ON A *CITED SHARED GROUND* WAS DERIVABLE -> PRESENT IT
  DECIDED (USER VETOES), AND RECORD THE GROUND. A FORK THE SWARM SPLITS ON, OR
  AGREES ON WITH *NO CITABLE GROUND* (UNGROUNDED-CONSENSUS), IS A DIRECTION
  FORK -> THE USER'S CALL. THE LINE IS GROUNDED-DERIVABILITY VS PREFERENCE,
  NOT SMALL VS LARGE, AND NOT BARE AGREEMENT.
A FORK THE ORCHESTRATOR'S OWN ENUMERATION FLAGGED OPEN BUT THE SWARM CLOSED IS
  SURFACED TO THE USER ANYWAY — THE SWARM NEVER ERASES A FORK THE ORCHESTRATOR
  INDEPENDENTLY HELD OPEN.
THE DECIDING WORK IS NEVER SKIPPED. A DESIGN PRESENTED WITHOUT THE FORK
  ENUMERATION + SWARM + TRIAGE DONE IS THE RUBBER-STAMP BETRAYAL, NOT DISCOVERY.
DESIGN DIRECTION IS SET HERE BY THE USER — NEVER DELEGATED TO THE SWARM, NEVER
  TO `specify`.

Every clause is non-negotiable. The swarm is evidence, not an oracle: it populates the space and exposes where stances split, but the convergent-vs- direction verdict is the orchestrator's derivability judgement (the same one specify Step 1.5 applies), and bare agreement among same-model stances is never that judgement — only agreement on a citable ground is.

The Process

Step 1 — Explore project context

Before enumerating anything:

  • git log -5 --format=full for the full bodies of the most recent iter / audit commits — current state of the project.
  • If the project has a design ledger (its CLAUDE.md project facts name it), walk to the relevant contracts for the invariants the new cycle might touch.
  • When reading any file under the project's design models, note its status / validated-against frontmatter if present: status: aspirational means its code is a target, not verified fact. Track which content is 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, decompose.

Step 2 — Enumerate the load-bearing forks

List the load-bearing design forks the cycle forces — the choices that, decided differently, would change what ships — exactly as the clarifying questions you would otherwise have put to the user. Cover at least:

  • Purpose: what problem does this solve?
  • Constraints: what semantic / performance / compatibility invariants must hold?
  • Success criteria: how do we know it shipped?
  • Scope: what is OUT of scope?

For each fork, privately note whether you think it is derivable or genuinely open. This enumeration is the swarm's input and your own independent signal: a fork you flagged open that the swarm later closes is surfaced to the user anyway (the Iron Law cross-check). Do not interview the user here — no serial questions.

Step 2.5 — Fire-check (skip the swarm when it would be ceremony)

The swarm is justified only when there are multiple non-trivial forks whose derivability is genuinely uncertain and there is enough checked-in ground to answer them honestly. Skip it, and resolve inline, when:

  • Too few forks. Zero or one real fork — answer it directly (a single derivable fork is decided and noted; a single open one is one question to the user). Spinning up a swarm for one fork is more machinery than the ceremony it replaced.
  • Grounding floor not met. No design ledger, a thin or absent glossary, an under-specified audience — a greenfield or new-territory project. With nothing to cite, every synthetic stance confabulates and "convergence" is 100% hallucination wearing a quorum. Below this floor the swarm is NOT dispatched; fall back to a direct human interview (and under /boss, that is a bounce-back — see § Under /boss).

Record the skip reason in the cycle's notes / the run's reference issue. The swarm is an optimization for context-rich mature projects, not an unconditional default.

Step 3 — Populate the space with the synthetic-user swarm

Dispatch the read-only agents/synthetic-user.md agent in parallel, one per stance, in a single turn — the same ad-hoc fan-out specify uses for spec-skeptic. (brainstorm's ad-hoc plan-recon is a SINGLE dispatch, never a fan-out — ../docs/pipeline.md § Cycle recon.) No Workflow wrapper: a one-shot stateless fan-out has no re-loop, no ordering, and no in-code verdict to enforce, so it is a direct dispatch, not an implement-loop-style script.

The roster is fixed convention (no per-project config knob; only the grounding — the project's declared audience / ledger / glossary, reached via standing reading — varies):

  • minimalist — convention over config, the smallest change that ships.
  • power-user / composability — capability, extension, what it unlocks.
  • maintainer / future-self — invariants, drift cost, long-term carry.
  • skeptic — does this need to exist at all (the feature-acceptance criterion incarnate).
  • off-ledger wildcard — advocates the direction the project does not imply. Inherently ungrounded by design, so it can only ever surface a fork, never close one; it exists to keep the swarm from collapsing into status-quo unanimity.

Each stance answers the whole fork_set with a mandatory per-answer source citation or an honest ungrounded:true (the agent's Iron Law). The swarm ONLY answers the forks; it never authors approaches.

Step 4 — Triage and present the populated space

This is the one user stop in interactive mode. Cluster the stances' answers per fork and apply the derivability test — the same one specify Step 1.5 uses, measured here against the swarm:

  • Converged on a cited shared ground → DECIDED. Present it as decided with the ground shown; the user only vetoes. Record the ground.
  • Split, or converged with no citable ground (ungrounded-consensus) → DIRECTION FORK. The user's call. Surface the conflicting positions (and the wildcard's off-ledger alternative where it raised one) as the things to weigh. Bare agreement among same-model stances is not a decision — demote it.
  • Cross-check. Any fork your own Step-2 enumeration flagged open that the swarm closed is surfaced anyway, never auto-decided.

Then author the 2-3 approaches yourself — the orchestrator's job, never the swarm's. They crystallise out of the populated space: the converged axes are fixed; each genuine direction fork's conflicting answers is an approach the user weighs. Lead with your recommended option and why; for each:

  • concrete code first, prose second. The primary artefact is the actual program or invocation that should work under this approach, in the project's canonical authoring or consumer form. The implementation shape (changed struct / signature / match-arm, before → after) is secondary supporting detail, never a substitute for the user-facing code.
  • substantive trade-offs (semantic fit, schema impact, performance, composability).
  • effort observation (NOT effort as rationale — see the project's CLAUDE.md on design rationale ≠ implementation effort).

Present the conceptual design alongside — Architecture, Components, Data flow, Error handling, Testing strategy — each scaled to complexity. This design is conceptual: the concrete user-facing code and the before → after shapes are materialised downstream when specify writes the spec and applies the acceptance criterion. Your job here is to get the design decision right and ratified, not to write the artefact.

If the populated space shows every candidate approach is bad, that is the "problem is mis-framed" signal — STOP and escalate to the user, do not ratify a known-bad shape. Three unsatisfying approaches mean the problem is wrong, not that one must be picked.

Step 5 — Deepen the forks the user opens

Deepening is free chat with the orchestrator by default — the user's native mode, and the one place they have chosen to engage. A direction fork is by definition one the swarm could not ground, so re-running the swarm on it asks the machinery that already failed to converge to try again; do not make a second swarm round the default. It is an optional tool the orchestrator MAY reach for, scoped to one fork, only to populate in-direction sub-options once the user has tilted toward a direction, or to rescue a fork that turns out to be mis-framed — spec-skeptic-style, a tool reached for, not a gate.

Capture the resolution. Whatever the chat settles is folded into the ratified design narrative handed to specify, and minuted on the run's reference issue (the specify Step-1.5 reconciliation-comment / boss decision-log discipline). The free-chat deliberation that used to evaporate now lands in the pipeline.

Step 6 — Hand off to specify

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.

Hand off carries the ratified design narrative, in-context (same orchestrator context — no intermediate artefact):

  • the approach chosen and why
  • the constraints and invariants surfaced in the swarm + deepening
  • the design sections the user ratified (Step 4)
  • the decided forks with their cited grounds, and the resolved direction forks with the user's choice — so specify's chain-entry (Step 1.5, "re-ground lightly … rather than re-deriving it") reads them as already settled instead of re-litigating them
  • the iteration scope ("the first iteration covers section X+Y")

specify reads this narrative as its source, applies the acceptance criterion, writes the spec, runs the parse and grounding-check gates, takes sign-off, and hands off to planner. The production gates live there, not here.

Under /boss (autonomous)

When the user is away, the swarm runs autonomously — the discovery is now bounded and context-compacting (the orchestrator gets back a triaged populated space, not a 10-round interview transcript), so a fresh brainstorm is no longer a mandatory pre-dispatch bounce. The autonomous contract mirrors specify's bold-decide stance:

  • Decide the convergent forks. A fork the swarm settles on a cited shared ground is decided autonomously and recorded on the run's reference issue with the ground (the boss § Direction-freedom decision-log discipline) — exactly as specify Step 1.5 records a derived fork.
  • Bounce only the divergent direction forks. A genuine direction fork (split, or ungrounded-consensus, or one the Step-2 cross-check held open) is the user's call; there is no user present, so it routes to a problem-state bounce — a vetoable notify naming, in the user's terms, the design choice that needs them. The convergent decisions ride along; only the genuine forks stop the loop.
  • Grounding floor → bounce. If Step 2.5's grounding floor is not met (greenfield, no ledger), the swarm cannot run honestly and the work needs a human interview — that remains a bounce-back, on grounding grounds, not on the retired "fresh brainstorm is too high-context" rationale.

See ../boss/SKILL.md § Direction freedom (trigger 4) and the Entry-path reflection for how this folds brainstorm into the autonomous cascade.

Handoff Contract

Direction Carrier
user → brainstorm new cycle request with a genuinely open design
brainstormsynthetic-user swarm (Step 3) fork_set + one stance per dispatch + grounding pointers; read-only, parallel, no Workflow
brainstorm → user / reference issue (Step 4 / /boss) the triaged populated space: decided forks + cited grounds, direction forks surfaced for the user's call
brainstormspecify (Step 6) ratified design narrative (approach, constraints, ratified sections, decided forks + grounds, resolved direction choices, iteration scope) — in-context; no spec file written

Common Rationalisations

Excuse Reality
"User says 'clear vision, just plan it' — skip the discovery" "Clear vision" is a starting point, not a settled design. Enumerate the forks; the swarm will show which the vision actually resolves and which it papers over. The ones it papers over are the user's to settle.
"Present my own derived design without the swarm — I already know the answer" Deriving one answer alone and presenting it polished is the single-guess rubber-stamp. The swarm's diversity is what surfaces the constraint you did not think to derive; the cross-check is what stops your own prior from erasing a fork. Run the swarm (above the fire-check floor) or you are shipping unfiltered intuition with extra steps.
"The swarm all agreed, so the fork is decided" Only if they agreed on a cited shared ground. Same-model stances agree by shared prior all the time — that is ungrounded-consensus, and it is a direction fork for the user, not a decided one. Bare agreement is the false-convergence trap, not a verdict.
"There's a direction fork left — re-run the swarm on it to be thorough" A direction fork is the one the swarm could not ground; re-swarming asks the same non-oracle the same unanswerable question at higher resolution, and the extra detail only makes the guess more persuasive. Deepen it in free chat with the user; a scoped re-swarm is optional and only for in-direction sub-options after the user has tilted.
"Three approaches in, none feel right — ship the least bad" Three unsatisfying approaches usually means the problem is mis-framed. Stop, capture what fails about each, escalate to the user. End-of-day pressure is the worst signal to resolve a design fork.
"Spec exists from previous cycle, append to it" The previous cycle's spec was retired at its close (see ../docs/conventions.md § Lifecycle) — there is nothing to append to. New cycle = new spec file; mixing scopes makes drift review unreadable.
"Let the swarm author the approaches — it has the stances already" The swarm answers forks; the orchestrator authors approaches. A finished design from the swarm delegates design DIRECTION to a fan-out — the same downstream-delegation sin the reform exists to prevent, just relocated from specify to the agents.

Red Flags — STOP

  • "Skip the discovery" thoughts (any flavour) on a genuinely open design.
  • Presenting a design without having enumerated the forks, run the swarm (above the fire-check floor), and triaged it.
  • Treating bare swarm agreement as a decision — an ungrounded-consensus silently auto-decided instead of surfaced as the user's call.
  • A fork your own Step-2 enumeration held open, quietly closed by the swarm and not surfaced (the cross-check skipped).
  • Letting the swarm author the 2-3 approaches, or delegating any design direction to it.
  • Re-running the swarm on a direction fork as the default deepening path instead of free chat with the user.
  • Running the swarm below the grounding floor (greenfield, no ledger) and trusting its confabulated convergence.
  • "The 2-3 approaches all suck, just pick one" — that is the mis-framed-problem escalation, not a forced pick.
  • Inventing a design rationale that's actually about effort, not semantics.

Cross-references

  • Agent dispatched: agents/synthetic-user.md — the read-only synthetic design-stance respondent, dispatched as a parallel swarm in Step 3. A spec-skeptic sibling: a fixed read-only lens family that returns a finding, never a verdict.
  • 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.
  • Shared derivability test: ../specify/SKILL.md Step 1.5 — the derivable-vs-pure-preference line brainstorm measures against the swarm is the same one specify applies to the sources; defined there, referenced here, so the two cannot drift.
  • Alternative entry path / bounce-back source: ../tdd/SKILL.md — a test-specifiable feature enters through tdd instead; 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.
  • Autonomous behaviour: ../boss/SKILL.md § Direction freedom (trigger 4) and the Entry-path reflection — how the autonomous swarm-brainstorm decides convergent forks and bounces only divergent ones.
  • 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. Subject to the coverage condition in ../docs/pipeline.md § Cycle recon, that dispatch then IS the cycle's one full recon; specify and planner reuse its report.
  • Project feature-acceptance criterion: declared in the project's CLAUDE.md — applied prospectively by specify (its Step 2), not here.