fix(wake): #932 stop reconciler re-enumerating already-CONSUMED detector state
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
Wake-pilot finding #7 (safe-but-noisy G2a alarm-hygiene): after consume-truncation a consumed detector-observed state matched NO accounting record — the inbox was truncated, the reconciler's seen-ledger only covers its OWN enumerations, and the detector hash-file is correctly DISTRUSTED — so the reconciler treated it as UNACCOUNTED and re-enumerated it: one DUPLICATE orientation wake + one SPURIOUS rc=1 CRITICAL per detector-active window per cycle (functionally safe, no lost obligation, but cry-wolf erosion at fleet scale). Fix (Mos ruling, built exactly): 1. store.sh records the last-consumed observed_hash per (kind,id) at consume-truncation into a NEW store-owned durable record consumed-hashes.jsonl (atomic write; ADDITIVE — existing on-disk format unchanged/read-compatible; #908 allocator untouched). 2. reconcile.sh adds a THIRD accounting source alongside the inbox and its seen-ledger: a detector-observed state whose observed_hash MATCHES the store's recorded last-consumed hash for that (kind,id) is ACCOUNTED — not re-enumerated (no dup wake, no spurious CRITICAL). 3. Trust boundary (load-bearing): the 3rd check consults ONLY the store-written record. Its existence implies the state was durably enqueued+consumed, so it structurally cannot exhibit the §5 hash-advance-without-enqueue swallow signature. Trusting DETECTOR hash-files STAYS REJECTED. 4. G3 not weakened: only states the store RECORDED as consumed are suppressed. A genuinely-unaccounted state (enqueued-but-unconsumed, still in the inbox, OR a real gap) still re-enumerates + alarms. Red-first tests: - store-ack T12: consume writes the store-owned last-consumed record (per-(kind,id), monotonic last-seq wins, lazily created). - reconcile R10: a consumed state is ACCOUNTED (rc=0, UNACCOUNTED=0, no re-enumeration). - reconcile R11: pilot repro — consumed state SUPPRESSED while a distinct unconsumed/gap state STILL re-enumerates (G3 teeth intact; no over-suppression). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
This commit is contained in:
@@ -36,6 +36,12 @@ wake_state_dir() {
|
||||
# {observed_seq, locators, class, emit_ts, hmac}.
|
||||
# ack-ledger.jsonl — local-write-only ack ledger (RECEIVED / CONSUMED).
|
||||
# ack-sync.state — background-sync bookkeeping (last shipped / outage flag).
|
||||
# consumed-hashes.jsonl — #932 store-owned last-consumed record: one object per
|
||||
# (kind,id), {kind,id,observed_hash,observed_seq}, written at
|
||||
# consume-truncation. The reconciler's THIRD accounting source
|
||||
# (a consumed state matches neither the truncated inbox nor the
|
||||
# reconciler's own seen-ledger). ADDITIVE / lazily created;
|
||||
# older code ignores it (on-disk read-compat preserved).
|
||||
|
||||
# _wake_tmp_glob DIR — the glob used for atomic-write temp files, so readers can
|
||||
# ignore in-flight/crashed writes. A crash leaves one of these; it is NEVER the
|
||||
|
||||
Reference in New Issue
Block a user