Closes #946. The digest omitted a quarantined entry's claim from disclosure while still advancing the ack watermark it instructed the consumer to run — converting a fail-safe HOLD into a silent DISCARD, through the documented normal path. Measured: the burial instruction was re-issued FIVE times, four fresh digests plus one system-initiated redelivery fired purely because the entry had gone unconsumed for 1826s. That redelivery is the proof of the 'indefinitely' half: the mechanism re-asserted itself with no new information. SCOPE — this was NOT a missing check in the consume path. Measured before the fix: dead-letter occurrences were digest.sh 27, store.sh 0, ack.sh 0, detector.sh 0, reconcile.sh 0. Quarantine was owned ENTIRELY by the renderer; the store that advances the watermark had zero knowledge the ledger existed, so an entry could be quarantined by one subsystem and consumed by another with no possible interaction. The fix is therefore a deliberate cross-module decision — option (b), quarantine recorded into a store-owned file, preserving the existing direction of dependency — pre-registered by the consumer before any diff existed. VERIFICATION - Pipeline 2107 terminal SUCCESS ate11bc6622, read clone-inclusive from the provider API rather than through `pipeline-status.sh` (which filters `.type != "clone"` per workflow and would hide a clone failure behind an all-green table): 9/9 children success, exit 0 each, no non-success member. Its `test` step runs all nine wake harnesses via turbo -> packages/mosaic `test` -> `test:framework-shell`. - Independent review by the consumer on the affected lane: eleven pre-registered acceptance checks, authored and delivered BEFORE the diff was read — the file list deliberately unlooked-at, because a filename alone would have disclosed which option was chosen. All eleven resolved, no blocker. - The check that decides it: a RAW `ack.sh consumed --upto N` with no digest involved must refuse to advance past a quarantined seq — the case an agent hits when a digest is MISSED, and the one that would have sunk a disclosure-only fix. Covered at the head as a named assertion (T13 ordinary-path bypass), written independently of the reviewer's list. - Mutation: one asserted site disabled -> TWELVE assertions die, every one BEHAVIOURAL, ZERO count assertions, including one killing across the module boundary the fix spans. - RED control at basea6b5f6a: 34 and 10 assertions fail, matching the body exactly. - Coordinator re-verify by a different instrument than the reviewer used: static reference counts across the base/head boundary — store.sh 0 -> 49, ack.sh 0 -> 6, `--agent` unchanged at 4 (so #949 correctly stayed out). A fix present-but-inert passes the count and fails the mutation; a fix behaviourally correct but smuggling #949 passes the mutation and fails the count. Neither result is reachable by repeating the other. KNOWN RESIDUALS - The `consumed-hashes` repair criterion is met only for keys that RE-EMIT. A corrupted row whose key never recurs stays false indefinitely; the sweep covers those, and the known-false row named in the acceptance criteria had already self-healed by re-emission rather than by design — safe by population, not by design. - The audit's clean-sweep message names one unprovable class; a second exists (a surviving dead-letter row with an empty `observed_hash` cannot be convicted either). Wording, not logic. Filed separately. - The audit's provability bound makes dead-letter RETENTION load-bearing for auditability. Nothing prunes it today, so this is latent — but any future rotation or size cap silently converts provable rows into unprovable ones with no signal at either end. This is not a defect; it is a property that BECAME load-bearing and is recorded nowhere. Filed separately. - `test-wake-detector.sh` D4 fails at this head AND identically at base, with an empty diff over detector files — pre-existing, tracked, not introduced here. Authored by pepper (sb-it-1-dt); reviewed independently by mos-dt (sb-it-1-dt). The mos-dt-0 commit and fork identity does not identify the author — attribution collapse tracked separately. Co-authored-by: mos-dt-0 <[email protected]>
This commit was merged in pull request #951.
This commit is contained in:
@@ -112,6 +112,14 @@ Exit codes:
|
||||
diagnostic (#924/G2a) — it never wedges the whole render either.
|
||||
Reconciler enumerations (locators.reconciled==true) render ORIENTATION-tier,
|
||||
gate-exempt.
|
||||
#946: quarantined entries are DISCLOSED in a QUARANTINED section (by
|
||||
seq/class only — content stays excluded) and the embedded ack copy-run
|
||||
line is CLAMPED below the lowest quarantined seq (the digest never
|
||||
instructs the consumer to record a delivery that never happened; the
|
||||
clamp is announced as an ACK CLAMPED note). A store-mode render also
|
||||
REPLACES the store's quarantined.set (store.sh quarantine-sync) so the
|
||||
consume path enforces the same clamp; --from-file/--stdin renders never
|
||||
touch the set.
|
||||
2 usage error.
|
||||
3 jq is required but missing.
|
||||
|
||||
@@ -544,7 +552,7 @@ cmd_render() {
|
||||
# #920 head-of-line-blocking defect that exit-4'd the entire cumulative-state
|
||||
# drain). Reconciler enumerations (locators.reconciled==true) are ORIENTATION-
|
||||
# tier and gate-exempt, so they pass straight through to the deliverable set.
|
||||
local line loc seq pending_ok='' quarantined=0
|
||||
local line loc seq pending_ok='' quarantined=0 q_seqs='' q_disclose=''
|
||||
while IFS= read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
printf '%s' "$line" | jq -e . >/dev/null 2>&1 || continue
|
||||
@@ -554,6 +562,17 @@ cmd_render() {
|
||||
seq="$(jq -r '.observed_seq // "?"' <<<"$line")"
|
||||
_quarantine_entry "$line" "$seq"
|
||||
quarantined=$((quarantined + 1))
|
||||
# #946: collect the quarantined identity for DISCLOSURE + the ack
|
||||
# CLAMP. Disclosure is by durable identity (observed_seq) + class ONLY:
|
||||
# this entry failed the locator gate, so its content is exactly what
|
||||
# this digest refuses to re-inject (the exclusion property Q1/Q4
|
||||
# assert) — the consumer re-verifies via the dead-letter ledger, never
|
||||
# via this line.
|
||||
case "$seq" in
|
||||
'' | *[!0-9]*) : ;; # an unnumbered entry cannot clamp the numeric cursor
|
||||
*) q_seqs="$q_seqs$seq"$'\n' ;;
|
||||
esac
|
||||
q_disclose="$q_disclose * seq $seq [$(_scrub_inline "$(jq -r '.class // "actionable"' <<<"$line")")] HELD — dead-lettered (no §2.1 hard locator); content withheld, NOT delivered."$'\n'
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
@@ -563,6 +582,33 @@ cmd_render() {
|
||||
pending="$(printf '%s' "$pending_ok" | grep -v '^[[:space:]]*$' || true)"
|
||||
depth="$(printf '%s\n' "$pending" | grep -c . || true)"
|
||||
|
||||
# --- #946: quarantine truth-sync + ack clamp ------------------------------
|
||||
# (1) SYNC: an AUTHORITATIVE full-set render (src=store) REPLACES the store's
|
||||
# quarantined.set with THIS render's quarantined seqs (possibly none — an
|
||||
# empty replace IS the #944 recovery: once the gate is fixed and everything
|
||||
# renders, the stale set clears and the store-side clamp self-heals). A
|
||||
# foreign-data render (--from-file/--stdin) must NEVER rewrite lane truth.
|
||||
if [ "$src" = "store" ]; then
|
||||
if ! printf '%s' "$q_seqs" | "$STORE_SH" quarantine-sync; then
|
||||
echo "digest.sh: WARN (#946) — store.sh quarantine-sync FAILED; the store-side consume clamp may be stale for this lane (the clamped ack line rendered below is still correct)." >&2
|
||||
fi
|
||||
fi
|
||||
# (2) CLAMP: the embedded ack may advance AT MOST to just below the LOWEST
|
||||
# quarantined seq — consume requires a contiguous prefix, so one held seq
|
||||
# caps everything above it. With nothing quarantined this is the observed
|
||||
# cursor unchanged. Render-local on purpose: it protects the copy-run line in
|
||||
# EVERY mode, including hermetic --from-file renders.
|
||||
local ack_upto="$observed" min_q='' qs q_list=''
|
||||
while IFS= read -r qs; do
|
||||
[ -n "$qs" ] || continue
|
||||
if [ -z "$min_q" ] || [ "$qs" -lt "$min_q" ]; then min_q="$qs"; fi
|
||||
done <<<"$q_seqs"
|
||||
if [ -n "$min_q" ] && [ "$((min_q - 1))" -lt "$ack_upto" ]; then
|
||||
ack_upto=$((min_q - 1))
|
||||
fi
|
||||
[ "$ack_upto" -ge 0 ] || ack_upto=0
|
||||
q_list="$(printf '%s' "$q_seqs" | tr '\n' ' ' | sed -e 's/[[:space:]]*$//')"
|
||||
|
||||
# --- render (all validated) ----------------------------------------------
|
||||
local n_actionable=0
|
||||
{
|
||||
@@ -656,6 +702,16 @@ cmd_render() {
|
||||
printf '%s\n' "$hbody"
|
||||
fi
|
||||
|
||||
# #946: QUARANTINED disclosure — a held entry must be VISIBLE in the digest
|
||||
# it was held from (five successive live digests each silently stepped the
|
||||
# consumer past buried seq 68). Disclosure is by seq/class ONLY; the
|
||||
# entry's content already failed the locator gate and stays EXCLUDED.
|
||||
if [ -n "$q_disclose" ]; then
|
||||
printf '\n-- QUARANTINED (dead-lettered; HELD — NOT delivered; the ack below does NOT cover these) --\n'
|
||||
printf '%s' "$q_disclose"
|
||||
printf ' disposition: see %s/dead-letter.jsonl — fix the source locator (re-delivery is automatic once the entry passes the gate), or step past EXPLICITLY with ack.sh consumed --force-past-quarantine.\n' "$STATE_DIR"
|
||||
fi
|
||||
|
||||
# Embedded ack copy-run line (W2). CONSUMED is a consumer act; this is the
|
||||
# exact local-write line the consumer runs after durable capture.
|
||||
#
|
||||
@@ -670,12 +726,19 @@ cmd_render() {
|
||||
# itself was env-less (agent=="default"), baking "default" is no worse than
|
||||
# today — the fix wins the common case where WAKE_AGENT was set at render.
|
||||
printf '\n-- ACK (copy-run; local-write only, never blocks on network) --\n'
|
||||
# #946: the embedded --upto is the CLAMPED cursor (ack_upto), never the raw
|
||||
# observed cursor while a quarantined seq sits inside (consumed, observed] —
|
||||
# the copy-run line itself must not instruct the consumer to record
|
||||
# deliveries that never happened. The clamp is disclosed loudly.
|
||||
if [ "$ack_upto" -ne "$observed" ]; then
|
||||
printf '# ACK CLAMPED (#946): embedding --upto %s, not observed_seq %s — quarantined seq(s) %s were dead-lettered and NEVER delivered; an ordinary ack cannot step past them. Only ack.sh consumed ... --force-past-quarantine (loud) can.\n' "$ack_upto" "$observed" "$q_list"
|
||||
fi
|
||||
local ack_line agent_scrubbed
|
||||
agent_scrubbed="$(_scrub_inline "$agent")"
|
||||
if [ -n "$wake_id" ]; then
|
||||
ack_line="$("$ACK_SH" embed --upto "$observed" --agent "$agent_scrubbed" --wake-id "$wake_id" 2>/dev/null || true)"
|
||||
ack_line="$("$ACK_SH" embed --upto "$ack_upto" --agent "$agent_scrubbed" --wake-id "$wake_id" 2>/dev/null || true)"
|
||||
else
|
||||
ack_line="$("$ACK_SH" embed --upto "$observed" --agent "$agent_scrubbed" 2>/dev/null || true)"
|
||||
ack_line="$("$ACK_SH" embed --upto "$ack_upto" --agent "$agent_scrubbed" 2>/dev/null || true)"
|
||||
fi
|
||||
printf '%s\n' "${ack_line:-# ack unavailable}"
|
||||
} | _redact_secrets
|
||||
|
||||
Reference in New Issue
Block a user