Commit Graph

6 Commits

Author SHA1 Message Date
mosaic-coder
7603cb1c10 fix(wake): reconciler fails closed on the observed_seq dual-allocator hazard (#908)
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
Review of #909 found a blocking correctness defect: the reconciler's
"serialised => safe" claim was FACTUALLY WRONG. observed_seq has two INDEPENDENT
allocators — the detector's private counter ($STATE_DIR/detector/
observed_seq_counter, W4) and the reconciler's store-cursor+offset — so even
STRICTLY SEQUENTIAL calls collide: reconciler enumerates alpha->seq1, beta->seq2
(store observed_seq=2, detector private still 0); the detector's next delta
allocates private 0->1 and enqueues seq1, ALIASING alpha. A consumer acking
CONSUMED 1 then silently DROPS a distinct obligation — the exact G3 swallow the
reconciler exists to prevent, via seq-aliasing. Reproduced with sequential,
never-concurrent calls.

Fix (W5-scoped; full store-side allocator unification stays deferred to #908 —
detector.sh/W4 untouched):
  * Enumeration now FAILS CLOSED. Before writing any observed_seq, the reconciler
    REFUSES (loud, non-zero; the obligation is FLAGGED, never swallowed) when a
    seq it would allocate could be reissued/aliased:
      - if a detector is co-feeding this store (its private state dir exists) —
        ALWAYS refuse (read-only detection; W4 never touched);
      - else require the operator to assert reconciler-SOLE-FEEDER via
        --allow-enumerate / WAKE_RECONCILE_ALLOW_ENUMERATE=1.
    --no-enumerate and `check` never write, so they stay unconditionally safe.
  * Corrected the false "serialised => safe" rationale in the header comment to
    state the real dual-allocator hazard honestly, reference #908, and record the
    operational guard: a detector and the reconciler MUST NOT co-feed one store
    until #908 lands.
  * RED-FIRST test R9 reproduces the serialized-collision scenario (detector
    co-feeding + pre-existing state) and asserts the reconciler FAILS LOUD and
    enqueues NO aliasable seq (depth unchanged). Verified red: removing the guard
    re-enables the collision (R9 depth 0->2) and turns R9 red.

R5/R6 now enumerate under an explicit sole-feeder assertion (no detector
co-feeds those stores). test:framework-shell + shellcheck + firewall all green.

Part of #892

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
2026-07-25 20:52:45 -05:00
mosaic-coder
60efd6a01e feat(wake): W5 — synthetic-canary FN-oracle + source-parity reconciler
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
Adds A6 (fn-oracle.sh) and A7 (reconcile.sh) of the wake/heartbeat canon
(EPIC #892, W5), building on merged W2/W3/W4 via their public APIs only
(store.sh/ack.sh/detector.sh untouched).

A6 fn-oracle.sh — synthetic-canary FN-oracle (§4 vector: FN-rate=0; §7 res5).
  Injects a KNOWN delta at the SOURCE boundary, drives the pipeline through the
  detector's public poll-once (a black box), and renders its verdict SOLELY from
  the terminal store cursor (did a CONSUMED ack cover the canary's observed_seq
  within the per-class SLO?). Off-domain / detector-independent: it never reads a
  detector hash-file or self-report, so a detector that silently DROPS changes —
  including a fully-disabled one at a perfect 0-wake rate — FAILS the oracle
  (the §4/A8 false-negative-blindspot killer). Runs in its own isolated XDG
  namespace, never the operator's live queue. No invented SLO (design law):
  --slo-seconds is required.

A7 reconcile.sh — source-parity reconciler (§4/G3).
  (i) source-coverage PARITY INVENTORY first: a declared source not covered by
      any watch, a dangling reference, an empty lane, or a required_sources
      omission FLAGS — an omitted source cannot make the §4 vector pass
      vacuously (not silently green).
  (ii) periodic full reconcile: enumerate each covered source's current state vs
      observed_seq/inbox => 0 unaccounted; any gap FLAGS. Handles the W4-ratified
      division (detector first-seen-baseline does NOT wake) by ENUMERATING
      pre-existing/startup state into the durable store; inbox-reflected state is
      accounted (no double-enumeration). Fail-loud (G2a) on adapter error.

RED-FIRST tests (wired into test:framework-shell), shellcheck clean:
  test-wake-fn-oracle.sh   O1 healthy FN-rate=0; O2 disabled detector -> FN-DETECTED
    at perfect no-op; O3 CONSUMED-but-late -> FN; O4 off-domain verdict; O5 SLO required.
  test-wake-reconcile.sh   R1 complete inventory; R2 omitted-source vacuous-pass
    prevented; R3 required_sources omission; R4 dangling; R5/R6 pre-existing ->
    flagged + enumerated -> re-run 0; R7 inbox-accounted no-double; R8 G2a fail-loud.

manifest.txt version 0.3.0 -> 0.4.0 + inventory (schema range untouched).
Operator-agnostic (XDG/env only; no operator paths/names/hosts/secrets).

Part of #892

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
2026-07-25 20:29:33 -05:00
5df47e735e feat(wake): W4 — per-host delta-gated detector daemon (fail-loud source semantics, enqueues to W2 store) (#907)
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
2026-07-26 01:04:55 +00:00
dd1391fd76 fix(wake): digest hard-locator gate covers top-level .claim entries (Closes #905) (#906)
Some checks failed
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was canceled
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
2026-07-26 00:58:40 +00:00
10d957d095 feat(wake): W3 — cumulative-state digest renderer + non-circular HMAC signer (#904)
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
2026-07-26 00:32:12 +00:00
28f022d9c0 feat(wake): W2 — three-cursor durable store + RECEIVED/CONSUMED ack-wrapper + watch-list schema (#903)
Some checks failed
ci/woodpecker/push/publish Pipeline was canceled
ci/woodpecker/push/ci Pipeline was canceled
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
2026-07-25 23:58:08 +00:00