Files
stack/docs/fleet/proposals/mosaic-platform-prd/PRD-hermes-decommission.md
Jarvis 2708de55b9
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
docs(prd): fold 2026-07-09 debate-pass findings into Mosaic Platform PRD
All 24 panel findings (P0#1-5, P1#6-13, P2/P3#14-24) accepted and folded:
- DEBATE-FINDINGS.md: disposition record + open-disagreement judgment calls
- north-star: NS-14, J2a/J2b split, J6 wake router, K3 push pipeline,
  M1 memory subsystem, workstream L (MALS lineage), real DAG edges
- J: workspace lease J-R16, resume protocol J-R18, write-side trust,
  needs-decision lifecycle, atomic card publish
- P: CAS approval state machine, gateway-only credentials, default-closed
  gating, principal resolution + policy snapshot (Codex #2/#7)
- W: butt-in exclusive lease, structured control plane, break-glass
  doctrine, trial metric panels
- Q: external_refs table, pending-link, echo-loop guard, crash barriers
- X: storage authority (Postgres sole record), machine-generated census,
  memory retrieval-eval retirement gate, honest rollback scope,
  4 artifact-existence machine gates, bounded day-30 review
- README: Gate Zero, conflict register, DoD line, silent-roster rule

One item OPEN for Jason at ratification: gate superstructure (§3.1).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RMoEx7hfdFGjUiCHuN1RRi
2026-07-09 16:29:37 -05:00

20 KiB
Raw Blame History

PRD — Hermes Decommission & Tenant-1 Migration · Workstream X

Status: DRAFT for ratification · Goals: X1X3 · Doctrine: NS-13, ASM-8 (Hermes untouched until verified parity) Ratified direction (D2, 2026-07-09): Mosaic absorbs all four Hermes functions — messaging bridge, task board, permission relay, multi-platform reach. Debate pass 2026-07-09: panel findings folded — this PRD took the heaviest rewrite (storage authority, migration census, memory-store hygiene, honest rollback scope). See DEBATE-FINDINGS.md.

Deployment scope (D12/ASM-9)

The trial runs in the homelab. Hermes and the primitive-era stack (mos-claude.service, jarvis-brain boards) live in the USC/web1 environment, which is untouched during the trial. This workstream therefore lands in two stages: X-in-homelab (prove parity where the fleet is native — mainly K/P/Q verification plus tenant-1 migration) and X-at-USC (post-trial adoption: apply the parity checklist to web1, migrate Mos-on-web1 to mosaic-agent@orchestrator, then decommission Hermes there, with /src/infrastructure GitOps updates in the same delivery set).

Trial go/no-go (D12/ASM-9 gate): the homelab→USC promotion is owner-judgment, not an automated metric. The stage gate is: Jason instantiates and operates the split-agent stack in the homelab and is satisfied with its operation. Only on that explicit sign-off does X-at-USC begin. The capability ACs (AC-NS-8…11) are the evidence Jason weighs; they inform the decision but do not auto-trigger USC deployment.

Mission

Retire Hermes entirely. Mosaic becomes the platform for transport (Matrix connector), task board (native backlog + webUI/adapters), approvals (permission relay), and multi-platform reach (mautrix bridges). In the same arc, Jason's jarvis-brain flat-file data migrates into the product as tenant #1, making the product's PA feature set the dogfooded default.

Parity map (what replaces what)

Hermes function Mosaic replacement Workstream
Messaging bridge (Discord/Telegram/…) Matrix connector + mautrix bridges K1, K2
Kanban / task board Native Mosaic Backlog + webUI board + provider adapters A*, Q, W3
Permission relay (permissions_*) Guard-rails engine + approval queue (Matrix + webUI) P1P3
Cross-platform user reach mautrix bridges (agents speak Matrix only) K2
Hermes MCP tools in agent sessions Per-tool equivalence table (Gate Zero artifact): approvals → P2, board ops → Q1/A*, messaging → K1 — not a generic "gateway API" gesture P2, Q1, K1

Requirements

Parity checklist + cutover plan (X1)

ID Requirement
X-R1 A written, testable parity checklist per row above; each item verified in production before its Hermes counterpart is disabled. The checklist is seeded from a pre-trial usage audit: per-MCP-tool and per-capability call counts over a trailing window, plus an inventory of Hermes-held provider callbacks/webhooks and secrets. Parity rows with n < 5 real invocations in the window cannot be "verified by traffic" — they get scheduled drills in weeks 13 of the observation window instead of silent green.
X-R1a Approval-routing cutover is per-agent atomic: a cutover table states, per agent, the single moment its permissions_* path flips from Hermes to the P relay. No agent ever has two live approval paths; no approval window where neither path is live.
X-R2 Cutover is staged with rollback at every stage; Hermes runs untouched until AC-NS-11 is verified (ASM-8). Rollback is honestly scoped (debate #16): it restores transport (Hermes services + MCP registrations) — board/approval state created natively during the trial does NOT back-migrate. The point of no return is the first native-only card; the runbook says so explicitly, and the abort path (below) is written before cutover, not during an incident.
X-R3 The Matrix charter's live-cutover rules apply: stated window, announce before/after, rollback ready.

Tenant-1 migration (X2)

Framing (ratified 2026-07-09, storage authority clarified by debate P0 #1): jarvis-brain is the P0 (prototype) Mosaic Stack — its flat-file data layer is the zeroth implementation of what the product does properly. Migration is therefore P0 → proper Mosaic Stack. Native Postgres is the sole authoritative store for every product entity (consistent with workstream Q's "sole record" doctrine and NS-3/NS-4/NS-5). A flat-file backend, where offered, is a derived, regenerated, read-only projection — the same relationship generated views have to JSON in the P0 today — never a co-equal write target. Two distinct data classes migrate — they are not the same destination and neither is frozen:

  • (a) PA data (projects, tasks, events, tickets, knowledge) → product entities in the Jason workspace (Project/Task/Event/KnowledgeEntry), authoritative in Postgres; flat-file export available as a read-only projection.
  • (b) Agent memory & operational knowledge (runbooks, digests, scratchpads, OpenBrain thoughts) → the enhanced memory subsystem (goal M1: vector DB + memory service). This flow stays live and writable throughout — it was never Hermes and must not be frozen by the PA cutover.
ID Requirement
X-R4 Stage 1 of the migrator is a machine-generated source census, not a hand-written file list (debate P0 #5 — the hand list was already wrong about its own tree). The census walks the live repo (tracked + untracked), inventories every data path — data/**, all memory stores (memory/, memories/, memory_store*, memory.md, brain.jsonl, jarvis.db, digests), scratchpads, notes, prior-generation artifacts — and assigns each a disposition: migrate-as-PA(entity type) / migrate-as-memory(M1 class) / derived-regenerate / retire-with-history. Any path dispositioned unknown blocks the run. Stage 2 migrates per-disposition, preserving source ids in metadata; idempotency via anti-join on the shared external_refs table (Q-R8); named crash barriers at each phase boundary. A field-map table covers the full brain.py query surface (status, progress, due, priority, domain, notes, staleness) → product entity fields, so AC 2 is checkable field-by-field.
X-R5 Dry-run mode with a diffable report generated from the census (counts per disposition, per-entity field mapping, unmapped-field list — must be empty or explicitly waived); Jason ratifies the report before the real run (canonical-data gate — this is the one migration step that is his call).
X-R6 External sync jobs (GLPI, Google Calendar, ICS, Gmail, Vikunja — disposition decided here: re-point or retire, not silently dropped) each get a written per-integration transition protocol: freeze flat-file sync job → verify product integration live → re-point → verify → retire old job. Provider-sourced events migrate FROM the provider, not from flat files (flat files supply only brain-native events) — the provider join key is authoritative, so re-pointing cannot duplicate the calendar (debate #6). Calendar fixture (Codex): a DST-crossing recurring event with one moved and one cancelled occurrence, plus an all-day event, round-trips with zero duplicates and correct local times.
X-R7 Agent memory/operational knowledge (b) is migrated into the M1 memory subsystem before any jarvis-brain retirement; the memory write path stays continuously available (no read-only freeze of an active substrate). The census classifies every memory item: ratified / superseded / draft / rejected / debate-artifact / protocol-normative / protocol-parametric. Parametric measurement artifacts (thresholds, seeds, drill timings, canary templates) are excluded from embedding (§3.5 disposition — rules the agent is scored against stay retrievable; the knobs do not). Superseded/rejected items get tombstones, and supersession triggers re-embedding of affected summaries. Retirement gate: a retrieval eval — ≥50 representative queries, ≥90% of baseline recall@5, plus negative queries (rejected/superseded content must NOT surface) — passes against M1 before any flat-file store goes read-only. After cutover: write paths to retired stores are killed and a CI lint fails any reintroduction. Only once both (a) and (b) are migrated and verified is the jarvis-brain repo retired read-only (history preserved); generated views and brain.py retire. This closes the P0 prototype.

Decommission (X3)

ID Requirement
X-R8 Pre-stop evidence snapshot is a machine gate: before Hermes stops, a checksummed snapshot of its state (board items, pending approvals, bridge registrations, per-tool usage counts) is captured and stored with the trial artifacts. The drill schedule (X-R1) and the credential-revocation report both cite the snapshot checksum — no snapshot, no stop. Then: services stopped, disabled, and removed from infra (GitOps: /src/infrastructure updated in the same delivery set); credentials revoked — the revocation report cites a final scan showing zero live references; MCP registrations removed from agent runtimes.
X-R9 Bounded day-30 review between stop and removal, pre-registered before cutover (dossier: what will be measured, panels cited, drill results attached — see W-R15/L1 for where the metrics live, stack_version-segmented so mid-window upgrades don't blur rates). The review records exactly one of three outcomes: promote (remove Hermes), extend with named blockers (each blocker a card with an owner), or abort (execute the pre-written abort runbook; transport-only rollback per X-R2). "Insufficient data" is a recordable outcome that forces extend — never a shrug into promote. Any in-window regression flips back per X-R2.

Machine gates on irreversible transitions (debate §3.1 agreed floor)

Four artifact-existence gates — dumb, checkable, ungameable — sit on the irreversible transitions. Each is "the artifact exists and passes its check", not a scored rubric:

  1. Pre-stop snapshot exists with valid checksum (X-R8) — gates Hermes stop.
  2. Census with zero unknown rows exists (X-R4) — gates the PA migration run.
  3. Retrieval eval pass record exists (X-R7) — gates memory-store retirement.
  4. All parity rows green-or-drilled (X-R1: verified by traffic or by scheduled drill; no silent low-n green) — gates Hermes removal at day-30.

The gate superstructure beyond this floor (tiered blocking pack vs pre-registered dossier) is OPEN — Jason at ratification; convener recommendation in DEBATE-FINDINGS.md §3.1.

Acceptance criteria

  1. AC-NS-11: with Hermes stopped, no fleet or main-agent capability regresses.
  2. python tools/brain.py today's information content is fully answerable by Jarvis from the product workspace post-X2, verified field-by-field against the X-R4 field-map table.
  3. Zero references to Hermes MCP tools in any active agent runtime config after X3.
  4. The X-R6 calendar fixture (DST-crossing recurrence, moved + cancelled occurrence, all-day event) round-trips with zero duplicates.
  5. The X-R7 retrieval eval passes against M1 before any memory store goes read-only; negative queries return no superseded/rejected content.
  6. All four machine gates above have their artifacts on record before their respective transitions execute.

Sequencing note

X depends on the longest chains (K1→K2, P2, Q1, J2a→J2b, M1 — X2 cannot complete class (b) without the memory subsystem existing). Dependencies are real DAG edges in north-star-additions.yaml (X2 depends_on [J2a, P2, M1]), not prose phases (debate P0 #3). Expected order of value delivery: J1J4 (Jarvis on existing transport interim) → K1/J5 (Matrix room) → P2, W1W3, Q1 in parallel → X1 checklist → X2 migration → K2 bridges → X3 decommission.

  • ASSUMPTION (interim transport): until K1 lands, Jarvis may run against the tmux connector (CLI/agent send) rather than standing up any Discord channel — keeps D1 (Matrix-first, no #jarvis Discord) intact.