8.0 KiB
Wake/Heartbeat Canon — FRAMEWORK PACKAGING PLAN (MS-LEAD)
Author: MS-LEAD (framework packaging role, named in CONVERGED-DESIGN footer) · Date: 2026-07-25
Input: jarvis-brain@31f1f6fd5 docs/scratchpads/heartbeat-planning/CONVERGED-DESIGN.md (GO-WITH-GATES,
RATIFIED) + ENHANCE-CADENCE-WRITER-FIX.md + ENHANCE-BASELINE.md.
Scope: §6 category-A framework-component items (A1–A11) + WAKE-DOCTRINE guide. NOT pilot (B*, mos-dt-0)
or operator-config values (C*). Proposal only — no framework PR cut until Mos acks this plan (per Mos).
Repo facts verified against mosaicstack/stack origin/main (read-only ls-tree) — not assumed.
1. Repo layout (grounded in verified paths)
Framework source lives in packages/mosaic/framework/ and installs to ~/.config/mosaic/. Verified:
tools/<subdir>/ (git, tmux, fleet, orchestrator, lease-broker, context, …); guides/*.md;
install.sh; systemd/; tools/tmux/agent-send.sh (+ agent-send.test.sh).
| Item | Source path (new unless noted) | Installs to |
|---|---|---|
| A1 detector daemon | framework/tools/wake/detector.sh |
~/.config/mosaic/tools/wake/ |
| A2 store+drain lib | framework/tools/wake/store.sh (three-cursor, atomic write-tmp+rename) |
XDG state ~/.local/state/mosaic/wake/ |
| A3 digest renderer | framework/tools/wake/digest.sh |
" |
| A4 ack-wrapper | framework/tools/wake/ack.sh (RECEIVED/CONSUMED, local-write+async) |
ledger under XDG state |
| A5 HMAC signer | framework/tools/wake/sign.sh (non-circular tuple, load_credentials by-name) |
" |
| A6 FN-oracle · A7 reconciler | framework/tools/wake/{fn-oracle,reconcile}.sh |
" |
| A8 off-host beacon | framework/tools/wake/beacon.sh + alarm integration |
off-host monitor |
A9 digest class validator |
MODIFY framework/tools/tmux/agent-send.sh (+ .test.sh) |
— |
| A10 idempotent installer | MODIFY framework/install.sh + framework/systemd/user/mosaic-wake.service |
~/.config/systemd/user/ |
| A11 WAKE-DOCTRINE | framework/guides/WAKE-DOCTRINE.md (lift §"WAKE-DOCTRINE" verbatim) |
~/.config/mosaic/guides/ |
| C1 watch-list SCHEMA (framework) | framework/defaults/wake-watch-list.schema.json |
operator supplies values |
Note: gitea-pr-watch / mos-comms (the pollers the detector generalizes) are NOT under
framework/tools/ on main — they are host/operator artifacts today. A1 becomes the canonical framework
generalization; it does not depend on those existing in-repo. The detector runs as a long-lived
service (not a timer) — the whole point is retiring unconditional timers; fallback cadence is a
per-class SLO bound inside the daemon, not a systemd interval.
2. PR slicing (dependency-ordered, ≤2 concurrent builders, each builder→indep-review→Mos id-11)
Dependency spine: store/ack (A2/A4) → digest/sign (A3/A5) → detector (A1) → oracle/reconciler (A6/A7); beacon (A8), A9, A11 are near-independent; installer (A10) lands last (needs all files present).
| PR | Contents | Notes |
|---|---|---|
| W0 | A11 WAKE-DOCTRINE.md | docs-only, independent; lands first as normative reference. Resolves #889 (see §5). |
| W1 | A9 agent-send.sh digest-class validator + test |
tiny, independent, red-first (like Patch 2b). Good opener. |
| W2 | A2 store+drain lib + A4 ack-wrapper | core three-cursor transaction; red-first heavy. The heart. |
| W3 | A3 digest renderer + A5 HMAC signer | depends on W2 store; hard-locator + scrub + non-circular MAC tests. |
| W4 | A1 detector daemon | depends on W2/W3; repo-section/anchor-scoped hashing; flock; in mos-comms loop. |
| W5 | A6 FN-oracle + A7 reconciler | depends on W4; the non-optional G3/§4 cost, built explicitly. |
| W6 | A8 off-host beacon + alarm | semi-independent; the independent liveness leg (G1). |
| W7 | A10 idempotent install.sh (blank-reset idiom + snapshot-guard) + mosaic-wake.service + C1 schema |
LAST; absorbs batch (d); #869 publish-gate (enforcement path). |
~8 PRs pipelined; at ≤2 lanes this is several convergence cycles. Each: fresh-clone builder
(mosaic-coder), author≠reviewer independent review at exact head, RoR packet, Mos id-11 stamp+merge.
Red-first mandatory on all code PRs; test:framework-shell chain extended per PR.
3. Versioning + #869 compatibility
- Component ships inside the framework (
packages/mosaic/framework/) → inherits framework version. - §5.4 decoupling requirement: a host must adopt "just the component + its watch-list without a full
framework bump." Enabler: the watch-list carries an explicit
schema_version; the detector validates schema-version and FAILS LOUD on incompatible (no silent degrade — #869 discipline, same fail-loud posture as Patch 2b). WAKE-DOCTRINE is version-agnostic doctrine. - A10 installer is an enforcement path → #869 publish-gate: fail-closed, idempotent, snapshot-guard
blocks a reap/clean-checkout without a snapshot; post-apply verify = exactly one
OnUnitActiveUSec. - web1 rides #869 Point-2 (currently HELD/non-autonomous). dragon-lin pilots NOW (separate host, outside the #869 freeze) — so canon PRs can land + be piloted without touching the web1 release hold.
4. Rollout sequence (§5, retire-net-LAST)
- Snapshot-first (B5, mos-dt-0/pilot): dragon-lin
jarvis-heartbeat.{service,timer}— snapshot already present atheartbeat-planning/pilot/snapshot-dragon-lin/. Canon is version-controlled from day one (the failure class — deployed-from-uncommitted — cannot recur). - Land W0→W7 to main (reviewed framework PRs).
- dragon-lin: enable canon alongside ad-hoc (B1) → dual-ledger compare (B2) → run §4 vector (B3) → delete ad-hoc units after pass (B4). Every step leaves old-or-new live (sol F7).
- web1: adopt component + watch-list on #869 resolution.
- Do NOT land the ad-hoc
infra/fleet/*subsystem to main first (§5.1, Mos ruling) — it is exactly what canon retires.
5. Disposition of adjacent items
- Batch (d) — ABSORBED into A10. The blank-reset bug is in
infra/fleet/install.sh(deployed-from-uncommitted, NOT on main — confirms my "could not verify on main"). Host drop-ins already corrected + live-verified 2026-07-25 (planner-opus/planner-sol now fire 30min not 15min). Nothing standalone to land; the proven idiom (byte-identical toinstaller-7) becomes an A10 requirement + a post-apply test. Batch item (d) is therefore closed-as-absorbed, not a separate PR. - PR #889 (my layering note) — recommend CLOSE-SUPERSEDED. Its constraints (one liveness substrate,
framework-vs-product split, state location, blank-reset invariant) are now canonized in
CONVERGED-DESIGN §0/§1.1/§1.4/§5.2 (W-jarvis confirmed the constraint was accepted for relay). The
canonical heartbeat docs live in jarvis-brain
heartbeat-planning/; keeping a superseded duplicate inmosaicstack/stack docs/scratchpads/is cross-repo drift. Lean: close #889 without merge (design input delivered + absorbed). Defer to Mos: close-superseded (my rec) vs merge-as-historical-record.
6. Open questions for Mos (before I cut W0)
- Repo home —
framework/tools/wake/for A1–A8 +framework/defaults/for C1 schema: confirm names. - #889 — close-superseded (my rec) vs merge-as-record?
- PR granularity — ~8 pipelined PRs OK, or coarser (fewer, larger) / finer?
- Pilot boundary — design assigns pilot (B1–B5) to mos-dt-0; I own framework packaging (A*). I do NOT build pilot items unless you reassign. Confirm.
- Sequencing vs tooling batch — #890 (a) in flight for id-11; (b) held on scopes; (c) HALTED. Does W0 start now (dragon-lin outside #869), or after the tooling batch clears? My lean: W0/W1 can start now (doc + tiny validator, no #869 dependency), heavier W2+ after (b)/(c) resolve to keep ≤2 lanes.
- Tracking issue/EPIC — create a
mosaicstack/stackEPIC for the canon component (parent for W0–W7), analogous to Matrix EPIC #887 / tooling umbrella #891? I'll open it on your nod.