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:
@@ -206,21 +206,41 @@ a real DOM API. Marks land at `data-booth-mark="<id>"` anchors, which keeps the
|
||||
page*. If the line is absent, the Booth injects it at **one** insertion point, so
|
||||
every existing verbatim booth keeps working untouched.
|
||||
|
||||
**What this deletes**, and this is the whole point of the decision:
|
||||
**What this deleted** — landed as U3, 2026-09-22:
|
||||
|
||||
- `booth/inline.py` — 114 lines of placeholder DSL, entirely
|
||||
- `booth/inline.py` — 119 lines of placeholder DSL, entirely. One line survived:
|
||||
`form_id`, which builds the shared `<form>` id scattered question groups bind
|
||||
to, and which moved to `app.py` beside the route that renders them.
|
||||
- `wrap_verbatim_html` and its six regexes against arbitrary HTML
|
||||
(`_HEAD_CLOSE_RE`, `_HTML_OPEN_RE`, `_DOCTYPE_RE`, `_BODY_CLOSE_RE`,
|
||||
`_HTML_CLOSE_RE`, `_ICON_RE`) and the doctype/charset-ordering constraints
|
||||
they are threading
|
||||
- `_BACK_CHIP`, `asks_chip` — two floating chips positioned by guessed offsets
|
||||
- `GET /b/<name>/asks` — the standalone page that existed only because a verbatim
|
||||
booth could not show its own asks
|
||||
`_HTML_CLOSE_RE`, `_ICON_RE`) **and both of the constraints they were
|
||||
threading.** Not satisfied more carefully — gone: nothing can displace a
|
||||
leading doctype into quirks mode and nothing can push the charset `<meta>`
|
||||
out of its detection window, because the Booth only ever APPENDS now.
|
||||
- `_BACK_CHIP`, `asks_chip` — two floating chips positioned by guessed offsets.
|
||||
embed.js builds both in the DOM.
|
||||
- the `styles()` macro. The scoped `.bk-ask-*` rules live in embed.js next to
|
||||
the code that mounts them, emitted once by construction instead of by a
|
||||
seen-set.
|
||||
- `GET /b/<name>/asks` was already a 308 into `/marks` by U2; this unit left it
|
||||
there. The standalone page it named is gone, but the URL is in the operator's
|
||||
history and in landed reports, and a dead link teaches nothing.
|
||||
|
||||
Regex-injecting into arbitrary author HTML is the single most fragile thing in
|
||||
the service, and it is load-bearing for the operator's most important workflow.
|
||||
**What replaced them is a substring test and a `+`.** `if EMBED_SRC not in
|
||||
html: html += EMBED_SCRIPT_TAG`. A page that declares the line is served with
|
||||
nothing added to it at all.
|
||||
|
||||
Regex-injecting into arbitrary author HTML was the single most fragile thing in
|
||||
the service, and it was load-bearing for the operator's most important workflow.
|
||||
A declared seam costs the author one line and removes the whole class.
|
||||
|
||||
**What it cost, stated because it is real.** The verbatim path used to work with
|
||||
no JavaScript: an ask rendered server-side and submitted through a plain form.
|
||||
It now needs the script. The guarantee that an ask is never invisible survives
|
||||
in a weaker and still-true form through surfaces that need no script — the index
|
||||
card's open-mark badge, and `/b/<name>/marks`, which renders every mark
|
||||
server-side.
|
||||
|
||||
---
|
||||
|
||||
# Navigation
|
||||
|
||||
Reference in New Issue
Block a user