# 2026-10-11 — merlin > Screen. Every claim below carries a path, a hash, a URL, or a command with its output, or the word > `unverified`. Nothing secret is printed anywhere in this check-in or in the files it lands. --- ## Did Claimed and finished **Q26 — make the silent token classes loud, and measure the fifth slot**, the item nominated to me by the control plane after Q25 closed at `a9f23a6` (Q20 is zephyrus-sparkborn's and stays the top unclaimed item; Q9 blocked on the audio handover; Q13/Q19 gated on Alexander). Deliverable: `recoveries/prose-anchor-hardening.md` (**15,250 B / sha256 `607b29403e61db44f15657386531ef11d009f964b90b1a4a5a25542612325108`**, this host, 2026-10-11T00:24:34Z). Queue block appended to `WORK-QUEUE.md` (383,205 B / sha256 `9be863624751711afb0b1c745b7cf4147ea9f838b6189ccadc32689b3d4b5d3c`). **What Q25 left silent, now loud.** The Q25 prototype shipped a typo as raw braces on the page and could not see a token outside its four panels. The fix is a pre-write scan — `check_tokens` per entry, `check_gaps` for the index — sitting **above** the `OUT` cleanup in `build()`, so a `die()` can never leave a half-emitted tree. The panel set is computed **per entry**: `body` is a panel only when `body_kind == "summary"`. The diff: `build_blocks_proto.py` → `build_blocks_hard.py` **+70 / −6 lines, 5,817 B** (`/root/crucible/q26/DIFF.txt`); against the shared tree's `build_blocks.py` (sha256 `97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672`) **+118 / −11, 9,949 B**. The hardened script is **27,878 B / sha256 `d45cc28f7d69afcdab4eccb16e9e0cc264e4317e059e17f1ba53eb23f792cb60`**; the Q25 prototype copied into the scratch tree verified byte-identical first (`5af80b78961b4f55…`). **The five Q25 legs, re-run green** (`Q26-VERIFY.txt`, full log `Q26-VERIFY-run.txt`): 1. No-token build on the unmodified `blocks.json` (278,459 B / sha256 `63c9cee6103a6824c90c71440fa983d2f5592e380f9c3fb40f7ad366ae41723d`): `Built 123 pages from 121 entries (121 cleared, 0 research-only)`, tree digest **`91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8`** = baseline, 125 files, `diff -rq /site-ledger /root/stackchain-legends-build/site-ledger` silent. 2. Registry unchanged: **8** handles (`@anthonydessauer @arizonanhodl @guiamadogomes @happyclowntime @rockachopa @satskeeper_ @saylor @yoshishisatoshi`). 3. Uncited-handle negative test: `exit 1`, `BUILD FAILED: block-25:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites`. 4. H1–H4 token demo: `exit 0`, **3 of 125** emitted files changed (`event-2022-07-18-the-5-invitation-becomes-a-chain/index.html`, `magazine-002/index.html`, `magazine-005/index.html`), 6 emitted anchors, all the contributor form. 5. The diff itself. **Two negative sets, 12 fixtures, every one `exit 1` with its own message.** Malformed (`MALFORMED.txt`): `{{x:saylor}` open brace, `{{x:}}` empty handle, `{{ x:saylor }}` whitespace-padded, `{{y:saylor}}` wrong namespace, `{{x:abcdefghijklmnopq}}` handle over 15 chars, lone `}}`, close-then-open `}}{{x:saylor}}` — all seven **previously built and shipped the literal** under the Q25 prototype, exit 0. Outside-panel (`OUTSIDE-PANEL.txt`): quote branch (`block-6:body`, whose error prints the panel set *without* `body` — the per-entry `body_kind` rule visible in the failure), `magazine-001:title`, `magazine-001:excerpts[0].text`, `magazine-035:contributor.display_name`, `coverage.gaps[4]`. Positive control (`POSITIVE.txt`): a cited `{{x:AriZonanHODL}}` in `block-5`'s `body_provenance` builds, expands on the `block-5` page **and** the genesis page, and moves exactly 2 files. **One new silent class, found while writing the positive control and closed:** `render_genesis` routed `body_provenance` and `uncertainty` through `esc()`, so a token those panels carry would expand on `block-5` and print raw braces on `genesis/`. Both now go through `expand_prose`; byte-neutral with no token present (proved by leg 1). The first hardening pass also missed the quote branch for the same reason a path-based panel set fails — `body` is a panel only on the summary branch — and the fix was the per-entry panel set. **The fifth slot, measured without building it** (`DISPLAY-NAME-MEASURE.txt`, each Q24 delta applied in its own scratch tree): | entry | Q24 clause | `display_name` / `handle` today | live page today | after the staged delta | |---|---|---|---|---| | magazine-035 | G1 | `@BTC_Freeborn and @AnthonyDessauer` / `null` | text only, anchors NONE | `BTC_Freeborn and Anthony Dessauer (@BTC_Freeborn)` — anchor `x.com/BTC_Freeborn`; sha `871638b8…` → `565e6f68…` | | magazine-056 | G2 | `Red Tail Hawk (@RedTailHawk1923)` / `null` | text only, anchors NONE | `Red Tail Hawk (@RedTailHawk1923)` — anchor `x.com/RedTailHawk1923`; sha `33b55f8f…` → `8094e862…` | | magazine-070 | I2 | `@MidyReyes` / `null` | text only, anchors NONE | `MidyReyes (@MidyReyes)` — anchor `x.com/MidyReyes`; sha `6227e199…` → `c994e055…` | **Recommendation: `magazine-056` (G2) and `magazine-070` (I2) take the handle-only fix — one account, one `handle` slot, and the build already anchors `contributor.handle` (line 310). `magazine-035` (G1) is the hard case: handle-only anchors `@BTC_Freeborn` and leaves `@AnthonyDessauer` unanchored, because `contributor` has exactly one `handle` slot while the byline names two accounts — and `@AnthonyDessauer` *is* in the registry, so a token for it would be admitted today. The only instrument that anchors both is `display_name` as a fifth panel carrying `{{x:AnthonyDessauer}}` beside the handle slot — a build change, Alexander's.** All three live-page digests reproduce Q24's fix-pack figures to the nibble, so the live tree is still the tree Q24 measured. **Which of Q24's 31 deltas the hardened convention can carry as links: H1–H4 only, 4 of 31.** The hardening widens no clause's carrier; it makes the four token carriers safe to publish. The publication precondition the 2026-10-10 18:13Z addendum stated is satisfied on the build side. **Nothing touched.** Shared tree still at `97fedb5dd5e85d2…`, its `site-ledger` byte-identical to this run's scratch build (125 files each, `diff -rq` silent), and `find /root/stackchain-legends-build -newermt 2026-10-10 18:00 -type f` returns nothing. Live archive unchanged: `https://alexanderwhitestone.com/stackchain/blocks/` **200 / 34,488 B / sha256 `4f764ef4dfb9c08b2654ff0783550d20ad1bb7a31cb0c32070974a5fe451557e`** at 2026-10-11T00:23:25Z. `blocks.json` read-only throughout; `decisions/` and `inbox/` untouched, nothing executed, no another-party file edited. ## Blocked Nothing blocked the run. Two things deliberately **unverified**, both recorded as such in the deliverable: - **The `display_name` fifth panel was measured, not built.** No fifth-panel implementation exists; the recommendation is a decision input, not a staged change. - **12 fixtures are the item's own lists plus two extras, not a census of typos.** A sentinel in a field no entry has today cannot be enumerated from today's data. Also outside this run by construction: Q25's census (46 rows / 25 X fetches) is cited, not re-run — no X page was fetched this tick, so no liveness figure in this check-in is dated by this run. ## Next - **Q20** (excerpt fidelity and placement, the 91 magazine entries) remains the top unclaimed item and is zephyrus-sparkborn's; I take nothing over it. - **Alexander's call, not mine:** whether to publish the build change at all. The hardened prototype is scratch-local and stays there until he says so — the same gate Q13 states. If he approves the convention, the immediate payload is the 4-of-31 H1–H4 clauses; the `display_name` fifth panel is a separate, larger decision with exactly one entry (G1) that needs it today. - **Q7, measured:** Q9 blocked on the audio handover; Q13/Q19 gated on Alexander; Q20 active. The executable set is empty of unclaimed items, so the never-dry obligation is triggered and a successor item is owed — I propose none this tick, because Q26 just closed and the successor should be the pipe's to open on a fresh measurement rather than mine to invent on the same finding. Stated plainly: this is the second consecutive tick where the set fell to zero and the successor came from the control plane's own measurement, and that is the pattern worth naming rather than a gap in the queue. ## Ask 1. **Alexander — approve, decline, or defer the prose-anchor convention as a build change.** If approved, the unit of work is the four H1–H4 clauses plus the hardened prototype; nothing publishes without a further go. If declined, Q24's 25 clauses stay staged as notes exactly as they are. 2. **Alexander — the `display_name` fifth slot, G1 only.** Is a second anchor on one byline worth a build change, or does G1 take the handle-only fix and leave `@AnthonyDessauer` as a name? 3. **Nothing asked of zephyrus-sparkborn this tick.** His lane is Q20; my two asks are both Alexander's, per §4. --- ## Landing evidence (appended after push, 2026-10-11T00:25:14Z) Deliverable commit **`f05179e`** (Merlin, `merlin@agents.invalid`, 2026-10-11), three files, pushed to `origin/main` (`git log --oneline -1 origin/main` → `f05179e`). Read back over the anonymous raw path (`…/raw/branch/main/`), no credential, each **HTTP 200 and `cmp` byte-identical to disk**: | file | status / bytes | sha256 (first 16) | |---|---|---| | `checkins/2026-10-11-merlin.md` | 200 / 9,153 | `5b5e94b885313c1e` | | `recoveries/prose-anchor-hardening.md` | 200 / 15,250 | `607b29403e61db44` | | `WORK-QUEUE.md` | 200 / 383,205 | `9be863624751711a` | Re-verified in the same breath: the shared build tree's `build_blocks.py` is still sha256 `97fedb5dd5e85d2…`, its `site-ledger` byte-identical to the scratch build, nothing under `/root/stackchain-legends-build` modified since 2026-10-10 18:00Z, and the live ledger index `https://alexanderwhitestone.com/stackchain/blocks/` is 200 / 34,488 B / `4f764ef4dfb9c08b…`. `blocks.json` was read-only throughout; `decisions/` and `inbox/` were not touched and nothing was executed. --- ## Run 2 — Q27: render-site coverage, and the scope clause closed (Merlin, 2026-10-11 ≈02:30 UTC) ### Did Claimed and finished **Q27 — a fixture at every render site** (the top unclaimed item; Q20 is zephyrus-sparkborn's, Q9 blocked on the audio handover, Q13/Q19 gated on Alexander). The item is Q26 §9 limit 2's honest answer: Q26 proved 12 token classes die, not that every emit site is watched. Deliverable: `recoveries/render-site-coverage.md` (**20,865 B / sha256 `34716145492bd265cceb9cded8363f0a59a057862e1c90f74625e93b39d51ac1`**, this host). Scratch tree `/root/crucible/q27/` (35 fixture trees under `fixtures/`, verify trees under `verify/`, re-runnable with `python3 q27-fixtures.py` then `python3 q27-verify.py`). **32 sites, enumerated from the source, not the data:** 28 `esc()` calls that render a `blocks.json` value plus the 4 prose panels, each with its `build_blocks.py` line number, field and landing. One row per site in the deliverable — fixture class, exit code, files-written-at-failure, first stderr line. **28 covered by fixture, 4 structural exclusions** (`slug`/canonical: `slug_for()` sanitises `{{` out; `year`: a 4-char slice; sitemap `loc`: same sanitised slug; `contributor.handle`: an account name interpolated into a URL by construction — and it still carries a die-fixture). Every exclusion is a stated reason, not "no entry does". **35 fixtures, every negative writes 0 files.** 4 valid-panel builds (`{{x:arizonanhodl}}` cited → expands; 4 anchors on `magazine-001`, moves nothing else), 12 malformed-panel dies, 4 uncited dies, 10 non-panel field dies (`title`, `date`, `date_display`, `date_basis`, `contributor.display_name`, `excerpts[0].text`, `receipt.reuse_status`, …), 2 URL-field dies, 3 class-field dies (`status`/`ledger` die at entry validation — `unknown status '{{x:'`; `variant` at the sentinel scan), head-block JSON-LD author, index label/date, pager `n`, coverage gap, genesis body, 1 no-token control. **URL-field scope decision — a token in a URL field must die**, measured both ways (`URL-CHECK.txt`): `body_source_url` non-https → `safe_url` fires (`must be https, got '{{x:'`); https-with-token → sentinel scan fires; `excerpts[].url` (never passed through `safe_url`) → sentinel scan. All exit 1, 0 files. **The scope clause closed with option (a).** New `check_uncited()` beside a shared `panels_for()`, running the same `TOKEN_RE` scan and the same message as `expand_prose`'s `die()`, **above `OUT.mkdir`**; `expand_prose` keeps the check as a backstop behind `pre_checked=True`. Measured: the `{{x:NotACitedHandle}}`-in-`uncertainty` fixture wrote **20 files** before the patch and **0** after — 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 partial-tree state the clause reproduced cannot arise from any of them. Patched builder `build_blocks_hard.py` sha256 `c4127c6c9325ed9f8cab03b80b454cccde0f9f1e768289ff216d2fb79e78dbf2` (29,174 B; diff `DIFF-SCOPE.txt`, +65/−12 over the Q26 prototype `d45cc28f…`). **Control:** unmodified `blocks.json` (`63c9cee6…`) through the patched builder → exit 0, **125 files, tree digest `91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8`** (the Q26 baseline), `diff -rq` against the shared `site-ledger` silent (leg 8). Leg 3: an uncited token in a quote-branch `body` dies at `check_tokens` first (correct ordering — the sentinel class is the wider net). Leg 7: the `pre_checked=False` backstop still dies on the same fixture. **Nothing touched.** Shared tree at `97fedb5dd5e85d2…` / `blocks.json` `63c9cee6…`, nothing modified since 2026-10-10 18:00Z (leg 9). Live archive unchanged: `https://alexanderwhitestone.com/stackchain/blocks/` **200 / 34,488 B / sha256 `4f764ef4dfb9c08b2654ff0783550d20ad1bb7a31cb0c32070974a5fe451557e`** at 2026-10-11 ≈02:31 UTC. `blocks.json` read-only throughout; `decisions/` and `inbox/` untouched, nothing executed, no another-party file edited. Patched builder is scratch-local and stays there. ### Blocked Nothing blocked the run. Deliberately unverified, recorded as such: the 4 structural exclusions are **reasoned from the source, not fuzzed** — no random-token fuzzer ran against the builder, so "no `{{` can survive `slug_for()`" is a code-reading claim backed by the sanitising regex (`[^a-z0-9-]+` → `-`, build_blocks.py:93) and the 4-char slice (`sortable[:4]`), not by a fixture. ### Next - **Alexander's call, not mine:** whether to publish the patched builder (the scope-clause close is a real behavioural change: uncited-handle failures can no longer leave a partial tree). Scratch until he says so — the same gate Q26/Q13 state. - **Q7, measured:** Q20 active (zephyrus's); Q9 blocked on the audio handover; Q13/Q19 gated on Alexander. The unclaimed executable set is empty again, so a successor is owed; this record opens none — the successor should come from a fresh measurement, not from this run's own finding. ### Ask 1. **Alexander — publish, hold, or decline the scope-clause close.** It is the difference between "20 files written on an uncited-token failure" and "0", on a prototype that is not in production. 2. **Nothing asked of zephyrus-sparkborn this tick.** His lane is Q20. ### Landing evidence (appended after push, 2026-10-11 ≈02:36 UTC) Deliverable commit **`08013ba`** (Merlin, `merlin@agents.invalid`, 2026-10-11; parent `179adc3`), 3 files, pushed to `origin/main` (`git log --oneline -1 origin/main` → `08013ba`). Read back over the anonymous raw path (`…/raw/branch/main/`), no credential — each HTTP 200 and `cmp` byte-identical to disk: | file | status / bytes | sha256 (first 16) | |---|---|---| | `checkins/2026-10-11-merlin.md` | 200 / 15,667 | `8ab0221e7f7065fe` | | `recoveries/render-site-coverage.md` | 200 / 20,865 | `34716145492bd265` | | `WORK-QUEUE.md` | 200 / 398,374 | `0b19045f3c961830` | Re-verified in the same breath: shared `build_blocks.py` still `97fedb5dd5e85d2…`, `blocks.json` `63c9cee6…`, nothing under `/root/stackchain-legends-build` modified since 2026-10-10 18:00Z, and the live ledger index `https://alexanderwhitestone.com/stackchain/blocks/` is 200 / 34,488 B / `4f764ef4dfb9c08b…`. `blocks.json` read-only throughout; `decisions/` and `inbox/` untouched, nothing executed, no secret printed anywhere.