# U3 landed — the page declares the seam, the Booth mounts into it _2026-09-22 · booth_ **Ten regular expressions against author-written HTML are gone.** 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. What replaced them, in full: ```python return html if declares_embed(html) else html + EMBED_SCRIPT_TAG ``` A substring test and a `+`. **Both of the old wrapper's hard constraints stopped existing rather than being satisfied more carefully** — nothing can displace a leading doctype into quirks mode and nothing can push the charset `` out of its first-1024-byte window, because nothing in front of them ever moves. ## What moved where | was | is | |---|---| | `wrap_verbatim_html` + 6 regexes | `embed_verbatim` — one `in`, one `+` | | `booth/inline.py`, 119 lines | deleted; `form_id` survived into `app.py` | | `_BACK_CHIP`, `asks_chip` | built in the DOM by `embed.js` | | `inject_asks` | `GET /b//embed.json` + placement in `embed.js` | | `_ask_inline.html`'s `styles()` | the CSS lives in `embed.js` | | `FAVICON_LINK` string injection | `document.querySelector('link[rel~="icon"]')` | **The fragments are still rendered by Jinja.** `embed.js` places what comes back and never builds one — a second renderer in JavaScript would be the same bug INV-1 exists to stop, in a new language. The payload also decides openness (`open_marks`) and order, so the page has no opinion about either. ## The thing the contract got wrong, and the seam review caught The payload first keyed `questions` by question key. **A single-question pick normalizes to `questions: [{"key": None, …}]`** (`asks.normalize_ask`, the `multi: False` branch), and `json.dumps` writes that key as the string `"null"` — inventing a name that collides with a real key. Every one-question ask in the fleet would have hit it, including the live `sindra-voice-1`. `questions` is a LIST of `{key, html}` now; the key is nullable, and declaration order rides in the format instead of leaning on object-key insertion order. The cold contract panel could not have found this: it is a fact about `booth/asks.py`, which an artifact-only reader never sees. Third time the seam review has caught what the cold pass structurally cannot — see [[2026-09-21-two-gates-are-complementary]]. ## The live report that was already subtly broken `dfa-concepts/index.html` writes `

The one asset that must survive

`. `_EL_RE` matched the **opening tag** and replaced it, so the author's `.ask` wrapper class vanished, the heading was orphaned and the `
` went stray. Nobody filed a bug, because a page that is 95% right does not look broken. `el.insertAdjacentHTML("beforeend", frag)` keeps the element and its contents and puts the fragment inside. Verified live in a real browser: 5 author `.ask` wrappers intact, 5 headings intact, 14 radios mounted inside them, zero console errors. **The replacement is not just less fragile, it renders the operator's own report more faithfully than the thing it replaced.** ## The cost, stated because it is real The verbatim path used to work with **no JavaScript** — server-rendered ask, plain form POST, HTML5 `form=` binding resolved at parse time. It needs the script now. The operator's 2026-09-21 ruling accepts that; this entry records the consequence so nobody meets it as a surprise. The never-invisible guarantee survives in a weaker and still-true form through surfaces needing no script: the index card's open-mark badge, and `/b//marks`. ## Anchor syntax `data-booth-mark` is canonical (U2 made an ask one shape of mark). `data-booth-ask` is a kept alias — 2 of the 4 live verbatim booths spell it that way, in the operator's own reports, and the alias is one clause in one selector string. The `` comment forms were **dropped, not ported**: zero users across all 21 live booths, and a page that used one falls back to the append path, so its ask still renders. ## Verification 431 tests (410 → 431). Live: all 21 booths 200, and each of the four verbatim booths grew by exactly 46 bytes — `len(EMBED_SCRIPT_TAG)`, one append, nothing else. Related: [[2026-09-22-the-browser-became-a-test-surface]], [[2026-09-22-seven-of-seven-falsifiers]], [[2026-09-21-regex-injecting-chrome]].