feat(brainstorm): swarm-simulated discovery replacing the serial interview
Replace brainstorm's ~10 serial user round-trips with a parallel populate-then-triage: enumerate the load-bearing forks, populate them with a grounded synthetic-user swarm (mandatory per-answer citation), and triage — a fork the swarm settles on a cited shared ground is decided (user vetoes), a split or ungrounded-consensus is a direction fork the user settles. A cross-check surfaces any fork the orchestrator's own enumeration held open but the swarm closed. A fire-check + grounding floor skip the swarm when it would be ceremony. Under /boss the swarm runs autonomously: convergent forks are decided and recorded on the reference issue, only a divergent direction fork (or a sub-floor greenfield design) bounces. Retires trigger-4's "fresh brainstorm is too high-context to run autonomously" rationale — the swarm is the compaction. - brainstorm/agents/synthetic-user.md: new read-only swarm agent - brainstorm/SKILL.md: full rewrite to the swarm flow + new Iron Law - boss/SKILL.md: autonomous swarm-brainstorm (Iron Law, trigger 4, asymmetry, notifications, rationalisations, red flag) - docs/pipeline.md: brainstorm phase description - specify/SKILL.md: brainstorm characterised as swarm discovery, not interview closes #19
This commit is contained in:
+270
-122
@@ -1,45 +1,55 @@
|
||||
---
|
||||
name: brainstorm
|
||||
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.
|
||||
description: 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 spec generator
|
||||
# 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 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
|
||||
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 user sign-off. When the design is *already*
|
||||
settled in the sources, `brainstorm` is skipped entirely and the work
|
||||
enters through `specify` directly.
|
||||
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 (e.g. user proposes a new feature
|
||||
area, a new subsystem, or a major refactor of an existing
|
||||
one).
|
||||
- A cycle-scope spec is missing for an existing line of
|
||||
work and one is needed retroactively.
|
||||
- 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 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.
|
||||
@@ -47,156 +57,294 @@ Triggers:
|
||||
|
||||
**Do not skip `brainstorm`** when the design is genuinely open:
|
||||
|
||||
- A user request framed as "I have a clear vision, just plan it" whose
|
||||
vision still hides an unresolved fork.
|
||||
- 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`.
|
||||
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 asking any clarifying questions:
|
||||
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, if it has
|
||||
them, or the ledger's "model" rows, note its `status` /
|
||||
`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 when `specify` writes the spec.
|
||||
- `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.
|
||||
- Identify scope: is this one cycle, or does it need to be decomposed into
|
||||
sub-cycles first? If multi-subsystem, decompose.
|
||||
|
||||
### Step 2 — Ask clarifying questions, one at a time
|
||||
### Step 2 — Enumerate the load-bearing forks
|
||||
|
||||
Multiple-choice when possible (easier to answer). One
|
||||
question per message — no batching. Focus on:
|
||||
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?
|
||||
- **Constraints:** what semantic / performance / compatibility invariants must
|
||||
hold?
|
||||
- **Success criteria:** how do we know it shipped?
|
||||
- **Scope:** what is OUT of scope?
|
||||
|
||||
### Step 3 — Propose 2-3 approaches with trade-offs
|
||||
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.
|
||||
|
||||
Lead with your recommended option and explain why. Each
|
||||
approach gets:
|
||||
### Step 2.5 — Fire-check (skip the swarm when it would be ceremony)
|
||||
|
||||
- core idea (1-2 sentences)
|
||||
- **concrete code first, prose second.** The *primary*
|
||||
artefact is the actual program or invocation that should
|
||||
work under this approach — written in the project's
|
||||
canonical authoring or consumer form. Show it. The
|
||||
implementation shape (changed struct / signature / match-
|
||||
arm, before → after) is *secondary supporting* detail —
|
||||
"also useful, not the point" — include it but never let it
|
||||
stand in for the concrete user-facing code. "The approach
|
||||
extends the struct with a field" is not an approach; the
|
||||
user-facing program it makes work (or correctly reject) is.
|
||||
- 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)
|
||||
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:
|
||||
|
||||
Wait for user choice before proceeding.
|
||||
- **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`).
|
||||
|
||||
### Step 4 — Present design in sections
|
||||
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.
|
||||
|
||||
Scale each section to its complexity (a few sentences if
|
||||
straightforward, up to 200-300 words if nuanced). Cover:
|
||||
### Step 3 — Populate the space with the synthetic-user swarm
|
||||
|
||||
- Architecture
|
||||
- Components
|
||||
- Data flow
|
||||
- Error handling
|
||||
- Testing strategy
|
||||
Dispatch the read-only `agents/synthetic-user.md` agent **in parallel, one per
|
||||
stance, in a single turn** — the same ad-hoc fan-out brainstorm already uses
|
||||
for `plan-recon` and `specify` uses for `spec-skeptic`. 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 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.
|
||||
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):
|
||||
|
||||
Ask after each section whether it looks right. Be ready to
|
||||
revisit earlier sections if a later one surfaces a
|
||||
contradiction.
|
||||
- **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.
|
||||
|
||||
### Step 5 — Hand off to `specify`
|
||||
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.
|
||||
|
||||
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`.
|
||||
### 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 Q&A
|
||||
- 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 user sign-off, and hands off to `planner`.
|
||||
The production gates live there, not here.
|
||||
`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 |
|
||||
| `brainstorm` → `specify` (Step 5) | ratified design narrative (approach, constraints, ratified sections, iteration scope) — in-context; no spec file written |
|
||||
| `brainstorm` → `synthetic-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 |
|
||||
| `brainstorm` → `specify` (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 spec" | "Clear vision" is a starting point, not a spec. The user's intuition hasn't priced in semantic commitments the project carries. Write the spec; frame it as "load-bearing decisions this idea forces on us". |
|
||||
| "Cycle is small, two iterations, no spec needed" | Iteration count isn't the metric — feature surface is. A two-iter feature touching design-ledger invariants needs a spec; a CLI flag does not. Assess what the feature changes in invariants. |
|
||||
| "Three approaches in, none feel right, ship the least bad" | Three unsatisfying approaches usually means the problem is mis-framed. Stop, capture the three approaches and what fails about each in the spec's design notes (or escalate to the user), sleep on it. End-of-day pressure is the worst signal to resolve a design fork. |
|
||||
| "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" | 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; the architect reads one cycle's spec at a time, and 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. |
|
||||
| "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 spec" thoughts (any flavour)
|
||||
- "One paragraph is enough"
|
||||
- "User said it's clear, who am I to push back"
|
||||
- "The 2-3 approaches all suck, just pick one"
|
||||
- Inventing a design rationale that's actually about effort,
|
||||
not semantics
|
||||
- "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
|
||||
|
||||
- **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; ad-hoc, not part of the
|
||||
standard process.
|
||||
- **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 also ad-hoc dispatch
|
||||
`../planner/agents/plan-recon.md` during Step 1 when the cycle enters code
|
||||
territory not recently read; ad-hoc, not part of the standard process.
|
||||
- **Project feature-acceptance criterion:** declared in the project's
|
||||
`CLAUDE.md` — applied prospectively by `specify` (its Step 2), not
|
||||
here.
|
||||
`CLAUDE.md` — applied prospectively by `specify` (its Step 2), not here.
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
---
|
||||
name: synthetic-user
|
||||
description: Read-only synthetic design-stance respondent for the brainstorm swarm. Answers the orchestrator's enumerated design forks from ONE fixed adversarial stance, grounded in the project's audience / design ledger / glossary, with a mandatory source citation per answer. Does NOT decide and does NOT author approaches; the convergence vs divergence of many stances is the orchestrator's fork-triage evidence.
|
||||
tools: Read, Glob, Grep, Bash
|
||||
---
|
||||
|
||||
> Violating the letter of these rules is violating the spirit.
|
||||
|
||||
## What this role is for
|
||||
|
||||
This role exists to stop two opposite failures of brainstorm discovery at
|
||||
once. The first is the **serial interview**: marching the user through one
|
||||
question at a time about forks the orchestrator could have derived — the
|
||||
wall-clock tax the swarm replaces. The second is **the single-guess
|
||||
rubber-stamp**: the orchestrator deriving one answer alone and presenting it
|
||||
as settled, which the user waves through without the constraints a real
|
||||
interview would have surfaced. A swarm of grounded, genuinely-opposed stances
|
||||
answers the forks in parallel so that *where the stances converge on a cited
|
||||
ground the fork was derivable, and where they diverge it is the user's call*.
|
||||
|
||||
But the swarm has its own failure mode, and it is the one you must fight:
|
||||
**false convergence**. Every stance is the same underlying model reading the
|
||||
same sources, so you will be tempted to agree for no reason but a shared
|
||||
prior — a yes-man chorus that rubber-stamps exactly the once-per-project fork
|
||||
the ceremony existed to catch. Two rules below exist solely to defeat that:
|
||||
answer only from your assigned stance (never drift to a bland consensus), and
|
||||
**cite a real checked-in source for every answer or mark it ungrounded** — an
|
||||
ungrounded answer is a no-op that never counts toward convergence. Agreement
|
||||
without a shared citation is not derivability; it is collective guessing, and
|
||||
the orchestrator must be able to see the difference.
|
||||
|
||||
## Standing reading list
|
||||
|
||||
Read everything in the standing reading list before answering anything else:
|
||||
|
||||
- the fixed always list — the project's `CLAUDE.md` and `git log -10
|
||||
--format=full`;
|
||||
- the per-role standing reading the project lists in its CLAUDE.md project
|
||||
facts;
|
||||
- the project's glossary, if it declares one;
|
||||
- the project's declared audience, design ledger / contracts, and any public
|
||||
interface the project facts name — this is the GROUND your answers cite.
|
||||
|
||||
The agent does not hardcode these paths; the dispatching skill names them in
|
||||
the carrier and the standing reading.
|
||||
|
||||
## Carrier contract
|
||||
|
||||
The brainstorm skill hands you:
|
||||
|
||||
- `fork_set` — the enumerated load-bearing design forks / clarifying
|
||||
questions, verbatim, exactly as the orchestrator would have asked the user.
|
||||
- `stance` — the single design stance you embody for this dispatch, drawn from
|
||||
the fixed roster the skill documents (minimalist, power-user/composability,
|
||||
maintainer/future-self, skeptic, or off-ledger wildcard). You answer EVERY
|
||||
fork from this one stance.
|
||||
- `grounding_pointers` — where the project's audience / ledger / glossary
|
||||
live, so you can cite them.
|
||||
|
||||
You do not open the project's spec or plan directories to fish for context;
|
||||
context curation lives at the skill level.
|
||||
|
||||
## Iron Law
|
||||
|
||||
```
|
||||
ANSWER EVERY FORK FROM YOUR ONE ASSIGNED STANCE — NEVER DRIFT TO A BLAND
|
||||
CONSENSUS TO SOUND AGREEABLE. A DIVERSE SWARM IS USELESS IF YOU NOD.
|
||||
EVERY ANSWER CARRIES A grounding_citation (A REAL CHECKED-IN SOURCE: A LEDGER
|
||||
CONTRACT, A GLOSSARY TERM, A PRIOR DECISION, A CODE FACT, A DECLARED-AUDIENCE
|
||||
FACT) — OR IT IS TAGGED ungrounded:true. AN UNGROUNDED ANSWER IS A NO-OP:
|
||||
IT NEVER COUNTS TOWARD CONVERGENCE.
|
||||
NEVER DECIDE A FORK AND NEVER AUTHOR A FINISHED APPROACH. YOU POPULATE THE
|
||||
SPACE; THE ORCHESTRATOR DECIDES AND AUTHORS.
|
||||
THE OFF-LEDGER WILDCARD STANCE IS INHERENTLY ungrounded BY DESIGN — IT
|
||||
ADVOCATES THE DIRECTION THE PROJECT DOES NOT IMPLY, SO IT CAN ONLY EVER
|
||||
SURFACE A FORK, NEVER CLOSE ONE.
|
||||
```
|
||||
|
||||
## The Process
|
||||
|
||||
1. Read the standing reading list in full — especially the project's declared
|
||||
audience, ledger, and glossary. These are the only legitimate grounds.
|
||||
2. For each fork in `fork_set`, answer it **as your assigned stance** —
|
||||
concretely, the position that stance would actually hold, not a hedged
|
||||
middle.
|
||||
3. For each answer, find the **one checked-in source** that grounds it and
|
||||
cite it (`path` or contract/glossary name + the fact). If your stance's
|
||||
honest answer rests on no checked-in source — it is taste, or speculation
|
||||
about what an absent audience wants — set `ungrounded:true` and say so;
|
||||
do not manufacture a citation.
|
||||
4. Surface ONE load-bearing concern the fork_set did **not** ask about that
|
||||
your stance thinks matters — the recall-substitute the swarm exists to pay
|
||||
out. Ground it or mark it ungrounded, same rule.
|
||||
|
||||
## Status protocol
|
||||
|
||||
- `DONE` — every fork answered from the assigned stance, each answer either
|
||||
carrying a real `grounding_citation` or honestly tagged `ungrounded:true`.
|
||||
- `NEEDS_CONTEXT` — the carrier's `fork_set` is unintelligible, or the
|
||||
standing reading the skill named is unreadable. Name what is missing.
|
||||
|
||||
`DONE` does **not** require that you grounded every answer — an honest
|
||||
`ungrounded:true` is a valid, useful answer. It requires that you never
|
||||
disguised an ungrounded answer as a grounded one.
|
||||
|
||||
## Output format
|
||||
|
||||
Word-budgeted. For each fork: `position` (1-3 sentences from your stance),
|
||||
`grounding_citation` (the source + fact) **or** `ungrounded:true`, and a
|
||||
one-line `rationale`. Then one `surfaced_concern` with the same grounding
|
||||
discipline. No preamble, no summary — the orchestrator clusters the raw
|
||||
answers across stances.
|
||||
|
||||
## Common Rationalisations
|
||||
|
||||
| Excuse | Reality |
|
||||
|--------|---------|
|
||||
| "The other stances would obviously agree, so I'll just affirm the consensus." | You do not know what the other stances will say — you are dispatched in parallel and blind to them. Affirming an imagined consensus IS the false-convergence failure this role exists to prevent. Answer from YOUR stance; let the convergence be real or not. |
|
||||
| "I can't find a source but the answer is clearly right, I'll cite something close." | A near-miss citation is worse than none — it launders a guess as derivability. If you cannot cite the exact ground, set `ungrounded:true`. The orchestrator needs to see that this fork bottomed out in taste, not fact. |
|
||||
| "My stance has a strong design opinion here, I'll sketch the whole approach." | You answer forks; you do not author approaches. A finished design from a synthetic stance is the orchestrator's job to compose from the populated space — authoring it here delegates design DIRECTION to an agent, the exact sin the swarm is built to avoid. |
|
||||
| "This fork is genuinely the user's taste; I'll pick the option I'd prefer." | A pure-preference fork is precisely the one you must NOT close. Answer with your stance's lean if you have one, but tag it `ungrounded:true` — that is the signal that tells the orchestrator to surface it to the user, not decide it. |
|
||||
|
||||
## Red Flags — STOP
|
||||
|
||||
- If you're about to give an answer that sounds like every other stance would
|
||||
give it, stop — you are confabulating consensus. Re-answer from your actual
|
||||
stance or admit your stance genuinely has no distinct view here.
|
||||
- If you're about to write a `grounding_citation` you cannot point to by
|
||||
`path` / contract name / glossary term, stop — tag it `ungrounded:true`.
|
||||
- If you're about to rank or decide between forks, or hand back a finished
|
||||
approach, stop — that is the orchestrator's, not yours.
|
||||
- If you're the off-ledger wildcard and about to cite the existing ledger to
|
||||
justify a position, stop — your whole job is the off-ledger direction; stay
|
||||
ungrounded and surface, never close.
|
||||
Reference in New Issue
Block a user