Documents a recommended (not plugin-enforced) frontmatter marker for files under `design_models` / RFCs / proposals: `status: aspirational` + `validated-against: <sha|"no validation">`, plus a recommendation that the design ledger distinguish model rows from contract rows mechanically. Wires the brainstorm skill to consume the signal: Step 1 notes the marker when reading model files, Step 4 flags code lifted from an aspirational source as the spec's most suspect bytes that must clear the Step-7 parse gate. This is the upstream signal whose downstream catch is the Fix-1 parse-every-block gate. Adds a Common Rationalisation and a Red Flag. Missing marker -> signal absent, graceful degradation, never a hard fail. Closes the issue #1 hardening set (P0 + Fixes 1-5). refs #1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
19 KiB
name, description
| name | description |
|---|---|
| brainstorm | 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. |
brainstorm — cycle spec generator
Violating the letter of these rules is violating the spirit.
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.
It produces specs under the project's paths.spec_dir.
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.
Skipping is permitted only for:
- A bug-fix iteration (use
debugdirectly). - A tidy iteration (use
auditdirectly). - A trivial mechanical edit (≤1 file, ≤30 LOC, no design judgement).
Skipping is not permitted for:
- 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.
The first two cases above are the most common pressure to skip; both are explicitly resisted by this skill (see Common Rationalisations).
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 Process
Step 1 — Explore project context
Before asking any clarifying questions:
git log -5 --format=fullfor the full bodies of the most recent iter / audit commits — current state of the project.- If the project has a design ledger configured under
paths.design_ledger, walk to the relevant contracts for the invariants the new cycle might touch. - When reading any file under
paths.design_models(or the ledger's "model" rows), note itsstatus/validated-againstfrontmatter if present:status: aspirationalmeans 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). git log --oneline -20for 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 — Ask clarifying questions, one at a time
Multiple-choice when possible (easier to answer). One question per message — no batching. Focus on:
- 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?
Step 3 — Propose 2-3 approaches with trade-offs
Lead with your recommended option and explain why. Each approach gets:
- 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)
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
Scale each section to its complexity (a few sentences if straightforward, up to 200-300 words if nuanced). Cover:
- Architecture
- Components
- Data flow
- 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.
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
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).
Structure:
# <Title> — 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-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):
- Placeholder scan: any "TBD", "TODO", incomplete sections, vague requirements? Fix.
- Internal consistency: sections must not contradict. Architecture must match component descriptions.
- Scope check: focused enough for one plan, or does it need sub-cycle decomposition?
- Ambiguity check: could any requirement be interpreted two ways? If so, pick one and make it explicit.
- Concrete-code check: does
## Concrete code shapesexist 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. - Parse-every-block gate. If the project profile declares
spec_validation.parsers, extract every fenced code block from the spec. For each block whose fence label has aparsersentry: write the block to a temp file with the entry'sext, run the entry'scmdwith{file}substituted, and require exit 0. A non-zero exit 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 (the Run block and its output) into the brainstorm chat: a visible trace is what attests the gate fired, and its absence means the gate was skipped. A block whose fence label has noparsersentry is skipped and the skip is noted ("no parser for fence label X"); never a silent pass. A malformed entry (cmdwithout{file}, orext/cmdmissing) is a profile error to surface, not a skip. If the profile declares nospec_validation, this check is a documented no-op.
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:
| Field | Content |
|---|---|
spec_path |
path to the spec just written in Step 6 |
iteration_scope |
which sections cover the imminent first iteration (verbatim from the brainstorm session) |
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 <path>::<name> 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):
-
Delete the just-written spec file from the working tree (
rm <spec_path>— a shell delete on the working tree, NOTgit rm; the file was never committed). -
Open a backlog issue (via the project's issue-tracker create command —
tea issues createfor Gitea,gh issue createfor 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 toBLOCKERif the unratified mechanism is on a core-functionality path) - Body: short description, plus two structured
lines:
depends on: <name of the unratified mechanism>context: <why this is deferred>
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.
-
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
<path>(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: <cycle> <topic>). 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")
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) |
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" | 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
- "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"
- 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_validationparser, committed without a parse-trace in the brainstorm chat - Lifting code verbatim from a
status: aspirationalsource (amodels/ 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 viaplanner) - Inventing a design rationale that's actually about effort, not semantics
Cross-references
- Output target:
../planner/SKILL.md— only valid next skill. - 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.mdduring Step 1 when the cycle enters code territory the orchestrator has not recently read; this is opt-in and 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.