diff --git a/persistent-memory.d/2026-09-22-three-cold-panels-on-one-unit.md b/persistent-memory.d/2026-09-22-three-cold-panels-on-one-unit.md
new file mode 100644
index 0000000..f922203
--- /dev/null
+++ b/persistent-memory.d/2026-09-22-three-cold-panels-on-one-unit.md
@@ -0,0 +1,53 @@
+# Three cold panels on one unit, and what each lens could only see alone
+
+_2026-09-22 · booth_
+
+U6 ran all three `/heid*` gates plus two in-session passes. **Every one of the
+five found something the others structurally could not**, which is the
+strongest evidence this repo has for running them all rather than picking one.
+
+## The scoreboard
+
+| gate | when | found |
+|---|---|---|
+| **seam review** (in-session, sibling-aware) | before code | **3 real contract defects** — a claim about a sibling test that was false, `resolve_booth` named as a per-row predicate when it RAISES 404, and silence on percent-encoding |
+| **adversarial self-pass** (in-session) | during | **4 defects** — a FIFO hang, `unquote` leaking control characters, a fail-closed-by-accident guard, a stranded scratch file |
+| **`/heid-contract-review`** (4 arms) | parallel | **the import/apply selection gap, 4-of-4** — plus per-field cap semantics, and two passages of the document contradicting each other |
+| **`/heid-code-review`** (4 arms) | parallel | **3 surface-drift findings 4-of-4**, an IPv6 identity bug, and **a falsifier that could not fail** |
+| **`/heid-bug-hunt`** (4 arms) | parallel | a `
` inside a ``, a symlink disagreement, an append outside its lock |
+
+## The three findings worth remembering
+
+**1. The highest-value finding was a MISSING FEATURE, and the paraphrase lens
+found it.** `bench import --apply` registered every candidate while the same
+contract said ~14 of 35 were bookmarks that must stay on the board. The dry-run
+report existed *because* the decision is not mechanizable — and then `--apply`
+ignored it. A code-vs-contract lens cannot see this: the code matched the
+contract. Only reading the contract *as prose*, for what it promises a human,
+surfaces "these two sentences cannot both be satisfied."
+
+**2. A falsifier that could not fail, again.** INV-4's tie-break test went
+through the registry, and `_write_all` serializes with `sort_keys=True` — so
+both insertion orders came back off disk already id-sorted, and removing the
+tie-break left the test green. Same class as the five vacuous U4 falsifiers.
+**We ran a vacuity pass and still shipped one**; a cold reader caught it. See
+[[2026-09-22-vacuous-falsifiers]].
+
+**3. The single sharpest line came from a cross-module memory no new-module
+review could have.** Three bug-hunt arms independently noted that **this repo
+had already paid for the `RecursionError` class in `marks.py`, with a test
+documenting it — and the new module re-introduced the unguarded parse.** No
+amount of reading `benches.py` in isolation surfaces that.
+
+## Complementarity, measured in both directions on one diff
+
+The bug-hunt panel found **three live defects the in-session pass missed** — all
+three invisible to any test (a layout nesting, a symlink disagreement, a
+lock-ordering race). The in-session pass had **already closed three of that
+panel's four convergent findings** before the reply landed. Neither substitutes
+for the other, and this round is the cleanest specimen of it so far.
+
+**One finding was declined**, with reasoning recorded in the contract: on a host
+where `booth.links` cannot be imported, `booth link` now refuses every URL
+rather than only booth ones. A guard that fails open is not a guard, and that
+state is a broken install where most of the CLI is equally broken.
diff --git a/persistent-memory.d/2026-09-22-u6-benches-landed.md b/persistent-memory.d/2026-09-22-u6-benches-landed.md
index 4bb864a..0e85d83 100644
--- a/persistent-memory.d/2026-09-22-u6-benches-landed.md
+++ b/persistent-memory.d/2026-09-22-u6-benches-landed.md
@@ -58,8 +58,10 @@ SR-4 and SR-5 were **verified rather than assumed**: both `list_booths` and
a dot, so the registry is safe from the sweeper by two guards, not one. Had
either been absent the design would have eaten its own registry on tick one.
-## Still open at the time of writing
+## How it closed
-Both cold gates are IN FLIGHT — contract review `01M35BWCJ806MT75NA630Y4WFH`,
-code review `01M35CK8YKEKMV7T15JXEF6A8N`. The bug-hunt has not run. **Committed
-but NOT tagged**, per the v0.2.0 lesson: if a gate is outstanding, the tag waits.
+All three cold gates came back and were folded in full, with exactly one finding
+declined. Released as `v0.6.0` — see [[2026-09-22-u6-benches-released]] and
+[[2026-09-22-three-cold-panels-on-one-unit]]. The tag waited for the gates, per
+the v0.2.0 lesson, and that sequencing was right: the panels produced ten code
+fixes after this entry was first written.
diff --git a/persistent-memory.d/2026-09-22-u6-benches-released.md b/persistent-memory.d/2026-09-22-u6-benches-released.md
new file mode 100644
index 0000000..84c9d57
--- /dev/null
+++ b/persistent-memory.d/2026-09-22-u6-benches-released.md
@@ -0,0 +1,58 @@
+# U6 released as v0.6.0 — benches, and the number that was two defects
+
+_2026-09-22 · booth_
+
+**The sixth of seven v1 units. Only U7 remains.** 444 → 607 tests. Tagged
+`v0.6.0` (minor, operator-approved). **NOT PUSHED** — push is his call.
+
+## What shipped
+
+- **`booth/benches.py`** — stdlib-only AND sibling-free. `Bench`,
+ `normalize_bench_url` (the identity), a lenient `read_benches` on the render
+ path and a strict `_load_strict` on the write path, `mkstemp` + `fsync` +
+ `os.replace` under an flock, and `order_benches` with a stated total order
+ `(state rank, name casefolded, id)`.
+- **`links.booth_target`** — ONE predicate for "is this a booth URL",
+ host-agnostic, path-shaped, percent-decoding, control-character-rejecting,
+ never raising. Three callers: the CLI refusal, the board's dead marker,
+ `bench import`.
+- **`booth link` refuses** a booth URL (naming `booth new --why`) and a
+ credentialed one, writing nothing in either case.
+- **The board marks dead rows** — 161 of 221 live. Removal stays the operator's
+ two clicks through the bulk control that already existed. Nothing deletes.
+- **`booth bench add|ls|state|rm|import`**. `--apply` REQUIRES the ids.
+
+## The decision that shaped the unit, and it was measured
+
+**The design doc's headline "69% rot" was two defects wearing one number**, and
+splitting them is what made the unit the right size — see
+[[2026-09-22-one-number-was-two-defects]]. 178 of 221 rows are booth
+announcements (156 already dead) whose *cause* U5 had already closed; only 8 are
+the bench re-post the registry fixes. A unit scoped off the unsplit number would
+have built the registry, declared victory, and left 178 rows rotting.
+
+**Identity is the FULL normalized URL, not the origin**, and that was measured
+rather than chosen: origin identity merges eight distinct gitea repositories
+into one row, three unrelated HuggingFace model cards into one, and the two LRPG
+surfaces on `10.100.10.50:8321` — *the design doc's own example of two real
+benches* — into one. It destroys more than it deduplicates.
+
+**`booth link` is NOT deprecated**, against the design doc's plan. Roughly 14 of
+the 35 distinct non-booth targets are reference bookmarks (repos, model cards,
+docs) for which the board is the right and only home. Deprecating it would have
+evicted a third of its live content. The IA doc is corrected.
+
+## The gates
+
+All four closed, and every one paid — see
+[[2026-09-22-three-cold-panels-on-one-unit]]. Contract review
+`01M35BWCJ806MT75NA630Y4WFH`, code review `01M35CK8YKEKMV7T15JXEF6A8N`, bug hunt
+`01M35CRRK2RTVWWF1BN09AFQG3`, one consolidated reply sent to heid at
+`01M35FY8QZTB9E5VR4WXDSBGEV`.
+
+## Live evidence, unplanned
+
+The sweeper ran mid-session: **23 booths → 19**, and dead board rows went
+**156 → 161 in about fifteen minutes**. The defect compounding in real time
+while the fix was being built — which is the argument for U6-before-U7 playing
+out on its own.
diff --git a/persistent-memory.md b/persistent-memory.md
index 5a939b0..972bf38 100644
--- a/persistent-memory.md
+++ b/persistent-memory.md
@@ -19,109 +19,65 @@ loop it turned out to actually be.
_As of 2026-09-22:_
-- **v1 is gated on seven units** in `ROADMAP.md`, dependency-ordered
- **U1 → U2 → {U3, U4, U5} → U7**, with **U6 independent**.
-- **U1, U2, U3, U4 and U5 are landed — the whole middle tier is closed.** U1
- `ce598b3`; U2 `c7f9437` → `v0.2.0`, `5e41108` → `v0.2.1`, `026a1fc` →
- `v0.2.2`; U5 `c015a91` + `95beede` → `v0.3.0`; U4 `c3a97c1` → `v0.4.0`.
- **U3 landed 2026-09-22 and released as `v0.5.0`** — 444 tests green
- (410 → 444), deployed and verified live, 23/23 booth pages 200, and each of
- the four verbatim booths served at exactly +46 bytes, which is
- `len(EMBED_SCRIPT_TAG)` — one append, nothing else. `87e2c53` is the unit,
- `5c20e2f` the panel fixes, `7996fbd` the release. **PUSHED AND DEPLOYED**
- 2026-09-22 on the operator's word — and it was **the first push of this
- repo's history**: `main` was 26 commits ahead of `origin/main`
- (`ce598b3..7996fbd`), so `v0.2.0` through `v0.5.0` all reached
- `git@gitea.phasefinal.com:vh/booth.git` in the same motion. `main` tracks
- `origin/main` clean now; a future session can assume a remote exists, which
- no earlier one could.
-- **U4 released as `v0.4.0`** (operator approved the minor on 2026-09-22).
- `c3a97c1` is the unit; the release commit carries the pre-existing fixes the
- bug-hunt panel surfaced in touched files. The tag waited for the last gate to
- close, per the `v0.2.0` lesson — see Tried and abandoned.
-- ⚠ **The 17 consuming handles are NOT being told** that `keep` no longer means
- "waiting on an answer" — operator decision, 2026-09-22, no broadcast. This is
- deliberate and it CHANGES HOW THE 2026-10-06 RE-COUNT READS: the hold rides
- for free, but not-pressing-`keep` has to be learned, so a flat `.forever` rate
- does not falsify anything. Read its entry before measuring.
-- **U6 LANDED 2026-09-22 — ONE UNIT LEFT TO v1.** Benches: a registry keyed by
- normalized URL, `booth link` refusing a booth URL, dead rows marked on the
- board, and a non-destructive `bench import`. 444 → 555 tests, deployed and
- verified live (23/23 booths 200, 156 of 221 rows marked dead — matching an
- independent pre-implementation count exactly). ⚠ **COMMITTED BUT NOT TAGGED
- AND NOT RELEASED**: both cold gates were still in flight at commit time
- (contract review `01M35BWCJ806MT75NA630Y4WFH`, code review
- `01M35CK8YKEKMV7T15JXEF6A8N`) and the bug-hunt had not run. Per the v0.2.0
- lesson, the tag waits for the gates. → `persistent-memory.d/2026-09-22-u6-benches-landed.md`
-- ⚠ **U6 WAS CHOSEN WITHOUT THE OPERATOR ANSWERING.** He set an autonomous goal
- ("hydrate and land next unit stated in handoff") and the handoff named no
- unit. The session recommended U6 on measured grounds (its defect compounds —
- 145 → 156 dead rows in a day — while U7's is dormant, and U6 had no
- unresolved design questions) and proceeded rather than blocking. **The scope
- call is still his to reverse**; nothing is pushed and nothing is tagged.
-- **U7 IS THE LAST UNIT, and its premise degraded again.** ⚠ Read
+- **NOTHING IS IN FLIGHT.** U6 (benches) landed, all four review gates closed,
+ **released as `v0.6.0`** and deployed. Tree clean at `3296a86`, 607 tests
+ green, 19/19 booths 200 live. ⚠ **NOT PUSHED** — push is the operator's call
+ and he did not give it this session; `main` is ahead of `origin/main`.
+ → `persistent-memory.d/2026-09-22-u6-benches-released.md`
+- **v1 is gated on seven units. SIX ARE LANDED. U7 IS THE LAST ONE.** U1
+ `ce598b3`; U2 → `v0.2.0`/`v0.2.1`/`v0.2.2`; U5 → `v0.3.0`; U4 → `v0.4.0`;
+ U3 → `v0.5.0`; U6 `1c3ce5d` → `v0.6.0`.
+- ⚠ **Before starting U7, read
`persistent-memory.d/2026-09-21-u7-section-premise-half-wrong.md` AND
- re-count first. On 2026-09-22 the four large booths U7 was sized against
- (`pancake-v3-full`/`pancake-v4-full` at 270 items, `sindra20-engines`,
- `sindra-finalists`) had ALL been swept. Largest live booth is `miranda-is` at
- **92 items, flat**. Two of 23 booths have subfolders and **both are reports**.
- Sections buy close to nothing; the rail, filters and grid keyboard are the
- unit.
-- **U3's tier was MINOR and the operator approved it** (2026-09-22). The
- argument that settled it, recorded because the tie-break rule says patch: a
- capability arrived AND one left — the verbatim path gained a declared public
- API (`