feat(u3): a verbatim report declares the seam, the Booth mounts into it

A booth that ships its own index.html was served through ten regular
expressions applied to markup the Booth did not write: six in
wrap_verbatim_html hunting for somewhere to hang a favicon and a chip, four
in booth/inline.py substituting rendered ask markup into the author's own
tags. Both worked. Both were the most fragile thing in the service, on the
path the operator uses most.

The whole class is replaced by a declared seam. A report carries one line —
<script src="/_booth/embed.js" defer></script> — and the chrome mounts
through DOM APIs. What the server does to author HTML is now, in full:

    return html if declares_embed(html) else html + EMBED_SCRIPT_TAG

Two substring tests and a concatenation. Both of the old wrapper's hard
constraints stop existing rather than being satisfied more carefully:
nothing can displace a leading doctype into quirks mode and nothing can push
the charset meta out of its detection window, because nothing in front of
them ever moves. A page that declares the seam is served exactly as written.

Fragments are still rendered by the _ask_inline.html macros and handed over
GET /b/<name>/embed.json; embed.js places them and decides nothing. Openness
comes from open_marks, order from (created, id), questions in declaration
order. A single-question pick normalizes to key None, so the payload carries
questions as a list rather than an object — keying by name would serialize
that as the string "null".

Placement is an anchor fill, not a replacement: el.insertAdjacentHTML(
'beforeend'), so an author's wrapper and its contents survive. The regex it
replaces was eating the opening tag of dfa-concepts' styled .ask blocks and
orphaning their headings, live, unreported.

data-booth-mark is canonical; data-booth-ask stays a kept alias because two
live reports use it. The comment placeholders are dropped — no users.

Declared cost: the verbatim path now needs JavaScript. The never-invisible
guarantee holds through the index badge and /b/<name>/marks, both of which
render server-side.

Deleted: booth/inline.py entire, wrap_verbatim_html and its six patterns,
_BACK_CHIP, asks_chip, inject_asks, FAVICON_LINK, the styles() macro.

Tests 410 -> 434. tests/test_embed_browser.py drives a real Chromium: the
placement algorithm and the form= binding of a scattered multi-question form
cannot be observed any other way, and that binding was measured rather than
assumed (N=3 per condition, with a form-first positive control and a
points-at-nothing negative control).

Contract: docs/contracts/u3_declared_embed_seam.contract.md, with the
in-session seam review and the cold contract panel both recorded. Two of the
panel's findings were code fixes: a vacuous INV-3 falsifier that a renamed
regex walked straight through, and a bare-substring seam detection that read
a report merely quoting the path as declaring it and silently served it with
no chrome.
This commit is contained in:
vh
2026-09-22 10:43:41 -07:00
parent 42ea67f33f
commit 87e2c5364c
17 changed files with 2015 additions and 503 deletions
+33 -24
View File
@@ -21,11 +21,13 @@ _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** — 410 tests green (341 → 410), deployed and
verified live, 25/25 booth pages 200, layout probe clean. Tree clean at
`8f81d8f`; NOT PUSHED (push is the operator's call and he has not given it).
- **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** — 431 tests green (410 → 431), deployed and verified
live, 21/21 booth pages 200, and each of the four verbatim booths grew by
exactly 46 bytes, which is `len(EMBED_SCRIPT_TAG)` — one append, nothing else.
NOT PUSHED (push is the operator's call and he has not given it).
- **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
@@ -35,25 +37,29 @@ _As of 2026-09-22:_
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.
- **THE NEXT UNIT IS THE OPERATOR'S CALL and has not been made.** U3 (declared
embed seam) and U6 (benches) are both unblocked; U7 waits on the rest.
**The session's recommendation is U3**, on three grounds that do not need
re-deriving: (1) U7 depends on {U3, U4, U5}, so U3 is the only remaining unit
on the critical path to the endgame — U6 is independent and can land any time;
(2) U4 added a fourth reason to want it, because a verbatim booth has no
Booth-rendered header and so carries its lifetime line only on the index card
and the marks page; (3) it is the biggest DELETER in the plan — `inline.py`
entire, six regexes against arbitrary author HTML, two floating chips and a
route — and regex-injecting into author HTML is named in the IA doc as the
single most fragile thing in the service. ⚠ The counter-argument, stated
because it is real: U3 is also the RISKIEST unit, since it changes how every
verbatim booth renders and verbatim booths are the operator's own reports.
U6 is the low-risk session and closes the biggest single number (69% rot).
- **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`,
- **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.
- ⚠ **U3's RELEASE TIER IS WITH THE OPERATOR.** It reads minor — the verbatim
path gained a declared public API (`<script src="/_booth/embed.js" defer>`),
a JavaScript dependency it did not have, and an author-facing anchor syntax —
and **minor needs his explicit approval**. `pyproject.toml` still says
`0.4.0`; nothing is tagged. Do not bump it on your own.
- ⚠ **TWO U3 GATES ARE STILL IN FLIGHT** and must be drained, triaged and
answered: `/heid-code-review` (`01M352RXV1ZET566KV73C7TSB8`) and
`/heid-bug-hunt` (`01M352TPCSN52G6NGJ07T5WSGY`), both dispatched 17:32Z.
**The `/heid-contract-review` panel (`01M351WKV666D681SSRNY7D7X6`) is CLOSED**
— 12 findings, 10 adopted, 2 already settled, 1 declined, reply sent. Two of
its adopted findings were CODE fixes, not wording: the vacuous INV-3 falsifier
and the bare-substring seam detection. 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`).
- **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
@@ -79,6 +85,9 @@ _As of 2026-09-22:_
## 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]` **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`