feat(wake): W5 — synthetic-canary FN-oracle + source-parity reconciler #909

Merged
Mos merged 2 commits from feat/wake-fn-oracle-reconciler into main 2026-07-26 02:04:21 +00:00
Owner

Implements W5 of the wake/heartbeat canon (EPIC #892): the FN-oracle (A6) and the source-parity reconciler (A7), building on merged W2/W3/W4. Calls their PUBLIC APIs only — store.sh / ack.sh / detector.sh are untouched.

A6 — fn-oracle.sh (synthetic-canary) → §4 vector { synthetic-canary FN-rate = 0 }, §7 residual 5

  • Injects a KNOWN synthetic-canary 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? It measures the false-negative rate; §4 requires FN-rate = 0.
  • Off-domain / detector-independent (the §4/A8 false-negative-blindspot killer): the injection and the CONSUMED-assertion never read a detector hash-file, poll counter, or self-report. A detector that silently DROPS changes — including a fully-disabled detector at a "perfect" 0-wake rate — therefore FAILS the oracle. The success metric is a vector, not a wake-count.
  • 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, §7 residual 5

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

Blocking-defect fix (review 5a): observed_seq dual-allocator — now FAILS CLOSED

The first revision claimed the observed_seq collision risk was bounded because "reconcile and poll are serialised." That was factually wrong — reproduced with strictly sequential, never-concurrent calls. 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. The detector's next seq is private_counter+1, not store_observed_seq+1, so serializing does not prevent collision: after the 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, via seq-aliasing.

Fix (W5-scoped; full store-side allocator unification deferred to #908; detector.sh/W4 untouched): the reconciler's enumeration fails closed. Before writing any observed_seq it refuses (loud, non-zero; the obligation is FLAGGED, never swallowed) whenever 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 mode via --allow-enumerate / WAKE_RECONCILE_ALLOW_ENUMERATE=1.

--no-enumerate and check never write, so they stay unconditionally safe. Operational guard (until #908): a detector and the reconciler MUST NOT co-feed one store.

Red-first evidence (each test goes RED if its invariant regresses)

Wired into test:framework-shell; shellcheck clean; full suite green (exit 0).

test-wake-fn-oracle.sh — O1 healthy → FN-rate 0; O2 disabled detector (perfect no-op) → FN-DETECTED; O3 CONSUMED-but-late → FN; O4 off-domain verdict; O5 no invented SLO → fail-loud. (Demonstrated red: blinding the oracle turns O2/O3/O4 red.)

test-wake-reconcile.sh — R1 complete inventory; R2 omitted source → FLAG (vacuous-pass prevented); R3 required_sources omission; R4 dangling; R5/R6 pre-existing state → flagged + enumerated (sole-feeder) → re-run 0; R7 inbox-accounted (no double-enumerate); R8 adapter error → FAIL LOUD (G2a); R9 serialized dual-allocator collision → reconciler FAILS LOUD, enqueues no aliasable seq (depth unchanged). (Demonstrated red: removing the guard re-enables the collision — R9 depth 0→2 — and turns R9 red.)

Discipline

  • manifest.txt 0.3.0 → 0.4.0 + inventory; schema range untouched.
  • Operator-agnostic: XDG/env only; no operator paths/names/hosts/secrets. grep -niE 'jason|woltje|jarvis' = 0.
  • Out of scope: off-host beacon (W6), installer (W7).

Contract notes (flagged, not guessed)

  1. observed_seq dual-allocator → fail-closed (above); #908 tracks the store-side allocator unification that makes detector+reconciler co-feeding safe. Until then the reconciler refuses rather than aliasing.
  2. "Accounted" universe = observed_seq/inbox (per §4/G3 wording) + the reconciler's own durable reconciled-state ledger — deliberately not the detector's hash-file, so a silent first-seen baseline cannot swallow a pre-existing obligation. Consequence: a source consumed before the reconciler ever recorded it is enumerated once as a fail-safe backstop (in sole-feeder mode), then quiet.

Part of #892

Implements **W5** of the wake/heartbeat canon (EPIC #892): the FN-oracle (A6) and the source-parity reconciler (A7), building on merged W2/W3/W4. Calls their PUBLIC APIs only — `store.sh` / `ack.sh` / `detector.sh` are untouched. ## A6 — `fn-oracle.sh` (synthetic-canary) → §4 vector `{ synthetic-canary FN-rate = 0 }`, §7 residual 5 - Injects a **KNOWN** synthetic-canary 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**? It measures the false-negative rate; **§4 requires FN-rate = 0**. - **Off-domain / detector-independent (the §4/A8 false-negative-blindspot killer):** the injection and the CONSUMED-assertion never read a detector hash-file, poll counter, or self-report. A detector that silently **DROPS** changes — **including a fully-disabled detector at a "perfect" 0-wake rate** — therefore **FAILS** the oracle. The success metric is a vector, not a wake-count. - 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, §7 residual 5 - **(i) source-coverage PARITY INVENTORY first (§4-G3-i):** a declared source **not covered by any watch** (an omitted source), a **dangling** reference, an **empty lane**, or a `required_sources` omission **FLAGS** — an omitted source **cannot make the §4 vector pass vacuously**, never silently green. - **(ii) periodic full reconcile (§4-G3-ii):** enumerate each covered source's current state vs `observed_seq`/inbox → **0 unaccounted**; any gap FLAGS. **Handles pre-existing/startup obligations** per the W4-ratified division (the detector's first-seen-baseline does **not** wake) by **enumerating** pre-existing state into the durable store; inbox-reflected state is accounted (no double-enumeration). Fail-loud (**G2a**) on adapter error / ambiguous-empty. ## Blocking-defect fix (review 5a): observed_seq dual-allocator — now FAILS CLOSED The first revision claimed the `observed_seq` collision risk was bounded because "reconcile and poll are serialised." **That was factually wrong** — reproduced with strictly sequential, never-concurrent calls. `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**. The detector's next seq is `private_counter+1`, **not** `store_observed_seq+1`, so serializing does not prevent collision: after the 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, via seq-aliasing. **Fix (W5-scoped; full store-side allocator unification deferred to #908; detector.sh/W4 untouched):** the reconciler's enumeration **fails closed**. Before writing any `observed_seq` it **refuses** (loud, non-zero; the obligation is **FLAGGED, never swallowed**) whenever 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** mode via `--allow-enumerate` / `WAKE_RECONCILE_ALLOW_ENUMERATE=1`. `--no-enumerate` and `check` never write, so they stay unconditionally safe. **Operational guard (until #908):** a detector and the reconciler MUST NOT co-feed one store. ## Red-first evidence (each test goes RED if its invariant regresses) Wired into `test:framework-shell`; shellcheck clean; full suite green (exit 0). **`test-wake-fn-oracle.sh`** — O1 healthy → FN-rate 0; **O2 disabled detector (perfect no-op) → FN-DETECTED**; O3 CONSUMED-but-late → FN; O4 off-domain verdict; O5 no invented SLO → fail-loud. (Demonstrated red: blinding the oracle turns O2/O3/O4 red.) **`test-wake-reconcile.sh`** — R1 complete inventory; **R2 omitted source → FLAG (vacuous-pass prevented)**; R3 `required_sources` omission; R4 dangling; **R5/R6 pre-existing state → flagged + enumerated (sole-feeder) → re-run 0**; R7 inbox-accounted (no double-enumerate); R8 adapter error → FAIL LOUD (G2a); **R9 serialized dual-allocator collision → reconciler FAILS LOUD, enqueues no aliasable seq (depth unchanged)**. (Demonstrated red: removing the guard re-enables the collision — R9 depth `0→2` — and turns R9 red.) ## Discipline - `manifest.txt` `0.3.0 → 0.4.0` + inventory; **schema range untouched**. - Operator-agnostic: XDG/env only; no operator paths/names/hosts/secrets. `grep -niE 'jason|woltje|jarvis'` = 0. - Out of scope: off-host beacon (W6), installer (W7). ## Contract notes (flagged, not guessed) 1. **observed_seq dual-allocator → fail-closed (above); #908** tracks the store-side allocator unification that makes detector+reconciler co-feeding safe. Until then the reconciler refuses rather than aliasing. 2. **"Accounted" universe** = `observed_seq`/inbox (per §4/G3 wording) + the reconciler's own durable reconciled-state ledger — deliberately **not** the detector's hash-file, so a silent first-seen baseline cannot swallow a pre-existing obligation. Consequence: a source consumed before the reconciler ever recorded it is enumerated once as a fail-safe backstop (in sole-feeder mode), then quiet. Part of #892
jason.woltje added 1 commit 2026-07-26 01:30:15 +00:00
feat(wake): W5 — synthetic-canary FN-oracle + source-parity reconciler
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
60efd6a01e
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
jason.woltje added 1 commit 2026-07-26 01:52:50 +00:00
fix(wake): reconciler fails closed on the observed_seq dual-allocator hazard (#908)
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
7603cb1c10
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
Author
Owner

Record of Review — PR #909 W5 (FN-oracle + reconciler) — POST-5a-FIX, full-40, supersedes prior

VERDICT: APPROVE (GO on CI terminal-green). Reviewer: independent subagent af4d2541 (opus, per §4/G3/§7) — the SAME reviewer that FOUND the 5a defect, confirming the fix. ≠ builder (mosaic-coder).
REVIEWED-HEAD (full-40): 7603cb1c10525fcd6cc5a6b582334cc66ec349e2.

Original review (head 60efd6a0): 7/8 PASS, 1 BLOCKING (5a)

FN-oracle OFF-DOMAIN (disabled detector at 0-wake → FN-DETECTED, the §4/A8 killer), parity inventory (no vacuous pass), reconcile-0-unaccounted, pre-existing enumeration, accounted-universe=observed_seq/inbox/ledger-not-detector-hash (G3-correct), store-API discipline, red-first O1-O5/R1-R8, gates — all PASS. Blocking: 5a observed_seq seq-aliasing swallow.

5a fix — delta re-review PASS (defect GENUINELY closed, verified not masked)

  1. Scope — diff 60efd6a0→7603cb1c = ONLY reconcile.sh (+97/-16) + test (+44); fn-oracle/store/detector/manifest/package.json BYTE-UNCHANGED → prior 7/8 carries.
  2. ★ Swallow closed — reconciler now FAILS CLOSED on the observed_seq write path: detector co-feeding detected read-only via $STATE_DIR/detector (detector.sh mkdir -p on ANY poll incl silent baseline → always caught; W4 untouched) → REFUSE enumerate (obligation FLAGGED never swallowed, depth stays 0 = no aliasable seq); --allow-enumerate overridden to still-refuse when a detector is present; sole-feeder write path runs only when ONE allocator exists (aliasing impossible). Reviewer RE-RAN its alpha/beta repro at the new head → FAIL LOUD, depth 0 (was 0→2); stripping the guard brings the collision back (load-bearing, not cosmetic). R9 regression encodes the repro; R5/R6 assert the enumerate path stays covered. Residual (operator asserts sole-feeder then launches a detector) = documented operator-contract breach, fail-closed by default, deferred to #908.
  3. Rationale corrected — false "serialised⇒safe" retracted in code header + PR body; honest dual-allocator hazard + #908 (3×) + operational guard (detector+reconciler MUST NOT co-feed one store til #908) stated.
  4. Gates — R 8/8 + all wake harnesses green; shellcheck/firewall/verify-sanitized clean; mergeable; body Part of #892.
    GO for id-11 + merge at FULL-40 7603cb1c10525fcd6cc5a6b582334cc66ec349e2 on CI terminal-green. #908 tracks the full store-side allocator unification (reachable, pre-pilot). Non-executor.
# Record of Review — PR #909 W5 (FN-oracle + reconciler) — POST-5a-FIX, full-40, supersedes prior **VERDICT: APPROVE** (GO on CI terminal-green). **Reviewer:** independent subagent `af4d2541` (opus, per §4/G3/§7) — the SAME reviewer that FOUND the 5a defect, confirming the fix. ≠ builder (`mosaic-coder`). **REVIEWED-HEAD (full-40):** `7603cb1c10525fcd6cc5a6b582334cc66ec349e2`. ## Original review (head 60efd6a0): 7/8 PASS, 1 BLOCKING (5a) FN-oracle OFF-DOMAIN (disabled detector at 0-wake → FN-DETECTED, the §4/A8 killer), parity inventory (no vacuous pass), reconcile-0-unaccounted, pre-existing enumeration, accounted-universe=observed_seq/inbox/ledger-not-detector-hash (G3-correct), store-API discipline, red-first O1-O5/R1-R8, gates — all PASS. Blocking: 5a observed_seq seq-aliasing swallow. ## 5a fix — delta re-review PASS (defect GENUINELY closed, verified not masked) 1. **Scope** — diff 60efd6a0→7603cb1c = ONLY reconcile.sh (+97/-16) + test (+44); fn-oracle/store/detector/manifest/package.json BYTE-UNCHANGED → prior 7/8 carries. 2. **★ Swallow closed** — reconciler now FAILS CLOSED on the observed_seq write path: detector co-feeding detected read-only via `$STATE_DIR/detector` (detector.sh mkdir -p on ANY poll incl silent baseline → always caught; W4 untouched) → REFUSE enumerate (obligation FLAGGED never swallowed, depth stays 0 = no aliasable seq); `--allow-enumerate` overridden to still-refuse when a detector is present; sole-feeder write path runs only when ONE allocator exists (aliasing impossible). Reviewer RE-RAN its alpha/beta repro at the new head → FAIL LOUD, depth 0 (was 0→2); stripping the guard brings the collision back (load-bearing, not cosmetic). R9 regression encodes the repro; R5/R6 assert the enumerate path stays covered. Residual (operator asserts sole-feeder then launches a detector) = documented operator-contract breach, fail-closed by default, deferred to #908. 3. **Rationale corrected** — false "serialised⇒safe" retracted in code header + PR body; honest dual-allocator hazard + #908 (3×) + operational guard (detector+reconciler MUST NOT co-feed one store til #908) stated. 4. **Gates** — R 8/8 + all wake harnesses green; shellcheck/firewall/verify-sanitized clean; mergeable; body Part of #892. **GO for id-11 + merge at FULL-40 `7603cb1c10525fcd6cc5a6b582334cc66ec349e2` on CI terminal-green. #908 tracks the full store-side allocator unification (reachable, pre-pilot). Non-executor.**
Mos approved these changes 2026-07-26 02:04:18 +00:00
Mos left a comment
First-time contributor

GO — Gate-16 id-11 stamp, pinned to exact FULL head 7603cb1c10.
Basis: verbatim RoRs — substance review 7/8 carried (fn-oracle/store/detector byte-unchanged) + the finder's delta re-review APPROVE (RoR 18953) at the fix head: the seq-aliasing swallow it discovered is verified GENUINELY CLOSED, not masked — reviewer re-ran its own alpha/beta repro (store depth stays 0, was 0→2), proved the guard load-bearing by mutation (R9), and validated the co-feed detection + sole-feeder gate. Reconciler now fails closed (flags, never swallows; refuses seq allocation under any collision possibility). #908 carries the full store-side allocator unification (reachable, pre-co-feed bound, per Mos re-scope). CI terminal-green. W5 of EPIC #892: FN-oracle (off-domain black-box canary — the false-negative blindspot killer) + parity/reconciler. Named executor: Mos (id-11), squash pinned.

GO — Gate-16 id-11 stamp, pinned to exact FULL head 7603cb1c10525fcd6cc5a6b582334cc66ec349e2. Basis: verbatim RoRs — substance review 7/8 carried (fn-oracle/store/detector byte-unchanged) + the finder's delta re-review APPROVE (RoR 18953) at the fix head: the seq-aliasing swallow it discovered is verified GENUINELY CLOSED, not masked — reviewer re-ran its own alpha/beta repro (store depth stays 0, was 0→2), proved the guard load-bearing by mutation (R9), and validated the co-feed detection + sole-feeder gate. Reconciler now fails closed (flags, never swallows; refuses seq allocation under any collision possibility). #908 carries the full store-side allocator unification (reachable, pre-co-feed bound, per Mos re-scope). CI terminal-green. W5 of EPIC #892: FN-oracle (off-domain black-box canary — the false-negative blindspot killer) + parity/reconciler. Named executor: Mos (id-11), squash pinned.
Mos merged commit 320f5bfb6f into main 2026-07-26 02:04:21 +00:00
Mos deleted branch feat/wake-fn-oracle-reconciler 2026-07-26 02:04:21 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#909