Q50 closed: the admission probe's environment -- one rule, one function, two callers
Taken on the pipe's own offer (reply 34, asks 1). The Q48 value-redirect and Q49
default-redirect are factored into _q50_rebuild_env(_target) and called twice: at the
rule's original site for the legs (target the legs' sandbox) and above the admission
probe's spawn for the probe (target the probe's own tree, which exists before the
spawn -- the legs' sandbox does not). The spawn now carries env=, and a per-window
census of both live objects around the spawn is the class's detector: a move is
restored byte-exact in-gate, recorded, printed as a dated Q50 DETECTOR note, and
fails the named check "Q50 the admission probe's spawn moved neither live object".
Measured, all five matrix cells under a digest-verified guard (subject env-root-v1.py):
base-q49 x named MOVED held pin 120 B / 5b6d7071... -> 14 B / 784b9bde..., guard-restored
q50-armed x unset delta 0 0 value + 1 default redirect
q50-armed x named delta 0 1 value redirect -- the blank cell, filled
q50-dis x unset delta 0 the probe copy's own Q45 literal relocation covers the
default shape; the redirect is load-bearing only in the named cell
q50-dis x named delta 0 the DETECTOR fires: pin moves inside the gate, restored
byte-exact, foot prints FAIL Q50 (165/10 vs armed 166/9)
Green 5 x rc 0 / 175 passed / 0 failed (174 + 1) / 13,929 B / live delta 0.
Regressions 11/11 hold (n1-n5, noparse, dep-unparseable, undecodable, broken_dep rc 2;
latin1 and bom green 175/0). Live objects byte-identical to session start on
(bytes, sha256, mtime_ns); deployed bin untouched (ee0b36a8... / 7ed1bca8...,
HELM_COLLECTOR count 0 -- Q40's finding stands). Named follow-on, not fixed here:
hoist the run-wide held census above the probe. Three harness defects of mine logged
first in the record. Nothing deployed; no another-party file edited; no secret.
This commit is contained in:
1 parent
e2a9a6d205
commit
4c6cd50baf
3 files changed
+347
No files matched your search
@@ -6993,6 +6993,27 @@ a digest-verified backup; both live objects byte-identical at session end
|
|||||||
configurations. **Finish line:** live delta 0 on both objects in every cell, the fix in a gate revision, and
|
configurations. **Finish line:** live delta 0 on both objects in every cell, the fix in a gate revision, and
|
||||||
the census extended to that spawn (or the probe's own held-write delta measured) so the class has a detector
|
the census extended to that spawn (or the probe's own held-write delta measured) so the class has a detector
|
||||||
as well as a prevention. Nothing in Q50 is deployed; the gate is Merlin's file.
|
as well as a prevention. Nothing in Q50 is deployed; the gate is Merlin's file.
|
||||||
|
- **Q50 — DONE 2026-10-13 (Merlin, run 16; record `recoveries/helm-probe-spawn-env.md`).** Taken on the
|
||||||
|
pipe's own offer in reply 34 §Asks 1. Gate **`a951dbe87d3394e0…`** (134,086 B / 2,552 lines / 125 `check(`
|
||||||
|
registrations) on the Q49 gate `085ddf4f…` (128,948 / 2,445 / 123): `out/DIFF-vs-q49.txt` = 388 lines =
|
||||||
|
5 hunks + 226 added − 119 removed, 2,445 + 226 − 119 = 2,552 exactly. One rule, one function
|
||||||
|
(`_q50_rebuild_env(_target)`), two callers — the legs (target `_q43_dir`) and the admission probe (target
|
||||||
|
`_q39_dir`, hoisted above the spawn because `_q43_dir` does not exist there); the spawn at q50:917 now
|
||||||
|
carries `env=`; and a per-window census of both live objects around the spawn is the detector (move →
|
||||||
|
byte-exact in-gate restore + dated `Q50 DETECTOR` note + named failing check). **All five matrix cells
|
||||||
|
measured** (subject `env-root-v1.py`, each under a digest-verified guard): the base gate with
|
||||||
|
`Q48_ROOT=/root/.helm` moves the live held pin 120 B / `5b6d7071…` → 14 B / `784b9bde…` (restored by the
|
||||||
|
guard — the defect reproduced from this host); armed × unset delta 0 (default redirect); **armed × named
|
||||||
|
— the blank cell — delta 0, the value redirect fires, Q50 check PASS**; disarmed × unset delta 0 (the
|
||||||
|
probe copy's own Q45 literal relocation covers the default shape — the redirect is load-bearing only in
|
||||||
|
the named cell); disarmed × named: the detector fires, the pin moves inside the gate, is restored
|
||||||
|
byte-exact, and the foot prints `FAIL Q50 …` (165/10 against the armed rows' 166/9 — the counts isolate
|
||||||
|
the check). Green 5 × rc 0 / **175 passed / 0 failed** (174 + 1) / 13,929 B / live delta 0; regressions
|
||||||
|
11/11 hold (n1–n5, noparse, dep-unparseable, undecodable, broken_dep rc 2; latin1 and bom green 175/0).
|
||||||
|
Live objects byte-identical to session start on (bytes, sha256, mtime_ns); deployed bin untouched
|
||||||
|
(`ee0b36a8…` / `7ed1bca8…`, `HELM_COLLECTOR` count 0 — Q40's finding stands). Named follow-on, not fixed
|
||||||
|
here: hoist the run-wide held census (`_q44_held_before`) above the probe so the per-run instrument sees
|
||||||
|
the window too.
|
||||||
- **Adoption, now conditional — still Alexander's.** Collector `4e45021d…` + gate `085ddf4f…` is not to be
|
- **Adoption, now conditional — still Alexander's.** Collector `4e45021d…` + gate `085ddf4f…` is not to be
|
||||||
paraphrased as the closure of this class until Q50 lands: as written that gate reports `live delta 0` in every
|
paraphrased as the closure of this class until Q50 lands: as written that gate reports `live delta 0` in every
|
||||||
one of its own channels while writing the live held pin whenever the ambient environment names the live root.
|
one of its own channels while writing the live held pin whenever the ambient environment names the live root.
|
||||||
|
|||||||
@@ -504,3 +504,113 @@ Pushed as **`de74527`** (`a7b52e5..de74527`, remote `main`), 3 files / +335. Ano
|
|||||||
- `WORK-QUEUE.md` — **823,541 B**, sha256 **`d0bf9080f9ef61570d30cb85a639b56adbf98bceb3ba30adf2b15e142677b8d2`**
|
- `WORK-QUEUE.md` — **823,541 B**, sha256 **`d0bf9080f9ef61570d30cb85a639b56adbf98bceb3ba30adf2b15e142677b8d2`**
|
||||||
- Commit: `git -c user.name=Merlin -c user.email=merlin@agents.invalid commit -F /root/crucible/q49/q49-commit-msg.txt` → `de74527`.
|
- Commit: `git -c user.name=Merlin -c user.email=merlin@agents.invalid commit -F /root/crucible/q49/q49-commit-msg.txt` → `de74527`.
|
||||||
- Scratch tree `/root/crucible/q49/` is **not** committed; the gate copies (`helm-selftest-q49.py` `085ddf4f42ae80ea…`, `-nodefault` `46ba830cd4b9e690…`, `-inproc-off` `d1481ca890fcd543…`, `-disarmed` `63d5409b3502a22e…`) and the fixture (`env-root-v1.py` `76b55b8ab0203c4f…`) stay in the scratch tree, reproducible by `patch_gate_q49.py` and `reproduce_q49.py`.
|
- Scratch tree `/root/crucible/q49/` is **not** committed; the gate copies (`helm-selftest-q49.py` `085ddf4f42ae80ea…`, `-nodefault` `46ba830cd4b9e690…`, `-inproc-off` `d1481ca890fcd543…`, `-disarmed` `63d5409b3502a22e…`) and the fixture (`env-root-v1.py` `76b55b8ab0203c4f…`) stay in the scratch tree, reproducible by `patch_gate_q49.py` and `reproduce_q49.py`.
|
||||||
|
|
||||||
|
—
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Run 16 — Q50: the admission probe's environment
|
||||||
|
|
||||||
|
### Did
|
||||||
|
|
||||||
|
Claimed and finished **Q50** (Helm lane; the top unclaimed executable item, opened by the
|
||||||
|
pipe in `replies/2026-10-13-to-merlin-34.md` §Asks 1 with an explicit offer to take it —
|
||||||
|
"the gate is your file and I will not edit it, only propose"). Deliverable:
|
||||||
|
`recoveries/helm-probe-spawn-env.md`. Queue block appended to `WORK-QUEUE.md`. Scratch
|
||||||
|
tree `/root/crucible/q50/`; nothing deployed, no `cp` into `/root/.helm/bin/`,
|
||||||
|
`decisions/` and `inbox/` untouched, no another-party file edited, no secret printed.
|
||||||
|
|
||||||
|
**The item's three parts, all measured.** (1) The spawn's rebuilt environment: the
|
||||||
|
Q48 value-redirect + Q49 default-redirect, factored into one function
|
||||||
|
`_q50_rebuild_env(_target)` with two callers — the legs (original site, target the legs'
|
||||||
|
sandbox) and the admission probe (target its own tree, hoisted above the spawn because
|
||||||
|
the legs' sandbox does not exist there). (2) The blank cell (armed × named root): the
|
||||||
|
base gate with `Q48_ROOT=/root/.helm` moves the live held pin **120 B / `5b6d7071…` → 14 B
|
||||||
|
/ `784b9bde…`** (guard-restored; the defect reproduced from this host, same payload digest
|
||||||
|
as my Q49 attribution record); the Q50 gate in the same cell holds **delta 0** with the
|
||||||
|
value redirect firing (`Q50 NOTE … 1 value redirect(s) … Q48_ROOT /root/.helm ->
|
||||||
|
<probe tree>`). (3) The detector: a per-window census of **both** live objects around the
|
||||||
|
spawn — a move is restored byte-exact in-gate, recorded, printed as a dated
|
||||||
|
`Q50 DETECTOR` note, and fails the named check. Exercised on the disarmed variant
|
||||||
|
(prevention cut): the pin moves inside the gate, is restored, and the foot prints
|
||||||
|
`FAIL Q50 the admission probe's spawn moved neither live object` (165/10 against the
|
||||||
|
armed rows' 166/9 — the counts isolate the check; the 9 fixture-subject failures are
|
||||||
|
pre-existing scratch-root checks, identical on the base gate).
|
||||||
|
|
||||||
|
**The pair.** Collector byte-identical to Q33–Q49's (`4e45021d…`, 29,954 B, measured by
|
||||||
|
sha256) — every change is in the gate. Gate **`a951dbe87d3394e0…`** (134,086 B / 2,552
|
||||||
|
lines / **125** `check(` registrations, 2 × `check("Q50"` in mutually exclusive branches)
|
||||||
|
on the Q49 gate `085ddf4f…` (128,948 / 2,445 / 123, digest verified against the queue's
|
||||||
|
record); `out/DIFF-vs-q49.txt` = **388 lines = 5 hunks + 226 added − 119 removed**, and
|
||||||
|
2,445 + 226 − 119 = 2,552 exactly. Disarmed discriminator `6b1c431f…` — one line
|
||||||
|
different (the spawn's `env=` removed).
|
||||||
|
|
||||||
|
**Green pair, five consecutive invocations** (`run_green_q50.py`, subject
|
||||||
|
`/root/crucible/q48/helm-collect.py`, `Q48_ROOT` unset): rc 0 each, **175 passed / 0
|
||||||
|
failed**, ALL GATES PASS, 13,929 B stdout, 13.82–15.11 s, digests `b5391473` / `dd0b0989`
|
||||||
|
/ `d8905c97` / `21e04379` / `aea1ebb3`, live delta 0 on all five. 175 = 174 + 1; no
|
||||||
|
pre-existing check moved. **Regressions 11/11** (`run_regressions_q50.py`): n1–n5, noparse
|
||||||
|
(Q46 REFUSAL), dep-unparseable (repair 3), undecodable (Q47 REFUSAL), broken_dep (Q35
|
||||||
|
REFUSAL) rc 2; latin1 and bom green 175/0; live delta 0 on all 11.
|
||||||
|
|
||||||
|
**The full matrix, all five cells** (`run_matrix_q50.py`, subject `env-root-v1.py`, each
|
||||||
|
under the digest-verified guard `q50_guard.py`): base × named **MOVED** (above); armed ×
|
||||||
|
unset delta 0 (0 value + 1 default redirect); armed × named delta 0 (1 value redirect —
|
||||||
|
the blank cell); disarmed × unset delta 0 (the probe copy's own Q45 literal relocation
|
||||||
|
covers the default shape — the Q50 redirect is load-bearing only in the named cell);
|
||||||
|
disarmed × named delta 0 with the detector firing (in-gate restore). The `other probe
|
||||||
|
files` count in the Q39 OK line is the tell: **1** on armed rows (the redirected write
|
||||||
|
lands inside the probe tree, counted by the containment census), **0** on dis-named (the
|
||||||
|
write went live, and only the window census sees it).
|
||||||
|
|
||||||
|
**Live state, delta 0 across all 27 invocations** (5 green + 5 matrix + 11 regressions +
|
||||||
|
guard reads): snapshot **14,039 B / `aa842b0fd88037f8…` / mtime_ns `1791479579475780303`**;
|
||||||
|
held pin **120 B / `5b6d70716153c3f4…` / mtime_ns `1791478687099553071`**. `ctime_ns` moved
|
||||||
|
twice (the in-gate detector restores + the guard restore of the base row) — disclosed,
|
||||||
|
not hidden. Deployed bin untouched (`ee0b36a8…` / `7ed1bca8…` / `12570786…` / `73869998…`,
|
||||||
|
`grep -c HELM_COLLECTOR` on the deployed gate = **0** — Q40's finding stands). Final tree:
|
||||||
|
0 sandboxes. Nothing of Q31–Q50 is in production.
|
||||||
|
|
||||||
|
**Three defects of mine, logged first in the deliverable:** the green runner's first
|
||||||
|
attempt used the deployed collector (`ee0b36a8…`, the pre-Q33 collector — Q40's finding)
|
||||||
|
and was refused by Q35; re-run with the Q33–Q48 subject. The matrix/regression extractors
|
||||||
|
matched lines *starting* with `Q50 ` while the foot prints ` PASS Q50 …`; the Q50 lines
|
||||||
|
were re-derived from the saved logs (`figures_q50.py`), no invocation re-run. The
|
||||||
|
disarmed variant still prints the `Q50 NOTE` although the env it names is not the one the
|
||||||
|
spawn receives — a scratch discriminator's known inaccuracy.
|
||||||
|
|
||||||
|
### Blocked
|
||||||
|
|
||||||
|
Nothing in my lane. The named follow-on (record §7.2): hoist the run-wide held census
|
||||||
|
(`_q44_held_before`, taken after the spawn) above the probe so the per-run instrument
|
||||||
|
sees the window too. Same standing gates, all Alexander's: the **§4 adoption `cp`** —
|
||||||
|
now collector `4e45021d…` + gate **`a951dbe8…`** (superseding `085ddf4f…`, which the pipe
|
||||||
|
made conditional on this item) — Q9, Q13, Q19, Q42.
|
||||||
|
|
||||||
|
### Next
|
||||||
|
|
||||||
|
1. **The pipe's verification of this run**, when it lands. Everything re-runs from
|
||||||
|
`/root/crucible/q50/`: `patch_gate_q50.py`, `run_green_q50.py`, `run_matrix_q50.py`,
|
||||||
|
`run_regressions_q50.py`, `figures_q50.py`.
|
||||||
|
2. **The held-census hoist** above (my named follow-on) and Merlin's Q45 §9 follow-on
|
||||||
|
both stay open and unclaimed.
|
||||||
|
3. **Q7, measured: the Helm lane's executable set is empty again.** No new item opened —
|
||||||
|
the next Helm unit after the two follow-ons is a decision, not a task.
|
||||||
|
|
||||||
|
### Ask
|
||||||
|
|
||||||
|
Alexander: nothing blocking. The standing items, consolidated: (a) rule on the **§4
|
||||||
|
adoption `cp`** — collector `4e45021d…` + gate **`a951dbe8…`**, the pair that makes
|
||||||
|
`python3 helm-selftest.py` green with no environment and puts Q31–Q50's protection into
|
||||||
|
production; (b) the **`manifest_match` pin** decision (stale since 2026-10-08); (c) the
|
||||||
|
**Q13 publication call** (item 13's decided note still controls over its
|
||||||
|
`proposed_action`).
|
||||||
|
|
||||||
|
### Run 16 landing evidence
|
||||||
|
|
||||||
|
Pushed as its own commit (`git -c user.name=Merlin -c user.email=merlin@agents.invalid`),
|
||||||
|
read back over the anonymous raw path
|
||||||
|
(`https://forge.alexanderwhitestone.com/git/stackchain/troupe-standup/raw/branch/main/<path>`),
|
||||||
|
no credential — each HTTP 200 and `cmp` byte-identical on three sides (served = disk = `git
|
||||||
|
cat-file -p <rev>:<path>`). Table and digests land with the push; the check-in's own row
|
||||||
|
cites the revision it was written against, per the lane's no-self-hash convention.
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
# Q50 — the admission probe's environment
|
||||||
|
|
||||||
|
> Screen. Merlin, Helm lane, 2026-10-13, this host. Every figure below was measured
|
||||||
|
> this run from `/root/crucible/q50/`; the two things labelled as defects of mine
|
||||||
|
> are logged in §7. No secret is printed; the long strings are sha256 digests,
|
||||||
|
> refusal messages and file paths.
|
||||||
|
|
||||||
|
**The item** (queue, opened by the pipe on `replies/2026-10-13-to-merlin-34.md` §Asks 1,
|
||||||
|
2026-10-13): *"Give the Q39 probe spawn at `helm-selftest-q49.py:719` a rebuilt
|
||||||
|
environment by the Q48 rule (any ambient value resolving inside the live root → a
|
||||||
|
sandbox), hoisted above the probe so `_q43_dir` exists; then fill the matrix's blank cell
|
||||||
|
(armed × named root) and re-record all four configurations. Finish line: live delta 0 on
|
||||||
|
both objects in every cell, the fix in a gate revision, and the census extended to that
|
||||||
|
spawn (or the probe's own held-write delta measured) so the class has a detector as well
|
||||||
|
as a prevention."* Taken from the pipe's own offer in the same reply ("If you would
|
||||||
|
rather own it, say so and take it"). Nothing deployed; the gate is my file.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. The pair
|
||||||
|
|
||||||
|
| | base (Q49) | shipped (Q50) |
|
||||||
|
|---|---|---|
|
||||||
|
| gate | `helm-selftest-q49.py` | `helm-selftest-q50.py` |
|
||||||
|
| sha256 | `085ddf4f42ae80ea8b45e67ae157d0a8cf29d429fff8014dc319cd32c7f85b3c` | `a951dbe87d3394e030e16139781d447d86958818c186cc8ee296e4ed23ebaa10` |
|
||||||
|
| bytes / lines | 128,948 / 2,445 | 134,086 / 2,552 |
|
||||||
|
| `check(` registrations | 123 | **125** (2 × `check("Q50"`, mutually exclusive branches — one registers per run) |
|
||||||
|
|
||||||
|
- Base digest **verified by `sha256sum`** against the queue's recorded `085ddf4f…` — the
|
||||||
|
file this patch started from is the file the pipe verified.
|
||||||
|
- Collector **byte-identical to Q33–Q49's**: `/root/crucible/q48/helm-collect.py`,
|
||||||
|
29,954 B / sha256 `4e45021d80395d3f…` — every change is in the gate.
|
||||||
|
- Fixture: `/root/crucible/q50/env-root-v1.py`, 5,634 B / `76b55b8ab0203c4f…` — the Q49
|
||||||
|
witness fixture (default root `/root/.helm`, the live root).
|
||||||
|
- `out/DIFF-vs-q49.txt`: **388 lines = 5 hunks + 226 added − 119 removed**; the lane
|
||||||
|
decomposition, counted by `diff | grep -c`: 2,445 + 226 − 119 = **2,552** exactly.
|
||||||
|
- Disarmed discriminator: `helm-selftest-q50-disarmed.py`, 134,037 B /
|
||||||
|
`6b1c431fab857895078dedad11be66bfc6cd2653f6523bd0b9bd053ecd675bda` — one line different
|
||||||
|
from the shipped gate (the probe spawn's `env=` removed).
|
||||||
|
- Patch: `patch_gate_q50.py` — six count-asserted edits (each anchor must occur exactly
|
||||||
|
once or the run aborts), edit log in §9.
|
||||||
|
|
||||||
|
## 2. What changed — one rule, one function, two callers
|
||||||
|
|
||||||
|
1. **The rebuild is factored.** `_q50_rebuild_env(_target)` carries the Q48
|
||||||
|
value-redirect and the Q49 default-redirect, parameterised by sandbox root, and
|
||||||
|
returns `(env, redirects, default_redirects)`. It is called **twice**: at the rule's
|
||||||
|
original site for the legs (target `_q43_dir`, the legs' sandbox) and at a new site
|
||||||
|
above the probe for the admission probe (target `_q39_dir`, the probe's own tree).
|
||||||
|
One rule, two targets — the two paths cannot drift because they are the same code.
|
||||||
|
2. **The hoist.** The env machinery (`import os as _q48_os`, the two `ast` walkers, the
|
||||||
|
names/defaults computation, the live-root predicate) moved from ~line 862 to above the
|
||||||
|
probe branch (~line 685), because the probe spawns ~240 lines above the rebuild and
|
||||||
|
before Q50 it inherited the gate's ambient environment. The target had to be a
|
||||||
|
parameter because `_q43_dir` — the legs' sandbox — is created ~115 lines *after* the
|
||||||
|
probe; the probe's redirect target is its own tree, which exists before the spawn.
|
||||||
|
3. **The prevention.** The spawn (`helm-selftest-q50.py:917`, q49:719) now carries
|
||||||
|
`env=_q50_probe_env`: every variable the subject reads whose **ambient value**
|
||||||
|
resolves inside the live root is redirected into the probe tree, and every name whose
|
||||||
|
**default literal** resolves there is redirected when the ambient value is absent.
|
||||||
|
4. **The detector.** `_q50_census()` reads both live objects — the snapshot and every
|
||||||
|
file in the live held directory, bytes carried — on **both sides of the spawn**. A
|
||||||
|
move is restored byte-exact (`_q50_restore_census`, mtime re-stamped from the before
|
||||||
|
value), recorded in `_q50_probe_moves`, printed as a dated `Q50 DETECTOR` note on
|
||||||
|
stderr, and fails the named check `Q50 the admission probe's spawn moved neither live
|
||||||
|
object`. When no probe runs (no `SNAPSHOT_PATH =` assignment) the check is registered
|
||||||
|
vacuously so the suite carries the same census on every subject class.
|
||||||
|
|
||||||
|
## 3. The 2×2, all four cells plus the base-gate control
|
||||||
|
|
||||||
|
Subject `env-root-v1.py`; every row under the digest-verified guard `q50_guard.py`
|
||||||
|
(refuses to restore unless the backup digest matches); a live move is restored by the
|
||||||
|
guard and recorded. `Q48_ROOT` unset means removed from the environment, not blank.
|
||||||
|
|
||||||
|
| row | gate | `Q48_ROOT` | rc | passed / failed | guard live delta | Q50 check | probe-window redirects |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| `base-q49-named` | q49 `085ddf4f` | `/root/.helm` | 1 | 165 / 9 | **MOVED** — held pin 120 B / `5b6d7071…` → **14 B / `784b9bde…`** (`'q48-env-pin\n'`, the fixture's own payload), restored by the guard | — (no such check) | n/a |
|
||||||
|
| `q50-armed-unset` | q50 `a951dbe8` | *unset* | 1 | 166 / 9 | 0 | **PASS** | 0 value + **1 default**: `Q48_ROOT /root/.helm -> <probe tree>` |
|
||||||
|
| **`q50-armed-named`** | q50 `a951dbe8` | `/root/.helm` | 1 | 166 / 9 | **0** | **PASS** | **1 value**: `Q48_ROOT /root/.helm -> <probe tree>` — **the blank cell, filled** |
|
||||||
|
| `q50-dis-unset` | disarmed `6b1c431f` | *unset* | 1 | 166 / 9 | 0 | PASS | 0 value + 1 default (printed, unused) |
|
||||||
|
| `q50-dis-named` | disarmed `6b1c431f` | `/root/.helm` | 1 | **165 / 10** | 0 (**in-gate** restore) | **FAIL — the detector fired** | 1 value (printed, unused) |
|
||||||
|
|
||||||
|
- **The defect on the base gate, reproduced from this host.** `base-q49-named` moved the
|
||||||
|
live held pin exactly as reply 34's strace recorded: the same 14 B payload, digest
|
||||||
|
`784b9bded20e9e22…` — the content my own Q49 attribution file measured
|
||||||
|
(`out/Q49-ATTRIBUTION.json`). The guard restored byte-exact.
|
||||||
|
- **The blank cell.** Armed × named root: live delta 0, the value redirect fires
|
||||||
|
(`Q50 NOTE … 1 value redirect(s), 0 default redirect(s) into <probe tree>: Q48_ROOT
|
||||||
|
/root/.helm -> /root/crucible/q50/helm-q39-cyl_yd_e`), the Q50 check PASSes. On the
|
||||||
|
base gate the same cell moves the pin; one line apart, the outcome flips.
|
||||||
|
- **The detector's exercise.** Dis-named: the probe spawn inherited the ambient
|
||||||
|
`Q48_ROOT=/root/.helm` (prevention cut), the census saw the held pin go
|
||||||
|
120 B / `5b6d7071…` → 14 B / `784b9bde…` *inside the gate*, restored byte-exact at
|
||||||
|
`2026-10-13T11:21:39.333132+00:00`, and the foot printed
|
||||||
|
`FAIL Q50 the admission probe's spawn moved neither live object the probe-window
|
||||||
|
census moved: […before [120, 5b6d7071…, 1791478687099553071], after [14,
|
||||||
|
784b9bde…, 1791890499488341075]…]` (`out/q50-dis-named.out` line 176). The guard's
|
||||||
|
post-run compare saw delta 0 — the in-gate restore did its job.
|
||||||
|
- **The counts isolate the check.** The 9 failures on the fixture subject are
|
||||||
|
pre-existing scratch-root checks, identical on the base gate (165/9). The arithmetic
|
||||||
|
is exact: base 165/9 → armed 166/9 (the Q50 check added and passing) → dis-named
|
||||||
|
165/10 (the same check failing). Nothing else moved.
|
||||||
|
- **`other probe files` is the tell** (`Q39 OK` line, stderr): armed rows print
|
||||||
|
`other probe files=1` — the redirected write lands inside the probe tree, where the
|
||||||
|
containment census counts it (the disclosed side effect); dis-named prints
|
||||||
|
`other probe files=0` — the write went live, and only the window census sees it. The
|
||||||
|
count now distinguishes where the write landed, which the Q39 message could not say
|
||||||
|
before.
|
||||||
|
|
||||||
|
## 4. Green pair — five consecutive invocations, real collector
|
||||||
|
|
||||||
|
`run_green_q50.py`, subject `/root/crucible/q48/helm-collect.py` (`4e45021d…`),
|
||||||
|
`HELM_COLLECTOR` set, `Q48_ROOT` unset. rc 0 each, **175 passed / 0 failed**,
|
||||||
|
`VERDICT: ALL GATES PASS`, **13,929 B** stdout, 13.82–15.11 s; stdout digests
|
||||||
|
`b53914732ac2` / `dd0b0989ab12` / `d8905c971857` / `21e04379e825` / `aea1ebb31fe9`
|
||||||
|
(identical size; digests differ only in the gate's own randomised names). **175 = 174
|
||||||
|
(Q49) + 1 (Q50)**; no pre-existing check moved. Live delta 0 on all five;
|
||||||
|
`out/Q50-GREEN.json`. Leftovers after the set: **0** (`find … -name 'helm-legs-*' -o
|
||||||
|
-name 'helm-q39-*'` → 0).
|
||||||
|
|
||||||
|
## 5. Regressions — every accumulated negative, on the shipped Q50 gate
|
||||||
|
|
||||||
|
`run_regressions_q50.py`, 11 fixtures, `Q48_ROOT` unset: **11/11 hold, live delta 0 on
|
||||||
|
all 11.**
|
||||||
|
|
||||||
|
| fixture | rc | refusal / result |
|
||||||
|
|---|---|---|
|
||||||
|
| `n1-incident-shape.py` … `n4-comment-only.py` | 2 | `Q39 REFUSAL: … carries no WORKING destination rule` |
|
||||||
|
| `n5-live-literal.py` | 2 | Q39 refusal (575 B stdout, the legs' own refusal) |
|
||||||
|
| `noparse-with-markers.py` | 2 | `Q46 REFUSAL: … does not parse - invalid syntax` |
|
||||||
|
| `dep-unparseable.py` | 2 | `Q39 REFUSAL` — repair 3 (the dependency's SyntaxError raises with a traceback) |
|
||||||
|
| `collector-undecodable.py` | 2 | `Q47 REFUSAL: … cannot be read the way CPython reads a source file` |
|
||||||
|
| `broken_dep.py` | 2 | `Q35 REFUSAL: … carries no destination rule` |
|
||||||
|
| `collector-latin1.py` | 0 | **175 / 0**, ALL GATES PASS |
|
||||||
|
| `collector-bom.py` | 0 | **175 / 0**, ALL GATES PASS |
|
||||||
|
|
||||||
|
## 6. Live state, delta 0 across the whole run
|
||||||
|
|
||||||
|
27 invocations under census (5 green + 5 matrix + 11 regressions + the guard's own
|
||||||
|
reads). Session start = final, on (bytes, sha256, mtime_ns):
|
||||||
|
|
||||||
|
- snapshot `/root/.helm/data/snapshot.json` — **14,039 B / `aa842b0fd88037f8…` /
|
||||||
|
mtime_ns `1791479579475780303`**
|
||||||
|
- held pin `/root/.helm/data/held/stackchain-home.html.sha256` — **120 B /
|
||||||
|
`5b6d70716153c3f4…` / mtime_ns `1791478687099553071`**
|
||||||
|
|
||||||
|
`ctime_ns` moved on both objects (to `1791890492529766997` / `1791890499523343963`) —
|
||||||
|
the two in-gate detector restores' traces plus the guard restore of the base row.
|
||||||
|
A restore cannot undo ctime (Q43); the traces are the durable record and are disclosed,
|
||||||
|
not hidden. **Deployed bin untouched**: `/root/.helm/bin/` — `ee0b36a82f23fcf3…`
|
||||||
|
(helm-collect.py), `7ed1bca8f9da624f…` (helm-selftest.py), `12570786ba703787…`,
|
||||||
|
`7386999867789694…`; `grep -c HELM_COLLECTOR` on the deployed gate = **0**, so Q40's
|
||||||
|
finding stands and none of Q31–Q50 is in production. Scratch tree `/root/crucible/q50/`
|
||||||
|
is not committed; everything re-runs from `patch_gate_q50.py`, `run_green_q50.py`,
|
||||||
|
`run_matrix_q50.py`, `run_regressions_q50.py`, `figures_q50.py`.
|
||||||
|
|
||||||
|
## 7. Findings and limits
|
||||||
|
|
||||||
|
1. **The unset shape is covered twice.** Dis-unset (prevention cut) still holds delta 0:
|
||||||
|
the probe copy's own Q45 literal relocation covers the default literal, so the Q50
|
||||||
|
redirect is load-bearing only in the **named** cell. Both arms measured — the
|
||||||
|
prevention is not redundant, it is the only cover for the shape that actually moved
|
||||||
|
the pin.
|
||||||
|
2. **The detector is per-window, not per-run.** This run's once-per-run held census
|
||||||
|
(`_q44_held_before`, q49:1281 → q50:1388) is taken *after* the spawn and structurally
|
||||||
|
cannot see a probe write — the ordering defect that made the class invisible. The
|
||||||
|
permanent fix is to hoist that census above the probe, or to keep the window census
|
||||||
|
as the instrument. Named, not fixed: out of Q50's one-line scope, and the next
|
||||||
|
Helm-side follow-on.
|
||||||
|
3. **Citation shift from the hoist.** The probe spawn is q49:719 → **q50:917**; the
|
||||||
|
in-process `--deploy` branch is q49:2292–2325 → **q50:2399–2432** (`_rc =
|
||||||
|
hcg.main()` at q50:2432; the `# --dry-run at the live destination is NOT gated`
|
||||||
|
comment at q50:2390, q49:2283); the legs' env hand-off q49:1117 → **q50:1310**.
|
||||||
|
Reply 34's corrected citations describe the same regions.
|
||||||
|
4. **What is not covered** (carried from Q48/Q49's limits, unchanged): a variable name
|
||||||
|
the `ast` inventory cannot see (dynamically constructed), an argv-composed root passed
|
||||||
|
to the probe (the probe passes no argv), and a subject that reaches the live path
|
||||||
|
through a mechanism neither environment nor literals express. The parse, read-path and
|
||||||
|
redirect classes are untouched: 11/11 regressions hold.
|
||||||
|
5. **Harness defects of mine, logged first.** (a) The green runner's first attempt used
|
||||||
|
the deployed collector `/root/.helm/bin/helm-collect.py` (`ee0b36a8…` — the pre-Q33
|
||||||
|
collector, Q40's finding) and was refused by Q35's source precondition; re-run with
|
||||||
|
the Q33–Q48 subject (`4e45021d…`). (b) The matrix/regression extractors matched lines
|
||||||
|
*starting* with `Q50 ` while the foot prints ` PASS Q50 …`; the Q50 check lines were
|
||||||
|
re-derived from the saved logs by `figures_q50.py` — no invocation re-run. (c) The
|
||||||
|
disarmed variant still prints the `Q50 NOTE` although the environment it names is not
|
||||||
|
the one the spawn receives — a scratch discriminator's known inaccuracy, disclosed.
|
||||||
|
6. **Shared live objects, re-measured.** The queue's standing note (the live objects and
|
||||||
|
scratch trees need a lock or separate roots) stands: this session's ctime traces are
|
||||||
|
this run's own restores, and no foreign writer appeared in this tree's window. The
|
||||||
|
fixture's default live root means any unguarded invocation of `env-root-v1.py` writes
|
||||||
|
live; every row here either set `Q48_ROOT` explicitly or ran under the guard.
|
||||||
|
|
||||||
|
## 8. Verdict
|
||||||
|
|
||||||
|
**Q50 DONE.** The class the pipe attributed to the probe spawn is closed for both
|
||||||
|
shapes: prevention (the spawn's rebuilt environment) measured delta 0 in the blank cell
|
||||||
|
and in every other armed configuration, the detector measured firing and restoring in
|
||||||
|
the one configuration where prevention is cut, and the 2×2 now isolates the two
|
||||||
|
mechanisms row by row. The adoption pair the pipe made conditional on this item is now
|
||||||
|
collector `4e45021d…` + gate **`a951dbe8…`**.
|
||||||
|
|
||||||
|
## 9. Evidence
|
||||||
|
|
||||||
|
| claim | command / artifact | output |
|
||||||
|
|---|---|---|
|
||||||
|
| base gate identity | `sha256sum /root/crucible/q49/helm-selftest-q49.py` | `085ddf4f42ae80ea…` (matches the queue) |
|
||||||
|
| new gate identity | `sha256sum helm-selftest-q50.py`; `wc -l` | `a951dbe87d3394e0…`, 134,086 B / 2,552 lines |
|
||||||
|
| diff decomposition | `diff -u q49 q50 \| grep -c` | 388 = 5 hunks + 226 − 119; 2,445+226−119 = 2,552 |
|
||||||
|
| patch integrity | `python3 patch_gate_q50.py` | 6 edits, each anchor count 1; `py_compile` rc 0 ×2; 2 × `check("Q50"` |
|
||||||
|
| green | `python3 run_green_q50.py` | 5 × rc 0, 175/0, 13,929 B; `VERDICT: ALL GREEN` |
|
||||||
|
| matrix | `python3 run_matrix_q50.py` | 5 rows; base MOVED 120→14 B restored; armed cells delta 0; dis-named Q50 FAIL, in-gate restore |
|
||||||
|
| regressions | `python3 run_regressions_q50.py` | 11/11 rc as expected, delta 0; `VERDICT: ALL REGRESSIONS HOLD` |
|
||||||
|
| live state | `python3 q50_guard.py snapshot / compare / restore` | session start = final on bytes/sha/mtime; FINAL delta `{}` |
|
||||||
|
| deployed bin | `sha256sum /root/.helm/bin/*`; `grep -c HELM_COLLECTOR helm-selftest.py` | `ee0b36a8…` / `7ed1bca8…` / `12570786…` / `73869998…`; count **0** |
|
||||||
|
| artifacts | `out/Q50-{GREEN,MATRIX,REGRESSIONS,FIGURES}.json`, `out/DIFF-vs-q49.txt`, per-row `.out`/`.err` | on disk, re-runnable |
|
||||||
Reference in new issue
Block a user