Files
troupe-standup/recoveries/helm-hash-line-qualifier.md
T
Merlin be55b9542c G14 (Helm lane): the live-body-sha line carries its own clock, and the deploy sandbox that never left
Run 36. The unit is the residual Run 35's own record named and left open: the
page's "live body sha256" line is a present-tense label on the frozen pin
f27326e8 (pinned 2026-10-08T16:58:07.100Z) while the live body reads
c34ae2c2 (200 / 217,163 B), and no gate read it. The obvious predicate
(("live body sha256" not in text) or ("as of " in text)) is strictly weaker
than G10 and was falsified before it shipped (q65/probe_r36.py ->
out/R36-PROBE.json); the distinguishing cell is real -- the G11 renderer
306d4bee, the lane's current adoption payload, at the stale clock emits
11819 B / 951a8a7645fe on which G10, G12 and G13 row 1 all PASS while its
hash line is unqualified. Fix: the hash line's own div carries
"as of OBS . AGE ago . not re-checked since" (renderer a70998c8592a03cd,
22930 B); gate helm-selftest-q65.py 190330 B / 3619 lines / 145 check(
registrations / 833d08275977054a on 6a887f42 at five asserted anchors
(+7578 B / +155 lines / +3 registrations). Matrix (run_matrix_r36.py ->
out/R36-GATE.json, prediction stated before the run): shipped rc 1 / 192/3
(G10 deployed-page, G13 row 2 live, G14 row 1), byte-identical on rerun
after sandbox normalisation (07c1c58d, residual 0); twinI (g14-stale) rc 0 /
195/0 ALL GATES PASS; twinJ (g11-stale, the adoption payload) rc 1 / 194/1,
G14 row 1 only; control-g (q64 base, twinJ repoints) rc 0 / 192/0 -- the
hole measured: the adoption payload passes every gate the lane has today.
twinK's miss is a finding: predicted rc 0 / 195/0, measured rc 1 / 194/1
(G13 row 2) -- a fresh clock on the frozen manifest_match is still caught,
so the renderer alone does not make the page passable and re-collect ->
re-render -> deploy is load-bearing. Also fixed in the same build: the
Q31/G8 --deploy leg's mkdtemp was never removed (+1 leaked
/tmp/q31-g8-deploy-* per gate run, 474 on /tmp at the final census); the
cleanup lands after the two G8 checks that read it (the first form, in the
finally, turned both rows red -- measured shipped 190/5, twinI 193/2), and
post-fix delta is 0 on all five q65 legs while control-g still leaks.
Live state delta 0 across all seven legs (page 9865 B / 427b7b54c69b18d2,
snapshot 14039 B / aa842b0fd88037f8, pin 120 B / 5b6d70716153c3f4);
deployed bin untouched, grep -c HELM_COLLECTOR = 0 so Q40 stands and none
of Q31-G14 is in production; disk 41 G free of 154. Adoption, five files in
one order: renderer a70998c8 -> collector 4e45021d + gate 833d0827 ->
re-collect -> re-render -> deploy; acceptance rc 0 / 195 / 0 ALL GATES PASS
(twinI's shape), demonstrated a third time. Reply 60's correction
discharged: pin_stackchain is helm-collect.py:664, not 647-662. Nothing
deployed, no another-party file edited, decisions/ and inbox/ untouched,
no secret printed. No item closed, none opened. Merlin <merlin@agents.invalid>.
2026-10-15 08:41:41 +00:00

13 KiB
Raw Blame History

The live-body-sha line's own clock — G14, and the deploy sandbox that never left

Run 36, Helm lane. Merlin, 2026-10-15. Scratch /root/crucible/q65/. Deliverable: this record. Renderer helm-render-g14.py (22,930 B / sha256 a70998c8592a03cd68447e02126ce175732796c225f57ccaf90f973dfb5ff654 / 514 lines by wc -l), gate helm-selftest-q65.py (190,330 B / 3,619 lines / 145 check( registrations / sha256 833d08275977054a92dc6c9382ed08127307ac54552d738aef35b07825a39d3e), built from Run 35's shipped gate 6a887f42754a8d96… (182,752 B / 3,464 lines / 142 registrations) at five asserted anchors: +7,578 B / +155 lines / +3 registrations. Four twins and one control, each one to four asserted lines different. Subject collector 4e45021d80395d3f… / 29,954 B throughout, asserted by digest.

Nothing was deployed: no cp into /root/.helm/bin/, no --deploy, no write to the live document root, no write anywhere under /root/.helm. Live state measured around every leg: delta 0 (bytes + sha256 + mtime_ns on page, snapshot and pin). No another-party file edited; no secret printed; decisions/ and inbox/ untouched.


1. Why this unit

Run 35's record closed G13 with one stated open limit, in its own section 8:

"The page's 'live body sha256' line -- a present-tense label on a frozen
value -- is now covered transitively through the pin, but nothing checks
the label itself."

The line renders as live body sha256 f27326e8b13d1dec… on the deployed page. f27326e8… is the held pin, frozen 2026-10-08T16:58:07.100Z; the live body today is c34ae2c2… (200 / 217,163 B). The label claims the hash is live. G10 owns the page-level clock, G12 the pill's pairing, G13 the pill's truth — none reads that line. This run discharges the limit.

2. The obvious predicate, falsified before it shipped

q65/probe_r36.py → out/R36-PROBE.json, measured before anything was built. The first predicate that comes to mind:

obvious: ("live body sha256" not in text) or ("as of " in text)

G10's own predicate is ("not re-checked since" in text) and ("as of " in text). A body the obvious form refuses has the label present and no as of anywhere — which G10 refuses too. The obvious form is strictly weaker than G10; every body it refuses, G10 refuses. It cannot catch the defect on the G11 renderer, whose qualifier sits in its own <div> below the hash line.

The distinguishing cell is a real artifact, not a string I built. The G11 renderer (306d4bee…, the lane's current adoption payload) at the stale clock --as-of 2026-10-14T16:00:00.000Z emits 11,819 B / sha256 951a8a7645fe7ef42247de97d37ab10c99f89a9c05bff3fe8f36177456936485 — reproducing Run 29's and Run 33's recorded digest. Measured predicates on that body (R36-PROBE.json, cells.g11-stale):

predicate result
G10 (page-level clock) PASS — both as of and not re-checked since present
G12 (pill coherent with its clock) PASS — amber match (unverified)
G13 row 1 (published hash vs pin) PASS — f27326e8… is the pin
obvious predicate PASS
element predicate (the hash line's own <div> carries as of) FAIL

A page whose hash line is an unqualified present-tense claim of a frozen value passes every gate the lane has. That body is what the section-4 adoption would deploy today.

The rule that survives: the element that contains live body sha256 must itself contain as of — G10's page-level discipline applied to the line that makes the tense claim about a single value. Complementarity, stated rather than hidden: on today's deployed page (no clock anywhere) G10 and G14 are both red; on the G11 stale cell only G14 is red — which is the distinguishing work.

3. The renderer fix

q65/make_renderer_g14.py, pre-image q59/helm-render-g11.py (asserted 306d4befee7c9874…), one edit at a unique asserted anchor (line 350; my first anchor carried a trailing comma the source does not have — measured with grep -n + cat -A, the anchor corrected, the failure logged):

before: <div class="kv">live body sha256 <span class="mono">HEX…</span></div>
after:  <div class="kv">live body sha256 <span class="mono">HEX…</span>
        <span class="dim">as of OBS · AGE ago · not re-checked since</span></div>

The standalone match_qualifier div is untouched; the pill keeps its own clock. Emitted bytes, all four legs rc 0 (make_renderer_g14.py output, cells r36-*):

cell renderer clock bytes / sha256 as of in hash element
g11-stale 306d4bee… 2026-10-14T16:00:00Z 11,819 / 951a8a7645fe7ef4 False
g14-stale a70998c8… 2026-10-14T16:00:00Z 11,917 / ecb5838ed2953942 True
g11-fresh 306d4bee… 2026-10-08T18:00:00Z 11,624 / 1eec213e9e363d36 False
g14-fresh a70998c8… 2026-10-08T18:00:00Z 11,695 / 410e2f57b2aae51c True

The g11 digests reproduce the recorded ones exactly (control), and the G14 fresh element reads as of 2026-10-08T17:12:59.458Z · 47m 00s ago — the qualifier's tail (not re-checked since) appears only on the stale branch, same rule as the pill. Pre-image preserved byte-exact at q65/helm-render-g14-pre36.py.

4. The gate

q65/build_r36.py from q64/helm-selftest-q64.py (asserted 6a887f42754a8d96…) at five asserted anchors, +3 registrations (the deployed row, the discriminator, the read-only census), nothing renamed or removed. The twins repoint all four page subjects (_g10_deployed, _g12_deployed, _g13_deployed, _g14_deployed); control-g is the q64 base under twinJ's repoints.

The matrix, prediction stated before the run and met — with one exception, logged in §8 (run_matrix_r36.py → out/R36-GATE.json, generated_at run, live censused around every leg, live_delta_empty_all_legs: true):

config predicted measured verdict
shipped q65 rc 1, 192/3 rc 1, 192 passed, 3 failed (G10 deployed-page, G13 row 2 live, G14 row 1) met exactly
shipped again byte-identical stdout identical after sandbox normalisation, residual 0, sha256 07c1c58ddb969403… both runs met
twinI — all page subjects at the g14-stale render rc 0, 195/0 rc 0, 195 passed, 0 failed, ALL GATES PASS met exactly — the honest remediated state
twinK — all page subjects at the g14-fresh render rc 0, 195/0 rc 1, 194 passed, 1 failed — G13 row 2 NOT met; my prediction was wrong, §8.1
twinJ — all page subjects at the g11-stale render (the adoption payload) rc 1, 194/1 rc 1, 194 passed, 1 failed — G14 row 1 only, its evidence line reading hash_element='live body sha256 <span class="mono">f27326e8b13d1dec…</span>' met exactly
control-g — the q64 gate under twinJ's exact repoints rc 0, 192/0 rc 0, 192 passed, 0 failed, ALL GATES PASS met exactly — the hole, measured: the adoption payload passes every gate the lane has today

The twinJ / control-g pair isolates G14 row 1 and nothing else: same four page subjects, same pin, the only difference the row's existence.

twinK's red row is a finding, not a miss I can wave off. The g14-fresh cell carries a fresh clock (47m 00s ago) on the pill and the hash line — but manifest_match: true is still the frozen field, and G13 row 2's fresh fetch contradicts it (live_sha256=c34ae2c2… vs held_pin_digest=f27326e8…, pin_matches_live_now=False). A fresh clock on a false claim is exactly the laundering Run 34's G13 exists to catch, and it still catches it after the G14 fix. The G14 renderer alone does not make the page passable; only re-collect → re-render → deploy does — which is the same sequence the lane has carried since Run 28, now with the renderer first in it.

5. The sandbox leak, measured and fixed

Measured before the fix (sandbox_probe.py, one shipped leg): every sandbox pattern flat except /tmp/q31-g8-deploy-*, +1 per leg. The creation site is helm-selftest.py:2608 (tempfile.mkdtemp(prefix="q31-g8-deploy-") for the Q31/G8 --deploy leg), whose finally restored the patched constants but never removed the directory. 474 directories on /tmp at the final census — the residue of every gate run since the leg landed.

Fixed in the same build, edit B: capture the directory and remove it immediately after the two G8 checks that read it (the --deploy-writes and valid-JSON rows). My first form put the removal inside the finally, which turned both rows red (measured: shipped 190/5, twinI 193/2 — the cleanup firing before the checks read the file). The second form is what ships; the first is preserved in build_r36.py's comment block. Post-fix: sandbox delta 0 on all five q65 legs; control-g, the unfixed q64 base, still leaks its one — the hole leaks too.

6. Live state, delta 0 across all seven legs

Bytes + sha256 + mtime_ns, censused around every leg (out/R36-GATE.json, live_delta_empty_all_legs: true, per-leg live_unchanged: true ×6; out/R36-FINAL.json):

  • deployed page 9,865 B / 427b7b54c69b18d270288910fc810732463129f48ec4bdd7dbc75cdb22997ce4 / 1791709034017837233
  • snapshot 14,039 B / aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d / 1791479579475780303
  • held pin 120 B / 5b6d70716153c3f4bd82045d5d71edf88f793a240ce1275c3dfca5759d0ee297 / 1791478687099553071
  • deployed /root/.helm/bin/ untouched — five digests re-read (ee0b36a82f23fcf3… / 5c67473d89283c3d… / 7ed1bca8f9da624f… / 12570786ba703787… / 7386999867789694…) plus the __pycache__/ an adoption must not copy in; grep -c HELM_COLLECTOR = 0, so Q40 stands and none of Q31–G14 is in production.
  • disk 41 G free of 154 (74 %). Sandboxes 0 (/tmp/helm-legs-*); the q31-g8-deploy-* residue stands at 474 with the leak closed going forward.

7. Adoption — five files, one order

adopt renderer a70998c8… (22,930 B, superseding 306d4bee…) → adopt collector 4e45021d… (29,954 B) + gate 833d0827… (190,330 B, superseding 6a887f42… and everything before it) → re-collect → re-render → deploy.

The acceptance criterion is unchanged and now demonstrated a third time: the sequence is done when the gate reaches twinI's shape, rc 0 / 195 passed / 0 failed / ALL GATES PASS — and twinK measures that the renderer alone cannot reach it. The re-collect is load-bearing three times over: G13's live row stays red until a collect recomputes manifest_match, Finding 1 of Run 35 shows the re-pin can leave page and pin disagreeing, and the G14 qualifier only states a clock truthfully if the reading behind it is fresh.

Standing, unchanged and still human-gated: that cp; the stale manifest_match pin (measured false, four times now, on four instruments); the Q13 publication call; Q9's checksum handover; Q19's onboarding. 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 residual Run 35's own record named and left open.

8. Defects of mine, logged first

  1. My twinK prediction was wrong. It read rc 0, 195/0; measured rc 1, 194/1 (G13 row 2). The reason is in §4: I predicted the g14-fresh cell would be green, forgetting that the frozen manifest_match survives the renderer fix and G13 row 2 is the row that catches it. The prediction stands as first written in build_r36.py and run_matrix_r36.py; the miss is the record.
  2. My first anchor for the renderer edit carried a trailing comma the source does not have (grep -n + cat -A settled it; the Run 35 comment-only patch used the same file's line 350 correctly). Counted as the lane's anchor class.
  3. My first sandbox cleanup fired too early — in the finally, before the two G8 checks that read _deploy_snap (measured 190/5 and 193/2). The second form is what ships; both are in build_r36.py's comment.
  4. run_matrix_r36.py crashed on its own artifact ordering (out["byte_stability"] referenced before out existed — NameError — after the first full matrix had already printed every row). Fixed and re-run; the figures above are from the run that wrote the artifact.
  5. A no-op replace remains in build_r36.py (the OLD_C/NEW_C pair left after moving the cleanup out of the finally). Harmless, logged rather than edited out, so the first form stays visible.

Limits, stated as the item's first limits:

  • G14 detects and cannot repair. The remedy is still re-collect → re-render → deploy, an operator's call under §4 — and twinK shows the renderer is necessary but not sufficient.
  • The predicate reads the hash line's own <div>. A renderer that moved the qualifier into a sibling element while keeping the label would pass the letter of the rule; the pill's qualifier already lives in its own <div>, so this is the same trade G10 and G12 take, taken knowingly.
  • The fix is comment-free of any freshness judgement: the clock is always emitted with the hash, stale or fresh, because a page that decides for itself when its claim is current is the defect G13 catches.
  • The 474 leaked q31-g8-deploy-* directories are host residue from earlier runs; the fix stops the growth, and removing the old ones is a host operation this run does not take.

— Merlin (Run 36), Helm lane