queue: incident -- my own Q38 probe wrote the live snapshot; restored byte-exact; the guard admitted the writer

What happened. My probe /tmp/hermes-probe/probe2.py ran the Q38 gate with a fake subject whose SNAPSHOT_PATH
is the live path, which writes {} there and exits 0. The gate returned exit 0 with "Q38 OK: the subject
refused its sentinel destination (probe rc=1, sentinel written=False, live delta 0)" -- and the live
snapshot became 2 B / 44136fa355b3678a (the sha256 of {}), mtime_ns 1791789464458475582. A subject that
writes the live default was admitted, and the write landed inside the gate's own run while its summary
reported live delta 0.

Restore. /root/.helm/data/snapshot.json is back to
aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d / 14,039 B / mtime_ns
1791479579475780303, copied from /root/crucible/q31/snap-before.json; /root/crucible/verify-q31/snap-before.json
and /root/troupe-verify/q35/snap-before.json carry the identical digest, so the restored bytes are not a
single-point assumption. os.utime set both stamps to the original. The public page was never touched
(9,865 B, mtime 2026-10-11T08:57:14Z); no cp, nothing deployed, deployed bin unmoved.

The hole. Admission is decided by what the sentinel probe reports, not by where the subject's own default
resolves: a subject that fails its sentinel run for an unrelated reason (rc=1, nothing written) is admitted
and the suite then runs the subject itself. Hypothesis, labelled as one: a leg ran the unrewritten subject
with the live default, which is how {} reached production state. The fix is the resolution check -- refuse
any subject whose default destination resolves inside /root/.helm/data/ -- with the live snapshot's bytes
and mtime re-read after every leg rather than summarised once.

Correction to my own 02:48Z block: it recorded a limit of the Q35 guard as non-blocking. The same shape can
write production state through the Q38 admission path, so the guard is unproven until that check lands. No
probe will be run again against a subject whose default destination is not sandboxed.

Q38 identities re-read on this host: gate 1,141 lines / 64,454 B / 74aba34860b34ac6; collector 4e45021d80395d3f
(720 / 29,954, byte-identical to the Q34/Q35 pair); deployed helm-selftest.py 7ed1bca8f9da624f (609 / 33,647)
and helm-collect.py ee0b36a82f23fcf3 (687 / 27,907) unmoved. The section 4 pair is therefore collector
4e45021d80395d3f plus gate 74aba34860b34ac6 -- and the gate should not be adopted on this host until the
resolution check lands.
This commit is contained in:
timmy committed 2026-10-12 07:18:42 +00:00
1 parent 4ed1da96ae
commit 8d2b56cc9a
1 file changed
+28
+28
View File
@@ -5066,3 +5066,31 @@ Scratch tree `/root/crucible/q38/`; nothing deployed, nothing published; the sha
guard protects the gate's legs, not a direct CLI run of a pre-gate collector (the Q35 limit, unchanged). guard protects the gate's legs, not a direct CLI run of a pre-gate collector (the Q35 limit, unchanged).
- **Q7, measured:** the unclaimed executable set is unchanged and not empty — **Q37** (pipe tooling) is open. Nothing - **Q7, measured:** the unclaimed executable set is unchanged and not empty — **Q37** (pipe tooling) is open. Nothing
opened this tick beyond this item, which discharges Q36's candidate 2 on Alexander's direction. opened this tick beyond this item, which discharges Q36's candidate 2 on Alexander's direction.
**Incident — my own Q38 probe wrote the live snapshot (restored byte-exact), and the behavioural guard admitted the
writer. 2026-10-12 07:18Z (control plane).** Logged and fixed in the same tick; the content came back from three
independent copies of the original digest.
- **What happened.** My probe (`/tmp/hermes-probe/probe2.py`) ran the Q38 gate with a fake subject whose
`SNAPSHOT_PATH` is the live path, which writes `{}` there and exits 0. The gate returned **exit 0** with
`Q38 OK: the subject refused its sentinel destination (probe rc=1, sentinel written=False, live delta 0)` — and the
live snapshot became **2 B / `44136fa355b3678a…`** (the sha256 of `{}`), mtime_ns `1791789464458475582`. A subject
that writes the live default was therefore **admitted**, and the write landed inside the gate's own run while its
summary reported `live delta 0`.
- **Restore.** `/root/.helm/data/snapshot.json` is back to `aa842b0fd88037f83115b4a54d617f27666f4de06ef84f9a64c8fd0a5f04656d`
/ 14,039 B / mtime_ns `1791479579475780303`, copied from `/root/crucible/q31/snap-before.json`; two further copies
(`/root/crucible/verify-q31/snap-before.json`, `/root/troupe-verify/q35/snap-before.json`) carry the identical
digest, so the restored bytes are not a single-point assumption. `os.utime` set both stamps to the original. The
public page was never touched (9,865 B, mtime `2026-10-11T08:57:14Z`), and no `cp` was made, nothing deployed, the
deployed bin unmoved.
- **The guard's hole, stated as observed plus one labelled hypothesis.** Admission is decided by what the *sentinel*
probe reports, not by where the subject's own default resolves. Observed: a subject that fails its sentinel run for
an unrelated reason (`rc=1`, nothing written to the sentinel) is admitted, and the suite then runs the subject
itself. Hypothesis, labelled: a leg ran the unrewritten subject with the live default, which is how `{}` reached
production state. The fix that closes it is the resolution check — refuse any subject whose default destination
resolves inside `/root/.helm/data/` — with the live snapshot's bytes **and** mtime re-read after every leg rather
than summarised once at the end.
- **Correction to my own 02:48Z block.** That block recorded a *limit* of the Q35 guard ("a comment defeats it") as a
non-blocking observation. This tick shows the same shape can write production state through the Q38 guard's own
admission path, so the limit is not cosmetic: the guard must be treated as unproven until the resolution check
lands. No probe should be run again against any subject whose default destination is not sandboxed.