Files
stack/packages/mosaic/framework/tools/wake/manifest.txt
mosaic-coder 6905f84881
Some checks failed
ci/woodpecker/pr/ci Pipeline was canceled
fix(wake): #920 quarantine render-refused drain entry (no head-of-line block) + reconciler enumerations render orientation-tier
Live pilot finding #6 (BLOCKING): a reconciler enumeration enqueued
class=actionable with soft locators {kind,id,path,observed_hash} failed
§2.1's ACTIONABLE hard-locator taxonomy, so digest render exit-4'd the
ENTIRE cumulative-state drain — 4 consecutive timer failures, NOTHING
delivered, including clean unrelated entries (head-of-line blocking).

FIX 1 (quarantine, don't wedge): digest.sh cmd_render's fail-loud pass is
now PER-ENTRY. A render-refused ACTIONABLE entry (no hard locator) is
DEAD-LETTERED to $STATE_DIR/dead-letter.jsonl + a loud per-entry alarm and
EXCLUDED, while the REST of the cumulative set still renders (exit 0). The
bad entry is accounted-for, never silently dropped; one malformed entry can
no longer wedge the whole drain.

FIX 2 (AMENDED — render-tier, NOT class=digest): reconcile.sh's store class
is UNCHANGED (non-coalescing) — the naive class=digest was rejected because
store §2.3/T2 coalescing would silently collapse distinct enumerations
(proven: reconcile R6 goes RED). Instead digest.sh's actionable-classifier
now treats locators.reconciled==true (set only by reconcile.sh; not
source-forgeable) as ORIENTATION-tier: gate-exempt, rendered as an
orientation pointer via _locator_line's digest-class vocabulary. No exit-4,
no wedge, no coalescing loss; §2.3/T2/G3-R6 intact.

RED-FIRST: new test-wake-digest-quarantine.sh (openssl-independent) proves
(a) malformed {kind,id,path,observed_hash} quarantines while a clean sibling
still delivers, (b) a reconciled enumeration renders orientation-tier (no
exit-4), (c) TWO distinct enumerations both survive as separate orientation
renders (anti-collapse — the class=digest silent-drop we rejected), and the
preserved per-entry actionable fail-loud. D2/D6 in test-wake-digest-hmac.sh
updated from whole-digest exit-4 to per-entry quarantine. Wake manifest
bumped 0.6.2 -> 0.6.3 + inventory.

Closes #920
Part of #892

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
2026-07-26 03:13:30 -05:00

126 lines
8.6 KiB
Plaintext

# Mosaic wake component — VERSION metadata manifest (Gate B).
#
# EPIC #892, W2 + W3 of the wake/heartbeat canon.
#
# SCOPE — THIS FILE IS VERSION METADATA ONLY. It declares the wake component's
# semantic version and the RANGE of watch-list schema versions it supports. It
# does NOT authorize file/path ownership: path-ownership remains the sole domain
# of packages/mosaic/framework/framework-manifest.txt (Gate A). Do not read any
# ownership meaning into this file.
#
# Format: KEY=VALUE, one per line. '#' and blank lines ignored.
# Component identity + semantic version.
# 0.1.0 W2 — store+drain lib + ack-wrapper.
# 0.2.0 W3 — cumulative-state digest renderer + non-circular HMAC signer.
# 0.3.0 W4 — per-host single-instance delta-gated detector daemon.
# 0.4.0 W5 — synthetic-canary FN-oracle + source-parity reconciler.
# 0.5.0 W6 — off-host dead-man beacon emitter + pluggable alarm-sink adapter
# + beacon-absence alarm (fail-loud on unconfigured/unreachable).
# 0.6.0 W7 — A10 idempotent, fail-closed component installer (Gate-A
# intersect+validate against the framework-manifest SSOT), the
# mosaic-wake.service detector daemon, the blank-reset retire idiom
# for the legacy heartbeat timer + snapshot-guard, and fail-closed
# alarm-target/HMAC-key install-validation. Also folds in the two W6
# monitor-integration observations (monitor-side ingested_ts
# staleness + beacon HMAC-verify at record).
# 0.6.1 #908 — UNIFY observed_seq on a SINGLE store-side allocator. store.sh
# enqueue is now the sole allocator (reads its own cursor, next=+1
# under an exclusive lock, prints the seq; commits IFF the durable
# write succeeds). The detector-private observed_seq_counter and its
# --seq hand-off are DELETED; the reconciler enumerates via the same
# store allocator (its dual-allocator fail-closed guard retired). This
# dissolves the three defects rooted in the private-counter seam:
# burn-before-enqueue (arrow 1), W5 co-feed aliasing (arrow 2), and
# the migration-restart silent-swallow (arrow 3, now structurally
# impossible — allocation is always > consumed or fails loud).
# 0.6.2 #914 digest.sh renderer fixes (live wake-pilot findings): (a) the
# embedded ack copy-run line now bakes an explicit
# WAKE_AGENT=<render-time-agent> prefix (shell-quoted) so an
# env-less copy-run resolves to the correct per-agent namespace
# instead of silently falling back to `default`; (b) the
# ORIENTATION locator renderer now also recognizes the locator
# vocabulary detector.sh (A1) actually emits for a digest-class
# entry (kind/id/observed_hash/remote/path), so a digest-class
# pointer carries a usable (soft) locator instead of rendering
# empty. Display-only: the ACTIONABLE-tier hard-locator FAIL-LOUD
# gate (_has_hard_locator, exit 4) is unchanged.
# 0.6.3 #920 digest.sh drain-quarantine + reconciler-enumeration render tier
# (live wake-pilot finding #6, BLOCKING). (a) PER-ENTRY
# QUARANTINE: a render-refused ACTIONABLE entry (no §2.1 hard
# locator) is now DEAD-LETTERED to $STATE_DIR/dead-letter.jsonl +
# a loud per-entry alarm and EXCLUDED, while the REST of the
# cumulative set still renders (exit 0). Replaces the whole-digest
# exit-4 that let ONE malformed entry wedge the entire drain (head-
# of-line blocking — 4 consecutive live timer failures, nothing
# delivered). Fail-loud is preserved, now per-entry; the bad entry
# is never silently dropped. (b) Reconciler ENUMERATIONS render
# ORIENTATION-tier: an entry whose locators carry reconciled==true
# (set only by reconcile.sh) is EXEMPT from the actionable hard-
# locator gate and renders as an orientation pointer via
# _locator_line's digest-class vocabulary — a RENDER-layer change
# only. reconcile.sh's STORE class is UNCHANGED (non-coalescing), so
# distinct enumerations never collapse (§2.3/T2/G3-R6 intact); the
# rejected class=digest alternative would have silently coalesced
# them. store.sh and reconcile.sh are UNCHANGED by 0.6.3.
component=wake
version=0.6.3
# Watch-list schema this component consumes, and the INCLUSIVE range of
# schema_version values it supports. A wake-watch-list.json whose schema_version
# falls outside [schema_min, schema_max] is rejected by the component (fail-loud),
# never silently coerced.
schema=wake-watch-list
schema_min=1
schema_max=1
# Pieces shipped by this component version (informational):
# store.sh A2 — three-cursor durable store + drain lib. (W2)
# ack.sh A4 — RECEIVED/CONSUMED ack-wrapper (local-write + ship). (W2)
# digest.sh A3 — cumulative-state digest renderer (hard locators,
# two-tier trust, injection/secret scrub). PER-ENTRY
# quarantine: a render-refused entry is dead-lettered +
# alarmed + excluded, the rest still renders (no head-of-line
# block); reconciler enumerations (reconciled==true) render
# ORIENTATION-tier, gate-exempt. (W3, #920)
# sign.sh A5 — non-circular HMAC signer (independent wake_id,
# load_credentials by-name; fills the hmac placeholder). (W3)
# detector.sh A1 — per-host single-instance delta-gated detector daemon
# (flock, anchor-scoped hashing, fail-loud source semantics;
# enqueues deltas to store.sh and captures the store-allocated
# observed_seq — no private counter, #908). (W4)
# fn-oracle.sh A6 — synthetic-canary FN-oracle: injects a KNOWN delta at the
# source boundary, drives the pipeline through the detector's
# public poll-once, asserts CONSUMED within the per-class SLO
# (off-domain verdict from the terminal store cursor). §4
# requires FN-rate=0; a dropping/disabled detector FAILS. (W5)
# reconcile.sh A7 — source-parity reconciler: (i) source-coverage parity
# inventory (an omitted source cannot pass the vector
# vacuously) + (ii) periodic full reconcile to 0-unaccounted,
# enumerating pre-existing/startup state into the store via the
# SINGLE store-side allocator (co-feed is safe; the former
# dual-allocator fail-closed guard retired, #908). (W5)
# beacon.sh A8 — off-host DEAD-MAN liveness beacon: a monotonic beacon
# EMITTER (emit — the primitive the detector run-loop calls
# each cycle), the off-host monitor's RECEIVER + beacon-ABSENCE
# alarm (record, check), and a pluggable alarm-sink/beacon-sink
# ADAPTER INTERFACE. Liveness is SPLIT from work-triggering;
# the alarm fires on ABSENCE, routing to a human/other-host
# within its SLO (§4/G1). FAIL-CLOSED: an unconfigured OR
# unreachable target FAILS LOUD (no silent no-alarm host).
# A same-host sibling is REJECTED as non-independent; an
# isolated host degrades to a FLAGGED different-supervision-root
# beacon; capture-pane is a liveness HINT only. (W6)
# wake-install.sh A10 — idempotent, fail-closed COMPONENT installer. Selects the
# component file set and INTERSECTS-AND-VALIDATES it against the
# single SSOT framework-manifest.txt (Gate A) — this VERSION
# manifest authorizes no path. Ships the blank-reset retire
# idiom (exactly-one OnUnitActiveUSec) for the legacy heartbeat
# timer, the snapshot-guard (no reap without a snapshot), and
# fail-closed alarm-target + HMAC-key install-validation (the
# installer wires + install-validates the beacon target that
# beacon.sh's fail-loud primitive is designed for). (W7)
# Companion (framework subtree, not under tools/wake/): systemd/user/mosaic-wake.service
# — the long-lived detector daemon unit (per-class SLO lives in
# the daemon, NOT a systemd interval). (W7)