feat(wake): W2 — three-cursor durable store + RECEIVED/CONSUMED ack-wrapper + watch-list schema #903

Merged
Mos merged 2 commits from feat/wake-store-ack-schema into main 2026-07-25 23:58:08 +00:00
Owner

Implements W2 of the wake/heartbeat canon (EPIC #892) — the durable-queue "heart" — honoring the CONVERGED-DESIGN contracts exactly.

Piece → contract map

A2 store.sh — three-cursor durable store + drain lib

  • §1.2 three-cursor data-flow. observed_seq (detector-assigned monotonic int; this lib records/stores it) is the authoritative cursor; the durable pending-inbox retains until CONSUMED; consumed_seq advances over a contiguous prefix.
  • §2.4 cursor semantics. observed_seq is authoritative; source SHAs are descriptors, not the cursor. consumed_seq NEVER advances on enqueue / sender exit-0 / pane-paste — only on a consumer CONSUMED ack.
  • §2.3 classes & durability. class=digest REPLACES the pending cumulative-state entry (newest subsumes prior); actionable/human APPEND (never replaced). ALL classes land in the durable store — durability is never bypassed. Absent class ⇒ treated as actionable (fail-safe).
  • Durable entry = {observed_seq, locators, class, emit_ts, hmac}; hmac is an unsigned placeholder (HMAC signing is W3/A5, out of W2 scope).
  • drain returns the deliverable set (WHAT to deliver; actual paste via existing send-message.sh is out of scope), gated on an optional idle predicate.
  • Every state mutation is atomic write-tmp+rename (write temp in-dir → mv rename); all state under XDG (${XDG_STATE_HOME:-$HOME/.local/state}/mosaic/wake/).

A4 ack.sh — RECEIVED / CONSUMED ack-wrapper (§2.2)

  • RECEIVED records delivery; wake_id dedups DELIVERY only (dup delivery = re-RECEIVE, never re-action); never advances consumed_seq.
  • CONSUMED N is LOCAL-WRITE-ONLY to the XDG ledger, cumulative, and enforces the contiguous gapless prefix (rejects ack N while N-1 is unconsumed). A background sync ships the ack — the ack path never blocks on the network; the sync runs once and records an outage marker (no retry spam).
  • embed emits the one copy-run line meant to be embedded in each digest.

Watch-list SCHEMA contract + Gate B manifest

  • framework/defaults/wake-watch-list.schema.json — repos, board files, lane anchors, per-class SLOs, source-parity watches inventory; SCHEMA only (operator supplies values), with schema_version.
  • framework/tools/wake/manifest.txt — component semver + supported schema range (schema_min/schema_max) as Gate B. It is VERSION metadata only; path-ownership stays with framework-manifest.txt (Gate A) — the new paths are already framework-owned via the existing tools/** and defaults/** globs, so no ownership edit was needed.

RED-first evidence

Harness framework/tools/wake/test-wake-store-ack.sh, wired into test:framework-shell. Each invariant was proven to go RED when its contract point is mutated:

Test Invariant Mutation → RED
T1 three-cursor advancement enqueue also writes consumed_seq → "consumed_seq must NOT advance on enqueue"
T2 digest coalesce-REPLACE vs actionable-APPEND digest APPENDs → "digest must COALESCE to a single pending entry, got 2"
T3 contiguous-prefix CONSUMED drop gap guard → "CONSUMED 3 must be REJECTED while seq 2 is a gap"
T4 wake_id delivery-dedup dedup always false → "duplicate delivery should be DUP, got 'RECEIVED'"
T5/T5b atomic write-tmp+rename crash-safety _atomic_write → direct write → "target corrupted by a killed mid-write"
T6 durability survives restart human class bypasses store → "human must APPEND / stay durable, got 0"
T7 ack local-write never blocks on network run sync foreground → "ack path blocked 3s"

A real bug was caught RED-first during development: jq -e over an empty ledger returns exit 0, so the initial wake_id dedup false-positived on the first delivery (T4) — fixed to a count-based slurp check.

Gates

  • shellcheck clean on all four scripts.
  • verify-sanitized.sh passes; operator firewall grep -niE 'jason|woltje|jarvis' = 0.
  • Full pnpm test:framework-shell passes end-to-end with the harness wired in as the final step.
  • prettier --check passes on the schema + package.json (no TS changed).

Out of W2 scope (not built)

detector (W4), digest renderer/HMAC signer (W3), FN-oracle/reconciler (W5), beacon (W6), installer (W7).

Part of #892

Implements **W2** of the wake/heartbeat canon (EPIC #892) — the durable-queue "heart" — honoring the CONVERGED-DESIGN contracts exactly. ## Piece → contract map ### A2 `store.sh` — three-cursor durable store + drain lib - **§1.2 three-cursor data-flow.** `observed_seq` (detector-assigned monotonic int; this lib records/stores it) is the authoritative cursor; the durable **pending-inbox** retains until CONSUMED; `consumed_seq` advances over a contiguous prefix. - **§2.4 cursor semantics.** `observed_seq` is authoritative; source SHAs are descriptors, not the cursor. `consumed_seq` NEVER advances on enqueue / sender exit-0 / pane-paste — only on a consumer CONSUMED ack. - **§2.3 classes & durability.** `class=digest` **REPLACES** the pending cumulative-state entry (newest subsumes prior); `actionable`/`human` **APPEND** (never replaced). **ALL** classes land in the durable store — durability is never bypassed. Absent class ⇒ treated as `actionable` (fail-safe). - **Durable entry** = `{observed_seq, locators, class, emit_ts, hmac}`; `hmac` is an **unsigned placeholder** (HMAC signing is W3/A5, out of W2 scope). - **drain** returns the deliverable set (WHAT to deliver; actual paste via existing send-message.sh is out of scope), gated on an optional idle predicate. - Every state mutation is **atomic write-tmp+rename** (write temp in-dir → `mv` rename); all state under XDG (`${XDG_STATE_HOME:-$HOME/.local/state}/mosaic/wake/`). ### A4 `ack.sh` — RECEIVED / CONSUMED ack-wrapper (§2.2) - **RECEIVED** records delivery; `wake_id` **dedups DELIVERY only** (dup delivery = re-RECEIVE, never re-action); never advances `consumed_seq`. - **CONSUMED N** is **LOCAL-WRITE-ONLY** to the XDG ledger, **cumulative**, and enforces the **contiguous gapless prefix** (rejects ack N while N-1 is unconsumed). A **background sync** ships the ack — the ack path **never blocks on the network**; the sync runs **once** and records an outage marker (no retry spam). - `embed` emits the one copy-run line meant to be embedded in each digest. ### Watch-list SCHEMA contract + Gate B manifest - `framework/defaults/wake-watch-list.schema.json` — repos, board files, lane anchors, per-class SLOs, source-parity `watches` inventory; **SCHEMA only** (operator supplies values), with `schema_version`. - `framework/tools/wake/manifest.txt` — component semver + supported schema **range** (`schema_min`/`schema_max`) as **Gate B**. It is **VERSION metadata only**; path-ownership stays with `framework-manifest.txt` (Gate A) — the new paths are already framework-owned via the existing `tools/**` and `defaults/**` globs, so no ownership edit was needed. ## RED-first evidence Harness `framework/tools/wake/test-wake-store-ack.sh`, wired into `test:framework-shell`. Each invariant was proven to go **RED** when its contract point is mutated: | Test | Invariant | Mutation → RED | |---|---|---| | T1 | three-cursor advancement | enqueue also writes `consumed_seq` → "consumed_seq must NOT advance on enqueue" | | T2 | digest coalesce-REPLACE vs actionable-APPEND | digest APPENDs → "digest must COALESCE to a single pending entry, got 2" | | T3 | contiguous-prefix CONSUMED | drop gap guard → "CONSUMED 3 must be REJECTED while seq 2 is a gap" | | T4 | wake_id delivery-dedup | dedup always false → "duplicate delivery should be DUP, got 'RECEIVED'" | | T5/T5b | atomic write-tmp+rename crash-safety | `_atomic_write` → direct write → "target corrupted by a killed mid-write" | | T6 | durability survives restart | human class bypasses store → "human must APPEND / stay durable, got 0" | | T7 | ack local-write never blocks on network | run sync foreground → "ack path blocked 3s" | A real bug was caught RED-first during development: `jq -e` over an empty ledger returns exit 0, so the initial `wake_id` dedup false-positived on the first delivery (T4) — fixed to a count-based slurp check. ## Gates - `shellcheck` clean on all four scripts. - `verify-sanitized.sh` passes; operator firewall `grep -niE 'jason|woltje|jarvis'` = 0. - Full `pnpm test:framework-shell` passes end-to-end with the harness wired in as the final step. - `prettier --check` passes on the schema + package.json (no TS changed). ## Out of W2 scope (not built) detector (W4), digest renderer/HMAC signer (W3), FN-oracle/reconciler (W5), beacon (W6), installer (W7). Part of #892
jason.woltje added 1 commit 2026-07-25 23:29:32 +00:00
feat(wake): W2 — three-cursor durable store + RECEIVED/CONSUMED ack-wrapper + watch-list schema
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
0f1a37ed2d
Implements W2 of the wake/heartbeat canon (EPIC #892), honoring the
CONVERGED-DESIGN contracts exactly.

A2 store.sh — three-cursor durable queue (§1.2/§2.3/§2.4):
  - observed_seq authoritative monotonic cursor (detector assigns, lib records);
    SHAs are descriptors, not the cursor.
  - durable pending-inbox {observed_seq, locators, class, emit_ts, hmac}; hmac is
    an UNSIGNED placeholder (signing is W3/A5).
  - consumed_seq advances ONLY on a CONSUMED ack over a CONTIGUOUS gapless prefix
    <=N; never on enqueue/exit-0/paste.
  - coalesce: digest REPLACES the pending cumulative-state entry; actionable/human
    APPEND; ALL classes durable (durability never bypassed); absent class => actionable.
  - drain returns the deliverable set; every mutation is atomic write-tmp+rename.

A4 ack.sh — RECEIVED/CONSUMED wrapper (§2.2):
  - RECEIVED dedups DELIVERY via wake_id (dup = re-RECEIVE, never re-action).
  - CONSUMED N local-write-only to the XDG ledger, cumulative, gapless-prefix
    enforced; background sync ships the ack (never blocks on network).
  - `embed` prints the one copy-run line a digest embeds.

Watch-list SCHEMA contract (defaults/wake-watch-list.schema.json) with
schema_version; wake manifest.txt declares component semver + supported schema
range (schema_min/schema_max, Gate B — version metadata only, NOT path ownership).

RED-first shell harness wired into test:framework-shell covers each invariant
(three-cursor, coalesce-vs-append, contiguous-prefix CONSUMED, wake_id dedup,
atomic tmp+rename crash-safety, durability-across-restart, ack-never-blocks-on-net).
shellcheck clean; sanitization gate + operator firewall pass.

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-25 23:40:52 +00:00
Merge remote-tracking branch 'origin/main' into feat/wake-store-ack-schema
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
7575d42f01
# Conflicts:
#	packages/mosaic/package.json
Author
Owner

Record of Review — PR #903 W2 (wake store+ack+schema) AFTER union-rebase — full-40, supersedes prior

VERDICT: APPROVE (GO on CI terminal-green). Substance reviewer: a9dead50 (opus, all 8 contract criteria PASS vs CONVERGED-DESIGN §1.2/2.2/2.3/2.4; red-first T1-T7 reproduced; ack never-blocks-net verified). ≠ builder (mosaic-coder).
REVIEWED-HEAD (full-40): 7575d42f011c2b9a82dd96d68c3340e0ddd58a55.
Delta re-review (rebase) — PASS: git diff 0f1a37ed 7575d42f -- tools/wake/ defaults/wake-watch-list.schema.json = EMPTY (W2 contract code BYTE-UNCHANGED). The only change from the substance-reviewed head is the git merge origin/main bringing #901 + the package.json UNION-resolution of the test:framework-shell line — keeps BOTH agent-send.test.sh (#901) AND wake/test-wake-store-ack.sh (this PR); neither dropped. Builder verified full chain green (agent-send 18/18 + wake 8-groups) + prettier clean. mergeable=true.
★ CONSUMED gap semantics RATIFIED (reviewer + coordinator): gapless-contiguous-prefix over observed seqs = §1.2 contiguous-prefix + §2.2 cumulative-batch; strict one-at-a-time would CONTRADICT §2.2. Coalescing does not create false gaps (observed.set covers all classes). No change.
GO for id-11 at FULL-40 7575d42f011c2b9a82dd96d68c3340e0ddd58a55 on CI terminal-green. Part of #892. Non-executor.

# Record of Review — PR #903 W2 (wake store+ack+schema) AFTER union-rebase — full-40, supersedes prior **VERDICT: APPROVE** (GO on CI terminal-green). **Substance reviewer:** `a9dead50` (opus, all 8 contract criteria PASS vs CONVERGED-DESIGN §1.2/2.2/2.3/2.4; red-first T1-T7 reproduced; ack never-blocks-net verified). ≠ builder (`mosaic-coder`). **REVIEWED-HEAD (full-40):** `7575d42f011c2b9a82dd96d68c3340e0ddd58a55`. **Delta re-review (rebase) — PASS:** `git diff 0f1a37ed 7575d42f -- tools/wake/ defaults/wake-watch-list.schema.json` = EMPTY (W2 contract code BYTE-UNCHANGED). The only change from the substance-reviewed head is the `git merge origin/main` bringing #901 + the package.json UNION-resolution of the `test:framework-shell` line — keeps BOTH `agent-send.test.sh` (#901) AND `wake/test-wake-store-ack.sh` (this PR); neither dropped. Builder verified full chain green (agent-send 18/18 + wake 8-groups) + prettier clean. mergeable=true. **★ CONSUMED gap semantics RATIFIED** (reviewer + coordinator): gapless-contiguous-prefix over observed seqs = §1.2 contiguous-prefix + §2.2 cumulative-batch; strict one-at-a-time would CONTRADICT §2.2. Coalescing does not create false gaps (observed.set covers all classes). No change. **GO for id-11 at FULL-40 `7575d42f011c2b9a82dd96d68c3340e0ddd58a55` on CI terminal-green. Part of #892. Non-executor.**
Mos approved these changes 2026-07-25 23:58:07 +00:00
Mos left a comment
First-time contributor

GO — Gate-16 id-11 stamp, pinned to exact FULL head 7575d42f01. Basis: verbatim RoRs — substance APPROVE a9dead50 (all 8 contract criteria vs CONVERGED-DESIGN §1.2/2.2/2.3/2.4, red-first T1-T7 independently reproduced) + delta re-review 18877 (union-rebase: contract code byte-unchanged, package.json unions BOTH test entries). CONSUMED gapless-contiguous-prefix semantics RATIFIED (builder/Mos/reviewer concordant). CI terminal-green at head. W2 of EPIC #892 — the wake-canon heart. Named executor: Mos (id-11), squash pinned.

GO — Gate-16 id-11 stamp, pinned to exact FULL head 7575d42f011c2b9a82dd96d68c3340e0ddd58a55. Basis: verbatim RoRs — substance APPROVE a9dead50 (all 8 contract criteria vs CONVERGED-DESIGN §1.2/2.2/2.3/2.4, red-first T1-T7 independently reproduced) + delta re-review 18877 (union-rebase: contract code byte-unchanged, package.json unions BOTH test entries). CONSUMED gapless-contiguous-prefix semantics RATIFIED (builder/Mos/reviewer concordant). CI terminal-green at head. W2 of EPIC #892 — the wake-canon heart. Named executor: Mos (id-11), squash pinned.
Mos merged commit 28f022d9c0 into main 2026-07-25 23:58:08 +00:00
Mos deleted branch feat/wake-store-ack-schema 2026-07-25 23:58:09 +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#903