# Persistent memory — booth _Last updated: 2026-09-22_ > **Always check for `/tmp/booth-dev-handoff.md`** — if it exists and its > `Written:` stamp is under 8 hours old, read it (it carries the in-flight > handoff from the previous session), then delete it. Older than 8 hours: > stale — delete it unread. ## Repo purpose The Booth is the fleet's **operator-review surface**: agents post work by making a folder under `~/booth-data`, the operator looks at it and judges it in the browser, and the judgment gets back to the agent that posted it. It was built as a file-shuttle and is being converged, unit by unit, onto the review loop it turned out to actually be. ## Current state / in-flight _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, U4 and U5 are landed.** U1 `ce598b3`; U2 `c7f9437` → `v0.2.0`, `5e41108` → `v0.2.1`, `026a1fc` → `v0.2.2`; U5 `c015a91` + `95beede` → `v0.3.0`. **U4 landed 2026-09-22** — 396 tests green (341 → 396), deployed and verified live, 24/24 booth pages 200, layout probe clean. - **U4 IS NOT YET RELEASED — the version bump is an open operator decision.** Recommended **v0.3.0 → v0.4.0 (minor)**: U4 changes what `keep` MEANS for 17 agent handles ("stop pressing keep when you are only waiting"), which is release-note-worthy at the pre-1.0 bar and the same tier U2 and U5 took. The defensible alternative is v0.3.1 if U4 reads as internal plumbing, since no CLI verb or URL changed shape. **Commits are not releases**, so the work is committed unbumped and untagged; the tag waits on his word and nothing is blocked by the wait. - **THE NEXT UNIT IS THE OPERATOR'S CALL.** U3 (declared embed seam) and U6 (benches) are both unblocked; U7 waits on the rest. U6 is independent of everything and was conceptually unblocked by U5 giving job 5 a home; U3 is where verbatim-booth provenance was deferred to, and U4 added a fourth reason to want it — a verbatim booth has no Booth-rendered header, so its lifetime line lives only on the index card and the marks page. - **No gate is outstanding.** All three ran on U4 and were folded in: the `/heid-contract-review` panel (`01M34VX0SH23Y3VC92E7GM4S70`), the `/heid-code-review` panel (`01M34WAFJC3RTERFYBBZJN1SVG`) and the `/heid-bug-hunt` (`01M34Y2R0RAJRSN36Q8K4KAB36`). All loops closed with heid. The U5 round's three are also closed (`01M340PNVRS21HPASZT38PXQPN`, `01M341E9XAPZEFBSPK9HPGAM0S`, `01M343SXX27Z47C3STXXRC7M42`). - **Two dated predictions are pending and must not be forgotten.** U5's adoption re-measure on **2026-09-29** (two counts, see its entry — already at 3 of 24 announced and 2 with a `why`, all from peers told nothing), and the `.forever` re-count **on or after 2026-10-06**, a fortnight after U4 landed, which is U4's success criterion. ⚠ Only 4 booths carry marks at all, so the hold's live blast radius is small and the prediction rests on both halves of U4 — see its entry for what a null result would and would not mean. - **Three methodology proposals from this session sit with the operator**, routed by heid rather than decided unilaterally: reshaping the paraphrase gate toward a drift-check for narrative-heavy contracts, a standing "green-tests-prove-nothing" direction for the code-review gate, and regin's table-vs-signature consistency pass. They are changes to the `/heid*` skills, not to this repo. - The booth set churns hard: 26 → 24 during this session as the sweeper ran. Re-count rather than trusting any number written here. ## Recent decisions - `[2026-09-22]` **U4 landed — lifetime is derived, not declared** — three states, viewing is activity, and no new arithmetic anywhere → `persistent-memory.d/2026-09-22-u4-derived-lifetime-landed.md` - `[2026-09-22]` **The `.forever` diagnosis got a live positive control** — 3 of the 4 booths awaiting an answer were ALSO hand-pinned — RE-COUNT 2026-10-06 → `persistent-memory.d/2026-09-22-forever-had-a-live-positive-control.md` - `[2026-09-22]` **Four independent paths to one fail-open delete** — the bug-hunt panel's class, and the zsh word-splitting trap that shipped an empty bundle → `persistent-memory.d/2026-09-22-four-paths-to-one-fail-open-delete.md` - `[2026-09-22]` **Two reads of one file are not one read of one state** — a TOCTOU seam that composes two correct readers into a fail-open delete → `persistent-memory.d/2026-09-22-two-reads-are-not-one-state.md` - `[2026-09-22]` **Five of seven INV falsifiers did not falsify anything** — read before writing a *Falsifiable:* line; a green test cited one rather than being one → `persistent-memory.d/2026-09-22-vacuous-falsifiers.md` - `[2026-09-22]` **The third one-branch template miss** — this repo's recurring blind spot; read before adding a fact to any template → `persistent-memory.d/2026-09-22-third-one-branch-template-miss.md` - `[2026-09-22]` **The size cap opened a service-wide hang** — a FIFO has st_size 0; a bound that trusts it inherits what it does not mean → `persistent-memory.d/2026-09-22-size-cap-opened-a-hang.md` - `[2026-09-22]` **An existing test stopped me retiring documented behaviour** — the clean fix for the mtime race would have silently changed TTL doctrine → `persistent-memory.d/2026-09-22-doctrine-not-defect.md` - `[2026-09-22]` **Two U5 panels, and prose reached a released outage** — read the detail before assuming a conformance finding stops at its own module → `persistent-memory.d/2026-09-22-u5-panels-reached-a-released-bug.md` - `[2026-09-22]` **U5's adoption prediction split in two** — the handle rides for free, the why must be learned — RE-MEASURE 2026-09-29 → `persistent-memory.d/2026-09-22-u5-adoption-split-in-two.md` - `[2026-09-22]` **The U2 bug-hunt panel was not ceremony** — the lock-unlink race and the TTL guard that was failing at its own job → `persistent-memory.d/2026-09-22-u2-bug-hunt-panel.md` - `[2026-09-22]` **The lenient reader's blast radius was the whole service** — marks_for runs per booth per index load; a raise there is an outage → `persistent-memory.d/2026-09-22-lenient-reader-blast-radius.md` - `[2026-09-22]` **`booth marks` / `booth answer` got real exit codes** — read it before changing anything the 17 consuming handles call → `persistent-memory.d/2026-09-22-cli-exit-codes.md` - `[2026-09-22]` **`scripts/booth` went from zero tests to five** — they run the real script under system python3, so they also check INV-1 → `persistent-memory.d/2026-09-22-scripts-booth-got-tests.md` - `[2026-09-21]` **v0.2.0 was tagged while a gate was in flight** — the sequencing lesson: if a gate is outstanding, the tag waits → `persistent-memory.d/2026-09-21-v020-tagged-with-a-gate-in-flight.md` - `[2026-09-21]` **A write over a damaged `.marks.json` wiped the booth** — the reads-lenient / writes-strict asymmetry, and why it exists → `persistent-memory.d/2026-09-21-marks-write-wiped-judgment.md` - `[2026-09-21]` **Seam review and cold panel had zero overlap, twice** — evidence for running both; neither substitutes for the other → `persistent-memory.d/2026-09-21-two-gates-are-complementary.md` - `[2026-09-21]` **Every code-changing finding came from the AMBIGUITY pass** — a finding about the /heid-contract-review skill, not about this repo → `persistent-memory.d/2026-09-21-ambiguity-pass-did-the-work.md` - `[2026-09-21]` **Deterministic order is a cross-cutting v1 invariant** — operator directive; read before adding ANY ordered surface → `persistent-memory.d/2026-09-21-deterministic-order-invariant.md` - `[2026-09-21]` **U2 (marks) landed — one primitive for three mechanisms** — what moved where, and the HTTP mirror remote sessions poll → `persistent-memory.d/2026-09-21-u2-marks-landed.md` - `[2026-09-21]` **A partially-answered pick counts as OPEN** — declared, not smuggled; it is the reading that makes U4 correct → `persistent-memory.d/2026-09-21-partial-answer-counts-as-open.md` - `[2026-09-21]` **The U2 seam review earned its place, and how** — inline.place indexes by subscript — the miss a cold panel cannot see → `persistent-memory.d/2026-09-21-u2-seam-review-earned-it.md` - `[2026-09-21]` **Marks are one `.marks.json` per booth** — operator decision with two rejected alternatives; read before restructuring → `persistent-memory.d/2026-09-21-marks-storage-decision.md` - `[2026-09-21]` **U7's section premise is half wrong** — every booth that needs navigation is FLAT — read before starting U7 → `persistent-memory.d/2026-09-21-u7-section-premise-half-wrong.md` - `[2026-09-21]` **`sindra-finalists` is U2's flag motivation, caught live** — evidence, not argument → `persistent-memory.d/2026-09-21-sindra-finalists-is-the-motivation.md` - `[2026-09-21]` **The information architecture and the v1 gate landed** — the single defect the seven units decompose → `persistent-memory.d/2026-09-21-ia-and-v1-gate-landed.md` - `[2026-09-21]` **The `.forever` diagnosis is a falsifiable prediction** — U4's success criterion — re-count a fortnight AFTER U4 lands → `persistent-memory.d/2026-09-21-forever-diagnosis-is-a-prediction.md` - `[2026-09-21]` **Extracted from `eshpfi` into its own repo** — test_booth.py is the regression net the v1 rewrite is checked against → `persistent-memory.d/2026-09-21-extracted-from-eshpfi.md` ## Tried and abandoned - `[2026-09-21]` **Tagging a release while a review gate was in flight** — cost a same-hour v0.2.1 and a correction to 15 handles → `persistent-memory.d/2026-09-21-tagging-with-a-gate-in-flight.md` - `[2026-09-21]` **Letting the write path share the read path's leniency** — a tolerant reader and a tolerant writer are not the same decision → `persistent-memory.d/2026-09-21-tolerant-writer-over-tolerant-reader.md` - `[2026-09-21]` **Letting Jinja hot-reload templates in the deployment root** — caused a live outage: 19 of 25 booths at 500. Why auto_reload=False → `persistent-memory.d/2026-09-21-jinja-hot-reload-outage.md` - `[2026-09-21]` **Five mechanisms to get one question beside one artifact** — the accretion signature this whole v1 rewrite is undoing → `persistent-memory.d/2026-09-21-five-mechanisms-one-job.md` - `[2026-09-21]` **Regex-injecting chrome into arbitrary author HTML** — the defect U3 exists to close → `persistent-memory.d/2026-09-21-regex-injecting-chrome.md` - `[2026-09-21]` **A boolean escape hatch as the lifetime mechanism** — why `.forever` is a symptom; the defect U4 exists to close → `persistent-memory.d/2026-09-21-boolean-escape-hatch-as-lifetime.md` - `[2026-09-21]` **Letting the link board absorb the announce job** — 69% rot; U5 gave the job a home, which is what unblocks U6 → `persistent-memory.d/2026-09-21-link-board-absorbing-announce.md`