From 28ca8e5a5b22b32a99fe86d46eccfe2e3f83732d Mon Sep 17 00:00:00 2001 From: Merlin Date: Thu, 15 Oct 2026 16:23:59 +0000 Subject: [PATCH] Q45S12 (Helm lane): Run 39 -- the pin/hash convention split closed; the green pill ships green. pin_stackchain hashed curl's stdout read as TEXT (13 CRLFs fold, 217163 wire bytes -> 217119 chars, e40308e5) while G13 row 2 hashes the RAW bytes (c34ae2c2), so after a re-pin the page's green "match" was a claim the gate refused (Run 38: rc 1 / 194 / 1). The pin now hashes the wire -- the convention the gate's rows and any outside verifier already use. TWO FILES CHANGE, THE GATE DOES NOT: collector helm-collect-r39.py 31595 B / 5a99364bd4bbca2b5d7f1c4ff13dba5a1488154b6e363f238e2e265a243b9966 / 750 lines (on 4e45021d 29954 / 720) -- one bytes-mode fetch (the old block fetched the body twice, a race between two curl calls), both digests from the same bytes, manifest_match pin-vs-wire, the pin on the wire, live_body_sha256 kept folded because G6 requires both fields to differ; renderer helm-render-r39.py 23523 B / 117001e839dbbac5fb35c3d1c5f11da461c7e5564049b1aeb5d51a35a7bbfdc6 / 522 lines (on a70998c8 22930 / 514) -- the page's "live body sha256" line publishes the WIRE digest because G13 row 1 compares that published hash against the held pin; gate 833d0827 BYTE UNCHANGED (190330 / 3619 / 145) -- its contract was right, the producer was not. REHEARSED ON TWO SANDBOXES, PREDICTIONS WRITTEN FIRST, 13 OF 14 MET. Arm A (the fix, sandbox bin = a copy of /root/.helm/bin + the payload, every live-path literal the gate names redirected in, the real live pin seeded): collect #1 manifest_match false (wire c34ae2c2 vs held f27326e8); render #1 red drift pill 13849 B / 3dd6125f; gate rc 0 / 195 / 0; --pin writes c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4; collect #2 manifest_match true; render #2 GREEN pill, published hash c34ae2c245117ca7 == pin[:16]; GATE ON RENDER #2 rc 0 / 195 / 0 -- the leg Run 38 measured 194/1 on. Drift probe: mutated pin -> collect #3 false -> render #3 red -> gate 195/0, pin restored. ARM B (the control: the shipped collector + renderer, the same gate) REPRODUCES THE BUG: --pin writes the folded digest e40308e573d046d7, collect #2 true, render #2 green, gate rc 1 / 194 / 1, sole failure G13 row 2 (live_sha256=c34ae2c2 held_pin_digest=e40308e5 pin_matches_live_now=False) -- the before/after pair, differing only in the collector. THE OUTSIDE VERIFIER, the point of the alignment: curl -sS --max-time 20 https://www.stackchainmagazine.net/ | sha256sum -> c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4 (217163 B): == snapshot live_body_sha256_wire, == held pin, != live_body_sha256. THE ONE MISS is the twin's own artifact: the G11-contract twin (194/1) redirects the pre-G14 renderer path to the sandbox bin renderer -- which IS the payload renderer now -- so G14's discriminator negative leg collapses by construction; Run 38 logged the identical artifact on the identical twin. INCIDENTAL CATCH: the byte-stability re-run after the drift probe (page still the red render, pin restored to live) failed on G13 ROW 3 (unqualified_red_pill=True, live == pin), row 3 firing on a real state transition rather than a constructed cell. Byte-stability: the two acceptance-leg stdouts are 17027 B each, differing on exactly 4 lines, all per-run mkdtemp paths; normalised residual 0, digest 49eb85e9a1461769. LIVE DELTA 0 ACROSS EVERY LEG OF BOTH ARMS: page 9865 / 427b7b54, snapshot 14039 / aa842b0f, held pin 120 / 5b6d7071, five deployed bin digests unmoved; grep -c HELM_COLLECTOR = 0 (Q40 stands, nothing of Q31-Run 39 in production); /tmp/q31-g8-deploy-* 475 before and after; sandboxes 0 of 0. THE ADOPTION ASK, MATERIALLY AMENDED: Run 38 had to prescribe cp WITHOUT a --pin first because a green pill could not ship green while the site serves CRLF; that constraint is gone -- arm A measured the full sequence WITH the re-pin (rc 0 / 195 / 0 on a green page). Sequence, four files in one order: adopt renderer 117001e8 -> adopt collector 5a99364b + gate 833d0827 -> re-collect -> re-render -> deploy; the file list must be re-read at adoption time, never copied from an earlier block. Whether to re-pin at all (accepting today's live body as the drift reference) is a policy choice, not a technical one. Old-convention pins remain readable: a folded-digest pin simply fails manifest_match until a re-pin, which is today's state anyway. NO ITEM CLOSED, NONE OPENED -- the Helm executable set was empty at the start of the run by both lanes' measurement. Deliverable recoveries/helm-pin-hash-convention.md (12513 B). Nothing deployed, no another-party file edited, no secret printed. Merlin . --- WORK-QUEUE.md | 103 ++++++++++++++ checkins/2026-10-15-merlin.md | 81 +++++++++++ recoveries/helm-pin-hash-convention.md | 190 +++++++++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 recoveries/helm-pin-hash-convention.md diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 6ea5d92..7606f8f 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -9692,3 +9692,106 @@ edited, no secret printed. mean the convention split is still open. The `cp` itself remains Alexander's under §4. **No item closed, none opened** — the executable set was empty at the start of the run. + +--- + +**Q45S12 (Helm lane) — Run 39: the pin/hash convention split closed; the green +pill ships green (Merlin, 2026-10-15 ~16:1x-16:3xZ).** Deliverable +`recoveries/helm-pin-hash-convention.md` (**12,513 B** at the write; the +post-append digest is this run's landing block). Scratch `/root/crucible/q68/`; +instrument `fix_r39.py` / `build_r39.py` / `run_r39.py` / `stability_r39.py` / +`report_r39.py`, artifacts `out/FIX.json`, `out/BUILD39.json`, +`out/RUN39.json`, `out/R39-STABILITY.json`, `out/R39-STABILITY-{1,2}.txt` +(host-local, E13). Nothing deployed, no `cp` into `/root/.helm/bin/`, +`decisions/` and `inbox/` untouched, no another-party file edited, no secret +printed. **No queue item opened** — the Helm executable set was empty at the +start of the run by both this lane's and the pipe's measurement, so the unit +taken was the one defect Run 38's own record measured and named: *"align the +convention on one side."* + +- **The class.** `pin_stackchain` hashed curl's stdout read as **text** + (universal newlines: 13 CRLF pairs fold, 217,163 wire bytes -> 217,119 + chars), so the pin and `manifest_match` were over the CRLF-folded body, + while G13 row 2 (`helm-selftest-q65.py:3344-3376`) hashes the **raw bytes** + of a fresh fetch. After a re-pin the page printed a green "match" the gate + refuses — Run 38 measured rc 1 / 194 passed / 1 failed on exactly that + state. The pin moves to the wire, the side the gate's rows and any outside + verifier (`curl -sS | sha256sum`) already hash. +- **Two files change, the gate does not.** Collector `helm-collect-r39.py` + **31,595 B / sha256 `5a99364bd4bbca2b5d7f1c4ff13dba5a1488154b6e363f238e2e265a243b9966` / + 750 lines** on `4e45021d…` (29,954 / 720): one bytes-mode fetch (the old + block fetched the body twice — a race between two curl calls), both digests + from the same bytes, `manifest_match` pin-vs-wire, the pin itself on the + wire; `live_body_sha256` keeps its folded meaning because G6 requires both + fields to exist and to differ. Renderer `helm-render-r39.py` **23,523 B / + `117001e839dbbac5fb35c3d1c5f11da461c7e5564049b1aeb5d51a35a7bbfdc6` / + 522 lines** on `a70998c8…` (22,930 / 514): the page's "live body sha256" + line publishes the **wire** digest, because G13 row 1 compares that + published hash against the held pin. Gate **`833d0827…` byte unchanged** + (190,330 B / 3,619 L / 145 registrations) — its contract was right, the + producer was not. +- **The rehearsal, two arms, predictions written first (13 of 14 met).** + Arm A (the fix, sandbox bin = a copy of `/root/.helm/bin` + the payload, + every live-path literal the gate names redirected in, the real live pin + seeded): collect #1 `manifest_match false` (wire `c34ae2c2…` vs held + `f27326e8…`); render #1 red drift pill, 13,849 B / `3dd6125f…`; gate **rc 0 / + 195 / 0**; `--pin` writes `c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4`; + collect #2 `manifest_match true`; render #2 **green "match" pill**, published + hash `c34ae2c245117ca7` == pin[:16]; **gate on render #2 rc 0 / 195 / 0** — + the leg Run 38 measured 194/1 on. Drift probe: a mutated pin -> collect #3 + false -> render #3 red -> gate 195/0, pin restored. **Arm B (the control: + the shipped text-mode pin + shipped renderer, same gate) reproduces the + bug**: `--pin` writes the folded digest `e40308e573d046d7…`, collect #2 + `manifest_match true`, render #2 green pill, **gate rc 1 / 194 / 1**, sole + failure G13 row 2 `live_sha256=c34ae2c2… held_pin_digest=e40308e5… + pin_matches_live_now=False` — the before/after pair, differing only in the + collector. +- **The outside verifier, which is the point of the alignment.** `curl -sS + --max-time 20 https://www.stackchainmagazine.net/ | sha256sum` -> + `c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4` + (217,163 B): **== snapshot `live_body_sha256_wire`, == held pin, != + `live_body_sha256`** (`e40308e5…`). Through 2026-10-15 no stranger could + reproduce the pin; now any stranger can. +- **The one miss, and it is the twin's own artifact.** A-P7 (the + G11-contract twin at 195/0) measured 194/1: the twin redirects the pre-G14 + renderer path to the sandbox bin renderer — which *is* the payload renderer + now — so G14's discriminator negative leg (the old renderer's stale output + must lack the hash-line qualifier) collapses by construction. Run 38 logged + the identical artifact on the identical twin; the prediction was carried + from its docstring, where it was also not met. Every G11 contract row + passes; the parity gate (195/0) and the control arm (194/1) between them + isolate the fix. +- **An incidental catch.** The byte-stability re-run after the drift probe + (page still the red render, pin restored to live) returned rc 1 / 194 / 1 + with the sole failure **G13 row 3** — `unqualified_red_pill=True + live_sha256=c34ae2c2… held_pin_digest=c34ae2c2… pin_matches_live_now=True`. + Row 3 was demonstrated in Run 35 on a constructed cell; here it fired on a + real state transition the sandbox itself produced. +- **Byte-stability, measured not asserted.** The two acceptance-leg stdouts + are 17,027 B each and differ on exactly **4 lines**, all per-run `mkdtemp` + sandbox paths; a normalisation over those shapes gives residual 0, one + digest `49eb85e9a1461769…`. Portable citations: the rc, the tally, the + failing-row text. +- **Live state delta 0 across every leg of both arms**: deployed page 9,865 B + / `427b7b54…`; snapshot 14,039 B / `aa842b0f…`; held pin 120 B / + `5b6d7071…`; five deployed bin digests unmoved; `grep -c HELM_COLLECTOR` + /root/.helm/bin/helm-selftest.py` = **0** (Q40 stands, nothing of Q31–Run 39 + in production); `/tmp/q31-g8-deploy-*` **475 before and after**; sandboxes + created and not cleaned by the gate: 0 of 0. +- **The adoption ask, materially amended.** Run 38 had to prescribe + "cp **without** a `--pin` first" because a green pill could not ship green + while the site serves CRLF. That constraint is gone: arm A measured the + full sequence **with** the re-pin — `--pin` -> collect -> render -> gate + **rc 0 / 195 / 0 on a green page**. Both variants are green (no `--pin`: an + honest red drift page, 195/0; `--pin` first: a green page, 195/0), and + whether to re-pin at all — accepting the current live body as the drift + reference — is a policy choice, not a technical one. **Sequence (four + files, one order): adopt renderer `117001e8…` -> adopt collector + `5a99364b…` + gate `833d0827…` -> re-collect -> re-render -> deploy.** The + file list must be re-read at adoption time, never copied from an earlier + block. Old-convention pins remain readable: a folded-digest pin simply + fails `manifest_match` until a re-pin, which is today's state anyway. +- **Standing, unchanged and still human-gated:** that `cp`; the stale + `manifest_match` pin (measured false on five instruments now); Q13's + publication call; Q9's checksum handover; Q19's onboarding; Q42; Q52; + Q53. diff --git a/checkins/2026-10-15-merlin.md b/checkins/2026-10-15-merlin.md index 53a19e9..7e04343 100644 --- a/checkins/2026-10-15-merlin.md +++ b/checkins/2026-10-15-merlin.md @@ -955,3 +955,84 @@ Live and deployed unchanged and re-measured after the run: snapshot 14,039 B no another-party file edited, `decisions/` and `inbox/` untouched, no secret printed. Merlin , author=merlin. — Merlin (Run 38, landing) + + +--- + +## Run 39 — the pin/hash convention split closed (Helm lane, 2026-10-15 ~16:1x–16:3xZ) + +### Did + +Took the one executable unit the lane had measured and labelled but never +fixed — the defect Run 38's own record closed with: *"align the convention on +one side."* The Helm's held pin and `manifest_match` hashed curl's stdout read +as **text** (13 CRLF pairs fold: 217,163 wire bytes -> 217,119 chars) while the +gate's G13 row 2 hashes the **raw bytes**, so after a `helm pin` the page +printed a green "match" the gate refuses (Run 38: rc 1 / 194 / 1). The pin now +hashes the wire — the convention the gate's rows and any outside verifier +already use. Two files changed, the gate did not: + +- collector `helm-collect-r39.py` 31,595 B / sha256 + `5a99364bd4bbca2b5d7f1c4ff13dba5a1488154b6e363f238e2e265a243b9966` / 750 + lines (on `4e45021d…` 29,954 / 720): one bytes-mode fetch (the old block + fetched the body twice — a race between two curl calls), both digests from + the same bytes, `manifest_match` pin-vs-wire, the pin itself on the wire; +- renderer `helm-render-r39.py` 23,523 B / + `117001e839dbbac5fb35c3d1c5f11da461c7e5564049b1aeb5d51a35a7bbfdc6` / 522 + lines (on `a70998c8…` 22,930 / 514): the page's "live body sha256" line + publishes the wire digest, because G13 row 1 compares that published hash + against the held pin; +- gate `833d0827…` byte unchanged (190,330 B / 3,619 L / 145 registrations). + +Rehearsed on two sandboxes, predictions written before any gate ran, **13 of +14 met**. Arm A (the fix): collect #1 `manifest_match false` (wire `c34ae2c2…` +vs held `f27326e8…`); render #1 red drift pill 13,849 B / `3dd6125f…`; gate +**rc 0 / 195 / 0**; `--pin` writes `c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4`; +collect #2 `manifest_match true`; render #2 **green "match" pill**, published +hash `c34ae2c245117ca7` == pin[:16]; **gate on render #2 rc 0 / 195 / 0** — +the leg Run 38 measured 194/1 on. Drift probe: a mutated pin -> collect #3 +false -> render #3 red -> gate 195/0, pin restored. **Arm B (the control, the +shipped collector and renderer, the same gate) reproduces the bug**: `--pin` +writes the folded digest `e40308e573d046d7…`, collect #2 `manifest_match true`, +render #2 green pill, **gate rc 1 / 194 / 1**, sole failure G13 row 2 +(`live_sha256=c34ae2c2… held_pin_digest=e40308e5… pin_matches_live_now=False`). +The outside verifier — the point of the whole alignment — `curl -sS --max-time +20 https://www.stackchainmagazine.net/ | sha256sum` -> +`c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4` (217,163 B): +**== snapshot `live_body_sha256_wire`, == held pin, != `live_body_sha256`**. +Record: `recoveries/helm-pin-hash-convention.md` (12,513 B at the write); +queue block `Q45S12`. Live delta 0 across every leg of both arms (page 9,865 B +/ `427b7b54…`, snapshot 14,039 B / `aa842b0f…`, held pin 120 B / `5b6d7071…`, +five deployed bin digests unmoved), `grep -c HELM_COLLECTOR` = **0** so Q40 +stands and nothing is in production, `/tmp/q31-g8-deploy-*` 475 before and +after, sandboxes 0 of 0. + +### Blocked + +Nothing. The unit was executable end to end and ran to its acceptance leg. + +### Next + +The §4 adoption sequence is materially amended and remains the only +human-gated item on this lane: Run 38 had to prescribe "cp **without** a +`--pin` first" because a green pill could not ship green while the site serves +CRLF; that constraint is gone. **Adopt renderer `117001e8…` -> adopt collector +`5a99364b…` + gate `833d0827…` -> re-collect -> re-render -> deploy.** Both +adoption variants now pass: no `--pin` (honest red drift page, 195/0) and +`--pin` first (green page, 195/0) — whether to re-pin at all, i.e. accept the +current live body as the drift reference, is a policy choice, not a technical +one. The file list must be re-read at adoption time, never copied from an +earlier block. After that the Helm executable set is empty again; the next unit +is a decision, not a task. + +### Ask + +One line for Alexander, and it is a decision, not a task: **run the four-file +`cp` in the order above, and say whether the deploy step re-pins** (accepting +today's live body as the drift reference) or ships the honest red drift pill. +Until then the public page publishes a green "match" against a pin that +measurably does not match — the defect G10–G14 exist to catch, still live, with +no `as of` and no disclaimer. Everything else stands unchanged and is not +re-raised: the `manifest_match` pin, Q13, Q9, Q19, Q42, Q52, Q53. + +— Merlin (Run 39) diff --git a/recoveries/helm-pin-hash-convention.md b/recoveries/helm-pin-hash-convention.md new file mode 100644 index 0000000..542d380 --- /dev/null +++ b/recoveries/helm-pin-hash-convention.md @@ -0,0 +1,190 @@ +# Run 39 — the pin/hash convention split, aligned on the wire side + +**Merlin (Helm lane), 2026-10-15 ~16:1x–16:3xZ.** Scratch tree `/root/crucible/q68/`. +Nothing deployed: no `cp` into `/root/.helm/bin/`, no write to the live document +root, `decisions/` and `inbox/` untouched, no another-party file edited, no +secret printed. Instrument set: `fix_r39.py`, `build_r39.py`, `run_r39.py`, +`stability_r39.py`, `report_r39.py`; artifacts `out/FIX.json`, +`out/BUILD39.json`, `out/RUN39.json`, `out/R39-STABILITY.json`, +`out/R39-STABILITY-{1,2}.txt` (host-local, E13 — `git ls-files | grep -c '^out/'` += 0; the raw path 404s for `out/`, which is not a missing file). + +## 1. The unit, and why it was this one + +Run 38 (`recoveries/helm-adoption-rehearsal.md`) performed the §4 adoption on a +copy and measured the blocker: after `helm pin`, collect and render produce a +page whose green "match" pill the gate refuses — + + pin_stackchain (helm-collect.py:664-680) hashes curl's stdout read as TEXT + (Python universal newlines: 13 CRLF pairs fold, 217,163 wire bytes -> + 217,119 characters), so the pin and manifest_match were over the folded body; + G13 row 2 (helm-selftest-q65.py:3344-3376) hashes the RAW bytes of a fresh + fetch and compares them to the held pin. + +Run 38's own closing line named the fix — *"align the convention on one side"* — +and named which side: the wire. The gate's rows compare the pin against the +bytes an outside verifier reproduces with `curl -sS | sha256sum`; the +collector's comment through 2026-10-15 already admitted the normalised digest +is not independently reproducible, yet the pin was taken through the normalised +path. A drift detector whose reference a stranger cannot recompute is not a +detector. **The pin moves to the wire.** + +## 2. What changed — two files, the gate untouched + +* **The collector** (`helm-collect-r39.py`, from `4e45021d…`): + `collect_stackchain()` fetches the body **once, in bytes mode** and computes + both digests from the same bytes — `live_body_sha256_wire` (canonical) and + `live_body_sha256` (the CRLF-folded digest, kept under its historical field + name because the gate's G6 contract requires both fields to exist and to + differ). `manifest_match` is now **pin-vs-wire**. `pin_stackchain()` hashes + the wire bytes the same way, in one fetch. The old block fetched the body + twice — two curl calls that could return different bodies and pair two + digests that never described the same response; that race is gone too. + `body_hash_normalisation` still carries the substring G6 requires + ("CRLF->LF") and now names the pin convention explicitly. +* **The renderer** (`helm-render-r39.py`, from `a70998c8…`): the page's + "live body sha256" line publishes the **wire** digest, because G13 row 1 + compares that published hash against the held pin — with the pin on the wire + and the page on the folded body, a green pill would fail row 1 instead. The + old field stays as a fallback so pre-Run-39 snapshots render rather than blank. +* **The gate `833d0827…` (190,330 B / 3,619 lines / 145 registrations) is byte + unchanged.** Its contract was right; the producer was not. + +Pre-images preserved byte-exact beside the fixed files +(`helm-collect-r39-pre.py`, `helm-render-r39-pre.py`), every edit's anchor +asserted to occur exactly once, `compile()` before each write. + +| file | pre-image | fixed | bytes | lines (`wc -l`) | +|---|---|---|---|---| +| collector | `4e45021d80395d3f…` | **`5a99364bd4bbca2b5d7f1c4ff13dba5a1488154b6e363f238e2e265a243b9966`** | 29,954 -> 31,595 | 720 -> 750 | +| renderer | `a70998c8592a03cd…` | **`117001e839dbbac5fb35c3d1c5f11da461c7e5564049b1aeb5d51a35a7bbfdc6`** | 22,930 -> 23,523 | 514 -> 522 | +| gate | `833d08275977054a…` | unchanged | 190,330 | 3,619 | + +## 3. The rehearsal — two arms, one sandbox each, predictions first + +Arm A = the fix; arm B = the control (the shipped text-mode pin + the shipped +renderer). Both sandboxes are a copy of `/root/.helm/bin` with the payload +landed on top (`adoption_identical_to_payload: true` in both), every live-path +literal the gate names redirected into the sandbox (collector path x2, +renderer path x8, deployed page x8, held pin x2, G11 scratch renderer x3), and +the held pin seeded with the **real** live pin so the drift is the real drift. +Predictions were written into `build_r39.py`'s docstring and `run_r39.py`'s +`PREDICTIONS` dict before any gate ran; **13 of 14 met**, the miss named in §5. + +### Arm A — the fix + +| leg | result | +|---|---| +| collect #1 | `manifest_match: false` — wire live `c34ae2c245117ca7…` vs held `f27326e8b13d…` (pinned 2026-10-08); snapshot records both digests (`live_body_sha256` `e40308e573d0…`, `live_body_sha256_wire` `c34ae2c24511…`), freshness FRESH, `observed_at 2026-10-15T16:17:01.942Z` | +| render #1 | rc 0, **red drift pill**, 13,849 B / `3dd6125ff525462a…`, `as of` x2, `not re-checked since` x0, published hash `c34ae2c245117ca7` | +| gate on render #1 | **rc 0 / 195 passed / 0 failed** | +| `--pin` | rc 0, pinned `c34ae2c245117ca73ba5720b2c22b6fab689840070ff68cda7bffe3e723986d4` -> sandbox held (120 B / `3b543dbe732a3959…` / mtime_ns `1792081036093293752`) | +| collect #2 | `manifest_match: true`; `held_body_sha256` == `live_body_sha256_wire` == `c34ae2c24511…` | +| render #2 | rc 0, **green "match" pill**, 13,849 B / `6d134efce97782e2…`, `as of` x2, `not re-checked since` x0, published hash `c34ae2c245117ca7` == pin[:16] | +| **gate on render #2** | **rc 0 / 195 passed / 0 failed** — THE LEG Run 38 measured rc 1 / 194 / 1 on | +| gate repeat (byte-stability) | rc 0 / 195 / 0; the two raw stdouts are 17,027 B each and differ on exactly **4 lines**, all per-run `mkdtemp` sandbox paths (`/tmp/tmp*`, `/tmp/q31-g8-deploy-*`, `sbA/helm-legs-*`); a normalisation over those shapes gives **residual 0**, one normalised digest `49eb85e9a1461769…` | +| G11-contract twin | rc 1 / **194 / 1** — see §5, the sole failure is the twin's own artifact | +| drift probe | sandbox pin mutated to `0`*64 -> collect #3 `manifest_match: false` -> render #3 red drift pill -> gate **rc 0 / 195 / 0**; pin restored, content sha256 asserted equal to the post-pin value | +| outside verifier | `curl -sS --max-time 20 https://www.stackchainmagazine.net/ \| sha256sum` -> **`c34ae2c245117ca7…`**, 217,163 B: **== snapshot `live_body_sha256_wire`, == held pin, != `live_body_sha256`** (`e40308e5…`) | + +### Arm B — the control, the bug reproduced on this instrument + +| leg | result | +|---|---| +| collect #1 | `manifest_match: false` (normalised live `e40308e5…` vs held `f27326e8…`) | +| `--pin` | pinned **`e40308e573d046d7d503acecbfbde82b8ccd10758a345b0440d55b796e2d821e`** — the CRLF-folded digest, != the wire digest | +| collect #2 | `manifest_match: true` (both sides folded) | +| render #2 | green "match" pill, published hash `e40308e573d046d7` | +| **gate on render #2** | **rc 1 / 194 passed / 1 failed**, sole failure G13 row 2: *"an unqualified green pill is confirmed by a fresh fetch"* — `live_sha256=c34ae2c2… held_pin_digest=e40308e5… pin_matches_live_now=False` | + +That is Run 38's 194/1, reproduced here with the same gate on the same host, +differing only in the collector — the before/after pair the fix needed. + +## 4. The incidental catch + +The byte-stability script re-ran the parity gate **after** the drift probe, when +the sandbox page was still render #3's red pill but the pin had been restored to +the live digest. Both runs returned rc 1 / 194 / 1 with the sole failure +**G13 row 3**: *"a red pill is confirmed by a fresh fetch too"* — +`unqualified_red_pill=True live_sha256=c34ae2c2… held_pin_digest=c34ae2c2… +pin_matches_live_now=True`. Row 3 was demonstrated in Run 35 on a constructed +cell; here it fired on a **real state transition** the sandbox itself produced +(re-pin after a drift render). The failure is the sandbox's page being one +render behind its pin, not a defect in the fix. + +## 5. The one prediction miss, and it is the twin's own artifact + +**A-P7** (the G11-contract twin at 195/0) measured **194/1**. The sole failure +is the **G14 discriminator row**: *"the G14 predicate discriminates: the +adoption payload's own stale output (G11, `306d4bee`) v…"*. The twin redirects +the pre-G14 renderer path (`/root/crucible/q59/helm-render-g11.py`) to the +sandbox bin renderer — which **is** the payload renderer now — so the +discriminator's negative leg (the OLD renderer's stale output must lack the +hash-line qualifier) collapses by construction: both legs render with the fixed +renderer and both carry the qualifier. Every G11 contract row itself passes. +**Run 38 logged the identical artifact on the identical twin** ("The G11 twin's +second failure is Merlin's own artifact: its negative leg renders the same +scratch path the twin redirected"). The prediction was over-optimistic because +it was carried from Run 38's docstring, where it was also not met. A twin that +makes the two renderers identical cannot demonstrate a discriminator between +them; the honest unit is the parity gate (195/0, §3) plus the control arm's +194/1 (§3), which between them isolate the fix. + +## 6. Live, deployed, sandboxes, disk + +**Live delta 0 across every leg of both arms** (bytes + sha256 + mtime_ns, +censused before and after every leg): deployed page 9,865 B / +`427b7b54c69b18d2…` / mtime_ns `1791709034017837233`; snapshot 14,039 B / +`aa842b0fd88037f8…` / mtime_ns `1791479579475780303`; held pin 120 B / +`5b6d70716153c3f4…` / mtime_ns `1791478687099553071`; the five deployed bin +digests unmoved (`ee0b36a82f23…`, `5c67473d8928…`, `7ed1bca8f9da…`, +`12570786ba70…`, `738699986778…`). `grep -c HELM_COLLECTOR +/root/.helm/bin/helm-selftest.py` = **0**, so Q40 stands and none of Q31–Run 39 +is in production. `/tmp/q31-g8-deploy-*` census **475 before and after** — the +q65 gate's Edit B holds. Sandbox dirs created by the runs and not cleaned by +the gate: **0 of 0**. + +## 7. What this does to the adoption ask + +The ask was: cp the payload files, **without a `--pin` first**, acceptance +`rc 0 / 195 / 0` on a red drift page — because a green pill could not ship +green while the site serves CRLF. **That constraint is gone.** Arm A measured +the full sequence **with** the re-pin: `--pin` -> collect -> render -> gate += **rc 0 / 195 / 0 on a page carrying a green pill**, and the pill's reference +is now reproducible by any stranger with curl. Both adoption variants are +green: + +* no `--pin`: red drift pill, honest, 195/0; +* `--pin` first: green pill, 195/0 — the pin accepts the current live body as + the drift reference, which is a policy choice, not a technical one. + +**Adoption sequence, updated (four files, one order):** adopt renderer +**`117001e8…`** (23,523 B, superseding `a70998c8…`) -> adopt collector +**`5a99364b…`** (31,595 B, superseding `4e45021d…`) + gate **`833d0827…`** +(190,330 B, unchanged) -> re-collect -> re-render -> deploy. The file list must +be re-read at adoption time, never copied from an earlier block. The `cp` +itself remains Alexander's under §4. + +**Backward compatibility, stated:** a held pin written by the old convention +(e.g. today's `f27326e8…`) simply does not equal the wire digest, so +`manifest_match` reads False until a re-pin — the same state as today, since +the live pin is stale anyway. Nothing is deleted; `live_body_sha256` keeps its +meaning and both digests remain in every snapshot. + +## 8. Limits + +* The rehearsal's page is rendered from the sandbox snapshot while the gate's + producer legs render from the live snapshot (the live snapshot cannot be + written from here); the live fetch inside G13 rows 2 and 3 is a real network + read of the snapshot's own URL. +* The gate was run six times in arm A and twice in arm B; the 190 KB gate was + not re-run for the parity rows beyond those, and the failing-row text is + quoted from the recorded runs. +* The wire convention assumes the served bytes are the bytes to pin. A site + that re-encodes per response (gzip variants, chunk boundaries) would make + even the wire digest unstable; today's body is byte-stable across every + reading this lane has taken (217,163 B / `c34ae2c2…` since 2026-10-14). +* A subject that reads the held pin and re-writes it through a *different* + fetch path (e.g. a proxy that normalises newlines) would reintroduce a + split; the gate's G13 rows are the detector for exactly that, and they now + pass only when both sides agree.