Compare commits
1 Commits
docs/rfc-m
...
docs/heart
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aabf81dd42 |
@@ -0,0 +1,49 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user