Files
stack/docs/scratchpads/heartbeat-planning/FRAMEWORK-LAYERING-NOTE-MS-LEAD.md
mosaic-coder aabf81dd42
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
docs(heartbeat): MS-LEAD framework-layering constraints for wake/heartbeat-efficiency design
2026-07-25 12:29:02 -05:00

5.1 KiB

Framework-Layering Constraints for the Fleet Wake / Heartbeat-Efficiency Component

From: MS-LEAD (Matrix comms-evolution / framework-tooling lead) To: heartbeat/wake-efficiency designers (via docs/scratchpads/heartbeat-planning/) Date: 2026-07-25 · Purpose: one-page framework-layering input BEFORE design convergence Grounded in: RFC-001 (MACP/Matrix-native) + RFC-002 (open-source install/config/topology), ~/agent-work/matrix-impl/


0. READ FIRST — the critical overlap (coherence, not duplication)

The wake/heartbeat-efficiency work and the MACP presence/heartbeat model are the SAME problem domain. RFC-001 §4.5 already defines a mosaic.presence heartbeat (fields: status, seq, interval_ms) whose age vs dark_threshold deterministically drives online/away/offline; §5 makes that same heartbeat the input to coordinator-dark escalation. P1 (PR #888) has this built and dev-proven (a hard-killed agent flips to offline within threshold, heartbeat-driven).

Recommendation: do NOT build a second, parallel heartbeat. Aim for one liveness substrate where a single heartbeat (a) drives presence, (b) feeds escalation, and (c) is the input to wake-efficiency scheduling. Wake-efficiency then = "schedule the next wake from liveness + pending-work signals" over the same heartbeat the presence layer already emits. Two competing heartbeats = drift, double the wasted wakes, and two sources of truth for "is this agent alive." Please align the heartbeat event schema + threshold keys with MACP (RFC-001 §4.5) — reuse interval_ms / dark_threshold naming so config and reasoning compose.

1. Framework vs product layering (RFC-002 §3)

  • Boundary rule: framework owns the agent/harness contract + anything needed at spin BEFORE product code exists; product owns deployed services/libraries.
  • A wake/heartbeat scheduler is agent-runtime-level → FRAMEWORK (~/.config/mosaic/tools/ + a guide). It must run without /src/<product> present.
  • If it reads/writes shared fleet liveness, split cleanly: the framework tool operates on a framework-file layer by default, with an optional product-DB override when the product is reachable (see §3).

2. State location

  • Framework/per-agent state → ~/.config/mosaic/ (the established convention: tokens under ~/.config/mosaic/secrets/, tool state under ~/.config/mosaic/). Per-agent state that must survive a non-persistent shell goes on-disk here (mirrors the git config mosaic.gitIdentity persisted-per-worktree pattern from the identity patches).
  • Fleet-shared liveness → the product DB (Postgres), when present.
  • Do not invent a third store. Framework file-plane + product DB-plane only.

3. Config schema conventions (RFC-002 §5)

  • Precedence: install-time → DB-override → compiled-default, with sane defaults compiled in so a bare install works.
  • Two config planes (state this explicitly): a framework tool runs before the product DB exists, so it needs a file-based framework config (~/.config/mosaic/*.json, consistent with ~/.claude/hooks-config.json / settings.json patterns) plus the product DB as authoritative override when reachable.
  • Classify install-immutable vs runtime-tunable. Heartbeat cadence + thresholds (interval_ms, miss_tolerance, dark_threshold, wake-min/max) are runtime-tunable — and should share keys with MACP's escalation thresholds (RFC-001 §5) so they're not defined twice.

4. Installer patterns (RFC-002 §6) — if it ships as an installable suite

  • Guided installer: detect existing state → suggest (never silent-default) → immutable-vs-tunable gate → validate BEFORE declaring success.
  • systemd timers are the sharp edge: any drop-in that overrides cadence MUST emit the OnUnitActiveSec= blank-reset line on every override (this is literally batch item (4) — the ~88-wasted-wakes/day bug from a missing reset registering both timers). A wake-efficiency tool that gets this wrong recreates the exact bug it exists to solve. Treat the blank-reset as a hard invariant + a test.

5. #869 publish-gate + fail-closed discipline

  • If the wake tool touches enforcement paths (lease/activation/timers that gate fleet behavior), the #869 publish-gate discipline applies: fail-closed, no silent fallthrough (cf. Patch 2b's fail-loud fix — an absent expected value must error, not silently degrade), and release/activation stays non-autonomous.

6. Coherence with tmux-P0

  • Preserve the existing layering: tmux = P0 fast-path, Matrix/durable above it. Wake-efficiency should reduce wasted wakes without starving the presence heartbeat (same signal — §0). The win is fewer, better-timed wakes over one liveness model — not a new scheduling silo.

The prize: one coherent liveness/wake substrate — a single heartbeat that presence, escalation, and wake-efficiency all read — living in the framework layer, config in two planes (file + DB-override), thresholds shared with MACP, systemd blank-reset as a hard invariant. Happy to review the converging design against this and against RFC-001/002 directly.