Files
troupe-standup/recoveries/render-site-coverage.md
T
Merlin 08013ba55a queue: Q27 render-site coverage DONE (Merlin)
32 emit sites in build_blocks.py enumerated from the source (28 esc calls plus the 4
prose panels): 28 covered by fixture, 4 stated structural exclusions. 35 fixtures,
every negative exit 1 with 0 files written (4 valid-panel builds expand, 12
malformed-panel dies, 4 uncited dies, 10 non-panel field dies, 2 URL-field dies, 3
class-field dies, head/index/pager/gap/genesis, 1 no-token control).

URL-field scope decided: a token in a URL must die - safe_url rejects the non-https
body_source_url value, the pre-write sentinel scan catches the https-with-token and
excerpt cases, all exit 1 with 0 files.

The queue's scope clause closed with option (a): check_uncited() runs above OUT.mkdir
so all four token classes are pre-write (the uncited fixture wrote 20 files before the
patch, 0 after, same message).

No-token build still byte-identical at 91ecf6bf (125 files, diff -rq vs the shared
site-ledger silent). Shared tree untouched at 97fedb5d with blocks.json 63c9cee6; live
index 200 / 34,488 B / 4f764ef4dfb9. Patched builder c4127c6c is scratch-local,
nothing staged; decisions/ and inbox/ untouched.
2026-10-11 02:32:48 +00:00

20 KiB

Q27 — render-site coverage: every emit site in build_blocks.py, one fixture each

Author: Merlin. Run: 2026-10-11, scratch tree /root/crucible/q27/ (all 35 fixture trees under fixtures/, verify trees under verify/; re-runnable with python3 q27-fixtures.py then python3 q27-verify.py). Nothing published, no blocks.json edit, nothing staged.

Builder under test: /root/crucible/q27/build_blocks_hard.py — the Q26 prototype (d45cc28f7d69afcdab4eccb16e9e0cc264e4317e059e17f1ba53eb23f792cb60, 27,878 B) plus this item's scope-clause patch: sha256 c4127c6c9325ed9f8cab03b80b454cccde0f9f1e768289ff216d2fb79e78dbf2, 29,174 B. Diff DIFF-SCOPE.txt (77 lines, +65/-12). Pristine shared-tree builder 97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672 — untouched (leg 9).

Method

Every string the build emits comes from one of 32 named sites: 28 esc() calls that render a blocks.json value, plus the 4 prose panels (whose pristine esc() calls the Q26 prototype routes through expand_prose). Sites are enumerated from the source with line numbers, not from today's data, which is the difference between this item and Q26's §9 limit 2. Each site gets either a fixture — a valid {{x:<cited-handle>}} and/or a malformed {{x: token placed in that field, with the raw exit code and first stderr line — or a stated structural reason no entry can carry one there today.

Fixture tokens: valid {{x:arizonanhodl}} (a cited handle), malformed {{x:, uncited {{x:NotACitedHandle}}. Fixtures apply to magazine-001 (a summary-branch magazine entry with contributor, 3 excerpts, receipt-less), magazine-002 (pager neighbour), entry n=5 (block-5, genesis, body_kind null → quote branch) and entry n=6 (block-6, body_kind: quote).

Row table — one row per render site

site build_blocks.py line field fixture (class) exit · files first stderr line
S01 215 title nonpanel:title 1·0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_sum
S02 216 title (as desc) nonpanel:title 1·0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_sum
S03 217 slug (via slug_for) structural exclusion — no entry field reaches it — see below
S04 208 ld object head:jsonld-author 1·0 BUILD FAILED: magazine-001:contributor.display_name: token sentinel {{ in a field that is not a prose panel (panels: body, body_pr
S05 238 status class:status 1·0 BUILD FAILED: block[30] unknown status '{{x:'
S06 239 ledger class:ledger 1·0 BUILD FAILED: block[30] unknown ledger '{{x:'
S07 241 variant class:variant 1·0 BUILD FAILED: magazine-001:variant: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_s
S08 263 receipt (k,v) nonpanel:receipt.reuse_status 1·0 BUILD FAILED: block-5:receipt.reuse_status: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain
S09 266 receipt.reuse_status nonpanel:receipt.reuse_status 1·0 BUILD FAILED: block-5:receipt.reuse_status: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain
S10 297 title / n nonpanel:title 1·0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_sum
S11 299 title nonpanel:title 1·0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_sum
S12 303 date_display / date nonpanel:date_display 1·0 BUILD FAILED: magazine-001:date_display: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, pl
S13 303 date_basis nonpanel:date_basis 1·0 BUILD FAILED: magazine-001:date_basis: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plai
S14 286 date nonpanel:date 1·0 BUILD FAILED: magazine-001📅 token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summ
S15 308 contributor.display_name nonpanel:contributor.display_name 1·0 BUILD FAILED: magazine-001:contributor.display_name: token sentinel {{ in a field that is not a prose panel (panels: body, body_pr
S16 310 contributor.handle structural exclusion (fixture excl:contributor.handle still dies) exit 1 · 0 see below
S17 325 body (quote branch) genesis:body 1·0 BUILD FAILED: block-5:body: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain_summary.text, u
S18 323 body_source_url url-field:body_source_url 1·0 BUILD FAILED: magazine-001:body_source_url: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance,
S19 333 excerpts[].url url-field:excerpts[0].url 1·0 BUILD FAILED: magazine-001:excerpts[0].url: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance,
S20 335 excerpts[].text nonpanel:excerpts.0.text 1·0 BUILD FAILED: magazine-001:excerpts[0].text: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance
S21 351 n (prev) pager:n 1·0 BUILD FAILED: magazine-002:n: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary
S22 356 n (next) pager:n 1·0 BUILD FAILED: magazine-002:n: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary
S23 384 title index:label 1·0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_sum
S24 395 date/sort_date[:4] structural exclusion — no entry field reaches it — see below
S25 398 date_display / date index:date 1·0 BUILD FAILED: magazine-001:date_display: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, pl
S26 405 coverage.gaps[] index:coverage.gaps 1·0 BUILD FAILED: coverage.gaps[4]: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summa
S27 325 body (genesis) genesis:body 1·0 BUILD FAILED: block-5:body: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain_summary.text, u
S28 182 slug structural exclusion — no entry field reaches it — see below
S29 317 body (summary) panel-malformed:body 1·0 / 1·0 BUILD FAILED: magazine-001:body: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {
S30 340 plain_summary.text panel-malformed:plain_summary.text 1·0 / 1·0 BUILD FAILED: magazine-001:plain_summary.text: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must
S31 342 body_provenance panel-malformed:body_provenance 1·0 / 1·0 BUILD FAILED: magazine-001:body_provenance: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must rea
S32 344 uncertainty panel-malformed:uncertainty 1·0 / 1·0 BUILD FAILED: magazine-001:uncertainty: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read ex

Totals: 32 sites — 28 covered by fixture, 4 structural exclusions (S03 slug/canonical, S16 contributor.handle, S24 year, S28 sitemap loc; S16 also carries a die-fixture). 35 fixtures total: 4 valid-panel builds, 12 malformed-panel dies, 4 uncited dies, 10 non-panel field dies, 2 URL-field dies, 3 class-field dies, 1 head-block, 1 index, 1 pager, 1 gap, 1 genesis, 1 scope-clause measurement, 1 no-token control. Every negative fixture writes 0 files except the pre-patch scope-clause measurement (20 files, below).

The four structural exclusions, stated

  • S16 — contributor.handle is an account name interpolated into a URL by construction (https://x.com/{esc(handle)}, line 310); a token there is a URL-value error, not a prose token. Fixture excl:contributor.handle proves it still dies pre-write (exit 1, 0 files, sentinel message), so it is covered by the sentinel scan, not expanded.
  • S03 — slug is slug_for()'s sanitised output ([^a-z0-9-]+ -> -), so a {{ can never reach the canonical href from an entry field; the fixture class cannot be placed there from blocks.json. The n-keyed neighbour fields it is built from are covered by S10/S21/S22.
  • S24 — year is sortable[:4], a 4-char slice of a date string; {{ cannot survive the slice from any entry value. The unsliced source is covered by S12/S14/S25.
  • S28 — sitemap loc is built from the same sanitised slug, so it inherits S03's exclusion; no blocks.json field reaches it unsanitised.

URL fields: the scope decision

Decision: a token in a URL field must die. Both URL sites die pre-write on two different guards, and the pair is measured directly (URL-CHECK.txt):

  • body_source_url (S18) with a non-https value: safe_url (build_blocks.py:96-101) fires first — BUILD FAILED: block[30]: source URL must be https, got '{{x:', exit 1, 0 files.
  • body_source_url (S18) with an https value carrying the token (https://x.com/{{x:): safe_url passes, and the pre-write sentinel scan catches it — BUILD FAILED: magazine-001:body_source_url: token sentinel {{ in a field that is not a prose panel, exit 1, 0 files.
  • excerpts[].url (S19): safe_url is never called on excerpt URLs, so the sentinel scan is the only guard — same sentinel message (url-field:excerpts[0].url, exit 1, 0 files).
  • The class fields (status, ledger) die earlier still, at entry validation: BUILD FAILED: block[30] unknown status '{{x:' (class:status, exit 1, 0 files).

So a token in a URL field cannot ship: either safe_url rejects the value or the sentinel scan rejects the field, and both answers are fixtures with raw exit codes, not silence. The sentinel's declared scope is therefore stated to include URL fields.

The scope clause, closed with option (a)

The queue's 2026-10-11 00:43Z clause allowed either moving the cited-handle check above OUT.mkdir or restating the guarantee. Option (a) is implemented: check_uncited() is new (build_blocks_hard.py, beside panels_for()), runs the same TOKEN_RE scan expand_prose runs, with the same message, above OUT.mkdir; expand_prose keeps its die() as a backstop behind pre_checked=True. check_tokens now shares panels_for(b) instead of re-deriving the set.

Measured before and after (fixture prewrite:uncited-handle = {{x:NotACitedHandle}} in magazine-001.uncertainty):

state exit files written at failure
before (Q26 prototype, d45cc28f…) 1 20 (116 of 123 pages short of a full tree)
after (c4127c6c…) 1 0

Same message both times: BUILD FAILED: magazine-001:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites. All four token classes are now pre-write, so the deliverable's finding-3 language (a partial tree indistinguishable from a partial publish) cannot arise from any of them.

Verification legs (Q27-VERIFY.txt, full log)

== leg 1: no-token build == exit=0 files=125 digest=91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8 digest matches Q26 baseline 91ecf6bf...: True == leg 2: uncited pre-write (was 20 files before the patch) == exit=1 files=0 BUILD FAILED: magazine-001:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites == leg 3: uncited in quote-branch body (check_uncited fires first) == exit=1 files=0 BUILD FAILED: block-6:body: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain_summary.text, uncertainty) == leg 4: cited token in all four panels builds and expands == exit=0 files=125 anchors on magazine-001 page: 4 == leg 5: malformed still dies pre-write == exit=1 files=0 BUILD FAILED: magazine-001:body: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {{x:HANDLE}} with a 1-15 character handle == leg 6: gap still dies pre-write == exit=1 files=0 BUILD FAILED: coverage.gaps[4]: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty) == leg 7: backstop — expand_prose still dies on uncited when pre_checked=False == exit=1 BUILD FAILED: magazine-001:body: prose-anchor token names handle @NotACitedHandle which no entry cites == leg 8: control build byte-identical to shared site-ledger == diff -rq output: '' rc 0 files in shared site-ledger: 125 == leg 9: shared tree untouched == 97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672 /root/stackchain-legends-build/build_blocks.py 63c9cee6103a6824c90c71440fa983d2f5592e380f9c3fb40f7ad366ae41723d /root/stackchain-legends-build/blocks.json files newer than 01:00Z today: ''

Raw fixture log (Q27-RESULTS.json)

fixture entry exit files first stderr line
panel-valid:body magazine-001 0 125 (built)
panel-malformed:body magazine-001 1 0 BUILD FAILED: magazine-001:body: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {{x:HANDLE}} with a 1-15 charac
panel-uncited:body magazine-001 1 0 BUILD FAILED: magazine-001:body: prose-anchor token names handle @NotACitedHandle which no entry cites
panel-valid:plain_summary.text magazine-001 0 125 (built)
panel-malformed:plain_summary.text magazine-001 1 0 BUILD FAILED: magazine-001:plain_summary.text: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {{x:HANDLE}} with
panel-uncited:plain_summary.text magazine-001 1 0 BUILD FAILED: magazine-001:plain_summary.text: prose-anchor token names handle @NotACitedHandle which no entry cites
panel-valid:body_provenance magazine-001 0 125 (built)
panel-malformed:body_provenance magazine-001 1 0 BUILD FAILED: magazine-001:body_provenance: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {{x:HANDLE}} with a
panel-uncited:body_provenance magazine-001 1 0 BUILD FAILED: magazine-001:body_provenance: prose-anchor token names handle @NotACitedHandle which no entry cites
panel-valid:uncertainty magazine-001 0 125 (built)
panel-malformed:uncertainty magazine-001 1 0 BUILD FAILED: magazine-001:uncertainty: malformed prose-anchor token — sentinel {{ left after token expansion; tokens must read exactly {{x:HANDLE}} with a 1-15
panel-uncited:uncertainty magazine-001 1 0 BUILD FAILED: magazine-001:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites
nonpanel:title magazine-001 1 0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
nonpanel:date_display magazine-001 1 0 BUILD FAILED: magazine-001:date_display: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
nonpanel:date_basis magazine-001 1 0 BUILD FAILED: magazine-001:date_basis: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
nonpanel:date magazine-001 1 0 BUILD FAILED: magazine-001📅 token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
nonpanel:contributor.display_name magazine-001 1 0 BUILD FAILED: magazine-001:contributor.display_name: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text,
nonpanel:excerpts.0.text magazine-001 1 0 BUILD FAILED: magazine-001:excerpts[0].text: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertai
nonpanel:excerpts.0.url magazine-001 1 0 BUILD FAILED: magazine-001:excerpts[0].url: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertain
nonpanel:body_source_url magazine-001 1 0 BUILD FAILED: block[30]: source URL must be https, got '{{x:'
nonpanel:receipt.reuse_status 5 1 0 BUILD FAILED: block-5:receipt.reuse_status: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain_summary.text, uncertainty)
url-field:body_source_url magazine-001 1 0 BUILD FAILED: magazine-001:body_source_url: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertain
url-field:excerpts[0].url magazine-001 1 0 BUILD FAILED: magazine-001:excerpts[0].url: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertain
excl:contributor.handle magazine-001 1 0 BUILD FAILED: magazine-001:contributor.handle: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncert
class:status magazine-001 1 0 BUILD FAILED: block[30] unknown status '{{x:'
class:ledger magazine-001 1 0 BUILD FAILED: block[30] unknown ledger '{{x:'
class:variant magazine-001 1 0 BUILD FAILED: magazine-001:variant: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
head:jsonld-author magazine-001 1 0 BUILD FAILED: magazine-001:contributor.display_name: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text,
index:label magazine-001 1 0 BUILD FAILED: magazine-001:title: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
index:date magazine-001 1 0 BUILD FAILED: magazine-001:date_display: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
index:coverage.gaps coverage.gaps[4] 1 0 BUILD FAILED: coverage.gaps[4]: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
pager:n magazine-002 1 0 BUILD FAILED: magazine-002:n: token sentinel {{ in a field that is not a prose panel (panels: body, body_provenance, plain_summary.text, uncertainty)
genesis:body 5 1 0 BUILD FAILED: block-5:body: token sentinel {{ in a field that is not a prose panel (panels: body_provenance, plain_summary.text, uncertainty)
prewrite:uncited-handle magazine-001 1 0 BUILD FAILED: magazine-001:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites
control:notoken - 0 125 (built)

Control: no-token build unchanged

Unmodified blocks.json (sha256 63c9cee6103a6824c90c71440fa983d2f5592e380f9c3fb40f7ad366ae41723d) through the patched builder: exit 0, 125 files, tree digest 91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8 — the Q26 baseline, byte for byte — and diff -rq <scratch>/site-ledger /root/stackchain-legends-build/site-ledger silent. A cited token placed in all four panels of magazine-001 expands to exactly 4 anchors on that page and moves no other file (leg 4).

Live archive, re-measured (2026-10-11)

  • https://alexanderwhitestone.com/stackchain/blocks/ — HTTP 200, 34,488 B, sha256 4f764ef4dfb9c08b2654ff0783550d20ad1bb7a31cb0c32070974a5fe451557e.

Limits

  • Scratch only. The patched builder lives in /root/crucible/q27/ and is not staged to the shared tree; publishing it is Alexander's decision, the same gate Q26 and Q13 state.
  • Fixtures target one entry per shape, not a census. Q26's §9 limit 2 was about entries; this item's answer is about sites, and a site's behaviour does not vary by entry beyond the two body_kind branches, both of which are exercised (S17/S27 quote-branch, S29 summary).
  • Testimony only: none. Every number in this record was produced by a command in this run; the live index was fetched this run.