diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 2773fdf..f813a9a 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -6945,3 +6945,25 @@ it: Alexander's `cp` of collector `4e45021d…` + gate **`a590170f…`**, the `m - **Standing, unchanged and unclaimed.** Q49 open (name the argv that moved the live pin, or record the negative); nothing of Merlin's moved, so no reply is owed. Alexander's `cp` of collector `4e45021d...` + gate `a590170f...`; the `manifest_match` pin stale since 2026-10-08; the Q13 publication call. `magazine-091` remains decided-with-caveat — its decided note (add our note, escalate to author and publisher) controls over its `proposed_action` (publish the corrected wording to the live page); - **The decision that is his, named plainly.** PR #75 is mergeable with green CI and receipt-backed pins, but with 0 reviews and no working reviewer profile the only reviewer left is a human read of the diff, so merging it would be an unreviewed merge. #15's criterion 4 (cold/warm latency and VRAM on the target GPU) is instrumented but unmeasured, and its blocker is a **spend** (~$0.59/hr A40 secure cloud; recipe in the runpod-gpu-rendering skill) — not mine to authorize. Nothing deployed; `main` unchanged. - **Convention (b), applied rather than restated.** This append is the exception for a defective third-party block whose defects a later reader would cite, the same exception `c3f230c` named. It is the last one: from the next own-commit-only wake this lane writes nothing at all. + + +--- + +**Q49 CLOSED 2026-10-13 (Merlin, Helm lane) — `recoveries/helm-resolved-root-live-path.md` +(15,220 B, scratch tree `/root/crucible/q49/`, nothing deployed). (a) The invocation that +moved the live held pin during Q48 is NAMED and REPRODUCED, not withdrawn: the G8 +`--dry-run` original-subject leg, `HELM_COLLECTOR=`, +`Q48_ROOT` **unset** — argv recorded verbatim by the per-leg census. Q48's §6.2 attribution is +upheld as a measurement, and the pipe's negative (live root named → redirect fires → delta 0) +reproduces exactly. (b) The class is closed by the **DEFAULT redirect** (the item's stated +closure, "legs inheriting the rebuilt environment", already existed at `helm-selftest.py:1117` +and is a no-op when the variable is unset — measured, not argued), with a per-leg census of +both live objects as detection: green 5/5 at **174 passed / 0 failed**, checks **120 → 123**, +no pre-existing check moved, live delta 0. Two findings the item did not predict: the G8 +`--deploy` leg calls `hcg.main()` **in-process** and was wholly unguarded (it wrote the live +snapshot, 14,039 B → 137 B — reproduced, restored), and in the fully disarmed configuration +the live pin still moves with **no spawn the traced instrument can attribute** — that residual +is the Helm lane's next unit. Adoption pair is now collector `4e45021d…` + gate +`085ddf4f…`; the `cp` stays Alexander's. Six live writes under guard, every one restored from +a digest-verified backup; both live objects byte-identical at session end +(`aa842b0f…` / 14,039 B and `5b6d7071…` / 120 B).** diff --git a/checkins/2026-10-13-merlin.md b/checkins/2026-10-13-merlin.md index 0fcabac..edbc9c8 100644 --- a/checkins/2026-10-13-merlin.md +++ b/checkins/2026-10-13-merlin.md @@ -436,3 +436,66 @@ and `git cat-file -p 20623b6:`: Three-way identical on all three. `HEAD = 20623b66fd6d66da8bb38d95ba3a136f606a02dc`. The check-in's own row carries no self-hash, per the lane's no-self-hash convention; the blob above is the pre-append revision and this append is the post-append one. + + +## Run 15 — Q49: the runtime-resolved root's live write path + +### Screen + +Merlin, Helm lane, 2026-10-13, this host. Item **Q49** — the top open item in the queue and +the only Helm unit not human- or counterparty-gated (checked against `WIZARDS-TABLE.md` first: +no named lane for it). Scratch tree `/root/crucible/q49/`. Every figure measured this +run; the two things I could not measure are labelled. + +### Did + +- **(a) Named the invocation and reproduced it.** `env-root-v1.py` (5,634 B / + `76b55b8a…`) = `q48/env-root.py` with its two default literals put back to `/root/.helm` + (asserted count 2). Seven rows under a digest-verified guard (`q49_guard.py`, refuses to + restore unless the backup digest matches): the fixture run `--dry-run` / bare / + `--deploy --out ` with `Q48_ROOT` unset **each moved the live held pin**, and + `HELM_COLLECTOR= Q48_ROOT unset python3 q48/helm-selftest.py` moved it too + (rc 1). All three `Q48_ROOT=` controls: no move. Written content measured by a + 5 ms polling watcher: 14 B / `784b9bde…` / `'q48-env-pin\n'`. Artifact + `out/Q49-ATTRIBUTION.json` (6,495 B / `89a82729…`). +- **(b) Closed the class, green 5/5.** `helm-selftest-q49.py` (128,948 B / 2,445 lines / + `085ddf4f…`): the DEFAULT redirect (inventory every `os.environ.get("X","")` by + `ast`, redirect a default literal resolving inside the live data root), a per-leg census of + **both** live objects, and a guard on the in-process `--deploy` leg. Checks **120 → 123** + (`+3 check("Q49"`, nothing else). Five green runs: rc 0, `174 passed, 0 failed`, 13,863 B + stdout, digests `13cf5cf7` / `d4666b9f` / `0abd28cd` / `5ed81c37` / `bbbd1901`, live delta 0. + Artifact `out/Q49-GREEN.json`. +- **The 2×2 discriminator, predictions written first.** Armed/unset → delta 0; + default-redirect off → the pin moves **and the census names the leg**; in-process rebind + off and both off → the pin moves. Prevention and detection measured separately. + Artifact `out/Q49-WITNESS.json` (13,785 B / `877138d0…`). +- **Two findings beyond the item.** (i) G8's `--deploy` branch runs `hcg.main()` in-process + with only `SNAPSHOT_PATH` patched, so an import-time-resolved root wrote the **live + snapshot** (14,039 → 137 B, reproduced and restored). (ii) See Blocked. + +### Blocked + +- **One unattributed live write, and it is a residual, not a closed item.** In the fully + disarmed configuration the live pin moves (three runs), the traced twin records exactly one + fixture `main()` per run and its banner names the **sandbox**, no spawn names the live path, + both Q49 censuses report no move — and the watcher still sees 120 B → 14 B at t+280 ms. The + write is real and its content is the env fixture's own pin string; the mechanism is + **unattributed**. I will not guess. It is the Helm lane's next unit. +- **Nothing deployed, by design.** `/root/.helm/bin/helm-selftest.py` is still `7ed1bca8…` + and reads `HELM_COLLECTOR` 0 times, so none of Q31–Q49 is in production. The `cp` of + collector `4e45021d…` + gate `085ddf4f…` is Alexander's under §4. + +### Next + +- The §5 residual: find the writer the trace cannot see, or narrow the census window. +- Unchanged and still his: the `cp`, the `manifest_match` pin stale since 2026-10-08, the Q13 + publication call. + +### Ask + +- Alexander: authorise the `cp` of collector `4e45021d…` + gate `085ddf4f…` into + `/root/.helm/bin/`, or say to keep iterating. Nothing else in this run needs a decision. + +### Run 15 landing evidence + +*filled by `q49/append_landing_q49.py` after the push.* diff --git a/recoveries/helm-resolved-root-live-path.md b/recoveries/helm-resolved-root-live-path.md new file mode 100644 index 0000000..2405445 --- /dev/null +++ b/recoveries/helm-resolved-root-live-path.md @@ -0,0 +1,250 @@ +# Q49 — The runtime-resolved root's live write path: named, reproduced, and closed (with one residual) + +**Run 15, Merlin, Helm lane. 2026-10-13, this host. Scratch tree `/root/crucible/q49/`.** +Every figure below was measured on this host in this run. A claim I could not measure is +marked **Testimony only** or **unattributed** — nothing here is asserted from the record. + +**Verdict: Q49 (a) is discharged by measurement — the invocation that moved the live held pin +during Q48 is named with its argv and reproduced under a guard, twice, with the negative +control. Q49 (b) is closed for the class the item describes (the `--dry-run` original-subject +leg) by the DEFAULT redirect, green 5/5 at 174 passed / 0 failed with no pre-existing check +moved. Two things this run found that the item did not predict: the G8 `--deploy` leg runs +`hcg.main()` IN-PROCESS and was entirely unguarded (it wrote the live snapshot, 14,039 B → +137 B, reproduced and restored), and in the fully disarmed configuration the live pin still +moves with **no spawn the traced instrument can attribute** — that residual is named, not +closed.** + +--- + +## 0. My own defects, logged first + +1. **The rebind NOTE counts the census, not the rebind.** The Q49 NOTE line reports + `2 path constant(s) rebound` in the `C-inproc-off` and `D-disarmed` rows, where the + rebind is disarmed. The counter is filled before the `setattr` is replaced by `pass`, so + the note overstates what happened. No check depends on the count; the note is wrong and + is recorded here rather than silently fixed in a re-run. (Affects rows C and D of §4.) +2. **A restore is not silent on ctime.** `q49_guard.restore()` re-stamps mtime with + `os.utime`, and `utime` moves **ctime**. So after any restore, ctime is the restore's own + stamp and cannot evidence the write. Every restore record below therefore carries + `mtime_restamped_to` (recoverable) and `ctime_now_ns` (the restore's, not the writer's). +3. **The first witness JSON was overwritten.** `out/Q49-WITNESS.json` first held a 4-row run + whose `q49-armed-liveroot` row carried the M2 measurement quoted in §4; the 2×2 re-run + replaced it. The M2 evidence survives in that row's captured stdout + (`out/q49-armed-liveroot.out`), in the restore records printed at the time, and in §4 + below — not in the current JSON. +4. **The item's stated closure could not work as written.** Q49 (b) offers *"the + original-subject legs inheriting the rebuilt environment (one line in `_q39_run`)"*. That + line already exists in the Q48 gate — `helm-selftest.py:1117`, `_kw["env"] = _q48_env` — + and it is a no-op for the incident's shape, because with the variable **unset** there is + nothing to inherit. Measured, not argued: the shipped Q48 gate's own NOTE reads + `0 redirected from the live data root into the sandbox: none` while the pin moves + (§1, row R2). What closes the class is redirecting the subject's **default literal**, which + is what §2 implements. + +--- + +## 1. (a) The attribution: the invocation, named and reproduced + +The v1 fixture is rebuilt from `q48/env-root.py` by **one mechanical change back**: the two +default literals `/root/crucible/q48/protected` → `/root/.helm` (asserted count 2). +`env-root-v1.py` = **5,634 B / sha256 `76b55b8ab0203c4f…`**. v7's own assertion says the v1 +incident was *"carries the live default"*; the v1 driver's first armed row is recorded in +`q48/out/old/q48-armed-env.err` firing the redirect **from `/root/.helm`** with `Q48_ROOT` +unset, which is only possible when the subject's own resolution starts there. + +Guard: `q49_guard.py` takes a digest-verified backup of both live objects before any run, +compares `(bytes, sha256, mtime_ns, ctime_ns)`, and **refuses to restore unless the backup's +digest matches the recorded value**. + +Live state at session start (unchanged at session end): +`/root/.helm/data/snapshot.json` **14,039 B / `aa842b0fd88037f8…`**; +`/root/.helm/data/held/stackchain-home.html.sha256` **120 B / `5b6d70716153c3f4…`**. +Runner: `reproduce_q49.py` → `out/Q49-ATTRIBUTION.json` (6,495 B / `89a827295a3d148d…`). + +| # | Invocation (exact) | rc | Live held pin | Restored | +|---|---|---|---|---| +| R1a | `python3 env-root-v1.py --dry-run --skip-tests`, `Q48_ROOT` unset | 0 | **MOVED** 120 → 14 B | yes | +| R1b | `python3 env-root-v1.py --skip-tests`, `Q48_ROOT` unset | 2 | **MOVED** | yes | +| R1c | `python3 env-root-v1.py --deploy --skip-tests --out `, `Q48_ROOT` unset | 0 | **MOVED** | yes | +| R2 | `HELM_COLLECTOR=env-root-v1.py python3 /root/crucible/q48/helm-selftest.py`, `Q48_ROOT` unset | 1 | **MOVED** | yes | +| N1a | `python3 env-root-v1.py --dry-run --skip-tests`, `Q48_ROOT=` | 0 | no | — | +| N1b | `python3 env-root-v1.py --skip-tests`, `Q48_ROOT=` | 2 | no | — | +| N1c | `HELM_COLLECTOR=env-root-v1.py Q48_ROOT= python3 helm-selftest.py` | 1 | no | — | + +**R1a is the fixture-verification shape** (`make_fixtures_q48.py` v1's `verify_interpreter()`, +~05:5xZ): the held pin is written **before** the `--dry-run` early return, so a "writes +nothing" flag writes it anyway. Its own stdout says so — `"root": "/root/.helm"`, +`"held_dir": "/root/.helm/data/held"` — with the banner +`q48-env: held write -> /root/.helm/data/held`. + +**R2 is the driver's first armed row, and it is the one that settles the item's question.** +`Q48_ROOT` unset, the shipped Q48 gate prints +`Q48 NOTE: … 1 variable(s) the subject reads (Q48_ROOT), **0 redirected** … : none`, and the +pin moves. **Which leg:** the Q49 per-leg census in §4 row B names it verbatim — +`python3 …/env-root-v1.py --dry-run --skip-tests`, the G8 leg whose own source comment reads +*"--dry-run at the live destination is NOT gated: it writes nothing"* +(`helm-selftest.py:2274–2278`). That premise is the deployed collector's contract, asserted +for every subject the gate admits. + +**The written bytes:** 14 B, sha256 `784b9bded20e9e22…`, content `'q48-env-pin\n'` — +recorded by a 5 ms polling watcher (`watch_pin_q49.py`) that copies the pin on every +transition, so the content is measured rather than inferred. + +**So Q48's §6.2 attribution is upheld as a measurement, not withdrawn.** The item allowed +either outcome; this is the first: the gate's own `--dry-run` original-subject leg moved the +live held pin, with the argv above, and the pipe's negative (live root *named* → redirect +fires → delta 0) is reproduced exactly by N1c. + +--- + +## 2. (b) The closure: three changes, three checks + +`patch_gate_q49.py` → `helm-selftest-q49.py`, **128,948 B / 2,445 lines / sha256 +`085ddf4f42ae80ea…`** against Q48's `helm-selftest.py` **122,186 B / 2,287 lines** +(`a590170f…`). The shipped Q48 gate is untouched; nothing was copied into `/root/.helm/bin/`. + +1. **The DEFAULT redirect (prevention).** `_q48_env_default_sites()` inventories every + `os.environ.get("X", "")` pair by `ast`. A name whose **ambient** value is absent + and whose **default literal** resolves inside the live data root is redirected to the + per-invocation sandbox. Measured on the v1 fixture: + `Q49 NOTE: … 1 default literal(s) resolve inside the live data root and were redirected … + Q48_ROOT default /root/.helm -> /root/crucible/q49/helm-legs-0idqju7v`. +2. **The per-leg census of both live objects (detection).** `_q39_live_objs()` reads + `(bytes, sha256, mtime_ns, ctime_ns)` of the snapshot **and** the pin on both sides of + every spawn and appends the leg that moved them. +3. **The in-process `--deploy` leg (prevention).** §4. + +**Check census:** `check("` registrations go **120 → 123**; the per-prefix diff is exactly +`+3 check("Q49"` and nothing else — no pre-existing check moved, added or reworded. + +**Green pair, five consecutive invocations** (`run_green_q49.py`, subject = the Q33–Q48 +collector `4e45021d…`, `Q48_ROOT` unset): + +| run | rc | verdict | stdout | sha256 (16) | s | +|---|---|---|---|---|---| +| 1 | 0 | `helm-selftest: 174 passed, 0 failed` | 13,863 B | `13cf5cf75cd58b62` | 12.13 | +| 2 | 0 | same | 13,863 B | `d4666b9fd3d12676` | 12.64 | +| 3 | 0 | same | 13,863 B | `0abd28cd50fcc406` | 12.70 | +| 4 | 0 | same | 13,863 B | `5ed81c37caf679c4` | 12.57 | +| 5 | 0 | same | 13,863 B | `bbbd190164e3cbe6` | 12.39 | + +174 = 171 + 3, matching the check census exactly. **`live_delta` 0 on both objects** across +the set. Artifact: `out/Q49-GREEN.json` (5,169 B / `bbbc1c84ea0a3f0a…`). The control that +makes this meaningful: the real collector reads **no** environment variable, so both Q49 +mechanisms are inert for it (0 env names, 0 default redirects, 0 per-leg moves) — the green +pair proves the additions did not move a result, not merely that the suite passes. + +--- + +## 3. The 2×2 discriminator: prevention separated from detection + +Same instrument that opened the class (the gate driven with `HELM_COLLECTOR` at a +runtime-resolving subject), four rows. **Predictions were written before the run** +(`run_witness_q49.py`, `PREDICT`). Artifact: `out/Q49-WITNESS.json` +(13,785 B / `877138d09bbdac3e…`). + +| row | gate | `Q48_ROOT` | predicted | measured | +|---|---|---|---|---| +| A | `helm-selftest-q49.py` | unset | delta 0 | **delta 0** (no restore) | +| B | `-nodefault` | unset | pin moves (M1) | **pin moved**, 120 → 14 B, restored | +| C | `-inproc-off` | `/root/.helm` | both move (M2) | **pin moved**, restored | +| D | `-disarmed` | `/root/.helm` | both move | **pin moved**, restored | + +Every row is rc 1 with a named failing set, and **the expected red is stated in advance**: +the Q43 check *"the subject's own default destination resolves to the live snapshot the gate +protects"* cannot pass for a subject whose root is redirected into the sandbox — it is a +live-identity check, not a redirect check. The witness is the live objects' location, not +the check count. + +**A vs B is the closure of the class the item describes, by measurement.** Identical +configuration, one mechanism switched: armed → `live_delta` 0 on both objects; disarmed → the +pin moves and the per-leg census **names the leg**: +`"leg": "…python3 …/env-root-v1.py --dry-run --skip-tests"`. Prevention and detection are +therefore separate: the census does not prevent, the redirect does not report, and each is +measured with the other switched off. + +Live state after the whole witness run: snapshot **14,039 B / `aa842b0fd880…`**, pin +**120 B / `5b6d70716153…`** — byte-identical to session start. + +--- + +## 4. A defect the item did not name: the in-process `--deploy` leg + +G8's `--deploy` branch (`helm-selftest.py:2280–2294`) sets +`sys.argv = ["helm-collect.py", "--deploy", "--skip-tests"]` and calls **`hcg.main()` inside +the gate's own process**, having patched only `hcg.SNAPSHOT_PATH`. + +Measured 2026-10-13 with `HELM_COLLECTOR=` and +`Q48_ROOT=/root/.helm`, against the **shipped Q48 gate**: the live snapshot went +**14,039 B → 137 B** (sha256 `aec681402a3d03cb…`, the fixture's own payload) and the live held +pin **120 B → 14 B**, both restored byte-exact by the digest-verified guard. The Q44 check +caught the pin (`out/q49-armed-liveroot.out`: *"the held directory changed: before … 120 / +`5b6d7071…`"*); Q39's watch reported *"14 legs watched … delta 0 on each"* because **no +subprocess was spawned**; and the per-leg census is silent for the same reason. + +**A subject that resolves its root at import time ignores the `SNAPSHOT_PATH` patch**, so the +leg wrote both live objects from inside the gate. The Q49 closure runs that leg with the +rebuilt environment **and** rebinds every path-valued module constant of the imported subject +that resolves inside the live data root into the sandbox, and censuses both live objects +around the call. Measured on row A: `1 env name(s) rebuilt and 2 path constant(s) rebound … +live objects it moved: none`, and the new foot check passes. (The count in that note is the +census of candidates — see §0.1.) + +--- + +## 5. The residual, named and not closed + +In the **fully disarmed** configuration (row D: default redirect off, in-process rebind off, +`Q48_ROOT=/root/.helm`) the live pin moves — reproduced **three times** — and the instrument +cannot attribute it: + +- The traced twin (`env-root-v1-trace.py`, prints argv/pid/ppid/parent cmdline before its + held write) records **exactly one** fixture `main()` per run, and its banner reads + `q48-env: held write -> /root/crucible/q49/helm-legs-chn0zt3b/data/held` — the **sandbox**. +- `grep -a -o "held write -> [^\\\"]*"` over the run's full stdout **and** stderr returns + **one** occurrence, that sandbox one. No spawn names the live path. +- The Q49 per-leg census and the in-process census both report **no move**. +- A 5 ms polling watcher still records the transition: **120 B / `5b6d7071…` → 14 B / + `784b9bde…`, content `'q48-env-pin\n'`, at t+280 ms**, and the guard restores byte-exact. + +So the write is real, its content is the env fixture's own pin string, and **its mechanism is +unattributed**. I will not guess at it. It is handed on as the next Helm unit: either a +writer outside the subject's `main()` (a module-scope path in the fixture family, or a gate +leg that writes the imported module's `HELD_DIR` directly), or a hole in the census window +itself. Everything else in this run is measured. + +--- + +## 6. Limits, and what is owed to Alexander + +- **Nothing deployed.** `/root/.helm/bin/helm-selftest.py` is still `7ed1bca8…` and still + reads `HELM_COLLECTOR` **0** times, so none of Q31–Q49 is in production. The adoption pair + is now collector `4e45021d…` + gate `085ddf4f…` (Q48's `a590170f…` plus §2), and the `cp` + remains **Alexander's** — §4 puts deploy outside a wizard's initiative and no approval + artifact exists in this repo or in `decisions/`. +- **Live objects, whole session:** snapshot `aa842b0f…` / 14,039 B and pin `5b6d7071…` / + 120 B, byte-identical at start and end. Six live writes occurred under guard + (R1a/R1b/R1c/R2, rows B/C/D), every one restored from a digest-verified backup. ctime moved + on each restore and is not recoverable (§0.2). +- **Suite ≠ discriminator for this class.** No subject leg runs the copy with + `--deploy --pin`, which is why the witness path exists; the discriminator is the mechanism + itself, as in Q48. +- **The guard is static**, as every guard in this family is: it covers env names and default + literals the subject's own source contains, and a shape it cannot see is §5. +- **Q7, measured:** the Helm lane's executable set is not empty — §5 is the successor. Q13's + publication call and the `manifest_match` pin (stale since 2026-10-08) are unchanged and + still Alexander's. + +--- + +## 7. Landing evidence (computed after the commit, not before) + +| artifact | bytes | sha256 (16) | +|---|---|---| +| this file | — | see §7 note | +| `checkins/2026-10-13-merlin.md` Run 15 | — | see §7 note | +| `WORK-QUEUE.md` Q49 Status | — | see §7 note | + +*Note on the regress: a file cannot cite its own final digest, and a readback taken before +`git push` returns 404 for a new file. The digests above are filled by +`q49/append_landing_q49.py` after the push, from the anonymous raw read.*