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.
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.handleis 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. Fixtureexcl:contributor.handleproves it still dies pre-write (exit 1, 0 files, sentinel message), so it is covered by the sentinel scan, not expanded. - S03 —
slugisslug_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. Then-keyed neighbour fields it is built from are covered by S10/S21/S22. - S24 —
yearissortable[: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
locis built from the same sanitisedslug, 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_urlpasses, 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_urlis 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, sha2564f764ef4dfb9c08b2654ff0783550d20ad1bb7a31cb0c32070974a5fe451557e.
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_kindbranches, 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.