Files
booth/persistent-memory.md
T
vh 91fd8bc69d memory: snapshot — U3 released at v0.5.0, pushed and deployed
First push of this repo's history: main was 26 commits ahead of origin/main, so
v0.2.0 through v0.5.0 all reached the Gitea remote in one motion. A future
session can assume a remote exists, which no earlier one could.

Records the open defect U3 found and deliberately did not fix -- a well-formed
.marks.json with a wrong-shaped answer 500s the gallery and marks pages,
measured at 42ea67f so it predates the unit -- and marks it explicitly as
awaiting an operator decision with no issue filed, rather than letting it sit in
a detail file nobody is routed to.

No recommendation is recorded for the next unit. U6 and U7 are genuinely
independent and close different defects; the last two before a 1.0 cut are a
scope-direction call.
2026-09-22 13:00:34 -07:00

15 KiB

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, 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.
  • TWO UNITS LEFT TO v1, and they do not depend on each other. U6 (benches, independent, closes the 69% link-board rot) and U7 (navigation at 270 items, which U3 just unblocked — its only dependency was {U3, U4, U5}). Which goes next is the operator's call. ⚠ Before starting U7, read persistent-memory.d/2026-09-21-u7-section-premise-half-wrong.md: every booth that actually needs navigation is FLAT, so half its premise is already known to be wrong. No recommendation is recorded for this one on purpose — U6 and U7 are genuinely independent, they close different defects, and the last two units before a 1.0 cut are a scope-direction call rather than a dependency one.
  • 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 (<script src="/_booth/embed.js" defer>) and lost no-JavaScript operation. That asymmetry is what made it not a tie.
  • ALL FOUR U3 GATES ARE CLOSED. In-session seam review (5 findings, SR-2 a real payload-shape bug); /heid-contract-review (01M351WKV666D681SSRNY7D7X6, 12 findings, 10 adopted, 2 already settled by the seam review while it was in flight, 1 declined); /heid-code-review (01M352RXV1ZET566KV73C7TSB8, 3 more vacuous falsifiers
    • the prototype-pollution bug); /heid-bug-hunt (01M352TPCSN52G6NGJ07T5WSGY, 5 net-new, incl. the byte-exactness break). Seven of the adopted findings were CODE fixes, not wording — the cold gates were not ceremony on this unit. The seam review ran in-session and is folded in — five findings as a table at the end of the U3 contract, and SR-2 was a real payload-shape bug the cold panel structurally could not see. U4's three and U5's three are all closed (01M34VX0SH23Y3VC92E7GM4S70, 01M34WAFJC3RTERFYBBZJN1SVG, 01M34Y2R0RAJRSN36Q8K4KAB36; 01M340PNVRS21HPASZT38PXQPN, 01M341E9XAPZEFBSPK9HPGAM0S, 01M343SXX27Z47C3STXXRC7M42).
  • ⚠ ONE DEFECT IS OPEN, FOUND BUT DELIBERATELY NOT FIXED, AND IT HAS NO TRACKING SURFACE YET. A .marks.json that is well-formed JSON with a wrong-shaped answer 500s the gallery page and the marks page — reproduced, and measured at 42ea67f so it PREDATES U3. U3 guarded its own surface (_safe_fragments) and left those two alone rather than widening the unit; the gallery is named out of scope in the U3 contract. The operator was asked where the guard belongs and has not answered — _hydrate (session recommendation: one predicate, one place, every surface inherits it), per render site, or the template. No issue filed. Read persistent-memory.d/2026-09-22-a-wrong-shaped-answer-500s-the-gallery.md before touching marks rendering anywhere.
  • 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.
  • FOUR methodology proposals sit with the operator, all UNTRACKED BY OPERATOR CHOICE (no issue, no ticket — they are /heid* skill changes, not this repo's work, and are recorded here only so they are not lost). Three are from the U5 round: 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. The fourth is new and is the one with evidence behind it: a contract-time VACUITY PASS — for each invariant, name a change that defeats it and check the test goes red. Regin and Kimi proposed it independently on the U4 paraphrase round; the code-review panel then showed five of seven U4 falsifiers were vacuous, and heid rates that the strongest single data point for it so far. See persistent-memory.d/2026-09-22-vacuous-falsifiers.md.
  • The booth set churns hard: 26 → 24 → 25 across the last two sessions as the sweeper ran. Re-count rather than trusting any number written here.

Recent decisions

  • [2026-09-22] U3 landed — the page declares the seam, the Booth mounts into it — ten regexes against author HTML replaced by a substring test and a + → persistent-memory.d/2026-09-22-u3-declared-embed-seam-landed.md
  • [2026-09-22] A wrong-shaped answer 500s the gallery and the marks page — PRE-EXISTING (measured at 42ea67f), NOT U3; the v0.2.2 lesson is only half-implemented → persistent-memory.d/2026-09-22-a-wrong-shaped-answer-500s-the-gallery.md
  • [2026-09-22] The browser became a test surface — READ BEFORE TOUCHING playwright IN pyproject; the pinned upper bound is the foot-gun, and these tests SKIP rather than fail → persistent-memory.d/2026-09-22-the-browser-became-a-test-surface.md
  • [2026-09-22] A vacuity pass that tries the contract's own mutation agrees with itself — U3 ran one, reported 7/7, and a cold panel then showed one of the seven was vacuous; READ BEFORE WRITING A Falsifiable: LINE → persistent-memory.d/2026-09-22-seven-of-seven-falsifiers.md
  • [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] No fleetwide notice for U4, and what that does to the prediction — READ BEFORE THE 2026-10-06 RE-COUNT; a flat rate does not falsify the diagnosis → persistent-memory.d/2026-09-22-no-notice-and-what-it-does-to-the-prediction.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