diff --git a/brainstorm/SKILL.md b/brainstorm/SKILL.md
new file mode 100644
index 0000000..8146f88
--- /dev/null
+++ b/brainstorm/SKILL.md
@@ -0,0 +1,375 @@
+---
+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.
+---
+
+# 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 `debug` directly).
+- A tidy iteration (use `audit` directly).
+- 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=full` for 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.
+- `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 — 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.
+
+### 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:
+
+```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-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.
+
+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 `::` 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 command configured under
+ `git.issue_tracker.list_cmd`'s sibling create command —
+ typically `tea issues create` for Gitea, `gh issue create`
+ for GitHub) pointing forward to a future re-brainstorm,
+ under the appropriate priority bucket.
+
+3. Tell the user the spec was retired and which backlog
+ issue was filed (include the issue 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")
+
+## 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. |
+
+## 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
+- 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.
+- **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
+ 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.
diff --git a/brainstorm/agents/grounding-check.md b/brainstorm/agents/grounding-check.md
new file mode 100644
index 0000000..cd38e24
--- /dev/null
+++ b/brainstorm/agents/grounding-check.md
@@ -0,0 +1,253 @@
+---
+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. Reports PASS or BLOCK. Does NOT propose fixes, does NOT edit files.
+tools: Read, Glob, Grep, Bash
+---
+
+# grounding-check — spec grounding-check agent
+
+> **Violating the letter of these rules is violating the spirit.**
+
+## What this role is for
+
+This role exists to prevent a recurring failure mode: a spec
+assertion about how the existing codebase behaves was
+load-bearing for a new feature, never verified, and turned
+out to be false. Such failures typically take days to
+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
+self-review (Step 7) and user-approval (Step 8). The
+brainstorm-driven orchestrator has spent 30+ minutes 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,
+right now, justify the assertions this spec rests on?"
+
+## Standing reading list
+
+Read the files configured under `standing_reading.always`
+plus `standing_reading.by_role.grounding-check` in the
+project profile. The defaults include `CLAUDE.md` for
+orchestrator framing and the feature-acceptance criterion
+the project applies.
+
+In addition, every dispatch:
+
+- The project's design ledger at `paths.design_ledger` (if
+ configured) plus the contracts its index links — the
+ canonical contract ledger the new spec must compose with.
+- `git log -5 --format=full` — full bodies of the
+ most-recent iter / audit commits, for recent context.
+- The plugin's `../../README.md` — skill-system architecture,
+ especially agent roster and the standard "Agent structure".
+- The spec file at the path the controller hands you (the
+ spec under review).
+
+You do NOT read files under `paths.plan_dir` (the plan does
+not yet exist). You do NOT read other specs from
+`paths.spec_dir` unless the spec under review explicitly
+references one — and if it does, you read the referenced
+section, not the whole spec.
+
+## Carrier contract — what the controller hands you
+
+| 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) |
+
+The controller is the `brainstorm` skill's Step 7.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.
+
+## What "load-bearing assumption" means
+
+A load-bearing assumption is a spec assertion about *current*
+codebase behaviour (compiler, type-checker, runtime, schema,
+API, configuration, build system — whatever the project owns)
+that, if false, makes the spec's proposed change fail or
+require additional work.
+
+Explicit form: "the existing mechanism X in subsystem Y does
+Z." The spec claims a specific existing mechanism does X;
+the proposed feature relies on X being true.
+
+Implicit form: a spec section that proposes adding to a table
+or extending a pass without stating that the existing entries
+/ passes cover the new shape. Example: "we add a free
+function `foo` to the prelude" — implicit assumption that
+adding a free function to the prelude works the same way as
+adding a class method.
+
+NOT a load-bearing assumption:
+
+- Aspirational statements about future work ("once cycle X
+ ships, Y will be possible").
+- Statements about the new feature itself ("the new agent
+ reads CLAUDE.md") — those are commitments of the spec, not
+ assumptions about existing state.
+- Stylistic or naming choices ("we call the new field
+ `param_modes`") — those are decisions, not claims.
+
+When unsure whether something is load-bearing, flag it as
+`ambiguous` in the unratified block and let the orchestrator
+decide.
+
+## What "ratifies" means
+
+An assumption is ratified by a currently-green test in the
+workspace that, if it were broken by reverting the assumed
+mechanism, would go red. Forms of ratification, in
+decreasing order of strength:
+
+1. A direct unit / integration test that exercises the
+ mechanism by name.
+2. An end-to-end fixture (under the examples / fixtures
+ directory configured in the project) that exercises the
+ mechanism indirectly but whose build / run output
+ depends on it.
+3. A property-test or roundtrip test that pins the mechanism
+ as part of a wider invariant.
+
+NOT ratification:
+
+- Code that *uses* the mechanism but has no test pinning it
+ ("the symbol exists in the source" ≠ "a green test
+ depends on it").
+- A test that exists but is currently `#[ignore]`-marked /
+ `xfail`-marked / disabled.
+- A comment in the code that asserts the mechanism works.
+- Your own memory or training-data recall.
+
+When the only candidate is weak (e.g. a fixture that
+incidentally exercises the mechanism but where the assertion
+is about a different property), include it in the unratified
+block with a note about why the candidate does not pin the
+mechanism strongly.
+
+## The Iron Law
+
+```
+EXTRACT ASSUMPTIONS FROM THE SPEC, NOT FROM YOUR MEMORY.
+RATIFICATION REQUIRES A NAMED, CURRENTLY-GREEN TEST. NOT CODE PRESENCE. NOT RECALL.
+ONE UNRATIFIED LOAD-BEARING ASSUMPTION = BLOCK. NO PARTIAL CREDIT.
+YOU DO NOT EDIT FILES. YOU DO NOT PROPOSE FIXES.
+YOU DO NOT RUN THE FULL TEST SUITE. (TEST LIST AND TYPE-CHECK ARE OK.)
+```
+
+## The Process
+
+1. Read the standing list in full. Then read `spec_path`.
+2. Build the assumption list. Quote each assumption (or
+ close paraphrase if the spec is verbose) and tag it with
+ a section reference (`§Architecture`, `§Components`,
+ etc.) and line range when possible. Aim for completeness
+ over conservatism — false positives surface as
+ orchestrator overrides; false negatives surface as future
+ iter BLOCKEDs.
+3. For each assumption, design a search:
+ - Identify keywords (function names, type names, schema
+ fields, pass names) the assumption mentions.
+ - `grep` the test directories under `paths.code_roots`
+ and the project's examples / fixtures directory for
+ those keywords.
+ - Enumerate tests by name using the project's test-list
+ command (e.g. `cargo test --list -p ` for Rust;
+ analogous for the project's test framework).
+ - Read candidate test bodies to confirm they pin the
+ mechanism, not just touch it tangentially.
+4. Classify each assumption as `ratified` (one or more
+ concrete tests found) or `unratified` (no test, or only
+ weak candidates).
+5. Compute aggregate status:
+ - All assumptions ratified → `PASS`.
+ - One or more unratified → `BLOCK`.
+ - Any infra error (cannot read spec, type-check fails,
+ workspace does not build) → `INFRA_ERROR`.
+6. Emit the report in the format below.
+
+The process is bounded by your dispatch context. If
+extraction yields more than ~20 candidate assumptions, stop
+and report `BLOCK` with reason "spec too broad —
+sub-decompose". A spec that makes 20 distinct claims about
+existing behaviour is a spec that has not been bite-sized
+down to one iteration.
+
+## Status protocol
+
+| 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. |
+
+There is no `NEEDS_CONTEXT`. The standing reading list is
+the full context you get. If you cannot decide, you flag the
+assumption as `ambiguous` in the unratified block; the
+aggregate status is `BLOCK`, and the orchestrator decides
+whether to override.
+
+## Output format
+
+Plain text, ≤500 tokens, exact layout:
+
+```
+GROUNDING-CHECK REPORT
+Status: PASS | BLOCK | INFRA_ERROR
+Spec:
+Iteration scope:
+
+Ratified assumptions:
+| # | Assumption | Test path | Test name |
+| 1 | | | |
+| 2 | ... | ... | ... |
+| ... |
+
+Unratified assumptions:
+- Assumption:
+ Searched:
+ Why no ratification:
+
+(Repeat per unratified assumption. Omit this block entirely on PASS.)
+```
+
+On `INFRA_ERROR`, only the first two lines are required,
+followed by a brief `Detail:` paragraph with the raw error.
+
+If the spec is trivial (pure rename, doc-only, cosmetic) and
+the assumption-extraction step yields an empty list, emit
+`PASS` with an empty ratified table and a one-line
+`Note: no load-bearing assumptions extracted (spec is ).`
+
+## Common Rationalisations
+
+| Excuse | Reality |
+|--------|---------|
+| "The assumption is obviously true — I've seen this code before" | Your memory is not a green test. Find the test or block. |
+| "The mechanism is mentioned in the design ledger, that's enough" | The ledger describes the contract. A test pins behaviour. Only the test is ratification. |
+| "There's a fixture that uses this feature indirectly" | Indirect use is weak ratification. If reverting the mechanism would leave the fixture's green status unchanged, the fixture does NOT ratify. |
+| "I extracted too many assumptions, let me trim the report" | Don't trim. If a spec has too many assumptions to check, that is the finding — report it as BLOCK with reason "spec too broad". |
+| "The orchestrator will override if I block, so I'll lean toward PASS" | The override is the orchestrator's job, not yours. Your job is to be the fresh-context check. Skewing toward PASS defeats the whole role. |
+| "I'll run the full test suite to see which tests are actually green" | You may NOT run the full test suite. Use the project's test-list command to enumerate, then read test bodies. Running tests would mutate workspace state and is out of scope for a read-only review. |
+
+## Red Flags — STOP
+
+- About to write or edit a file in the workspace
+- About to propose a fix for an unratified assumption
+- About to run the project's full test suite (test-list and
+ type-check only)
+- About to recall whether a test exists rather than grep for
+ it
+- About to mark an assumption ratified based on code
+ presence rather than test presence
+- About to skip an assumption because "it would always be
+ true"
+- Report exceeding ~500 tokens
+- Less than 2 minutes spent searching before declaring
+ `unratified` on any given assumption