From 3e22e1b354f1dac8875b0937c4f64b761209a043 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 30 Jul 2026 16:36:40 -0500 Subject: [PATCH 1/3] fix(wake): #952 quarantine-audit clean sweep names BOTH unprovable residual classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wording-only measurement fix (#951 review finding 1, upgraded to measurement defect): the clean-sweep OK named only "rows without surviving dead-letter evidence", so an operator concluded NO evidence exists when evidence can exist and be UNUSABLE — a surviving dead-letter row whose locator extracts an empty observed_hash (live specimen: mos-dt seq 13, bench/malformed-locator-test) can never satisfy the four-field conviction match, because _record_last_consumed only writes rows with a non-empty hash. The conviction predicate is UNCHANGED. - store.sh: clean-sweep message + PROVABILITY BOUND comment name both classes ("no evidence" vs "evidence unusable"). - test T17: drives the REAL writer flow (12 fillers + bench key at seq 13) and plants the VERBATIM live specimen — nested .locators.* with no observed_hash key, never a hand-built flat dead-letter row (the #951 false-defect near-miss); asserts clean sweep exits 0, both classes named, no conviction, --repair removes nothing, ledger untouched. - manifest: wake 0.6.15 -> 0.6.16. Red-first: pre-fix fails exactly the two wording assertions (and the non-conviction guards pass pre-fix — predicate correct all along); fixed 18/18. All wake suites green; detector D4 intermittent red is a pre-existing lock-handoff timing flake in unmodified files, filed as Written-by: pepper (sb-it-1-dt) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NsKce8iZuSuRnu3gVMCBKB --- .../mosaic/framework/tools/wake/manifest.txt | 19 ++++++- packages/mosaic/framework/tools/wake/store.sh | 17 ++++-- .../tools/wake/test-wake-store-ack.sh | 53 +++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/packages/mosaic/framework/tools/wake/manifest.txt b/packages/mosaic/framework/tools/wake/manifest.txt index d0342b1b..45ecf81b 100644 --- a/packages/mosaic/framework/tools/wake/manifest.txt +++ b/packages/mosaic/framework/tools/wake/manifest.txt @@ -447,7 +447,24 @@ # #964 re-verdict regression needles: symlinked store, live # secret value, polarity, ledger deletion, allowlist-symlink). component=wake -version=0.7.0 +# 0.7.1 #952 quarantine-audit clean-sweep message named only ONE of the +# two unprovable residual classes ("rows without surviving +# dead-letter evidence"), so an operator reading the OK concluded +# NO evidence exists when evidence can exist and be UNUSABLE: a +# surviving dead-letter row whose locator extracts an empty +# observed_hash (live specimen: mos-dt seq 13, +# bench/malformed-locator-test, "deliberately non-conformant") +# can never satisfy the four-field conviction match, because +# _record_last_consumed only writes rows with a NON-empty hash. +# WORDING-ONLY fix (measurement defect, #951 review finding 1): +# the clean-sweep message + the PROVABILITY BOUND comment now +# name both classes; the conviction predicate is UNCHANGED. +# Test T17 drives the real writer flow and plants the verbatim +# live specimen (nested .locators.*, NO observed_hash key) — +# never a hand-built flat dead-letter row, which would make the +# audit's correct non-conviction look exactly like the defect +# under hunt (the #951 review's false-defect near-miss). +version=0.7.1 # Watch-list schema this component consumes, and the INCLUSIVE range of # schema_version values it supports. A wake-watch-list.json whose schema_version diff --git a/packages/mosaic/framework/tools/wake/store.sh b/packages/mosaic/framework/tools/wake/store.sh index 8ab104ce..3222b789 100755 --- a/packages/mosaic/framework/tools/wake/store.sh +++ b/packages/mosaic/framework/tools/wake/store.sh @@ -563,10 +563,17 @@ cmd_quarantine_sync() { # it on (kind, id, observed_seq, observed_hash) AND row.observed_seq <= # consumed_seq: the per-key max_by merge means the surviving row's provenance IS # that quarantined entry (a healed row differs in seq/hash and never matches). -# PROVABILITY BOUND: a row whose dead-letter evidence was pruned/rotated away is -# NOT provable and is never touched — this audit only ever removes what the -# ledger can convict. The dead-letter ledger itself is history and is NEVER -# modified here. +# PROVABILITY BOUND — TWO residual classes, both unprovable (#952): (1) a row +# whose dead-letter evidence was pruned/rotated away — no evidence to convict +# on; (2) a row whose dead-letter evidence SURVIVES but extracts an empty +# observed_hash (e.g. a deliberately non-conformant locator: nested +# .locators.* with no observed_hash key) — evidence exists but can never +# satisfy the four-field match, because _record_last_consumed only ever writes +# rows with a NON-empty hash. Neither class is touched — this audit only ever +# removes what the ledger can convict, and the clean-sweep message names BOTH +# classes: "no evidence" and "evidence unusable" are different operator +# conclusions. The dead-letter ledger itself is history and is NEVER modified +# here. cmd_quarantine_audit() { local repair=0 while [ $# -gt 0 ]; do @@ -605,7 +612,7 @@ cmd_quarantine_audit() { )) | length) > 0) ' "$rec" 2>/dev/null || true)" if [ -z "$false_rows" ]; then - echo "store.sh quarantine-audit: OK — no provably-false consumed-hash rows (rows without surviving dead-letter evidence are not provable and were not judged)" + echo "store.sh quarantine-audit: OK — no provably-false consumed-hash rows. Two residual classes are unprovable and were NOT judged: rows whose dead-letter evidence was pruned/rotated away (no evidence to convict on), and rows whose surviving dead-letter evidence extracts an empty observed_hash (evidence exists but can never satisfy the four-field conviction match)." return 0 fi local n row diff --git a/packages/mosaic/framework/tools/wake/test-wake-store-ack.sh b/packages/mosaic/framework/tools/wake/test-wake-store-ack.sh index ba172035..f925fb2c 100755 --- a/packages/mosaic/framework/tools/wake/test-wake-store-ack.sh +++ b/packages/mosaic/framework/tools/wake/test-wake-store-ack.sh @@ -28,6 +28,15 @@ # T16 #946 quarantine-audit: consumed-hashes rows provably false against the # dead-letter ledger are reported (exit 1) and removed only under --repair; # healed rows and the ledger itself are untouched +# T17 #952 quarantine-audit clean sweep names BOTH unprovable residual +# classes: evidence pruned (no evidence) AND evidence surviving with an +# empty observed_hash (evidence unusable). Fixture is the VERBATIM live +# specimen (mos-dt lane dead-letter seq 13, bench/malformed-locator-test) +# — a nested .locators.* row with NO observed_hash key. Do NOT hand-build +# a FLAT dead-letter fixture here: consumed-hashes rows are genuinely +# flat, dead-letter rows are genuinely nested, and a flat fixture makes +# the audit's CORRECT non-conviction look exactly like the defect under +# hunt (this false-defect near-miss actually happened in the #951 review) # # Isolated: every test runs against a fresh WAKE_STATE_HOME temp dir. set -uo pipefail @@ -680,6 +689,50 @@ echo "== T16: #946 — quarantine-audit: a consumed-hash row matching a dead-let grep -qi 'OK' "$TMP_ROOT/t16.ok" || fail_msg "T16: a clean audit must say OK [$(cat "$TMP_ROOT/t16.ok")]" ) && ok +echo "== T17: #952 — the clean-sweep message names BOTH unprovable residual classes; a surviving-but-empty-hash dead-letter row is correctly NOT convicted ==" +( + WAKE_STATE_HOME="$(fresh_state t17)" + export WAKE_STATE_HOME + unset WAKE_AGENT + STATE_DIR="$WAKE_STATE_HOME/default" + rec="$STATE_DIR/consumed-hashes.jsonl" + dl="$STATE_DIR/dead-letter.jsonl" + # Drive the REAL flow so the consumed-hashes row is produced by the actual + # writer (_record_last_consumed), not hand-built: 12 fillers, then the bench + # key lands at observed_seq 13 — the same seq as the live specimen below. + i=1 + while [ "$i" -le 12 ]; do + "$STORE" enqueue --class actionable --locators "{\"kind\":\"filler\",\"id\":\"f$i\",\"observed_hash\":\"HF$i\"}" >/dev/null || fail_msg "T17: filler enqueue $i failed" + i=$((i + 1)) + done + "$STORE" enqueue --class actionable --locators '{"kind":"bench","id":"malformed-locator-test","observed_hash":"H-REAL-CONSUMED"}' >/dev/null + "$STORE" consume --upto 13 >/dev/null 2>&1 || fail_msg "T17: baseline consume failed" + jq_any "$rec" '.kind=="bench" and .id=="malformed-locator-test" and .observed_seq==13 and .observed_hash=="H-REAL-CONSUMED"' || + fail_msg "T17: fixture broken — the real writer did not record the bench@13 row" + # VERBATIM live specimen: mos-dt lane dead-letter.jsonl line 1 (2026-07-26). + # Copied byte-for-byte per the #952 fixture constraint — nested .locators.* + # with NO observed_hash key, so the audit's extraction yields "". + printf '%s\n' '{"observed_seq":13,"locators":{"kind":"bench","id":"malformed-locator-test","note":"deliberately non-conformant"},"class":"actionable","emit_ts":1785055610,"hmac":""}' >"$dl" + # Guard the near-miss trap: the specimen must be genuinely NESTED (no + # top-level kind) and must extract an EMPTY hash via the audit's own paths. + jq -e '(has("kind") | not) and .locators.kind=="bench" and ((.locators.observed_hash // "") == "")' "$dl" >/dev/null || + fail_msg "T17: specimen fixture is not the genuine nested shape — rebuild it from the live lane, not the schema" + # Evidence SURVIVES (kind/id/seq all match the row) but extracts hash ""; + # _record_last_consumed never writes an empty-hash row, so the four-field + # match can never fire: this is unprovable class 2, NOT a false witness. + rep="$TMP_ROOT/t17.rep" + "$STORE" quarantine-audit >"$rep" 2>&1 || fail_msg "T17: the audit must exit 0 — nothing here is provable [$(cat "$rep")]" + grep -q 'FALSE WITNESS' "$rep" && fail_msg "T17: the empty-hash evidence must NOT convict (the predicate is correct and must not change) [$(cat "$rep")]" + # The wording under test (#952): BOTH residual classes, named. + grep -qi 'pruned' "$rep" || fail_msg "T17: clean sweep must name residual class 1 — evidence pruned away [$(cat "$rep")]" + grep -qi 'empty observed_hash' "$rep" || fail_msg "T17: clean sweep must name residual class 2 — surviving evidence with an empty observed_hash [$(cat "$rep")]" + # --repair on a clean sweep removes nothing: the unprovable row survives. + "$STORE" quarantine-audit --repair >"$TMP_ROOT/t17.fix" 2>&1 || fail_msg "T17: --repair on a clean sweep must exit 0 [$(cat "$TMP_ROOT/t17.fix")]" + jq_any "$rec" '.kind=="bench" and .observed_seq==13 and .observed_hash=="H-REAL-CONSUMED"' || + fail_msg "T17: --repair must NOT remove the unprovable bench@13 row — the audit only removes what the ledger can convict" + [ "$(grep -c . "$dl")" = "1" ] || fail_msg "T17: the dead-letter LEDGER must be untouched" +) && ok + echo if [ -s "$FAILFILE" ]; then echo "wake store/ack harness: FAILED ($(grep -c . "$FAILFILE") assertion(s))" >&2 -- 2.54.0 From 119ed97920068cfb4505ea83413df764553f98e8 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 30 Jul 2026 16:39:57 -0500 Subject: [PATCH 2/3] fix(wake): #952 usage() help text also names both unprovable residual classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-caught before verdict: the quarantine-audit help text still said "Rows whose dead-letter evidence was pruned are NOT provable" — the same one-class-only wording the clean-sweep fix removes, one surface over. An operator reading --help would form the same false "no evidence exists" conclusion the runtime message no longer teaches. Same cause, same fix shape; predicate untouched. Written-by: pepper (sb-it-1-dt) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NsKce8iZuSuRnu3gVMCBKB --- packages/mosaic/framework/tools/wake/store.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/mosaic/framework/tools/wake/store.sh b/packages/mosaic/framework/tools/wake/store.sh index 3222b789..c979e5a0 100755 --- a/packages/mosaic/framework/tools/wake/store.sh +++ b/packages/mosaic/framework/tools/wake/store.sh @@ -110,9 +110,13 @@ Commands: found); --repair removes exactly those rows (atomic, loud). The dead-letter ledger itself is NEVER modified (it is - history). Rows whose dead-letter evidence - was pruned are NOT provable and are - never touched. + history). TWO residual classes are + unprovable and never touched (#952): + rows whose dead-letter evidence was + pruned away, AND rows whose surviving + evidence extracts an empty + observed_hash (it can never satisfy + the four-field conviction match). cursors Print observed_seq / consumed_seq / depth. Environment: -- 2.54.0 From f1b63bccfbff7dd3ece46616a5a353ec6025a54a Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 30 Jul 2026 17:01:23 -0500 Subject: [PATCH 3/3] docs(wake): #952 the 0.7.1 changelog entry names all THREE fix surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The entry said the fix landed in 'the clean-sweep message + the PROVABILITY BOUND comment' — two surfaces. It landed in three: usage() came in the second commit (author-side self-catch) and the entry was never updated. This PR's whole thesis is naming a set completely; its own permanent record naming 2 of 3 of its own fix surfaces would reproduce the defect it fixes. Taken as the pre-merge clause (mos-dt flagged, MOS ruled) — this is the only window the entry can be made accurate in-place under the changelog-is-history ruling. Also rides along, comment-placement-only: the 0.7.1 entry moved above component= so component=/version= sit adjacent again (the split was verified inert — _manifest_val's anchored sed cannot match a comment — but placement is free to fix in the same comment-only commit). Keys re-verified parsing: component=wake, version=0.7.1, schema 1/1. Manifest-comment-only: zero code, zero manifest key changes. Written-by: pepper (sb-it-1-dt) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NsKce8iZuSuRnu3gVMCBKB --- packages/mosaic/framework/tools/wake/manifest.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/mosaic/framework/tools/wake/manifest.txt b/packages/mosaic/framework/tools/wake/manifest.txt index 45ecf81b..557772b6 100644 --- a/packages/mosaic/framework/tools/wake/manifest.txt +++ b/packages/mosaic/framework/tools/wake/manifest.txt @@ -446,7 +446,6 @@ # reconcile.sh (+ test-wake-preimage.sh P1-P17; P13-P17 are the # #964 re-verdict regression needles: symlinked store, live # secret value, polarity, ledger deletion, allowlist-symlink). -component=wake # 0.7.1 #952 quarantine-audit clean-sweep message named only ONE of the # two unprovable residual classes ("rows without surviving # dead-letter evidence"), so an operator reading the OK concluded @@ -457,13 +456,16 @@ component=wake # can never satisfy the four-field conviction match, because # _record_last_consumed only writes rows with a NON-empty hash. # WORDING-ONLY fix (measurement defect, #951 review finding 1): -# the clean-sweep message + the PROVABILITY BOUND comment now -# name both classes; the conviction predicate is UNCHANGED. +# THREE surfaces — the clean-sweep message, the PROVABILITY +# BOUND comment, and (second commit, author-side self-catch) +# the usage() help text — now name both classes; the +# conviction predicate is UNCHANGED. # Test T17 drives the real writer flow and plants the verbatim # live specimen (nested .locators.*, NO observed_hash key) — # never a hand-built flat dead-letter row, which would make the # audit's correct non-conviction look exactly like the defect # under hunt (the #951 review's false-defect near-miss). +component=wake version=0.7.1 # Watch-list schema this component consumes, and the INCLUSIVE range of -- 2.54.0