helm: Run 24 -- Q45S10, the discovery channel closed by a seeded sandbox with the artifact as the detector (recoveries/helm-discovery-channel-seed.md 13218 B / 83acffe0). The named residual every record since Q45 carries -- resolve every path the subject declares AT RUNTIME -- is discharged: Q48 closed env and argv, Q52 closed Path.home()/expanduser, Q45S9 closed pwd.getpwuid, and the filesystem SEARCH was the remainder, the one channel no redirect can reach because every redirect keys on how the destination is declared and this class declares nothing. Measured on the shipped gate before the change: collector-discover.py (31076 B / 1f3dae9e, the real collector 4e45021d with the held directory resolved at call time -- walk up from the module's own location, then scan the candidate roots, for the held pin) is admitted on the same terms as every other collector (Q39 OK: probe rc=2, sentinel written=False, live delta 0) and the suite is GREEN: 176 passed / 0 failed, ALL GATES PASS, live delta {} -- the Q45 resolved-destination probe prints HELD_DIR=None so check 2 passes vacuously, i.e. the gate is green on a subject whose held directory is the live one. The interpreter's own verdict: run bare, both fixtures read the LIVE held pin (held_body_sha256 = f27326e8b13d1dec9eb158fe40e5091f79dcaf73b47312c4e7d3958ba1d95d18) and a scratch HOME changes nothing. The escape's write path: shipped x discover --q52-witness -> rc 0 and the live held pin MOVES (5b6d7071 -> 4e98bb00), restored byte-exact by the guard, copy_pin_files_anywhere_in_sandbox [] -- nothing inside the gate sees it. The control: the EAGER form IS reported (FAIL Q45, HELM_HOME=/root/.helm, HELD_DIR=/root/.helm/data/held, 175/1) -- the call-time form is the blind one. The fix, two inserts: (1) the SEED -- the sandbox is given its own .helm/data/held/stackchain-home.html.sha256 carrying a DECOY digest (1e0c8aeefeadd3a1af732b94b2b2b342dfc0a38446714f812305416323ee1ce3), so the copy's walk-up finds the sandbox's own tree first; a decoy, never the live bytes; (2) the ARTIFACT CHECK -- one more subject leg writes a snapshot into the sandbox and the artifact must not carry the live held pin's digest, the only instrument that can see a call-time resolution because the probe is vacuous on it by construction. The pair: gate c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e (147151 B / 2798 lines / 127 check( registrations -- 126 + 1) on the Q45S9 gate cd43284ff009 (143389 / 2735 / 126): DIFF-vs-q55.txt = 2 hunks, +63 -0 lines, +3762 -0 B, and 143389 + 3762 = 147151 exactly; disarmed twin 820b7afdff6821a092a64d8a5c24d27f33baaa624534e9f1bfe351ef065a6e4a (147074 / 2796 / 127), the seed's write_text statement cut, 3 lines removed 1 added, 77 B smaller. The matrix, 8 cells under the digest-verified guard: shipped x discover 176/0 silent; shipped x witness the live pin moves (restored); armed x discover 177/0 with the artifact carrying the decoy and NOT the live digest; armed x witness live delta {} with the pin INSIDE the sandbox; disarmed x discover 176/1 -- FAIL Q45S10 with live_digest_in_artifact=True, detection without prevention; disarmed x witness the live pin moves again -- the seed is load-bearing; shipped x eager 175/1 reported; armed x eager 177/0. Green pair x5: rc 0, 177/0, 14254 B each (byte-stable), live delta {}; the shipped gate's control on the real collector reproduces its historical baseline to the byte (176/0 at 14044 B); no pre-existing check moved (176 -> 177 is the one new check). Regressions 11/11: n1-n4 and dep-unparseable -> Q39 rc 2; noparse -> Q46 rc 2; undecodable -> Q47 rc 2; broken_dep -> Q35 rc 2; n5 -> rc 2 (its own destination rule on the redirected sandbox dest); latin1 and bom green 177/0 at 14254 B. Live delta 0 on bytes/sha256/mtime across all 25 invocations (snapshot 14039 / aa842b0f / mtime_ns 1791479579475780303; pin 120 / 5b6d7071 / mtime_ns 1791478687099553071; ctime moved on both by the guard restores, disclosed); deployed /root/.helm/bin/ untouched with HELM_COLLECTOR count 0 so Q40 stands and none of Q31-Q45S10 is in production; sandboxes 0 in the q56 tree and 0 across /root/crucible, 406212 B reclaimed; disk 45 G of 154. Adoption: the section 4 cp is collector 4e45021d + gate c56230e5a075, superseding cd43284ff009 / 78b290ecf2d9 / e4967da9 / a951dbe8 -- Alexander's, unchanged. Six defects of mine logged first in the record, the first being that the initial PEP 562 __getattr__ design was wrong twice over (a global name lookup never consults module __getattr__, and the gate refuses a subject with no SNAPSHOT_PATH = assignment), so the fixture was rebuilt to move only the held channel to call time and the class statement moved with it. Landing evidence: queue 84/0 and check-in 116/0 insertions vs 8ba7c8e, zero deletions, measured by git diff --numstat; the append script's own printed byte deltas are superseded by those numstat figures because the working tree moved under the append (recorded in the check-in). Nothing deployed, no another-party file edited, decisions/ and inbox/ untouched, no secret printed. No new item opened -- the Helm executable set is empty and the next Helm unit is a decision, not a task.

This commit is contained in:
timmy committed 2026-10-14 06:03:20 +00:00
1 parent 8ba7c8ea87
commit 32ad55b3ed
3 files changed
+384

No files matched your search

+84
View File
@@ -8270,3 +8270,87 @@ point). **The §4 `cp` pair is sound and needs no re-cite** — collector `4e450
- **One premise of the brief does not hold: the green stdout *is* kept.** The brief reports the published gate-stdout digest `585e0e4b…` as unre-derivable because "its raw output was not kept under `out/`". It is there — `out/h-green-1.out` through `h-green-5.out`, each **14,044 B**, with `out-control.txt` and the r10/r11 refusals at the same size. The digest's five other occurrences are in the cite files (`r23-commit-msg.txt`, `out/R23-VERIFY.json`, the three append scripts), not in a missing artifact. **So the finding is not a missing file but a property: the green stdout varies per run** because it prints per-run tmp and sandbox names — which is what the pipe isolated, and why the right citation is the byte count plus verdict and rc, with the digest marked per-run.
- **Live, deployed and boundary unchanged.** Snapshot 14,039 B / `aa842b0f…` / mtime_ns `1791479579475780303`; pin 120 B / `5b6d7071…` / `1791478687099553071`; ctime_ns `1791907371554631194` on both; `HELM_COLLECTOR` 0 in every deployed file, so none of Q31–Q45 §9 is in production; zero sandboxes under `q55/`; disk 45 G of 154 G. Replies 45 and 46 exist and carry the read closure and the two corrections; nothing is owed the pipe or the lane.
- **Standing set unchanged, with one item the recent blocks keep dropping: the §4 `cp` of collector `4e45021d…` + gate `cd43284f…`, the `manifest_match` pin stale since 2026-10-08, Q13, Q9, Q19, and Q53 — the career lane, held for Alexander, item 7 expiring.**
---
**Q45S10 (Helm lane) — Run 24: the discovery channel closed by a seeded sandbox, with the artifact as
the detector (Merlin, 2026-10-14).** The named residual every record since Q45 has carried — *resolve every
path the subject declares at runtime* — is discharged: Q48 closed environment values and argv, Q52 closed
`Path.home()`/`expanduser`, Q45S9 closed `pwd.getpwuid`, and **the filesystem search was the remainder, the
one channel no redirect can reach, because every redirect keys on how the destination is declared and this
class declares nothing.** Deliverable: `recoveries/helm-discovery-channel-seed.md`. Scratch tree
`/root/crucible/q56/`; nothing deployed, no `cp` into `/root/.helm/bin/`, `decisions/` and `inbox/`
untouched, no another-party file edited, no secret printed. Internal label `Q45S10` follows `Q45S9`; the
queue's Q52 is Mercury's and Q53 the career lane's, so neither number is reused.
- **The class, measured on the shipped gate before the change.** `collector-discover.py` (the real collector
`4e45021d…`, 720 / 29,954, with the held directory resolved at call time by walking up from the module's
own location and then scanning the candidate roots for the held pin) is **admitted on the same terms as
every other collector** — `Q39 OK: the subject refused its sentinel destination (probe rc=2, sentinel
written=False, other probe files=0, no traceback, live delta 0)` — and the suite is **green**:
`helm-selftest: 176 passed, 0 failed`, `VERDICT: ALL GATES PASS`, live delta `{}`. The Q45
resolved-destination probe prints `HELD_DIR=None` (the module-level constant the copy declares), so check 2
passes **vacuously**: the gate is green on a subject whose held directory is the live one. The interpreter's
own verdict of the class: run bare, both fixtures read the LIVE held pin (`held_body_sha256` =
`f27326e8b13d1dec…`, the live pin's digest), and a scratch HOME changes nothing — the subject never reads
HOME, so Q52's redirect is satisfied by a mechanism the subject does not use. The control shows the probe
is not broken: the **eager** form (`HELD_DIR = _discover_helm_home() / "data" / "held"` at module level) is
**reported**, `FAIL Q45 … HELM_HOME=/root/.helm, HELD_DIR=/root/.helm/data/held` (175/1). The call-time
form is the blind one.
- **The escape's write path, measured:** `shipped × discover --q52-witness` → rc 0 and **the live held pin
moves** (`5b6d70716153c3f4…` → `4e98bb00650e…`), restored byte-exact by the guard, with
`copy_pin_files_anywhere_in_sandbox` `[]` — the pin is not in the sandbox because it is in the live tree.
Nothing inside the gate sees it.
- **The fix, two inserts.** (1) **The seed — prevention:** at the sandbox-creation site the sandbox is given
its own `.helm/data/held/stackchain-home.html.sha256` carrying a **decoy** digest
(`1e0c8aeefeadd3a1af732b94b2b2b342dfc0a38446714f812305416323ee1ce3`), so the copy's walk-up — the copy sits
at `<sandbox>/subject-legs.py` — finds the sandbox's own tree first and every discovery resolves inside
the sandbox. A decoy, never the live bytes. (2) **The artifact check — detection:** one more subject leg
writes a snapshot into the sandbox (through the same wrapper as every other leg) and the artifact must not
carry the live held pin's digest; this is the only instrument that can see a call-time resolution, because
the probe is vacuous on it by construction.
- **The pair.** Gate **`c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e`** (147,151 B /
**2,798** lines / **127** `check("` registrations — 126 + 1, the new one) on the Q45S9 gate
`cd43284ff009…` (143,389 / 2,735 / 126): `out/DIFF-vs-q55.txt` = **2 hunks, +63 −0 lines, +3,762 −0 B**,
and 143,389 + 3,762 = 147,151 exactly (asserted in `patch_gate_q56.py`). Disarmed twin
**`820b7afdff6821a092a64d8a5c24d27f33baaa624534e9f1bfe351ef065a6e4a`** (147,074 / 2,796 / 127): the seed's
`write_text` statement cut, 3 lines removed and 1 added, **77 B smaller** — the Q50/Q51 twin pattern.
- **The matrix, 8 cells under the digest-verified guard** (`out/Q56-MATRIX.json`,
`out/Q56-MATRIX2.json`): shipped × discover **176/0 silent**; shipped × witness **the live pin moves**
(restored); armed × discover **177/0**, the artifact carrying the **decoy** and not the live digest;
armed × witness `live delta {}` with the pin **inside the sandbox**; **disarmed × discover 176/1** —
`FAIL Q45S10 … live_pin_digest=f27326e8b13d1dec… live_digest_in_artifact=True`, detection without
prevention; **disarmed × witness the live pin moves again** — the seed is load-bearing; shipped × eager
175/1 (the probe reports the import-time form); armed × eager **177/0** — the seeded sandbox resolves even
the eager form inside. **Green pair ×5: rc 0, 177/0, 14,254 B each** (byte-stable), live delta `{}`; the
shipped gate's own control on the real collector reproduces its historical baseline to the byte
(**176/0 at 14,044 B**). The +210 B on the armed runs is the seed's paths in the Q43 sandbox-census print
plus the artifact leg and the new check's name; **no pre-existing check moved** (176 → 177 is the one new
check). **Regressions 11/11:** n1–n4 and dep-unparseable → Q39 rc 2; noparse → Q46 rc 2; undecodable → Q47
rc 2; broken_dep → Q35 rc 2; n5 → rc 2 (its own destination rule, on the redirected sandbox dest); latin1
and bom → green 177/0 at 14,254 B, live delta `{}` on all eleven.
- **Live, deployed, sandboxes, disk** (`out/Q56-CENSUS.json`, re-measured): delta 0 on bytes/sha256/mtime
across all 25 invocations — snapshot 14,039 B / `aa842b0fd88037f8…` / mtime_ns `1791479579475780303`; pin
120 B / `5b6d70716153c3f4…` / mtime_ns `1791478687099553071`; **ctime moved on both**
(`1791957230760646867` / `1791957230761646950`), the guard restores of the four deliberately-live cells —
disclosed. Deployed `/root/.helm/bin/` untouched (five digests re-read) and `grep -c HELM_COLLECTOR` =
**0**, so **Q40 stands and none of Q31–Q45S10 is in production**. Sandboxes **0 in the q56 tree and 0
across `/root/crucible`**; 406,212 B reclaimed. Disk 45 G free of 154 (72 %).
- **Adoption:** the §4 `cp` is collector `4e45021d…` + gate **`c56230e5a075…`**, superseding `cd43284ff009…`
(Q45S9), `78b290ecf2d9…` (Q52), `e4967da9…` (Q51), `a951dbe8…` (Q50). Alexander's, unchanged. Beside it:
the `manifest_match` pin stale since 2026-10-08, the Q13 publication call, Q9's checksum handover, Q19's
onboarding.
- **Limits, stated in the record as the item's first limits:** the seed answers a search that walks up from
the subject's own location or scans the candidate roots — a subject that globs the whole filesystem from
`/` finds the live tree too, and there the artifact check is the only instrument; the check is
artifact-shaped, so a discovery subject that reads the live pin and emits nothing catches nothing; the
marker is the collector's own held-pin filename; and a destination handed to the subject at runtime by a
*third party* (a config file, a sibling process) is the next channel and is not measured here. **Six
defects of mine are logged first in the record**, the first being that the initial PEP 562 `__getattr__`
design was wrong twice over — a global name lookup never consults module `__getattr__`, and the gate
refuses a subject with no `SNAPSHOT_PATH =` assignment — so the fixture was rebuilt to move only the held
channel to call time, and the class statement moved with it.
- **Q7, measured:** the Helm lane's executable set is empty again — the adoption, Q9, Q13/Q19 and Q42 are
human- or counterparty-gated, and Q52 is Mercury's and Q53 the career lane's. **No new item opened** — the
next Helm unit after this is a decision, not a task.
+116
View File
@@ -294,3 +294,119 @@ in `/root/crucible/q55/`: **0** (`ls | grep -c helm-legs` → 0). Nothing deploy
edited, `decisions/` and `inbox/` untouched, no secret printed.
— Merlin (Run 23, landing)
---
## Run 24 — Q45S10: the discovery channel
### Did
Claimed and finished **the lane's named residual — the filesystem-discovery channel** (Helm lane; the limit
every record since Q45 has carried: *resolve every path the subject declares at runtime*. Q48 closed env
and argv, Q52 closed `Path.home()`/`expanduser`, Q45S9 closed `pwd.getpwuid`; **the search was the
remainder and the one channel no redirect can reach**). Deliverable:
`recoveries/helm-discovery-channel-seed.md` (this host). Queue block appended at the foot of
`WORK-QUEUE.md`. Scratch tree `/root/crucible/q56/`; nothing deployed, no `cp` into `/root/.helm/bin/`,
`decisions/` and `inbox/` untouched, no another-party file edited, no secret printed. Internal label
`Q45S10` follows `Q45S9`; the queue's Q52 is Mercury's and Q53 the career lane's.
**The class, measured on the shipped gate before the change.** `collector-discover.py` (31,076 B /
`1f3dae9e7018a656…`, the real collector `4e45021d…` with the held directory resolved at call time: walk up
from the module's own location, then scan the candidate roots, for the held pin) is **admitted on the same
terms as every other collector** — `Q39 OK: the subject refused its sentinel destination (probe rc=2,
sentinel written=False, other probe files=0, no traceback, live delta 0)` — and the suite is **green**:
**176 passed / 0 failed, ALL GATES PASS, live delta `{}`**, 13,918 B stdout, 11.9 s. The Q45
resolved-destination probe prints `HELD_DIR=None` — the module-level constant the copy declares — so check 2
passes **vacuously**: the gate is green on a subject whose held directory is the live one. The interpreter's
own verdict: run bare, both fixtures read the LIVE held pin (`held_body_sha256` =
`f27326e8b13d1dec9eb158fe40e5091f79dcaf73b47312c4e7d3958ba1d95d18`, the live pin's digest), and a scratch
HOME changes nothing (`probe-scratch-home.json`) — the subject never reads HOME, so Q52's redirect is
satisfied by a mechanism the subject does not use. The control shows the probe is not broken: the **eager**
form is **reported** (`FAIL Q45 … values={"HELM_HOME": "/root/.helm", "HELD_DIR":
"/root/.helm/data/held", …}`, 175/1). The call-time form is the blind one.
**The escape's write path, measured:** `shipped × discover --q52-witness` → rc 0 and **the live held pin
moves** (`5b6d70716153c3f4…` → `4e98bb00650e…`), restored byte-exact by the guard, with
`copy_pin_files_anywhere_in_sandbox` `[]`. Nothing inside the gate sees it.
**The fix, two inserts** (`patch_gate_q56.py`, every anchor asserted `count == 1`, trailing newline asserted
on the written file). (1) **The seed — prevention:** at the sandbox-creation site the sandbox is given its
own `.helm/data/held/stackchain-home.html.sha256` carrying a **decoy** digest
(`sha256(b"Q45S10 sandbox decoy pin")` = `1e0c8aeefeadd3a1af732b94b2b2b342dfc0a38446714f812305416323ee1ce3`),
so the copy's walk-up finds the sandbox's own tree first. A decoy, never the live bytes. (2) **The artifact
check — detection:** one more subject leg writes a snapshot into the sandbox (through the same wrapper as
every other leg: argv rewrite, rebuilt environment, per-leg census, live watch) and the artifact must not
carry the live held pin's digest — the only instrument that can see a call-time resolution, because the
probe is vacuous on it by construction.
**The pair.** Gate **`c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e`** (147,151 B /
**2,798** lines / **127** `check("` registrations — 126 + 1) on the Q45S9 gate `cd43284ff009…` (143,389 /
2,735 / 126): `out/DIFF-vs-q55.txt` = **2 hunks, +63 −0 lines, +3,762 −0 B**, and 143,389 + 3,762 = 147,151
exactly. Disarmed twin **`820b7afdff6821a092a64d8a5c24d27f33baaa624534e9f1bfe351ef065a6e4a`** (147,074 /
2,796 / 127): the seed's `write_text` statement cut, 3 lines removed and 1 added, **77 B smaller**.
**The matrix, 8 cells under the digest-verified guard** (`out/Q56-MATRIX.json`, `out/Q56-MATRIX2.json`):
shipped × discover **176/0 silent**; shipped × witness **the live pin moves** (restored); armed × discover
**177/0** with the artifact carrying the **decoy** and not the live digest (*"the live held pin's digest is
NOT in the sandbox artifact, and the sandbox decoy's digest IS"*); armed × witness `live delta {}` with the
pin **inside the sandbox**; **disarmed × discover 176/1** — `FAIL Q45S10 … artifact=… exists=True leg_rc=0
live_pin_digest=f27326e8b13d1dec… live_digest_in_artifact=True`; **disarmed × witness the live pin moves
again** — the seed is load-bearing; shipped × eager 175/1 (reported); armed × eager **177/0** — the seeded
sandbox resolves even the eager form inside. **Green pair ×5: rc 0, 177/0, 14,254 B each** (byte-stable),
live delta `{}` each; the shipped gate's own control on the real collector reproduces its historical
baseline to the byte (**176/0 at 14,044 B**). The +210 B on the armed runs is the seed's paths in the Q43
sandbox-census print plus the artifact leg and the new check's name; **no pre-existing check moved**.
**Regressions 11/11:** n1–n4 and dep-unparseable → Q39 rc 2; noparse → Q46 rc 2; undecodable → Q47 rc 2;
broken_dep → Q35 rc 2; n5 → rc 2 (its own destination rule, on the redirected sandbox dest); latin1 and bom
→ green 177/0 at 14,254 B, live delta `{}` on all eleven.
**Live, deployed, sandboxes, disk** (`out/Q56-CENSUS.json`, re-measured): delta 0 on bytes/sha256/mtime
across all 25 invocations — snapshot **14,039 B / `aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d` /
mtime_ns `1791479579475780303`**; held pin **120 B / `5b6d70716153c3f4bd82045d5d71edf88f793a240ce1275c3dfca5759d0ee297` /
mtime_ns `1791478687099553071`**; **ctime moved on both** (`1791957230760646867` /
`1791957230761646950`) — the guard restores of the four deliberately-live cells, disclosed. Deployed
`/root/.helm/bin/` untouched (five digests re-read: `ee0b36a82f23…` / `5c67473d8928…` / `7ed1bca8f9da…` /
`12570786ba70…` / `738699986778…`) and `grep -c HELM_COLLECTOR` = **0** — **Q40 stands, so none of
Q31–Q45S10 is in production.** Sandboxes **0 in the q56 tree and 0 across `/root/crucible`**; 406,212 B
reclaimed. Disk **45 G free of 154 (72 %)**.
**Six defects of mine, logged first in the record**, the first being that the initial PEP 562 `__getattr__`
design was wrong twice over — a global name lookup inside a function never consults module `__getattr__`, and
the gate *refuses* a subject carrying no `SNAPSHOT_PATH =` assignment (Q39's failed-conditions list) — so the
fixture was rebuilt to move only the held channel to call time, and the class statement moved with it. The
others: the patch script read and wrote one path (double-insert, caught by the byte identity); the first twin
cut one line of a three-line statement (`IndentationError`); the first diff-vs-shipped compared the file with
itself; the first byte assertion added line counts where bytes were needed; and the green byte count moved
14,044 → 14,254 on the real collector — recorded, not smoothed over.
### Blocked
Nothing blocks the lane. The standing human gates are unchanged and none is new: the **§4 adoption `cp` —
now collector `4e45021d…` + gate `c56230e5a075…`** (superseding `cd43284ff009…` / `78b290ecf2d9…` /
`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-14 03:50Z hygiene ledger
(`git log --oneline --since=2026-10-14T00:00`: nothing after `8ba7c8e`).
### Next
1. **The pipe's verification of this run**, when it lands. Everything re-runs from `/root/crucible/q56/`:
`setup_q56.py`, `patch_gate_q56.py`, `run_matrix_q56.py`, `run_matrix2_q56.py`, `census_q56.py` and
`q56_guard.py` are self-contained; `out/` holds every cell's stdout and stderr plus `Q56-MATRIX.json`,
`Q56-MATRIX2.json`, `Q56-CENSUS.json` and `DIFF-vs-q55.txt` (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 again — the adoption, Q9, Q13/Q19 and Q42
are human- or counterparty-gated — so the next Helm unit is a decision, not a task.
### Ask
Alexander's, unchanged: **(a)** the §4 adoption `cp` — collector `4e45021d…` + gate
`c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e` (147,151 B / 2,798 lines / 127
registrations) — the only thing between Q31–Q45S10 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 (Q52 is Mercury's, Q53 Alexander's), and the lane's named residual
is discharged by measurement above.
— Merlin (Run 24)
+184
View File
@@ -0,0 +1,184 @@
# The discovery channel: a subject that finds its held root by searching the filesystem
**Helm lane — Q45S10 (Run 24), 2026-10-14.** Scratch tree `/root/crucible/q56/`; nothing deployed, no
`cp` into `/root/.helm/bin/`, `decisions/` and `inbox/` untouched, no another-party file edited, no secret
printed. Internal label `Q45S10` follows Run 22's `Q45S9`; the queue's Q52 is Mercury's and Q53 the career
lane's, so neither number is reused.
The named residual this discharges is the one every record since Q45 has carried: *resolve every path the
subject declares **at runtime***. Q48 closed environment values and argv; Q52 (Run 18) closed
`Path.home()`/`expanduser`; Q45S9 (Run 22) closed `pwd.getpwuid`. **The filesystem search was the remainder,
and it is the one channel no redirect can reach**, because every redirect keys on how the destination is
*declared* — a literal, a variable, an argument, a home read — and this class declares nothing.
---
## 1. The class
`collector-discover.py` is the real collector (`4e45021d80395d3f…`, 720 / 29,954, verified by sha256) with
one change: the held directory is resolved **at call time, by searching the filesystem** — walk up from the
module's own location, then scan the candidate roots, for the held pin:
```python
def _discover_helm_home():
here = Path(__file__).resolve().parent
for parent in (here, *here.parents):
cand = parent / ".helm"
if (cand / _MARKER).is_file():
return cand
for scan in (Path("/"), Path("/root")):
...
```
No absolute literal (Q45 relocates those), no environment read (Q48 rebuilds those), no argv (Q48 rule 4
rewrites those), no home-database read (Q52 redirects HOME, Q45S9 refuses `pwd`). The snapshot destination
keeps its literal, so the Q39 admission probe still has a module constant to rewrite and the subject is
admitted **on the same terms as every other collector** — which is the point.
**The interpreter's verdict, measured not asserted.** Run bare from `/root/crucible/q56/`, both fixtures
read the LIVE held pin (`probe-collector-discover.py.json`, `probe-collector-discover-eager.py.json`):
```
held_body_sha256: f27326e8b13d1dec9eb158fe40e5091f79dcaf73b47312c4e7d3958ba1d95d18
reads the LIVE held pin: True (live pin digest, 120 B, same value)
```
And under a **scratch HOME** the resolution does not move (`probe-scratch-home.json`): the subject never
reads HOME, so Q52's redirect is satisfied by a mechanism the subject does not use — the Q45S9 finding in a
new place.
| fixture | bytes | sha256 | lines |
|---|---|---|---|
| `collector-discover.py` (lazy) | 31,076 | `1f3dae9e7018a656722b8151226e4654931925f750f3154e49d2a103f987a0ba` | 753 |
| `collector-discover-eager.py` (control) | 31,094 | `8e58abeda872df2973ff1ce93b208f9c38f8efd4a9425c582f1f0b776efabdb3` | 753 |
## 2. The class on the shipped gate: silent
Shipped gate = `helm-selftest-q55.py` (`cd43284ff009d1cceb3aaa6a65b701d1076eaf801e32b705672601b4122b746a`,
143,389 B / 2,735 lines / 126 registrations, verified by sha256 from `/root/crucible/q55/`).
- **Cell A — `shipped × discover`, green shape:** rc 0, **`helm-selftest: 176 passed, 0 failed`**,
`VERDICT: ALL GATES PASS`, 13,918 B stdout, 11.9 s, **live delta `{}`**. The admission is normal
(`Q39 OK: the subject refused its sentinel destination (probe rc=2, sentinel written=False, other probe
files=0, no traceback, live delta 0)`), Q48/Q49 are vacuous on a subject that reads no variable, and the
Q45 resolved-destination probe prints `HELD_DIR=None` — the module-level constant the copy declares —
so check 2 passes **vacuously**. The suite is green on a subject whose held directory is the live one.
- **Cell A2 — `shipped × discover --q52-witness`:** rc 0 and **the live held pin moves**
(`5b6d70716153c3f4…` → `4e98bb00650e…`), restored byte-exact by the guard;
`copy_pin_files_anywhere_in_sandbox` = `[]` — the pin is not in the sandbox because it is in the live
tree. The gate's own witness writes live from an admitted subject and nothing inside the gate sees it.
- **Cell D — `shipped × discover-eager` (the control):** rc 1, **175/1**. The import-time form *is*
reported: `FAIL Q45 no module-level constant of the copy resolves inside the live data root` with
`values={"HELM_HOME": "/root/.helm", "SNAPSHOT_PATH": "<sandbox>/data/snapshot.json", "HELD_DIR":
"/root/.helm/data/held", …}`. So the probe catches the eager shape and is blind to the call-time one —
which is exactly why the artifact check below is the load-bearing half.
## 3. The fix: the sandbox answers the search, and the artifact is the detector
Two inserts, one function's worth of code, into the shipped gate (`patch_gate_q56.py`, every anchor asserted
`count == 1` before the write, trailing newline asserted on the written file):
1. **The seed — prevention.** At the sandbox-creation site, beside `_q43_held.mkdir`, the sandbox is given
its own `.helm/data/held/stackchain-home.html.sha256` carrying a **decoy** digest
(`sha256(b"Q45S10 sandbox decoy pin")` = `1e0c8aeefeadd3a1af732b94b2b2b342dfc0a38446714f812305416323ee1ce3`).
The copy the legs run sits at `<sandbox>/subject-legs.py`, so its walk-up finds the sandbox's own tree
first and every discovery resolves inside the sandbox. A decoy, never the live bytes: the live pin is not
copied into a sandbox.
2. **The artifact check — detection.** One more subject leg writes a snapshot into the sandbox
(`--out <sandbox>/q45s10-artifact.json --skip-tests`, through the same wrapper as every other leg: argv
rewrite, rebuilt environment, per-leg census, live watch) and the artifact must not carry the live held
pin's digest. This is the only instrument that can see a **call-time** resolution, because the probe is
vacuous on it by construction.
**The pair.** Gate **`c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e`** (147,151 B /
**2,798** lines / **127** `check("` registrations — 126 + 1, the new one). `out/DIFF-vs-q55.txt`:
**2 hunks, +63 −0 lines, +3,762 −0 B**, and 143,389 + 3,762 = 147,151 exactly (the byte identity is
asserted in `patch_gate_q56.py`, not printed and hoped). Disarmed twin
**`820b7afdff6821a092a64d8a5c24d27f33baaa624534e9f1bfe351ef065a6e4a`** (147,074 / 2,796 / 127): the seed's
`write_text` statement cut, 3 lines removed and 1 added, **77 B smaller** — the Q50/Q51 twin pattern, one
statement, and the directory is still created so the discriminator isolates the pin's presence and nothing
else.
## 4. The matrix, 8 cells, every cell under the digest-verified guard
`run_matrix_q56.py` → `out/Q56-MATRIX.json`; `run_matrix2_q56.py` → `out/Q56-MATRIX2.json`. The guard
(`q56_guard.py`, the q49/q55 discipline) holds a digest-verified backup of both live objects taken before
the first cell and restores byte-exact on a move.
| cell | gate × subject | rc | suite | live delta | the measurement |
|---|---|---|---|---|---|
| A | shipped × discover | 0 | **176/0** | `{}` | admitted, ALL GATES PASS — the class is silent |
| A2 | shipped × discover, witness | 0 | — | **MOVED** `5b6d7071…`→`4e98bb00…`, restored | the live pin is written from an admitted subject |
| B | armed × discover | 0 | **177/0** | `{}` | artifact NOTE: *the live held pin's digest is NOT in the sandbox artifact, and the sandbox decoy's digest IS* |
| B2 | armed × discover, witness | 0 | — | `{}` | `copy_pin_files_anywhere_in_sandbox` = `['.helm/data/held/stackchain-home.html.sha256']` — the pin lands inside the sandbox |
| C | disarmed × discover | 1 | **176/1** | `{}` | `FAIL Q45S10 … live_pin_digest=f27326e8b13d1dec… live_digest_in_artifact=True` — detection without prevention |
| C2 | disarmed × discover, witness | 0 | — | **MOVED** `5b6d7071…`→`0c4ec818…`, restored | the seed is load-bearing |
| D | shipped × discover-eager | 1 | **175/1** | `{}` | `FAIL Q45 … HELM_HOME=/root/.helm, HELD_DIR=/root/.helm/data/held` — the import-time form is reported |
| D2 | armed × discover-eager | 0 | **177/0** | `{}` | the seeded sandbox resolves even the eager form inside |
The green pair and the control (`out/Q56-MATRIX2.json`):
- **G1 — shipped × real collector:** rc 0, 176/0, **14,044 B** stdout — the shipped gate's own historical
baseline, reproduced to the byte.
- **G2–G6 — armed × real collector ×5:** rc 0, **177/0, 14,254 B each** (byte-stable across all five),
live delta `{}` each, 14.1–14.2 s. The real collector's own held read is `<sandbox>/data/held` — the
Q45-rewritten literal, which the seed does not touch — so its snapshot is unchanged in kind; the +210 B
stdout delta is the seed's paths in the Q43 sandbox-census print plus the artifact leg and the new check's
name. **No pre-existing check moved: 176 → 177 is the one new check and nothing else.**
- **Regressions 11/11:** n1–n4 and dep-unparseable → `Q39` rc 2; noparse → `Q46` rc 2; undecodable → `Q47`
rc 2; broken_dep → `Q35` rc 2; n5 → rc 2 (its own literal redirected into the sandbox, then its own
destination rule refuses the sandbox dest without `--deploy` — the subject's rule, not the gate's);
latin1 and bom → green **177/0 at 14,254 B**, live delta `{}` on all eleven.
## 5. Live state, deployed, sandboxes, disk
`out/Q56-CENSUS.json` (re-measured, not carried):
- **Live, delta 0 on bytes/sha256/mtime across all 25 invocations:** snapshot **14,039 B /
`aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d` / mtime_ns `1791479579475780303`**;
held pin **120 B / `5b6d70716153c3f4bd82045d5d71edf88f793a240ce1275c3dfca5759d0ee297` / mtime_ns
`1791478687099553071`**. **ctime moved on both** (`1791957230760646867` / `1791957230761646950`) — the
guard restores of the four deliberately-live cells; disclosed, not hidden.
- **Deployed `/root/.helm/bin/` untouched**, all five files re-read by digest (`ee0b36a82f23…` /
`5c67473d8928…` / `7ed1bca8f9da…` / `12570786ba70…` / `738699986778…`), and
`grep -c HELM_COLLECTOR /root/.helm/bin/helm-selftest.py` = **0** — **Q40 stands, so none of Q31–Q45S9 or
Q45S10 is in production.**
- **Sandboxes: 0 in the q56 tree and 0 across `/root/crucible`** (both censuses, `E14`'s standing line);
the q56 `__pycache__` (the C32 class) removed in the same pass, **406,212 B reclaimed**, after-count 0.
- Disk: **45 G free of 154 (72 %)**.
## 6. Adoption
The §4 `cp` is collector **`4e45021d80395d3f…`** + gate
**`c56230e5a075c5a12fd2f0d336dcac71c1078cb692a9e6c995780098a051f13e`** (147,151 B / 2,798 lines / 127
registrations), superseding `cd43284ff009…` (Q45S9), `78b290ecf2d9…` (Q52/home), `e4967da9…` (Q51) and
`a951dbe8…` (Q50). Alexander's, unchanged. Beside it: the `manifest_match` pin stale since 2026-10-08, the
Q13 publication call, Q9's checksum handover, Q19's onboarding.
## 7. Limits, and the defects of mine logged first
**Limits.** (a) The seed answers a search *that walks up from the subject's own location or scans the
candidate roots* — a subject that globs the entire filesystem from `/` finds the live tree too; the artifact
check catches that in the artifact, but the seed does not prevent it. (b) The check is artifact-shaped: a
discovery subject that reads the live pin and emits nothing catches nothing. (c) The inventory of what
counts as "the held pin" is the collector's own filename, carried by the gate — a subject that searches for
a *different* marker is outside the class as measured. (d) The discovery is static in one respect: the
fixture searches; a subject that receives its destination from a *third party* at runtime (a config file,
a sibling process) is the next channel, and it is not measured here.
**Defects of mine, in the order they happened.** (1) The first lazy fixture used PEP 562 `__getattr__` with
no module-level assignment; it died `NameError: name 'SNAPSHOT_PATH' is not defined`, because a global name
lookup inside a function never consults module `__getattr__` — and the gate *refuses* a subject carrying no
`SNAPSHOT_PATH =` assignment (Q39's failed-conditions list), so the design was wrong twice over. The
fixture was rebuilt to keep the snapshot literal and move only the held channel to call time; the class
statement moved with it, and §1 says so. (2) `patch_gate_q56.py`'s first run read and wrote the same path,
double-inserting (147,151 → 150,913 B on the second read); caught by the byte identity, fixed by
re-copying the pristine gate and asserting `count == 1`. (3) The first twin cut one *line* of a three-line
statement and left an `IndentationError`; the cut is now the whole statement. (4) The first
diff-vs-shipped compared the file with itself (0 hunks) because base and target were one path; a pristine
copy is now carried in the tree. (5) The first byte assertion added *line counts* where bytes were needed
(143,389 + 63 ≠ 147,151); the identity closes on bytes, +3,762. (6) The green byte count moved
14,044 → 14,254 on the real collector — caused by the seed's paths in the Q43 census print and the extra
artifact leg; recorded in §4, not smoothed over.
— Merlin (Run 24)