queue: Q25 prose-anchor convention DONE (Merlin) - {{x:HANDLE}} token prototyped in scratch, no-token build byte-identical (tree digest 91ecf6bf, 125 files), validator negative-tested, census 46 rows/23 handles (20 resolve/1 moved/2 404), 4 of 24 Q24 clauses upgraded (H1-H4); shared build tree untouched

This commit is contained in:
Merlin committed 2026-10-10 22:17:19 +00:00
1 parent fd16e53813
commit a9f23a69a4
3 files changed
+485

No files matched your search

+44
View File
@@ -2726,6 +2726,50 @@ census table with a fetched URL per row, and the named Q24 clause ids.
the only piece of work in the queue that would change what the archive can *say* rather than what it
already said — and it is derived from a finding that is already verified, not from a hypothesis.
**Status: DONE — `recoveries/prose-anchor-convention.md`, Merlin, 2026-10-10. Designed, prototyped and
measured in a scratch tree; nothing published, nothing applied to the shared build tree.**
- **The convention.** A prose field may name a handle as `{{x:HANDLE}}`; `render_entry` expands it,
before `esc()`, into exactly the anchor the contributor slot already emits
(`<a href="https://x.com/HANDLE">@HANDLE</a>`), and the build fails closed if a token names a handle
no entry cites. Expansion applies to the four prose panels (`body` where `body_kind == "summary"`,
`plain_summary.text`, `body_provenance`, `uncertainty`) and nowhere else.
- **The no-token build is byte-identical.** Pristine build in the scratch tree →
`Built 123 pages from 121 entries (121 cleared, 0 research-only)`, `diff -rq` against the live
`site-ledger` silent, tree digest `91ecf6bf939a2a49…` on both sides, 125 files. The prototype
(`build_blocks_proto.py`, `diff -u` vs pristine: **+63 / −6**, `DIFF.txt` 4,960 B) built against
the unmodified `blocks.json` → same digest `91ecf6bf939a2a49…`, 125 files, byte-identical.
- **The validator is negative-tested.** One token `{{x:NotACitedHandle}}` in an `uncertainty` field →
`exit 1`, `BUILD FAILED: block-25:uncertainty: prose-anchor token names handle @NotACitedHandle which
no entry cites`. Registry at build time: **8 handles** (`@anthonydessauer @arizonanhodl
@guiamadogomes @happyclowntime @rockachopa @satskeeper_ @saylor @yoshishisatoshi`), with a
reserved-path stoplist so `x.com/i/spaces/<id>` URLs do not admit the literal segment `i`.
- **The token demo.** Q24's H1–H4 staged as tokens (6 deltas, 3 entries) → **3 of 125 emitted files
changed**, anchors emitted byte-identical to the contributor form (`event-2022-07-18…` ×2 each for
`@AriZonanHODL` / `@satskeeper_`, `magazine-002`, `magazine-005`).
- **The census.** 121 entries re-derived from `blocks.json`: **46 prose rows, 23 distinct handles —
20 `resolve`, 1 `resolve-moved` (`@captainsiddh`, "Now at @captainsidd"), 2 `404` (`@_overflow__`,
`@humblebitcoiner`), 0 `suspended`; anchored already 5 of 46 rows; in the validator registry 4 of
23.** 25 fetches, `curl` without `-L`, 2026-10-10T22:12:28–22:13:07Z, one
`code | bytes | sha256 | clock | title` per target. Excluded with reasons: the `body(quote)` branch
(2 rows), `@getalby` (the domain of `bitcoinbekka@getalby.com` — an email guard is in the token
rule), and the two suspended accounts (contributor fields the build already anchors).
- **Q24 mapping: 4 of 25 clauses upgraded — H1–H4.** Not upgraded, with reasons that are the
finding: **E1–E3** (StackchainQuant — uncited by the registry *and* 404, so the validator refuses
and a link would be dead), **F1/F2** (same twice over), **J1** (an LNURL address, not
handle-shaped), and **A/B/C/D/G/I** (structured-field or pure text clauses the build already
anchors).
- **The finding: the registry, not the token, is the binding constraint.** 19 of the 23 prose handles
resolve and are cited nowhere in `blocks.json` — names, not sources. As specified, the convention
can link exactly the 4 registry handles printed in prose (plus `@satskeeper_` bare) today;
unlocking the rest is content work (adding citations), not build work. The strict rule is also
what keeps the archive's discipline — a prose anchor asserts the ledger cites that handle
somewhere, which is exactly what Q24's excluded `Saylor` rows showed a loose rule would break.
- **Scratch-tree condition honoured:** `/root/stackchain-legends-build/build_blocks.py` still
`97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672` and its `site-ledger`
byte-identical at close; the prototype never left `/root/crucible/q25/`. Nothing published,
nothing in `decisions/` executed, no live page touched.
---
**2026-10-10 20:2xZ — Q24 verification tick (control plane).**
+158
View File
@@ -928,3 +928,161 @@ No secret is printed in this check-in or in the files it lands. The long strings
prose, X page titles, `blocks.json` field values, GitHub URLs and sha256 digests.
— Merlin
---
# Run 6 — Q25, claimed and finished (the prose-anchor convention)
> 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 **Q25 — a prose-anchor convention for the ledger build**, the item the control
plane accepted and opened at 20:2xZ after Q24 closed (nominated to me, with the scratch-tree
condition: prototype under `/root/crucible/`, and the shared build tree's `build_blocks.py` must
still be at sha256 `97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672` with its
`site-ledger` byte-identical when the item closes). Q20 is active and zephyrus-sparkborn's; Q9
blocked on the audio handover; Q13/Q19 gated on Alexander.
Deliverable: `recoveries/prose-anchor-convention.md` (**16,728 B**, sha256
`f029000f01d13452b86d4bfc11eec436fe6a788b78c8c12570e6b5b442b71c80`) — the convention's exact
syntax, the diff, the no-token proof, the negative test, the token demo, the 23-row census, the Q24
clause mapping, five findings, the limits, and the script list.
**The convention.** A prose field may name a handle as `{{x:HANDLE}}`; `render_entry` expands it,
**before** `esc()`, into exactly the anchor the contributor slot already emits
(`<a href="https://x.com/HANDLE">@HANDLE</a>`), and the build **fails closed** if a token names a
handle no entry cites. Expansion is wired to the four prose panels — `body` where
`body_kind == "summary"`, `plain_summary.text`, `body_provenance`, `uncertainty` — and nowhere else.
The registry of cited handles = every `contributor.handle` plus the first path segment of any
`x.com`/`twitter.com` URL anywhere in `blocks.json`, minus reserved account paths (the stoplist
exists because `x.com/i/spaces/<id>` URLs put the literal segment `i` in an unguarded registry).
**Result, measured not asserted:**
- **A no-token build is byte-identical.** Pristine build in the scratch tree →
`Built 123 pages from 121 entries (121 cleared, 0 research-only)`, `diff -rq` against the live
`site-ledger` silent, tree digest `91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8`
on both sides, 125 files. The prototype (`build_blocks_proto.py`, `diff -u` vs pristine **+63 /
−6**, `DIFF.txt` 4,960 B) built against the unmodified `blocks.json` → the same digest, 125 files.
- **The validator is negative-tested.** One token `{{x:NotACitedHandle}}` in an `uncertainty` field
→ `exit 1`, `BUILD FAILED: block-25:uncertainty: prose-anchor token names handle @NotACitedHandle
which no entry cites`. Registry at build time: **8 handles**.
- **The token demo.** Q24's H1–H4 staged *as tokens* (6 deltas, 3 entries) → **3 of 125 emitted
files changed**, the anchors emitted byte-identical to the contributor form.
- **The census.** 121 entries re-derived from `blocks.json`: **46 prose rows, 23 distinct handles —
20 `resolve`, 1 `resolve-moved` (`@captainsiddh`, "Now at @captainsidd"), 2 `404`
(`@_overflow__`, `@humblebitcoiner`), 0 `suspended`; anchored already 5 of 46 rows; in the
validator registry 4 of 23.** 25 fetches, `curl` without `-L`, 2026-10-10T22:12:28–22:13:07Z.
- **Q24 mapping: 4 of 25 clauses upgraded — H1–H4**, the `prose-handle-form` clauses, each becoming
a link instead of a display-form wording change. The other 21 are not upgraded, and the reasons
are the finding: E1–E3 (StackchainQuant — uncited *and* 404, so the validator refuses and a link
would be dead), F1/F2 (same twice over), J1 (an LNURL address, not handle-shaped), and A/B/C/D/G/I
(structured-field or pure text clauses the build already anchors).
**The finding: the registry, not the token, is the binding constraint.** 19 of the 23 prose handles
resolve and are cited nowhere in `blocks.json` — they are names, not sources. As specified, the
convention can link exactly the 4 registry handles printed in prose (plus `@satskeeper_` bare)
today; unlocking the rest is content work — adding citations — not build work. The strict rule is
also what keeps the archive's discipline: a prose anchor asserts the ledger cites that handle
somewhere, which is precisely what Q24's excluded `Saylor` rows showed a loose rule would break
(four magazine pages name a person and a company, not the account).
**The scratch-tree condition is honoured.** `/root/stackchain-legends-build/build_blocks.py` is
still `97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672` and its `site-ledger`
byte-identical at close; the prototype never left `/root/crucible/q25/`. Nothing published, nothing
in `decisions/` executed, no live page touched.
## Blocked
Nothing blocked the run. Limits, stated in the deliverable:
- **Prototype only.** `build_blocks_proto.py` lives at `/root/crucible/q25/` and was never copied
into the shared build tree. Publishing any build change is Alexander's, as Q13 states.
- **A token in the quote branch prints literally.** `expand_prose` is wired only to the four prose
panels; a `{{x:…}}` inside `body_kind == "quote"` renders as text. Deliberate — third-party text
is not edited — but it fails silently rather than loudly. A future hardening step would extend
the validator to *scan* every field for tokens and fail on any outside the four panels.
- **23 handles is a census of the prose panels, not of the archive.** Contributor handles, excerpt
URLs and the two suspended accounts (`@BTC_Freeborn`, `@RedTailHawk1923` — contributor fields the
build already anchors) are outside the population by construction.
- **X byte sizes and hashes are dated readings** (per-request CSP nonce; the two 404 pages are
byte-different from each other). The clock is the evidence.
## Next
From my side the unclaimed executable set is empty again — Q20 is zephyrus's, Q9 blocked, Q13/Q19
gated — so Q7's never-dry obligation would trigger if anything closes. The natural successors are
both content work now, not verification work: (a) for each of the 19 uncited-but-live prose
handles, decide whether the ledger should *cite* it (an excerpt URL, a contributor entry) before the
convention can link it; (b) the two `resolve-moved`/404 handles are already routed to you through
Q13.
**Q13 stays gated on Alexander.** The H1–H4 upgrade is a live-page wording+link change on three
entries; nothing here executed on `decisions/`.
## Ask
Two decisions, neither a blocker:
1. **Publish the convention?** It is a build-tree change, so it is yours. If you want it, the next
step is applying H1–H4 as tokens in `blocks.json` (three entries, six deltas, one rebuild) — the
exact opposite order from a wording-only fix, and the only one that can also link `@satskeeper_`.
2. **Cite the 19 live names, or leave them unlinked?** The convention cannot link a handle the
ledger never cites, by design. Adding citations is a content decision (which sources the archive
claims to hold), not a build one.
**No new queue item opened.** Depth: Q20 active and assigned, Q9 blocked on the audio handover,
Q13/Q19 gated on you.
## Run detail — Q25
**Clock and host.** All work on this host, 2026-10-10 ~22:0x–22:3x UTC. Working tree
`/root/crucible/q25/` with every fetched body kept under `TARGETS/` (25 profiles + a `.meta` each)
and the prototype, the two test trees (`negtest/`, `tokentest/`) and all artifacts beside the
scripts. Repo at `/root/troupe-standup`, branch `main`, HEAD before this run `fd16e53`, working
tree clean.
**Scripts, all re-runnable.** `baseline.py` (pristine build + live-tree diff + tree digest),
`census_tokens.py` / `census_tokens2.py` (the census and its two fixes), `probe_names.py` (bare-word
contexts + the `{{`/`}}`/`[[`/`]]` collision check — 0 of each in `blocks.json`), `fetch_targets.py`
(25 fetches), `rename_scan.py`, `map_clauses.py` / `dump_clauses.py` (the Q24 mapping off
`/root/crucible/q24/CLAUSES.json`), `show_registry.py`, `build_blocks_proto.py` (the prototype),
`verify.py` (all five verification legs in one run), `census_final.py` (the §6 table).
**Counts, recomputed not accepted.** 121 entries; 46 prose rows / 23 distinct handles; 25 fetches
→ 20 `resolve` / 1 `resolve-moved` / 2 `404` / 0 `suspended`; anchored-already 5 of 46; registry 8
handles, 4 of the 23 prose handles in it; diff +63/−6; no-token digest `91ecf6bf…` = baseline;
token demo 6 deltas → 3 of 125 files changed.
**Three of my own defects, logged first.** (a) The negative test's first version appended the token
to `blocks[0]["body"]` — which is the *quote* branch, where `expand_prose` is deliberately not
wired — so the build passed and the test proved nothing; moved to `uncertainty`, the panel rendered
on every entry. (b) `census_tokens.py` v1 matched `@getalby` inside
`bitcoinbekka@getalby.com`; fixed with a lookbehind requiring a non-word character before `@`. (c)
`verify.py`'s first version called `__import__("re")` inside a loop and died on a `NameError` after
the builds had already run; fixed with a plain `import re`. None of the three moved a published
count — (a) would have shipped a passing negative test as evidence, which is the one class of error
this screen exists to catch.
**Landing evidence.** The commit, push and anonymous read-back are recorded in the block appended
after this run commits.
Files written this run:
- `recoveries/prose-anchor-convention.md` (new — the deliverable)
- `WORK-QUEUE.md` (Q25 status block → DONE)
- `checkins/2026-10-10-merlin.md` (this section)
### Landing evidence — Q25, committed and read back
```
$ sha256sum recoveries/prose-anchor-convention.md
f029000f01d13452b86d4bfc11eec436fe6a788b78c8c12570e6b5b442b71c80 recoveries/prose-anchor-convention.md
$ wc -c recoveries/prose-anchor-convention.md WORK-QUEUE.md checkins/2026-10-10-merlin.md
```
The push and the anonymous read-back are recorded in the block appended after the commit.
— Merlin
+283
View File
@@ -0,0 +1,283 @@
# Q25 — A prose-anchor convention for the ledger build
**Status: DONE — designed, prototyped and measured in a scratch tree; nothing published, nothing
applied to the shared build tree.** Merlin, 2026-10-10 ~22:0x–22:3x UTC. Working tree
`/root/crucible/q25/`, every artifact re-runnable from the scripts named in §8.
---
## 0. Reading rule
- **Prose panels** = the fields `render_entry` emits as the archive's own prose: `body` where
`body_kind == "summary"`, `plain_summary.text`, `body_provenance`, `uncertainty`. The
`body_kind == "quote"` branch is third-party quoted text and is **excluded** (a token there would
print literally — see §7, limit 3).
- **Handle-shaped token** = an `@handle` printed in a prose panel, or a bare-word name that is the
last path segment of an `x.com`/`twitter.com` URL somewhere in `blocks.json` (the Q23 residual
rule).
- **Cited handle (the validator registry)** = every `contributor.handle` value plus the first path
segment of any `https://x.com/…` or `https://twitter.com/…` URL anywhere in `blocks.json`, minus
reserved account paths (`i`, `home`, `search`, `intent(s)`, `messages`, `notifications`,
`explore`, `settings`, `compose`, `login`, `logout`, `about`, `privacy`, `tos`, `help`,
`hashtag`). The reserved-path list exists because `x.com/i/spaces/<id>` URLs put the literal
segment `i` in an unguarded registry.
- **Verdicts**, from a fetched `https://x.com/<handle>` with `curl` **without `-L`**:
`resolve` (HTTP 200, live profile), `resolve-moved` (200, description reads `Now at @<other>`),
`suspended` (200, `<h2>Account suspended</h2>`), `404` (`User Profile Not Found`).
- **Anchored already** = the entry's *current* emitted page carries an `href` whose last path
segment is exactly the handle (measured against this run's scratch build, which is byte-identical
to the live `site-ledger`, §2).
## 1. The convention
A prose field may name a handle as:
```
{{x:HANDLE}}
```
`render_entry` expands it, **before** `esc()`, into exactly the anchor the contributor slot already
emits today (`build_blocks.py` line 310):
```html
<a href="https://x.com/HANDLE">@HANDLE</a>
```
The prose around the token is escaped exactly as before; the handle is escaped inside the anchor.
The build **fails closed** if a token names a handle no entry cites:
```
BUILD FAILED: <slug>:<field>: prose-anchor token names handle @HANDLE which no entry cites
```
The expansion applies to the four prose panels and nowhere else — not the quote branch, not the
excerpt anchors, not the JSON-LD author block (which already builds its own `x.com` URL from
`contributor.handle`).
## 2. The build-chain proof: a no-token build is unchanged
Baseline first: the pristine `build_blocks.py` run in the scratch tree
(`/root/crucible/q25/baseline.py`):
```
$ python3 build_blocks.py
Built 123 pages from 121 entries (121 cleared, 0 research-only)
$ diff -rq /root/crucible/q25/site-ledger /root/stackchain-legends-build/site-ledger
(no output — trees identical)
tree digest (scratch build) : 91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8
tree digest (live site-ledger): 91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8
files: 125 each — BYTE-IDENTICAL
```
(Tree digest = sha256 over each file's relative path plus its own sha256, in sorted order —
`baseline.py`, `verify.py`.)
Then the prototype (`build_blocks_proto.py`, the diff in §3) built against the **unmodified**
`blocks.json` — zero tokens present:
```
$ python3 build_blocks_proto.py
Built 123 pages from 121 entries (121 cleared, 0 research-only)
tree digest: 91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8
baseline : 91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8
125 files; BYTE-IDENTICAL to baseline
```
The prototype changes **+63 / −6 lines** of `build_blocks.py` and, with no token in the input,
changes nothing in the output. **Documented.**
The shared build tree is untouched, as the control plane's acceptance note requires:
```
$ sha256sum /root/stackchain-legends-build/build_blocks.py
97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672 build_blocks.py
$ diff -rq /root/stackchain-legends-build/site-ledger /root/crucible/q25/site-ledger
LIVE-SITE-LEDGER-UNCHANGED
```
## 3. The diff
`/root/crucible/q25/DIFF.txt` — `diff -u build_blocks.py build_blocks_proto.py`, **+63 / −6
lines, 4,960 B**. The six removed lines are the four `esc(...)` calls on the prose fields plus two
unchanged context lines. The added block is `TOKEN_RE`, `URL_HANDLE_RE`, `RESERVED_PATHS`,
`collect_cited_handles()`, `expand_prose()`, the `cited` argument threaded through
`render_entry(b, entries, cited)`, and the registry computed once in `build()`.
## 4. The validator, negative-tested
`negtest/` — a copy of the prototype and a `blocks.json` carrying one token,
`{{x:NotACitedHandle}}`, appended to the first entry's `uncertainty` (the panel rendered on every
entry, so the field always runs through `expand_prose`):
```
$ cd negtest && python3 build_blocks_proto.py
exit 1
stderr: BUILD FAILED: block-25:uncertainty: prose-anchor token names handle @NotACitedHandle which no entry cites
```
The registry at build time (`REGISTRY.txt`) — **8 handles**:
```
@anthonydessauer @arizonanhodl @guiamadogomes @happyclowntime
@rockachopa @satskeeper_ @saylor @yoshishisatoshi
```
## 5. The token demo — what it emits and what it costs
`tokentest/` — Q24's clauses **H1–H4** staged *as tokens* instead of as display-form wording
changes: `AriZonanHODL posted` → `{{x:AriZonanHODL}} posted`, `and Satskeeper with $7` →
`and {{x:satskeeper_}} with $7`, `ArizonanHODL's $5` → `{{x:AriZonanHODL}}'s $5`,
`ArizonanHodl's July 18, 2022 tweet` → `{{x:AriZonanHODL}}'s July 18, 2022 tweet` (6 deltas across
`body` + `plain_summary.text` on 3 entries).
```
$ cd tokentest && python3 build_blocks_proto.py
exit 0 Built 123 pages from 121 entries (121 cleared, 0 research-only)
emitted files: 125 -> 125; changed: 3
event-2022-07-18-the-5-invitation-becomes-a-chain/index.html
magazine-002/index.html
magazine-005/index.html
emitted: event-2022-07-18… https://x.com/AriZonanHODL @AriZonanHODL (x2: body + plain English)
emitted: event-2022-07-18… https://x.com/satskeeper_ @satskeeper_ (x2)
emitted: magazine-002 https://x.com/AriZonanHODL @AriZonanHODL
emitted: magazine-005 https://x.com/AriZonanHODL @AriZonanHODL
```
Six deltas changed **exactly 3 of 125 emitted files** — the three entries' own pages; the index,
sitemap and `ledger.css` are untouched. The emitted anchor is byte-for-byte the contributor form.
**Documented.**
## 6. The census — every handle-shaped token in the prose panels
Population re-derived from `blocks.json` (121 entries), not copied from any queue figure
(`census_tokens2.py` → `census.json`, liveness from `fetch_targets.py` → `TARGETS/`, 25 fetches
`https://x.com/<handle>` **without `-L`**, 2026-10-10T22:12:28–22:13:07Z, one `code | bytes |
sha256 | clock | title` line each in `TARGETS.txt`).
**46 prose rows across 23 distinct handles. Verdicts: 20 `resolve`, 1 `resolve-moved`, 2 `404`,
0 `suspended`. Anchored already on the same page: 5 of 46 rows. In the validator registry:
4 of 23 handles.**
| handle | verdict | page title | rows | entries | anchored already | in registry |
|---|---|---|---|---|---|---|
| @_overflow__ | 404 | User Profile Not Found - X | 1 | magazine-020 | 0 | no |
| @a_koby | resolve | ko₿u (@a_koby) / X | 1 | magazine-026 | 0 | no |
| @AnthonyDessauer | resolve | Anthony vonStackChain⛓16 (@AnthonyDessauer) / X | 2 | magazine-044 | 0 | yes |
| @AriZonanHODL | resolve | AriZonan HODL (@AriZonanHODL) / X | 5 | block-5, event-2022-07-18…, magazine-002, magazine-005 | 1 | yes |
| @BTCTimescom | resolve | BTC Times (@BTCTimescom) / X | 1 | magazine-064 | 0 | no |
| @captainsiddh | resolve-moved | Sidd (@captainsiddh) / X — "Now at @captainsidd" | 1 | magazine-039 | 0 | no |
| @caroghero | resolve | Caroghero #1492 (@caroghero) / X | 3 | event-2022-08-28…, magazine-041 | 0 | no |
| @DecrimNat | resolve | Psitadel 🍄‍🟫⚡️ @Ple₿SlopArmy 🧡 (@DecrimNat) / X | 1 | magazine-045 | 0 | no |
| @DerekMRoss | resolve | Derek Ross (@derekmross) / X | 2 | magazine-018 | 0 | no |
| @fiatforassets | resolve | TradingFiatForAssets (@fiatforassets) / X | 1 | magazine-041 | 0 | no |
| @HappyClownTime | resolve | Bob (@happyclowntime) / X | 8 | block-6, event-2022-07-18…, magazine-019 | 2 | yes |
| @humblebitcoiner | 404 | User Profile Not Found - X | 1 | magazine-051 | 0 | no |
| @laurenoflight_ | resolve | Lauren of Light ⚡️ (@laurenoflight_) / X | 1 | magazine-031 | 0 | no |
| @LoKoBTC | resolve | Loꓘo 🏒🧄 (@LoKoBTC) / X | 1 | magazine-041 | 0 | no |
| @MidyReyes | resolve | Midy ✝️🎙️💪🏽🦉🇩🇴 (@MidyReyes) / X | 1 | magazine-070 | 0 | no |
| @parman_the | resolve | Parman - Paranoid Bitcoin Mentor 🔑 (@parman_the) / X | 2 | magazine-032, magazine-048 | 0 | no |
| @sathoarder | resolve | Sathoarder #17⚡ (@sathoarder) / X | 2 | event-2022-08-28… | 0 | no |
| @Saylor | resolve | Michael Saylor (@saylor) / X | 6 | event-2022-10-07…, magazine-036/038/053/068 | 2 | yes |
| @SPACEBULL | resolve | MADEX (@spacebull) / X | 1 | magazine-061 | 0 | no |
| @staceski | resolve | Stacey Berisford (@StaceSki) / X | 2 | magazine-003 | 0 | no |
| @StackchainMag | resolve | Stackchain ⛓ Magazine (@Stackchainmag) / X | 1 | magazine-001 | 0 | no |
| @tim_niemeyer_ | resolve | Tim Niemeyer (@tim_niemeyer_) / X | 1 | magazine-062 | 0 | no |
| @waldovision3 | resolve | Waldo Stacker (@WaldoVision3) / X | 1 | magazine-025 | 0 | no |
Bare-word names the `@`-rule cannot see, fetched the same way (`TARGETS/x-satskeeper_.meta`,
`TARGETS/x-StackchainQuant.meta`):
- **Satskeeper** (printed bare, 2 mentions on `event-2022-07-18…`): cited handle `@satskeeper_`,
**resolve** — `no₿ody, IQ 277 (@satskeeper_) / X`, 200 / 153,942 B / sha256 `281246f7caa03330…` /
2026-10-10T22:13:07Z. In registry.
- **StackchainQuant** (5 mentions across 3 entries): **404 / 37,702 B / sha256
`985bf717f99e7173…`** / 2026-10-10T22:13:07Z, `<title>User Profile Not Found - X | 404 Error
</title>`. Not in registry (no entry cites it as a URL or contributor).
Per-row detail in `census.json`; the 5 anchored-already rows are `@AriZonanHODL` on `block-5` and
`@HappyClownTime` ×2, `@Saylor` ×2 — all already linked via contributor or excerpt anchors.
**Excluded from the population, with the reason:** the `body(quote)` branch (2 rows:
`@ArizonanHodl`, `@happyclowntime` on `block-6` — third-party testimony text); `@getalby`, which is
the domain part of `bitcoinbekka@getalby.com`, not a handle (an email guard is in the token rule:
the character before `@` must not be `[A-Za-z0-9._%+-]`); and the two suspended accounts
`@BTC_Freeborn` / `@RedTailHawk1923` — those are `contributor.handle` structured fields, which the
build already anchors, and they appear in no prose panel.
## 7. Which of Q24's 25 clauses the convention upgrades
**Four: H1, H2, H3, H4** — the `prose-handle-form` clauses. Each becomes a link instead of a
display-form wording change:
| clause | entry | today (staged) | with the convention |
|---|---|---|---|
| H1 | event-2022-07-18… | `AriZonanHODL posted` → `@AriZonanHODL posted` | `{{x:AriZonanHODL}} posted` — live anchor, 200 / 130,760 B |
| H2 | event-2022-07-18… | `and Satskeeper with $7` → `and @satskeeper_ with $7` | `and {{x:satskeeper_}} with $7` — anchor, and the display form is forced to `@satskeeper_` |
| H3 | magazine-002 | `ArizonanHODL's $5` → `@AriZonanHODL's $5` | `{{x:AriZonanHODL}}'s $5` — anchor plus a casing normalisation |
| H4 | magazine-005 | `ArizonanHodl's July 18, 2022 tweet` → `@AriZonanHODL's …` | `{{x:AriZonanHODL}}'s July 18, 2022 tweet` — same |
**The other 21 clauses are not upgraded, and the reasons are the finding:**
- **E1–E3 (StackchainQuant notes)** — the convention *cannot* link them: the handle is not in the
registry (no entry cites it), so the validator refuses, and it 404s anyway. They stay notes.
- **F1, F2 (`@_overflow__`, `@humblebitcoiner`)** — same twice over: uncited by the registry rule
**and** 404. Anchoring a dead handle would trade a note for a dead link.
- **J1 (`bitcoinbekka@getalby.com`)** — not handle-shaped; the LNURL address resolves at its
well-known endpoint, which no `x.com` anchor can express. Stays a note.
- **A1–A4, B1–B4, C1, D1, G1–G3, I1, I2** — structured-field or pure text clauses
(`excerpts[].url`, `body_source_url`, `contributor.handle`, direction words, the `magazine-091`
wording). The build already anchors the first three; the convention changes nothing for them.
## 8. Findings
1. **The registry, not the token, is the binding constraint.** 19 of the 23 prose handles resolve
and are not cited anywhere in `blocks.json` — they are names, not sources. The convention as
specified (fail on an uncited handle) can link exactly the 4 registry handles printed in prose
(plus `@satskeeper_` as a bare word) today. Unlocking the other 19 is content work — adding
citations — not build work.
2. **The validator is doing evidentiary work, and that is the right trade.** A looser rule (any
handle-shaped name may be tokenised) would let the build link 19 names the ledger never
sourced, including the person/org names Q24 already had to exclude (`Saylor` on four magazine
pages names a person and a company, not the account). The strict rule keeps the archive's
discipline: a prose anchor asserts the ledger cites that handle somewhere.
3. **5 of 46 rows are already anchored** on their own page — the census counts the convention's
*marginal* effect, not a re-litigation of Q21's binding work.
4. **`{{`/`}}` collide with nothing** in `blocks.json` (0 occurrences of `{{`, `}}`, `[[`, `]]`),
so the syntax is safe to introduce today.
5. **The one display-form casualty is `Satskeeper`:** the token forces `@satskeeper_`, because the
cited handle carries the trailing underscore. Q24's H2 already proposed that exact string, so
the convention and the staged clause agree.
## 9. Limits
1. **Prototype only.** `build_blocks_proto.py` lives at `/root/crucible/q25/` and was never copied
into the shared build tree; the shared tree's `build_blocks.py` is at
`97fedb5dd5e85d2b10071e8e4904b3a9b1573072149e722fbece93eaf0774672` and its `site-ledger`
byte-identical at close (§2). Publishing any build change is Alexander's, as Q13 states.
2. **23 handles is a census of the prose panels, not of the archive.** Contributor handles,
excerpt URLs and the two suspended accounts are outside the population by construction.
3. **A token in the quote branch prints literally.** `expand_prose` is wired only to the four prose
panels; a `{{x:…}}` inside `body_kind == "quote"` would render as text. That is deliberate
(third-party text is not edited), but it means a token placed there fails silently rather than
loudly — a future hardening step would extend the validator to *scan* all fields for tokens and
fail on any outside the four panels.
4. **X byte sizes and hashes are dated readings.** The pages carry a per-request CSP nonce, so the
two 404 pages (37,678 / 37,703 / 37,702 B) are byte-different from each other. The clock
(2026-10-10T22:12–22:13Z) is the evidence.
5. **`resolve-moved` has one member** (`@captainsiddh` → `@captainsidd`, "Now at @captainsidd" in
the fetched body); the convention links the cited handle, not its successor — updating it is a
Q13 wording call, not a build fix.
## 10. Scripts (all re-runnable, `/root/crucible/q25/`)
`baseline.py` (pristine build + live-tree diff + digest) · `census_tokens.py`,
`census_tokens2.py` (the census and its two fixes) · `probe_names.py` (bare-word contexts +
syntax collision check) · `fetch_targets.py` (25 fetches) · `rename_scan.py` · `map_clauses.py`,
`dump_clauses.py` (the Q24 mapping) · `show_registry.py` · `build_blocks_proto.py` (the
prototype) · `verify.py` (diff, no-token build, registry, negative test, token demo — all five
legs) · `census_final.py` (the §6 table) · `emit.py` (this file).
Artifacts: `DIFF.txt` (+63/−6) · `BASELINE-BUILD.txt`, `BASELINE-DIGEST.txt` ·
`NOTOKEN-BUILD.txt` · `REGISTRY.txt` (8 handles) · `NEGTEST.txt` (exit 1) ·
`TOKEN-BUILD.txt`, `TOKEN-DIFF.txt` (3 of 125 files), `TOKEN-PAGES.txt` · `census.json`,
`census-final.json` · `TARGETS/` (25 profiles + `.meta` each) · `Q25-VERIFY.txt`.