Files
troupe-standup/recoveries/helm-deployed-pill-guard.md
T
Merlin 63158803e8 G12 (Helm lane): the deployed page's pin pill -- the half of the cell no gate read
grep 'held copy' over the shipped gate 125754b270bf (161122 B / 3053 L / 135
regs) returns three hits (:2841 G10's negative literal, :2882 a comment, :2893
G11's constant) and NONE is read off the deployed path, so G11's pill rule was
guarded on scratch renders only. New gate helm-selftest-q62.py 171979 B / 3256 L
/ 138 regs / sha256 4b18329c7437bec4c5c05be86ddd8376a7396eda9c97739410b1ab5952e4d270
on that base, twin 0fc58aabfb8d9345 differing on exactly one asserted line
(3073, _g12_deployed repointed at the production renderer's own stale output).

My first predicate was falsified by measurement before it shipped: the obvious
rule ("held copy" present implies "as of" present) is REDUNDANT with G10, since
G12-fail implies "as of" absent and G10-fail is "not re-checked since absent OR
as of absent", so every body it refused G10 already refused. Corrected rule is a
complement, not a duplicate: G10 owns the MISSING clock (today's page, G10 red,
G12 correctly green); G12 owns the INCOHERENT pair (green pill AND a staleness
disclaimer, which G10 passes because both its strings are present).

The discriminator runs on an artifact production would deploy, not a string I
built: helm-render-plain.py is byte-identical to /root/.helm/bin/helm-render.py
(21766 B / 5c67473d89283c3d) and at --as-of 2026-10-14T16:00:00.000Z emits
11806 B / 3f48643d8e7bac77 carrying the green pill, "as of" x1 and
"not re-checked since" x1 -- G10 passes it, G12 refuses it.

Prediction stated before the run and met exactly: shipped rc 1, 187 passed /
1 failed (sole failure G10's deployed-page row), twice at 16212 B each; twin
rc 1, 186 passed / 2 failed at 16583 B, adding G12 row 1. live_moved {} and
sandboxes [] on all three legs. Byte-stability measured: G12 rows identical
across both shipped runs, stdout identical after sandbox normalisation with
residual 0, normalised sha256 7a080e1616fb20e3.

Two defects of mine logged first: the first predicate's redundancy (measured
before shipping), and the runner's stdout normaliser matching (helm-legs-|
/tmp/tmp) while this host's TMPDIR is /root/.hermes/profiles/merlin/cache/
scratch, so it reported residual 2 with no characterisation -- the two lines
printed, the pattern corrected, the run re-run; no G12 row depended on it.

Live state delta 0 on bytes+sha256+mtime_ns across every leg: page 9865 B /
427b7b54c69b18d2, snapshot 14039 B / aa842b0fd88037f8, held pin 120 B /
5b6d70716153c3f4. Deployed /root/.helm/bin/ untouched (five digests re-read
plus __pycache__), grep -c HELM_COLLECTOR = 0 so Q40 stands and none of
Q31-Q62 is in production. Sandboxes 0. Repo main at 07fdaf9c8c, worktree
clean, remote identical; 102 merlin-authored commits before this push. Disk
41 G avail of 154.

Nothing deployed, no another-party file edited, decisions/ and inbox/
untouched, no secret printed. No item closed, none 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 the lane had measured
and labelled but never fixed. Append-only family, 0 deletions. Merlin
<merlin@agents.invalid>.
2026-10-15 01:23:33 +00:00

11 KiB
Raw Blame History

G12 — the deployed page's pin pill

Helm lane, Run 33, 2026-10-15. Merlin. Scratch tree /root/crucible/q62/. Nothing deployed: no cp into /root/.helm/bin/, no --deploy, no write to the live document root. decisions/ and inbox/ untouched. No another-party file edited. No secret printed.


1. The gap, measured before anything was built

/root/crucible/q62/probe_pill.py (1,963 B / sha256 0d124eaee1096b7358caa5e018eae394223bd24fefd962269d15b4eeb5583328, 51 lines) → out/PILL-PROBE.json, generated_at 2026-10-15T01:12:21+00:00.

The deployed page /var/www/alexander-whitestone/helm/index.html is 9,865 B / sha256 427b7b54c69b18d270288910fc810732463129f48ec4bdd7dbc75cdb22997ce4 / mtime_ns 1791709034017837233, and its manifest cell reads, verbatim:

<div class="kv">held copy <span style="color:#22c55e">match</span> (pinned vs live)</div>
<div class="kv dim">https://www.stackchainmagazine.net/</div>

with as of occurring 0 times and not re-checked since 0 times. There is no qualifier line at all.

G10 reads that file and checks the qualifier. G11 conditions the pill but only on scratch renders under /root/crucible/q59/. grep -n 'held copy' over the shipped gate 125754b270bf… (161,122 B / 3,053 lines / 135 registrations) returns exactly three hits — :2841 G10's negative literal, :2882 a comment, :2893 G11's constant — and none of them is read off the deployed path. So the pill half of the cell G11 exists to forbid is unguarded on the one artifact the public reads.

2. First predicate: falsified by measurement before it shipped

The obvious rule is a page presenting a pin pill must state the clock behind it: ("held copy" not in text) or ("as of " in text). It is redundant, and redundancy in a gate is not a cosmetic flaw — it is a gate that cannot fire while its sibling is green, which is theatre. /root/crucible/q62/distinguishing_cell.py (3,071 B / c4b9b9dacd64dd61…, 73 lines) proves it:

body G10 G12 (first form)
today's deployed page (9,865 B) False False
real current-generation stale render (11,819 B / 951a8a76…) True True
that render with the amber pill swapped to unqualified green (11,806 B / 3f48643d…) True True
amber pill, no qualifier False False
qualifier, no pill True True

G12-fail implies "as of " absent; G10-fail is "not re-checked since" absent OR "as of " absent. So every body the first predicate refused, G10 already refused — and the swapped body, a green "match" beside a five-day-old disclaimer, walked through both unreported. That is the exact defect the control plane named on 2026-10-14, and the first predicate could not see it. Logged rather than hidden; nothing was shipped in that form.

3. The distinguishing cell is a real artifact, not a string I built

/root/crucible/q62/standin_from_production.py (2,068 B / 5cbfff139f562a68…, 52 lines):

  • /root/crucible/q59/helm-render-plain.py is byte-identical to the renderer in production — both 21,766 B / sha256 5c67473d89283c3d4434928dc96d45ff48a41d8f443ecc3c98e9236be8b597f9. So the unpatched renderer is not a scratch toy; it is /root/.helm/bin/helm-render.py.
  • Rendering it at --as-of 2026-10-14T16:00:00.000Z emits 11,806 B / sha256 3f48643d8e7bac77020674198e6be78a35f27a0fec71b400d718b52b88ca4ad7, rc 0, carrying as of ×1, not re-checked since ×1 and the unqualified green pill ×1.

The digest is the same one the string substitution produced. So the body that passes G10 and fails G12 is an artifact production would deploy, not a construction of mine.

4. The corrected predicate, and why the two gates are complements

An unqualified green pin pill must never appear beside a staleness disclaimer. not (unqualified_green_pill and "not re-checked since" in text)

  • G10 owns the missing clock. Today's page: green pill, no as-of, no disclaimer. G10 refuses it; G12 correctly passes it.
  • G12 owns the incoherent pair. Green pill and a disclaimer saying the reading was never re-checked. G10 passes it — both of its strings are present — and G12 refuses it.

The mechanism is structural, not stylistic: the pill's colour and label come from the frozen manifest_match field (helm-render.py:323, :326) while the qualifier beside it is computed at render time (:343–:346). The two can disagree, and nothing read the pair together on the artifact the public reads.

5. The gate

Built by /root/crucible/q62/build_g12.py (3,600 B / 3af733da5b73773a…, 84 lines) from the shipped gate 125754b270bf… plus patch_g12.py (10,930 B / 12ca3ecbb29d6409…, 203 lines), inserted at the single # ---- report anchor (asserted count 1).

artifact bytes lines registrations sha256
helm-selftest-q62.py (shipped) 171,979 3,256 138 4b18329c7437bec4c5c05be86ddd8376a7396eda9c97739410b1ab5952e4d270
helm-selftest-q62-twin.py 171,982 3,256 138 0fc58aabfb8d9345ff80be1e4a24bbfca7f64518b938349ff1297d06504e2be5
q59 gate (base) 161,122 3,053 135 125754b270bf6b0f55911f407fa9c36c6161b45a71e646fa36a70db096d7de93

138 = 135 + 3. The twin differs on exactly one line (asserted, not claimed): line 3073, _g12_deployed repointed from the live path to /root/crucible/q62/out/g12-standin-deployed.html (11,806 B / 3f48643d…, the production renderer's own stale output).

Three checks, in this gate's house style:

  1. the deployed artifact — the pill the public reads must not claim a green match beside its own staleness disclaimer. Green today, because G10 owns that page's defect; the detail string says so rather than implying the gate found nothing.
  2. the discriminator — the production renderer's stale output violates the rule while G10 passes it, and the patched renderer's stale (951a8a76…, 11,819 B, amber pill) and fresh outputs both satisfy it. So the rule refuses the incoherent pair and not green.
  3. read-only — bytes + sha256 + mtime_ns identical around all four legs.

6. The run

/root/crucible/q62/run_gate_q62.py (5,192 B / e58a56d453c5de66…, 127 lines) → out/R33-GATE.json (6,453 B / 1a1744774ce3652f…), generated_at 2026-10-15T01:20:11+00:00, HELM_COLLECTOR=/root/crucible/q48/helm-collect.py throughout.

leg rc verdict stdout G12 rows
shipped-1 1 187 passed, 1 failed 16,212 B 3 PASS
shipped-2 1 187 passed, 1 failed 16,212 B 3 PASS
twin 1 186 passed, 2 failed 16,583 B 2 PASS, 1 FAIL

The prediction, stated before the run and met exactly: shipped 187/1 with the sole failure G10's deployed-page row; twin 186/2 adding G12 row 1. The twin's G12 row is red against a body that is a real production artifact, so the shipped gate's green row is a property of the deployed file and not of the predicate.

  • The twin's remaining failure is G10's row, unchanged — deployed=… exists=True bytes=9865 sha256=427b7b54…, i.e. the same defect, now seen by two gates from two directions.
  • Byte-stability: g12_lines_identical_across_shipped_runs: true; stdout_bytes_identical: true; stdout_sha_identical: false with the cause measured — mkdtemp suffixes. stdout_identical_after_sandbox_normalisation: true, residual_differing_lines_after_normalisation: 0, normalised stdout sha256 7a080e1616fb20e3e9685d67cb121b9a8af35614a7edba7b649aeca62e2612d0.
  • live_moved: {} on all three legs; sandboxes_after: [] shallow and recursive on all three.

7. A defect of mine, logged first

run_gate_q62.py's normaliser first matched (helm-legs-|/tmp/tmp) only, but this host's TMPDIR is /root/.hermes/profiles/merlin/cache/scratch, so the two mkdtemp suffixes the gate prints live under that prefix and were invisible to the pattern. It reported stdout_identical_after_sandbox_normalisation: false with residual 2 — a true figure with no characterisation behind it, which is this lane's own logged class. /root/crucible/q62/residual_lines.py (1,627 B / 17b8408dd57b0ace…) printed the two lines: tmp1prcmj7c vs tmph8sr6_e0 and q31-g8-deploy-ltgw0sri vs q31-g8-deploy-_j2jdsam. residual_lines_fixed.py (2,188 B / 62ddacff0b63f762…) shows the old pattern leaves 2 and the corrected one leaves 0. The runner was then patched and re-run, and §6's figures are the corrected ones. No G12 row and no verdict depended on the defect — the G12 rows were byte-identical across both shipped runs under either pattern.

8. Live state, delta 0

/root/crucible/q62/measure_final.py (2,702 B / 47d475ed7172c469…, 74 lines) → out/R33-FINAL.json (48,975 B / 7b3801eb20385144…), generated_at 2026-10-15T01:20:25+00:00. Unchanged on bytes + sha256 + mtime_ns across every leg of this run:

object bytes sha256 mtime_ns
deployed page 9,865 427b7b54c69b18d270288910fc810732463129f48ec4bdd7dbc75cdb22997ce4 1791709034017837233
snapshot 14,039 aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d 1791479579475780303
held pin 120 5b6d70716153c3f4bd82045d5d71edf88f793a240ce1275c3dfca5759d0ee297 1791478687099553071
  • Deployed /root/.helm/bin/ untouched: helm-collect.py 27,907 B / ee0b36a82f23fcf3…; helm-render.py 21,766 B / 5c67473d89283c3d…; helm-selftest.py 33,647 B / 7ed1bca8f9da624f…; helm-validate.py 3,556 B / 12570786ba703787…; summarize.py 1,463 B / 7386999867789694…; __pycache__/ holds four .pyc files an adoption must not copy in.
  • grep -c HELM_COLLECTOR /root/.helm/bin/helm-selftest.py = 0 — Q40 stands, so nothing of Q31–Q62 is in production.
  • Sandboxes: 0 shallow, 0 recursive, 0 helm-g12-*.
  • Repo: main at 07fdaf9c8cbaff8cc01f3dc6dc065eecb0070f16, worktree clean, git ls-remote origin main identical; 102 merlin-authored commits before this run's push.
  • Disk 41 G avail of 154 (74 % used).

9. Limits

  • The gate reads the deployed artifact but cannot make it current; the remedy is re-render and deploy, an operator's call under §4. G12 detects, it does not repair.
  • G12's predicate is about the pair, not about whether the pin actually matches. That is the collector's manifest_match job at collection time, and it is frozen by design.
  • No fuzzer: the enumerated render set only (patched stale, patched fresh, production stale).
  • The payload's raw < / & handling is Q29's territory and not revisited here.
  • No X page fetched this run.

10. Testimony only

None. Every figure in this record came from a command in this run, and each artifact carries its own digest above.

11. Standing, unchanged and still human-gated

The §4 adoption cp — now collector 4e45021d80395d3f… + gate 4b18329c7437bec4… (this run's, superseding 125754b270bf…) — the stale manifest_match pin, the G10 re-render, Q13's publication call, Q9's checksum handover, Q19's onboarding. No new 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 the lane had measured and labelled but never fixed.