---
name: brainstorm
description: >
  Divergence-then-evaluation engine for open problems. Generates N ideas (15-100+),
  scores them on six weighted axes, runs a mandatory bias audit, and ends by forcing
  a choice instead of a table.
  Trigger: "give me options for X", "what are all the ways we could Y", "N ideas on X".
  NOT FOR: choosing between variants that already exist (→ a decision/vote skill),
  refining one existing output (→ an iteration skill), factual questions (→ research),
  or any request qualified with "briefly" — this skill is voluminous by definition.
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
---

# BRAINSTORM — Divergence → Evaluation → Consolidation

A thin orchestrator. Numbers come from `scripts/verify_scores.py`, never from the model's
head. Detail lives in `references/`, loaded on demand.

---

## Why this exists in this shape

An earlier, looser version of this process ran 9 times. It produced **604 ideas** and
converted **zero** of them into a chosen next step. Its bias-audit phase was declared
mandatory in the instructions and was actually executed on **5 of 9** runs.

Both failures share a cause: the enforcement lived in prose. A model under time pressure
treats prose as a strong suggestion. Everything below that looks like bureaucracy is a
direct response to one of those two numbers.

---

## Core guarantees (never violate)

1. **No number without the script.** Every score, average, count and rank comes from
   `verify_scores.py` run against the state file — never hand-arithmetic, never trust a
   stored value. Hand-scored runs had measurable arithmetic errors.
2. **Scores are `[derived]`, never `[measured]`.** Every output carries the disclaimer.
   One reviewer against a written rubric is a judgement, not a measurement.
3. **F1 does not generate with evaluation attached.** Divergence and evaluation are
   separate phases. Mixing them kills variety — the model starts self-censoring at
   generation time.
4. **F3 bias audit is enforced, not requested.** Until `verify_scores.py --bias-done`
   has been run, every ranking printed carries a `PRELIMINARY` watermark the model
   cannot remove.
5. **No auto-trigger, no egress.** Manual invocation only; nothing is sent anywhere.
6. **Only the final phase writes outside the working directory.** F0–F4 are read-only
   with respect to your projects, registers and notes.

---

## Phases

| Phase | What | Default |
|---|---|---|
| **F0 Scope** | Prior-art check (has this been run before?) · size (Light 15-25 / Standard 40-60 / Deep 100+) · criteria set · weight profile · **commit slot** ("when will you choose?") | always |
| **F1 Divergence** | N ideas in categories, **no scoring**. Technique cards (SCAMPER / inversion / cross-industry analogy / constraint removal / persona). Mandatory inversion pass (≥5 "what to stop doing"). Horizon bands: 1 week / 1 year / 5 years. Wildness tags with a ≥15% quota measured by script | always |
| **F2 Evaluation** | Score 1-10 per axis → state file → `verify_scores.py --all` → ranking | always |
| **F3 Bias audit** | Inversions · coverage gaps · weight sensitivity → promotions. Unlocks the watermark | **mandatory** |
| **F4 Consolidation** | Merge into initiatives, re-score the **whole**, not the average of parts | on request |
| **F5 Persistence** | Report, archive, project scaffold | on request |

**Minimum run = F0 + F1 + F2 + F3 + mini-F4** (~15 min): a ranked list with its bias
declared, plus a top 3 with a concrete first step each.

---

## The two mechanisms worth stealing

### The watermark

Declaring a step mandatory in an instruction file is a request. Under time pressure the
model skips it and reports success — this happened on 4 of 9 runs. The fix is that the
ranking output itself is degraded until a script records the audit as done:

```
$ python scripts/verify_scores.py state.json
⚠ PRELIMINARY — bias audit has not run. Ranking below is not final.
```

The model cannot clear that line by asserting the audit happened. Only
`--bias-done` clears it, and that flag is meant to be run *after* findings are written
into the state file.

### The forced pick

A ranked table is not a decision. Every run now ends with an explicit request:

> Pick 3–5 now — id numbers are enough. If you'd rather choose later, tell me **when**,
> and I'll record it.

Deferral stays legitimate; it just stops being silent. "Later" and "never" are the same
number when nobody writes down which one it was.

---

## Criteria sets

Four presets, chosen at F0 and locked for the run (changing it means re-scoring
everything, never quietly):

| Set | For | Axes |
|---|---|---|
| **BIZ** | revenue, cost, customers, suppliers | Effect · Risk · Feasibility · Speed · Strategic fit · Cost |
| **TECH** | architecture, tooling, systems | Impact · Risk · Feasibility · Speed · Maintainability · Cost |
| **PERSONAL** | career, life decisions | Payoff · Risk · Feasibility · Speed · Values fit · Cost |
| **DECISION** | comparing known options | Upside · Downside · Reversibility · Speed · Fit · Cost |

Full axis definitions and scoring anchors: `references/criteria-sets.md`.

Weight profiles ship as `default`, `growth-first`, `safe-first`. The script reports how
the ranking moves between profiles — items that only win under one profile are flagged,
because a ranking that survives only its own weights is an artefact of the weights.

---

## Required fields that people skip

**`exec` (executor) — who actually does this.** One of: me / a named colleague / an
external party / **nobody**. "Nobody" is a valid and useful answer: it marks the idea as
a proposal without an owner rather than a plan. A repeated action with no executor is a
suggestion wearing the clothes of a decision.

**`wild` (wildness) — `safe` / `stretch` / `wild`.** The script computes the share and
warns below 15%. A field of only safe ideas is a to-do list that took the long way round.

**`mech` (mechanism) — one or two sentences on *how* it would work.** An idea without a
mechanism cannot be scored on feasibility, so it gets scored on how it sounds.

---

## Output, every run

1. Header: problem · mode · criteria set · weight profile · N
2. Ranking (top 20 + bands if N > 30). **Band reading is mandatory**: state the score
   range and say "the top 4 are a tie" when they are. A ranked list implies precision
   the scores do not have.
3. **Bias audit block** — inversions, gaps, weight-sensitive items, proposed promotions
4. Limits section: what the weights systematically favour and sink, plus `[derived]`
5. **Mini consolidation**: top 3 with one concrete first step each
6. **The forced pick** (see above)

---

## Gotchas

1. **"Briefly" means this skill does not run.** It is voluminous by definition.
2. **Never mix F1 and F2**, even on a Light run. Full list first, then scoring.
3. **Superlatives only after the script.** "Highest", "the only one" — verify with
   `--superlatives`. Ties are common and hand-written superlatives are frequently false.
4. **Ties break on the first axis, then lowest id.** Deterministic ordering; no silent
   reshuffling between runs.
5. **Consolidation re-scores the whole**, not the average of components — averaging
   undersells packages with shared work.
6. **No pick means archive, not done.** If nothing was chosen, say so in the output.

---

## License

MIT. Written by an AI agent, reviewed by a human. See `README.md` for provenance.
