The second-instrument rows for all fifteen discriminator rows and the four regression rows; the E6 mechanism correction (Q39 compiles the subject's text at legacy/q39:273 -- record-and-continue, not avoidance) with its two supporting figures (164 = Q39's suite size on the plain collector too; the BOM stderr is the shorter one because the dropped tree suppresses the assignment rows); the E5 residual logged, one unannotated 109,643 at checkins/2026-10-13-merlin.md:27; the capture-identity check Q47's green digests pass and Q46's failed; Q40 re-measured (deployed gate 7ed1bca8 reads HELM_COLLECTOR zero times), so the adoption pair 4e45021d + 76f2292b remains the only path into production; and no new item opened with the reason stated rather than implied -- the runtime-declared path class is held as a limit, not a measurement, and its measurement would aim a subject at the live snapshot (14,039 B / aa842b0f), where a miss writes the live file and a restore would move the mtime_ns and ctime_ns values three records cite as deltas. No lane is dry.
This commit is contained in:
1 parent
82334f76ae
commit
f75ba18d30
1 file changed
+18
@@ -6651,3 +6651,21 @@ Deliverable `recoveries/helm-read-path-guard.md` (12,821 B / sha256 `5bf9ba11507
|
|||||||
- **Limits and defects, logged first in the deliverable:** the harness's verdict block passed fixture names **with** `.py` into a row-name builder that strips it, so the verdict raised `StopIteration` → `RuntimeError` after the rows JSON was written (recomputed from the rows by `recompute_verdict.py`; `run_negatives_q47.py` patched; no gate invocation re-run); the negative fixtures' destination literals still name the **q46** tree (inherited by `cp -a`), so the fixture-dest census was vacuous this run (no `n*-dest`/`dep-dest` directory exists under `/root/crucible/q46/fixtures`, and each negative row's leg refused its own destination); the copies this gate writes are UTF-8 by construction (their header lines push the subject's cookie past PEP 263's line-2 limit), so non-ASCII in **executable strings** under a cookie would be re-encoded — recorded as a limit, not fixed; the guard stays static (runtime-generated code is out of every static guard's reach).
|
- **Limits and defects, logged first in the deliverable:** the harness's verdict block passed fixture names **with** `.py` into a row-name builder that strips it, so the verdict raised `StopIteration` → `RuntimeError` after the rows JSON was written (recomputed from the rows by `recompute_verdict.py`; `run_negatives_q47.py` patched; no gate invocation re-run); the negative fixtures' destination literals still name the **q46** tree (inherited by `cp -a`), so the fixture-dest census was vacuous this run (no `n*-dest`/`dep-dest` directory exists under `/root/crucible/q46/fixtures`, and each negative row's leg refused its own destination); the copies this gate writes are UTF-8 by construction (their header lines push the subject's cookie past PEP 263's line-2 limit), so non-ASCII in **executable strings** under a cookie would be re-encoded — recorded as a limit, not fixed; the guard stays static (runtime-generated code is out of every static guard's reach).
|
||||||
- **§4 consequence:** the adoption pair is now collector `4e45021d…` + gate **`76f2292b…`** (superseding `ae69d5dd…`). Q40's finding stands — the deployed gate `7ed1bca8…` reads `HELM_COLLECTOR` zero times — so the `cp` remains Alexander's and is the only thing that puts Q31–Q47's protection into production.
|
- **§4 consequence:** the adoption pair is now collector `4e45021d…` + gate **`76f2292b…`** (superseding `ae69d5dd…`). Q40's finding stands — the deployed gate `7ed1bca8…` reads `HELM_COLLECTOR` zero times — so the `cp` remains Alexander's and is the only thing that puts Q31–Q47's protection into production.
|
||||||
- **Q7, measured:** the Helm lane's executable set is empty again after this item (the adoption `cp`, Q9, Q13/Q19 and Q42 are human- or counterparty-gated). Merlin's Q45 §9 follow-on (resolve every path the subject declares **at runtime**, not only the literals it declares statically) stays open and unclaimed beside the adoption. **No new item opened.**
|
- **Q7, measured:** the Helm lane's executable set is empty again after this item (the adoption `cp`, Q9, Q13/Q19 and Q42 are human- or counterparty-gated). Merlin's Q45 §9 follow-on (resolve every path the subject declares **at runtime**, not only the literals it declares statically) stays open and unclaimed beside the adoption. **No new item opened.**
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Q47 (Helm lane) — VERIFIED and closed from this host by the pipe (2026-10-13, reply 32). Closure `8cb941f`; landing fill `1b3d7a44`. E6: one mechanism sentence of Merlin's does not hold and is corrected below; no acceptance claim moves.**
|
||||||
|
|
||||||
|
Verified on a second instrument written from scratch (`/root/crucible/q47/timmy-verify-13/verify.py`, rows in `rows.json`, row labels `tm-*` so no label is shared with his capture set), the gate invoked directly with `HELM_COLLECTOR`, readings taken **03:56–04:08Z**.
|
||||||
|
|
||||||
|
- **The pair, Documented.** Gate `76f2292b9a6cad08505956787cf05e65e3edaf7e0f23f73f4aed2e59a62866c1` **115,182 B / 2,124 lines**; collector `4e45021d…` **720 / 29,954 B** and byte-identical across `/root/crucible/q46/` and `/root/crucible/q47/` by sha256 — "every change is in the gate" is measured. My own `diff -u` decomposes to **130 = 2 file + 4 hunk + 96 added + 4 removed + 24 context** with 2,032 + 96 − 4 = **2,124**, and its **128 non-header lines are byte-identical to `out/DIFF-vs-q46.txt`** (only the `---`/`+++` path prefixes differ). Legacy gates in `legacy/q3{9,4,5}` and `legacy/q45` match the digest-verified `9b09f328…` / `c22601ec…` / `18580c10…` / `2bbca218…`.
|
||||||
|
- **The three read-path rows under the shipped gate, all four done-criteria reproduced.** `collector-latin1.py` — **rc 0, 169 passed / 0 failed, `VERDICT: ALL GATES PASS`, 13,312 B stdout**, `iso-8859-1` NOTE on stderr, no leftover. `collector-bom.py` — **rc 0, 169 / 0, ALL GATES PASS, 13,312 B**, `utf-8-sig` NOTE, no leftover. `collector-undecodable.py` — **rc 2, stdout 0 B (`e3b0c442…`)**, the dated `Q47 REFUSAL … cannot be read the way CPython reads a source file - 'utf-8' codec can't decode byte 0xe9 in position 30004 … refused at 2026-10-13T04:05:32.267768+00:00, before the admission probe, before any leg, and before any sandbox is created.` — no traceback, no leftover. Live snapshot digest-identical before and after every invocation (`aa842b0f…`, 14,039 B; held pin `5b6d70716153c3f4…`, 120 B).
|
||||||
|
- **The legacy controls, reproduced including the row he flagged as a finding.** latin-1 — Q39/Q43/Q45 all rc 1, `UnicodeDecodeError … position 30026`, 0 B stdout, no sandbox. BOM — **Q39 rc 0 / 164 passed / ALL GATES PASS / 11,398 B**, Q43 rc 1 575 B `SyntaxError: invalid non-printable character U+FEFF` with a sandbox left, Q44 rc 1 **0 B** `AttributeError: 'NoneType' object has no attribute 'body'` with a sandbox left, Q45 rc 1 575 B same SyntaxError with a sandbox left. undecodable — Q39/Q43/Q45 rc 1, same decode error at **position 30004**. My runs' three sandboxes were recorded and removed; the tree is back to **0**.
|
||||||
|
- **Regressions, none loosened.** `noparse-with-markers` under the shipped gate **rc 2** with the dated `Q46 REFUSAL` (`invalid syntax (noparse-with-markers.py, line 13)`); `n1`–`n5` all **rc 2** (`Q39 REFUSAL … carries no WORKING destination rule`; n5 via the `Q39 NOTE` path, 575 B); no leftover, live delta 0.
|
||||||
|
- **The green pair, and the check Q46's record failed.** The five `stdout_sha256` values in `out/Q47-GREEN.json` are **exactly** the digests of the five on-disk `out/q47-green-{1..5}.out` (13,312 B each), checked field by field — **Documented**, and the capture-identity trap is not repeated. `q47-green-1.out` vs `q46-green-1.out`: **184 lines each, exactly 4 differ**, all randomized names or the tree path (lines 1, 10, 183–184). The `Q47 NOTE` is absent from the plain-subject green run (`grep -c` = 0 on the 425 B stderr) and present on both non-utf-8 subjects.
|
||||||
|
- **The read path, in the code.** One reader at `:250`, one call at `:278`; the four subject reads route through it (`_q39_src_text = _q35_src` at `:453`, G8 source at `:1796`, G8 source-guard at `:2063`, Q35 precondition and the Q46 guard on `_q35_src` at `:303`/`:355`); the remaining `read_text()` calls are on the canary and the renderer, not the subject. **Documented.**
|
||||||
|
- **E6 — the Q39-bom mechanism, corrected (mine to make; three loci: `checkins/2026-10-13-merlin.md` Run 13 §6, `WORK-QUEUE.md:6647`, `recoveries/helm-read-path-guard.md` §6).** The sentence *"Q39 never compiles the subject's text"* is false: `legacy/q39/helm-selftest.py:273` is `_q39_tree = _q39_ast.parse(_q39_src_text)`, and `:275–276` catches the `SyntaxError`, drops the tree and appends `("parse", "-", "the subject does not parse: …")` to `_q39_report` (printed at `:393`/`:412`) — the message he quotes is produced by that call, and my BOM run of the frozen gate prints it on stderr. The class is a property of what a gate does **with** a failed parse — record-and-continue (Q39), dereference the dropped tree (Q44), import the decoded text (Q43/Q45) — not of whether it compiles the subject's text. **Two figures beside it:** Q39's **164 passed** is its suite size, not a BOM casualty (the same frozen gate on the plain collector also reads 164 / 11,398 B / `ALL GATES PASS`), and the BOM run's stderr is the *shorter* one (397 B vs 425 B) because the dropped tree suppresses the assignment rows. Grade **Documented**; no acceptance claim moves.
|
||||||
|
- **E5 residual — the superseded figure is still unannotated in his text.** `checkins/2026-10-13-merlin.md:27` (Run 12's section) reads "2,032 lines / 109,643 B" with no pointer to the correction every other locus now carries. Counted: that file **1 × `110,509` / 1 × `109,643`**; `recoveries/helm-read-path-guard.md` **1 / 0**; this queue **12 / 10**. His file, his call to annotate; logged here so the number does not survive unnoted.
|
||||||
|
- **Receipts.** `branch-head` = `head` = `1b3d7a44da46`; the monitor's moved paths 3/3 hash-identical to `git rev-parse HEAD:<path>`. Loopback API: one branch (`main`), **0 open PRs**, `private: false` / `internal: false`. Deployed gate `/root/.helm/bin/helm-selftest.py` `7ed1bca8…` with `grep -c HELM_COLLECTOR` = **0** — Q40 stands, so the §4 `cp` (now collector `4e45021d…` + gate `76f2292b…`) remains the only path into production. Nothing deployed, nothing published, `decisions/` and `inbox/` untouched, no counterparty file edited, no secret.
|
||||||
|
- **Q7, measured: no new item opened, and the reason is stated rather than implied.** The Helm lane's executable set is empty again and the one follow-on both records name — resolve every path the subject declares **at runtime**, not only the literals it declares statically (Q44 limit 1, Merlin's Q45 §9) — is held as a **limit**, not a measurement, so opening an item on it would be opening on a hypothesis. Its measurement is also the one this lane will not take unasked: a subject that composes its live destination at runtime is aimed at `/root/.helm/data/snapshot.json` (14,039 B / `aa842b0f…`), and a miss writes the live file, after which a restore would move the `mtime_ns`/`ctime_ns` values three records cite as deltas. **Named, unclaimed, with the missing measurement named.** No lane is dry: Q42 is zephyrus's, Q9/Q13/Q19 are Alexander's, and the `cp` is the same human call.
|
||||||
Reference in new issue
Block a user