Files
troupe-standup/checkins/2026-10-14-merlin.md
T

20 KiB
Raw Blame History

2026-10-14 — 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.


Run 22 — Q45 §9: the pwd channel

Did

Claimed and finished the Q45 §9 follow-on — the pwd channel (Helm lane; the lane's own named residual, the limit the Q45 §9 record carried: "a subject reading pwd.getpwuid(...).pw_dir directly bypasses HOME and the redirect cannot see it"). Deliverable: recoveries/helm-pwdir-channel-refusal.md (14,808 B / sha256 d4c381f713e9fe95beefbd14a93220ab4049625f280c116e656419f3e11b7b89, this host). Queue block appended at the foot of WORK-QUEUE.md (951,756 B / sha256 d8f54086edbcbbc96e39533d7b6dcf0e9effff108b596ed18685b03d1045e1db, +5,419 B / 63 lines, trailing newline asserted before and after). Scratch tree /root/crucible/q55/; nothing deployed, no cp into /root/.helm/bin/, decisions/ and inbox/ untouched, no another-party file edited, no secret.

The class, measured on the shipped gate before the change. The base gate is /root/crucible/q52/helm-selftest-q52.py = 78b290ecf2d93e0c… (140,365 B / 2,677 lines / 126 registrations), copied into q55/ and re-verified by sha256sum. Two fixtures transform the real collector (4e45021d…, 720 / 29,954, byte-identical to Q45 §9's) into a subject whose root comes from the user database — collector-pwdir-named.py (4d62da91…, 29,994 B) and collector-pwdir-root.py (8b368ead…, 29,979 B, the constant renamed HELM_HOME→ROOT). Run under a scratch HOME, both resolve ROOT=/root/.helm and HELD_DIR=/root/.helm/data/held with rc 0 — the interpreter's own verdict of the class. Under the shipped gate: the default run is 175/1 (Q45 FAIL, escapes={"ROOT": "/root/.helm", "HELD_DIR": "/root/.helm/data/held"}) while Q52 PASSES — the check asserts the legs' HOME is redirected, and pwd.getpwuid never reads HOME. Under the gate's own --q52-witness flag — the flag that exists to measure this class's write path: rc 0, copy_pin_files_anywhere_in_sandbox [], and the live held pin moves (5b6d7071…→fdd45f74…, mtime_ns 1791478687099553071→1791940472306970986; guard q55_guard.py compare after-pwr-witness: "moved": true), restored byte-exact. The named-constant fixture writes live through the same path (302bfda5…). A foot check reports after the legs; only a precondition refuses before them.

The fix. Gate cd43284ff009d1cceb3aaa6a65b701d1076eaf801e32b705672601b4122b746a (143,385 B / 2,735 lines / 126 registrations — unchanged; one edit, +3,020 B / +58 lines, 2,677 + 58 = 2,735 exactly) on the Q52 gate: a precondition after Q46's parse guard and the ast import, before the Q39 sandbox, the admission probe and any leg — a subject whose own AST reads the pwd module is refused (exit 2, dated, naming the subject, every pwd site with its line, the live snapshot before/after). No check() registered, so the green pair still reports exactly 176 / 0. Disarmed twin 8adad99bdc872ecd09ddea88ae55b5fc55a3886571ffaa5f49a053b52430586d (143,416 / 2,735 / 126), one line different, 31 B larger (the Q52-twin pattern). The internal label is Q45S9, not a queue number — the lane's own collision lesson applied to a fresh artifact before any readback or push, so these are the only digests this run carries.

The matrix, 25 cells, all guarded (run_matrix_q55.py → out/Q55-MATRIX.json, 12; run_matrix2_q55.py → out/Q55-MATRIX2.json, 13). Armed × pwr / pwr-witness / pwn → rc 2 refusal, stdout 0 B (e3b0c442…), live delta {}. Disarmed × pwr-witness → the escape reproduces (probe HELD_DIR=/root/.helm/data/held, pin in sandbox [], live pin 5b6d7071…→ced810a9… / 1791941106156792591, restored byte-exact) — the refusal is load-bearing. Disarmed × pwr → 175/1, Q52 PASS, Q45 FAIL (the shipped behaviour). Green pair ×5: 176/0, 14,044 B stdout / 1,216 B stderr, live delta {} each, 20.5–24.1 s. Regressions 11/11 (n1–n5, noparse, dep-unparseable, undecodable, broken_dep rc 2; latin1 and bom 176/0). Covered shapes are not over-refused and stay protected: armed × collector-home.py --q52-witness puts the pin inside the sandbox (q52-home/.helm/data/held/…) with the live pin unmoved; and the covered fixtures fail Q43 identically under the shipped gate (175/1 both, PASS/FAIL lists identical modulo sandbox names — measured side by side, so the fix introduces no behaviour change for them).

Live state, sandboxes, deployed. Delta 0 on bytes/sha256/mtime across all 25 cells (q55_guard.py compare final2, "moved": false): snapshot 14,039 B / aa842b0fd88037f8… / mtime_ns 1791479579475780303; pin 120 B / 5b6d70716153c3f4… / 1791478687099553071. ctime moved on the pin across the deliberately-live witness cells (guard restores) — disclosed. Sandboxes: the q55 tree 0/0 both ways (the refusal exits before the sandbox is created); the E14 leak re-measured at 26 across /root/crucible and all 26 removed (842,401 B reclaimed, after-count 0 both ways, out/Q55-CLEANUP.json), plus the q55 __pycache__ (the C32 class). Deployed /root/.helm/bin/ untouched (five digests re-read: ee0b36a8… / 5c67473d… / 7ed1bca8… / 12570786… / 73869998…), grep -c HELM_COLLECTOR = 0 — Q40 stands, so none of Q31–Q45 §9 is in production. Disk 45 G avail of 154 (71 %).

Five defects of mine, logged first in the deliverable: part 1's d/e rows pointed at fixtures not yet copied into the tree (a Q35 refusal against a nonexistent path — void rows, re-run in part 2, kept with the note); part 1's restored field compared a 12-char prefix to a full digest; part 1's Q45 filter matched the one-space rendering and missed the row it existed to find; my d/e expectation of 176/0 was assumed and the shipped-gate baseline taken after was the correction; and the gate's first-written Q55 label.

Blocked

Nothing blocks the lane. The standing human gates are unchanged: the §4 adoption cp — now collector 4e45021d… + gate cd43284ff009… (superseding 78b290ec… / e4967da9… / a951dbe8…), the manifest_match pin (stale since 2026-10-08), Q13's publication call (item 13's decided note controls over its proposed_action), Q9's checksum handover, Q19's onboarding. Q42 is zephyrus-sparkborn's, Q52 is Mercury's, Q53 is the career lane held for Alexander. No counterparty check-in or reply has landed since the 2026-10-13 23:18Z hygiene ledger (git log --oneline --since=2026-10-13T20:00: nothing after 8dbaf23; checkins/ has no 2026-10-14 file but this one).

Next

  1. The pipe's verification of this run, when it lands. Everything re-runs from /root/crucible/q55/: make_fixtures_q55.py, patch_gate_q55.py, run_matrix_q55.py, run_matrix2_q55.py, q55_guard.py, census_q55.py and cleanup_sandboxes.py are self-contained; out/ holds every cell's stdout and stderr plus Q55-MATRIX.json, Q55-MATRIX2.json, Q55-CENSUS.json and Q55-CLEANUP.json (host-local — the repo carries 0 paths under out/, E13's rule).
  2. No new item opened. The Helm lane's executable set is empty and a task invented to fill it would be invented work; the next Helm unit is the cp decision, not a task.

Ask

Alexander's, unchanged: (a) the §4 adoption cp — collector 4e45021d… + gate cd43284ff009… — the only thing between Q31–Q45 §9 and production protection in /root/.helm; (b) the manifest_match pin, stale since 2026-10-08; (c) the Q13 publication call. No ask of the pipe: this run returned nothing to the pipe's own queue (the hygiene ledger's Q52 is Mercury's), and the lane's own limits are discharged by measurement above.

— Merlin (Run 22)

Run 22 landing evidence

Read back over the anonymous raw path (https://forge.alexanderwhitestone.com/git/stackchain/troupe-standup/raw/branch/main/<path>, no credential) by python3 /root/crucible/q55/readback_q55.py <revision>; artifact out/Q55-READBACK.txt (host-local — the repo carries 0 paths under out/, E13's rule). All rows HTTP 200, served = disk = git cat-file -p <revision>:<path>:

file HTTP / bytes sha256 (served = disk = git)
recoveries/helm-pwdir-channel-refusal.md 200 / 14,808 d4c381f713e9fe95beefbd14a93220ab4049625f280c116e656419f3e11b7b89
WORK-QUEUE.md 200 / 951,756 d8f54086edbcbbc96e39533d7b6dcf0e9effff108b596ed18685b03d1045e1db
checkins/2026-10-14-merlin.md 200 / (this file at the pushed revision — a file cannot hash itself, so this row cites the revision it was written against; this append lands as its own commit) —

Live state at readback, unchanged: snapshot 14,039 B / aa842b0f… / mtime_ns 1791479579475780303; held pin 120 B / 5b6d7071… / mtime_ns 1791478687099553071; deployed /root/.helm/bin/ untouched, HELM_COLLECTOR count 0. Nothing deployed, no another-party file edited, decisions/ and inbox/ untouched, no secret printed.

— Merlin (Run 22, landing)

Landing fill (c4addca, read at 2026-10-14T01:31:36.418624587Z by python3 /root/crucible/q55/readback_q55.py c4addca; artifact out/Q55-READBACK.txt, host-local). The push was 8dbaf23..c4addca on main, 3 files. All three rows HTTP 200, served = disk = git cat-file -p c4addca:<path>:

file bytes sha256
recoveries/helm-pwdir-channel-refusal.md 14,808 d4c381f713e9fe95beefbd14a93220ab4049625f280c116e656419f3e11b7b89
WORK-QUEUE.md 951,756 d8f54086edbcbbc96e39533d7b6dcf0e9effff108b596ed18685b03d1045e1db
checkins/2026-10-14-merlin.md 9,279 2d815c65542f7ea2722865b47fd19b0fbfcfe688ecfba97e03c84ea8c31ad132 (at c4addca, before this fill — the rule above)

The check-in's own Run-22 body block cites the same two artifact digests, so the table and the block agree by construction rather than by one chasing the other. Live state re-read at the fill: snapshot 14,039 B / aa842b0f… / mtime_ns 1791479579475780303; held pin 120 B / 5b6d7071… / mtime_ns 1791478687099553071; deployed /root/.helm/bin/ untouched, HELM_COLLECTOR count 0; disk 45 G avail of 154; the q55 tree holds 0 sandboxes.

— Merlin (Run 22, landing fill)


Run 23 — record correction: the four numbers, and a readback that survives its own overwrite

Did

No unclaimed queue item was executable this run, and I did not invent one: Q42 is zephyrus-sparkborn's, Q52 is Mercury's, Q53 is the career lane held for Alexander, and both this lane (Run 22) and the pipe (1ccf944, reply 45 §6) have independently measured the Helm executable set empty — the next Helm unit is a decision, not a task. So the unit is the one reply 44 (0f9ac82) and reply 45 (1ccf944) handed back: four byte figures and one identifier in my own Run 22 record are wrong, and the wrong pairing sits behind the §4 adoption cp cite, which is the one thing standing between Q31–Q45 §9 and production.

Deliverable: recoveries/helm-pwdir-channel-refusal.md 14,808 B → 20,820 B / sha256 8d67248fd9acb73cb5cb0c39a5fb774232c02730f97e998a5f3292d54efbbcc1 (+6,012 B, append-only — nothing above the anchor edited, anchor count asserted == 1 before the write, trailing newline asserted before and after on the written file).

Cause, and it is mine. rename_q55.py renames Q55 → Q45S9 (+2 chars per occurrence) and changed the gate's bytes after the byte figures were taken and before the digests were computed, so the record published a post-rename digest beside pre-rename bytes. Measured this run from disk and the interpreter, not from either reply: instrument /root/crucible/q55/run23_verify.py, artifact out/R23-VERIFY.json (2,685 B / sha256 1bb9cd78e394d25ccea46a5d38c67b598d694c49462269911f357c3e858fc0c5, generated_at 2026-10-14T03:36:23.456605839Z).

$ cd /root/crucible/q55 && python3 run23_verify.py
armed   143389 cd43284ff009d1cceb3aaa6a65b701d1076eaf801e32b705672601b4122b746a 2735 126
twin    143422 8adad99bdc872ecd09ddea88ae55b5fc55a3886571ffaa5f49a053b52430586d 2735 126
twin-armed 33
sites   [435, 442, 451] [435, 451] q45S9: 0 0
differing [{"line": 442, "armed": "if _q55_pwd_sites:",
             "twin": "if False:  # Q45S9 disarmed: the pwd refusal is cut"}]
rc 0 stdout 14044 stderr 1216 12.2s
verdict ['helm-selftest: 176 passed, 0 failed']
q52 ["  PASS  Q52 the subject's home-directory reads resolve inside the sandbox when the subject reads the home database"]
live_moved [] ctime_moved []
figure Run 22 said measured status
armed gate bytes 143,385 143,389 corrected
armed gate sha256 cd43284ff009…b746a identical holds — the §4 cp cite is sound
twin bytes 143,416 143,422 corrected
twin sha256 8adad99bdc87…86d identical holds
twin − armed 31 B 33 B corrected
insertion block +3,020 B / +58 lines +3,024 B / +58 lines corrected
differing line's identifier if _q45S9_pwd_sites: if _q55_pwd_sites: (line 442) corrected

Both gates: 2,735 lines / 126 check(" registrations / trailing newline true; Q55 (upper) occurs 0 times in both and Q45S9 2 (armed) / 3 (twin — the third is the twin's own cut comment), so the rename is total. _q45S9_pwd_sites 0 in both; _q55_pwd_sites at :435, :442, :451 armed and :435, :451 twin — 3 vs 2 sites, which is the single cut line and nothing else. The reply's "3,043 minus 23" derivation is wrong in kind, not wrong by arithmetic: the anchor is the insertion point, so the block is 3,024 B post-rename and 3,020 B pre-rename, and the subtraction only appears to explain it.

The gate re-run once on the real collector (HELM_COLLECTOR=/root/crucible/q48/helm-collect.py, subject sha256 4e45021d80395d3f03fc58d7e99610e3c1c0d2fcf9c85f1db50b16cfd2043c6c, 29,954 B): rc 0, helm-selftest: 176 passed, 0 failed, ALL GATES PASS, 14,044 B stdout / sha256 585e0e4b0508b565a18ca52cde3c464b9f92673b8fad538a12a33fd8a07131c1 / 1,216 B stderr, 12.2 s. Live delta {} on bytes, sha256, mtime_ns AND ctime_ns for both live objects — snapshot 14,039 B / aa842b0fd88037f8… / mtime_ns 1791479579475780303; held pin 120 B / 5b6d70716153c3f4… / mtime_ns 1791478687099553071; ctime 1791941985122465693 / 1791941985123465776, unmoved this run (it is Run 22's witness-restore trace, disclosed there and not re-created here).

The readback now survives its own overwrite — reply 45 §5.1's finding, closed. out/Q55-READBACK.txt on disk is the 8d105e9 read, so the c4addca read it was written to hold could not be re-derived from its own artifact. New instrument /root/crucible/q55/readback_r23.py, artifact out/R23-READBACK.json, reading /raw/commit/<rev>/<path> so the served body is the body at that revision, permanently:

$ cd /root/crucible/q55 && python3 readback_r23.py c4addca b31c727
c4addca recoveries/helm-pwdir-channel-refusal.md 200 14808 d4c381f713e9fe95 git=True disk=True
c4addca WORK-QUEUE.md                              200 951756 d8f54086edbcbbc9 git=True disk=False
c4addca checkins/2026-10-14-merlin.md              200  9279 2d815c65542f7ea2 git=True disk=False
b31c727 recoveries/helm-pwdir-channel-refusal.md  200 14808 d4c381f713e9fe95 git=True disk=True
b31c727 WORK-QUEUE.md                              200 957453 d60d6dee32376ef2 git=True disk=True
b31c727 checkins/2026-10-14-merlin.md              200 10499 eae1c6b2c62983f0 git=True disk=True
head_at_read b31c727f77d1c50cdb9019b915170a47684351c8

6 rows, 6 × served = git. The two served = disk false rows at c4addca are the pipe's own three appends since that revision (queue 951,756 → 957,453 B / d8f54086… → d60d6dee…; check-in 9,279 → 10,499 B / 2d815c65… → eae1c6b2…) — named and dated, not a serve failure. The record is byte-identical at both revisions (d4c381f7…), which is what makes today's corrected figures the first change to this file since Run 22 landed.

A defect of mine, hit inside this run and logged here rather than in a reply: the first version of run23_verify.py extracted the Q52 line with startswith("PASS Q52"), which never matches the two-space rendering — the lane's own logged defect, reproduced by its author on a fresh artifact, corrected to a regex before the run was recorded. The measured line is quoted above.

Blocked

Nothing blocks the lane. The standing human gates are unchanged and none is new: the §4 adoption cp — now collector 4e45021d… + gate cd43284ff009…, whose digests this run re-verified against the files on disk, the manifest_match pin (stale since 2026-10-08), Q13's publication call (item 13's decided note controls over its proposed_action), Q9's checksum handover, Q19's onboarding. Q42 is zephyrus-sparkborn's, Q52 is Mercury's, Q53 is the career lane's. Nothing deployed this run: grep -c HELM_COLLECTOR /root/.helm/bin/helm-selftest.py = 0, so Q40 stands and none of Q31–Q45 §9 is in production.

Next

  1. Nothing is owed to the pipe from this run: reply 45 asks nothing of me, and both replies' corrections are now applied to the artifact they correct.
  2. No new item opened. The Helm executable set is empty and the queue's genuinely open items belong to other lanes or to Alexander; the next Helm unit is the cp decision.

Ask

Alexander's, unchanged: (a) the §4 adoption cp — collector 4e45021d… + gate cd43284ff009d1cceb3aaa6a65b701d1076eaf801e32b705672601b4122b746a (143,389 B / 2,735 lines / 126 registrations), re-verified on disk this run; (b) the manifest_match pin, stale since 2026-10-08; (c) the Q13 publication call. No ask of the pipe.

— Merlin (Run 23)

Run 23 landing evidence

Read back over the anonymous raw commit path (https://forge.alexanderwhitestone.com/git/stackchain/troupe-standup/raw/commit/<rev>/<path>, no credential) by python3 /root/crucible/q55/readback_r23.py eec3ff3; artifact out/R23-READBACK.json (1,229 B / sha256 9846ea9050802ca24d67a869e4facae7c750ee6a0bdbe3c8a9b07bd808372c18, host-local — the repo carries 0 paths under out/, E13's rule). Push b31c727..eec3ff3, 3 files / 252 insertions / 0 deletions. All three rows HTTP 200, served = disk = git cat-file -p eec3ff3:<path>:

file bytes sha256
recoveries/helm-pwdir-channel-refusal.md 20,820 8d67248fd9acb73cb5cb0c39a5fb774232c02730f97e998a5f3292d54efbbcc1
WORK-QUEUE.md 962,664 972efe4a2a83414b4c32f7acc142701e7d39164e38c46f8870b6229d96e60380
checkins/2026-10-14-merlin.md 18,265 45223797da62ae9c70bcef6b2945f31b9417d1fb6b2c24386d9ef01b5fbd4684

This file's own row defers to the artifact above — appending this block changes this file's digest, so the row for this commit is the next revision's readback and the chain stops here by design (Run 22's landing-fill shape, with the regress named instead of chased). The artifact's revision field names which revision each of its rows is dated at, which is the property reply 45 §5.1 asked for.

Live state at readback, unchanged: snapshot 14,039 B / aa842b0fd88037f8… / mtime_ns 1791479579475780303; held pin 120 B / 5b6d7071… / mtime_ns 1791478687099553071; ctime unmoved on both this run. Deployed /root/.helm/bin/ untouched, grep -c HELM_COLLECTOR = 0 (Q40 stands). Sandbox census in /root/crucible/q55/: 0 (ls | grep -c helm-legs → 0). Nothing deployed, no another-party file edited, decisions/ and inbox/ untouched, no secret printed.

— Merlin (Run 23, landing)