# Harvest — the stop pipeline

Load when: `/brainstorm stop` is invoked (facilitator), or executing any stop-gate dispatch
(twin). The pipeline's mechanical gates live in the detector (`--gate=manifest`, `--gate=move`);
this reference carries the routing judgment.

The pipeline, end to end:

```
converge → final sync/compose → manifest (Status: proposed)
  → ONE user approval (Status: approved)
  → apply, reading both sides of every destination (Status: applied)
  → uselessness test → gaps? new Round, back to approval
  → move to docs/history/brainstorms/{topic}/  ← the completion marker
  → offer: delete or commit — the user decides
```

**Harvest fails loud, never silent.** The move happens only after the full apply passes the
uselessness test. A partial apply — twin death, session kill, anything — leaves the folder
visibly unfinished in `docs/research/` and the user restarts the stop. The pipeline never resumes
silently from a half-applied state, and canonical docs are never written without an approved
manifest (gap-round fixes included).

## The routing map

Route each piece of the surface by scope. Format every artifact via the `documentation` skill;
where it is unavailable, fall back to own formatting and record which path ran in the manifest.
Read **both sides** of every destination before writing — the destination's current content is a
contract, not a blank page.

| What | Goes to | Shape |
| --- | --- | --- |
| **Source of truth** | The repo's canonical home for that knowledge: `docs/features/` for a feature, `docs/architecture/` for cross-cutting doctrine, else a topic `Readme.md` | One consolidated reader-first doc distilled from the whole surface: thesis → what it is; domain fragment → how it works; ledger → present-tense rationale **without entry codes** |
| **Executable work** | `docs/history/plans/` | Split by deliverable, never by pillar |
| **Decision records** | One record per decision *subject* | A decision revising an already-recorded subject updates that record in place (its changelog carries the journey) rather than minting a new one; declined alternatives ride along with their re-evaluate conditions |
| **Domain-model changes** | The living domain-model doc | The information-architecture contract the `boundary` skill reads at the next plan check |
| **Still-open (parked) forks** | The repo's open-questions home | Each with a *resolution-lands-in* pointer |
| **Backlog items** | The repo backlog | See the scope-guard trio below |
| **Fragments** | Their destinations — they were drafted in destination format precisely so this is a move, not a translation | Merge per the destination's existing structure |

**The scope-guard trio** disambiguates everything that isn't a commitment:

- *Will build later* → **backlog**.
- *Deliberately not building* → **non-goals**.
- *Weighed and chose another option* → a **Declined:** line inside the deciding ledger entry,
  with its evidence and re-evaluate condition — carried into the harvested decision record.

**Directional steering is not feature truth.** A harvested principle informs many decisions and
changes slowly; a feature fact belongs to its feature doc and changes at code speed. The harvest
**links** between the steering layer and feature docs — it never duplicates prose across them,
and it never invents a new top-level home for principles (they land in the *existing* living
docs).

Rejection rationale and reasoning chains must have explicit destinations — options-considered
sections, decision changelogs — or the uselessness test fails: the folder may never be deleted
into a knowledge loss.

## The uselessness test

The deletion-safety gate: after the apply, the post-harvest living docs alone must be enough.

- **The reader is always a freshly spawned, context-free agent** — a full-context reader cannot
  cold-read; it already knows every undefined term.
- **Isolation is enforced, not instructed:** the cold reader's prompt contains an explicit
  allowed-path list (the manifest's destinations — never the session folder), and the detector
  independently verifies no harvested doc links back into the session folder (BS-HARVEST-01) — a
  link into scaffolding is itself a harvest defect.
- **The task:** reconstruct the design — thesis, commitments, reasoning, declined branches — from
  the allowed paths only.
- **Grading:** the twin diffs the reconstruction against the ledger and thesis and names every
  gap; the session-replay evals audit the grading itself. Anything unrecoverable is a named
  harvest gap → recorded in the manifest (`Result: fail`), fixes enter a new manifest `Round`,
  approved like the first. Iterate until the folder is redundant.

## The move, and the offer

When the detector's move gate is clean: delete `ops/` entirely (transcript-grade residue never
enters git), `git mv` the folder to `docs/history/brainstorms/{topic}/`, set
`Status: harvested`, and update both indexes (row out of `docs/research/Readme.md`, row into
`docs/history/brainstorms/Readme.md`). The move is the completion marker — a folder still under
`docs/research/` is by definition unfinished, which is exactly what the maintenance census reads.

Then the offer, relayed by the facilitator: **delete the moved folder, or commit it.** The user
decides; the design assumes deletion — nothing anywhere may depend on the folder surviving.
Committing is the explicit way to keep git-history forensics; an uncommitted folder deleted here
is gone, and that residual is accepted by design.

## Field lessons — apply

Measured on live harvests; each is the rule, distilled.

- **Run the move gate clean immediately before the move and treat that as the verdict** — the
  gate's checks read `ops/`, which the move deletes, so a post-move re-run fails by construction.
  Verify the post-move state by hand: `Status: harvested`, no `ops/`, both index rows,
  `check-links` clean. And **distil the process record into `state.md` before the move** — the
  sync log dies with `ops/`, and a ten-line dispatch summary is what separates a record that shows
  its workings from one that asserts its commitments from nowhere.
- **Uncommitted harvest artifacts are deleted, not deprecated** — deprecate-in-place protects
  readers holding a pointer, and a never-committed file has none; a tombstone for a
  twenty-minute-old file is ceremony.
- **Audit the *other* decision records for impact at manifest time** — the manifest routes
  through the docs the commitments name and will not think of the neighbours. The test is
  commitment-level, not textual (grep finds nothing); read each AD's Decision and Open Questions
  against the new commitments, and report the unimpacted verdicts with evidence too.
- **A manifest enumerates sites; the file you open contains more of them.** Fix every
  same-doctrine site inside a file the manifest already opens — a self-contradicting document is
  worse than a wider diff — but never wander into an unnamed file: that becomes a backlog row.
  Say which you did, per row, in the application record.
- **Re-run the uselessness test when the destination *set* changes**, not only when content does —
  a consolidation that moves referrers produces a document set no cold reader has graded. The
  recurring find: a truth doc stating a decided-but-unbuilt mechanism in the present tense; the
  fix is one clause naming the unbuilt prerequisite.
- **Retirement wording beats suppression.** doc-lint's heuristics block the honest retirement
  sentence (`superseded by`, `no longer`); rephrase with no loss of meaning — "retired by
  AD-00N", "is not the product's position", "lives in a package that is gone" — and reach for
  `doc-lint-disable` only when the banned phrase is itself the claim.
- **Amending another session's draft: change the contradicting claim everywhere it is asserted,
  and nothing else** — a claim stated in nine places and fixed in three leaves the doc worse; a
  one-paragraph note saying what moved and what did not keeps the amendment legible to the doc's
  author.
- **A suppression marker is a dated assertion about code, and it decays faster than the docs
  around it.** A harvest that deletes doctrine rows corrects their wrappers first — a false wrapper
  is a correction row in the manifest, never collateral of a delete. A phantom guard propagates by
  citation: grep the guard *path*, not its name, and count live docs separately from frozen ones,
  which record what was believed and are not edited.
- **Retiring a guardrail row edits three artifacts.** The row is cited by ID from feature docs and
  frozen plans, wrapped in a marker asserting where its code lives, and restated in the
  out-of-scope register at the foot of the same file: keep the ID and mark the row retired with a
  pointer, correct the wrapper, and replace the register bullet with a pointer — otherwise the file
  contradicts itself twenty lines apart.
- **Size the decision records to the repo's AD doctrine before writing them.** One decision per
  subject argued feels natural and produces micro-ADs where the rule is one overarching AD per
  architectural subject; the test at manifest time is whether a reader would ever need one record
  without the others. The safe shape is one AD per plane with a section per settled subject — each
  keeping its Decision, Why and Declined table — and a separate AD only for a genuinely different
  subject. Link with section anchors where a bare pointer loses precision, and verify anchors by
  hand: the link checker strips them before resolving.
- **At manifest time, read every existing AD's Decision and Open Questions against the new
  commitments.** A harvest routes only through the docs its commitments name, and grep finds
  nothing because the ledger never names the others; report the unimpacted verdicts with their
  evidence too.
- **A manifest row names one site; the file you open holds more.** Fix the same-doctrine sites
  inside a file the manifest already opens, but never wander into an unnamed file — that becomes a
  backlog row, because a canonical doc is not rewritten outside an approved scope. Say which you did,
  per row, in the application record.
- **The per-file lint hook reads intermediate states.** It appends queue rows from mid-edit files;
  run the linter over the whole edited set before declaring the apply done, and leave the stale
  rows for the facilitator rather than draining them.
