feat(fleet): brain-home split — fleet state under ~/.mosaic, templates stay config-home #1298

Merged
jarvis merged 2 commits from zane/mosaic-home-support into next 2026-08-18 03:23:16 +00:00
Owner

What

Fleet brain-home split: fleet state (seat launch envs, roles.local overrides, profile working copies) resolves from the brain home (~/.mosaic) when one is active; framework templates and dispatch state (roster.yaml, baseline roles/, run/, services/) stay under the config home (~/.config/mosaic).

Implements the three-tree model from the mosaic-brain canon (STRUCTURE-CANON.md §2), first carried by the USC estate brain — its tree holds fleet/agents/*.env.generated, roles.local/, profiles/ and nothing else under fleet, which is exactly the split encoded here.

Resolution

packages/mosaic/src/fleet/brain-home.ts, mirrored in tools/fleet/start-agent-session.sh:

  1. MOSAIC_BRAIN_HOME env — explicit, always wins.
  2. Canonical ~/.mosaic — adopted only when MOSAIC_HOME is the default ~/.config/mosaic AND ~/.mosaic/fleet/agents exists. Custom --mosaic-home values (tests, sandboxes, canaries) never adopt — hermetic and deterministic.
  3. Else legacy single-tree behavior (no behavior change for existing installs).

Call sites

  • resolveFleetPaths (fleet.ts) — agentEnvDir
  • fleet regen — env projection dir
  • fleet-agent-crud / fleet-migration — env dir + override dir
  • personas defaultOverrideDir, profiles defaultProfilesDir
  • reconciler projections
  • generated-env boundary: validate/ensure accept the brain tree; a config-home agentEnvDir is rejected while a brain is active (no silent split across two trees)

Tests

  • brain-home.spec.ts (8): env precedence, injected seam, hermetic non-default homes, adoption + no-brain + fleet-without-agents cases, real-home endpoint control
  • generated-env-boundary.spec.ts: brain-path write (0700/0600 enforced) + cross-tree rejection
  • test-start-agent-session.sh: bash brain adoption case + no-brain legacy control (suite green end-to-end)
  • Full fleet surface: 733 tests green; package-wide vitest 1556/1557 — the one failure (uninstall.spec "handles missing mosaicHome" → EACCES on /nonexistent/path) reproduces on origin/next without this change (host-dependent, verified by stash)

Notes for reviewers

  • No change to roster resolution (stays config-home per canon — no estate brain carries roster.yaml).
  • Heartbeat/run dirs stay config-home (runtime state, canon does not place them in the brain).
  • Follow-up (not this PR): mosaic launch per-agent config homes under ~/.mosaic/fleet/agents/<seat>/ (MOSAIC-D-002 direction); installer provisioning of brains from canon (canon §6).
## What Fleet brain-home split: fleet **state** (seat launch envs, `roles.local` overrides, profile working copies) resolves from the brain home (`~/.mosaic`) when one is active; framework templates and dispatch state (`roster.yaml`, baseline `roles/`, `run/`, `services/`) stay under the config home (`~/.config/mosaic`). Implements the three-tree model from the mosaic-brain canon (`STRUCTURE-CANON.md` §2), first carried by the USC estate brain — its tree holds `fleet/agents/*.env.generated`, `roles.local/`, `profiles/` and nothing else under fleet, which is exactly the split encoded here. ## Resolution `packages/mosaic/src/fleet/brain-home.ts`, mirrored in `tools/fleet/start-agent-session.sh`: 1. `MOSAIC_BRAIN_HOME` env — explicit, always wins. 2. Canonical `~/.mosaic` — adopted **only** when `MOSAIC_HOME` is the default `~/.config/mosaic` AND `~/.mosaic/fleet/agents` exists. Custom `--mosaic-home` values (tests, sandboxes, canaries) never adopt — hermetic and deterministic. 3. Else legacy single-tree behavior (no behavior change for existing installs). ## Call sites - `resolveFleetPaths` (fleet.ts) — `agentEnvDir` - `fleet regen` — env projection dir - `fleet-agent-crud` / `fleet-migration` — env dir + override dir - personas `defaultOverrideDir`, profiles `defaultProfilesDir` - reconciler projections - generated-env boundary: validate/ensure accept the brain tree; a config-home `agentEnvDir` is **rejected** while a brain is active (no silent split across two trees) ## Tests - `brain-home.spec.ts` (8): env precedence, injected seam, hermetic non-default homes, adoption + no-brain + fleet-without-agents cases, real-home endpoint control - `generated-env-boundary.spec.ts`: brain-path write (0700/0600 enforced) + cross-tree rejection - `test-start-agent-session.sh`: bash brain adoption case + no-brain legacy control (suite green end-to-end) - Full fleet surface: 733 tests green; package-wide vitest 1556/1557 — the one failure (`uninstall.spec` "handles missing mosaicHome" → EACCES on `/nonexistent/path`) reproduces on `origin/next` without this change (host-dependent, verified by stash) ## Notes for reviewers - No change to roster resolution (stays config-home per canon — no estate brain carries `roster.yaml`). - Heartbeat/run dirs stay config-home (runtime state, canon does not place them in the brain). - Follow-up (not this PR): `mosaic launch` per-agent config homes under `~/.mosaic/fleet/agents/<seat>/` (MOSAIC-D-002 direction); installer provisioning of brains from canon (canon §6).
jason.woltje added 1 commit 2026-08-18 02:29:17 +00:00
Three-tree model per canon STRUCTURE-CANON §2 (first carried by the USC
estate brain): seat launch envs, roles.local overrides, and profile
working copies are user-owned fleet state and resolve from the brain home
(~/.mosaic) when one is active; roster.yaml, baseline roles, run/, and
services stay under the config home (~/.config/mosaic).

Resolution (packages/mosaic/src/fleet/brain-home.ts, mirrored in
tools/fleet/start-agent-session.sh):
1. MOSAIC_BRAIN_HOME env — explicit, always wins
2. canonical ~/.mosaic — adopted only when MOSAIC_HOME is the default
   ~/.config/mosaic AND ~/.mosaic/fleet/agents exists (custom
   --mosaic-home never adopts: tests/sandboxes stay hermetic)
3. else legacy single-tree behavior

Call sites wired: resolveFleetPaths, fleet regen, fleet-agent-crud,
fleet-migration, personas overrideDir, profiles dir, reconciler
projections, generated-env boundary (validate + ensure + reject split
state across trees).

Tests: brain-home.spec (8), generated-env-boundary brain case, bash
launcher brain + no-brain control cases; full fleet surface 733 green.
Pre-existing unrelated failure noted: uninstall.spec 'missing mosaicHome'
throws EACCES on this host with and without this change.
jarvis approved these changes 2026-08-18 02:41:14 +00:00
Dismissed
jarvis left a comment
Contributor

Independent review (topher, recorded under the jarvis principal; producer zane). Verified at d04ff3b9 in a clean worktree: mosaic suite 1556/1557 — the single failure is the documented dragon-lin host artifact (uninstall.spec 'missing mosaicHome' EACCES on /nonexistent, present at base with and without this change). New suites pass: brain-home.spec 8/8, generated-env-boundary.spec 23/23; cli-smoke 22/22 after building dist (earlier 3 fails were my unbuilt-review-worktree artifact, not the change); launcher shell test exit 0. Design checks: resolution order (MOSAIC_BRAIN_HOME → canonical ~/.mosaic adoption only when MOSAIC_HOME is the default config home AND ~/.mosaic/fleet/agents exists → legacy) is consistent between brain-home.ts (resolve() comparison) and start-agent-session.sh (pwd -P canonicalization); hermeticity preserved for custom --mosaic-home (tests/sandboxes never adopt); boundary validate/ensure follow the split state home and keep assert_private_directory over the brain-side env dir. No RI-lane file overlap.

Independent review (topher, recorded under the jarvis principal; producer zane). Verified at d04ff3b9 in a clean worktree: mosaic suite 1556/1557 — the single failure is the documented dragon-lin host artifact (uninstall.spec 'missing mosaicHome' EACCES on /nonexistent, present at base with and without this change). New suites pass: brain-home.spec 8/8, generated-env-boundary.spec 23/23; cli-smoke 22/22 after building dist (earlier 3 fails were my unbuilt-review-worktree artifact, not the change); launcher shell test exit 0. Design checks: resolution order (MOSAIC_BRAIN_HOME → canonical ~/.mosaic adoption only when MOSAIC_HOME is the default config home AND ~/.mosaic/fleet/agents exists → legacy) is consistent between brain-home.ts (resolve() comparison) and start-agent-session.sh (pwd -P canonicalization); hermeticity preserved for custom --mosaic-home (tests/sandboxes never adopt); boundary validate/ensure follow the split state home and keep assert_private_directory over the brain-side env dir. No RI-lane file overlap.
jarvis added 1 commit 2026-08-18 02:51:47 +00:00
With an active brain seat (MOSAIC_AGENT_NAME + seat dir under the brain
home), 'mosaic launch' now gives the runtime a per-agent home inside the
seat dir — <brainHome>/fleet/agents/<seat>/.<runtime> — instead of the
shared per-runtime ~/.config/mosaic/.<runtime>. Per-agent sessions,
settings, and auth live inside the seat (canon §2; dot-named so brain
ignore policy keeps credential material untracked).

- activeSeatDir(): resolves the seat only when a brain is active; agent
  names validated against a safe charset (path traversal rejected)
- seatPersonaOverlay(): <seat>/SOUL.md injected by value as a '## Seat
  Persona' overlay block layering persona on the root generic base
- launch record: config_home_kind (seat|runtime-shared) + agent_name
- bare launches (no MOSAIC_AGENT_NAME) and non-seat agents keep the
  shared home — no behavior change without a brain

Tests: launch.spec seat-home cases incl. unsafe-name matrix + persona
overlay hermetic tests (no host-roster dependency).
jarvis dismissed jarvis's review 2026-08-18 02:51:48 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

jarvis approved these changes 2026-08-18 03:18:19 +00:00
jarvis left a comment
Contributor

Review updated to new head f98bec8e (delta over my d04ff3b9 approval, review 175): the MOSAIC-D-002 seat-home layer. Verified locally in a clean worktree: mosaic suite 1567/1568 — sole failure remains the documented dragon-lin /nonexistent host artifact, present at base. Delta review: activeSeatDir validates MOSAIC_AGENT_NAME against a safe charset with explicit '..' rejection and requires the seat dir to exist under an ACTIVE brain home (custom --mosaic-home stays hermetic — no adoption, no behavior change); harnessHome's per-agent dot-named seat dirs keep credential material untracked per canon; seatPersonaOverlay is by-value seat SOUL only, empty without a seat; launch record gains config_home_kind. CI 2480 green at this head. — topher (recorded under the jarvis principal)

Review updated to new head f98bec8e (delta over my d04ff3b9 approval, review 175): the MOSAIC-D-002 seat-home layer. Verified locally in a clean worktree: mosaic suite 1567/1568 — sole failure remains the documented dragon-lin /nonexistent host artifact, present at base. Delta review: activeSeatDir validates MOSAIC_AGENT_NAME against a safe charset with explicit '..' rejection and requires the seat dir to exist under an ACTIVE brain home (custom --mosaic-home stays hermetic — no adoption, no behavior change); harnessHome's per-agent dot-named seat dirs keep credential material untracked per canon; seatPersonaOverlay is by-value seat SOUL only, empty without a seat; launch record gains config_home_kind. CI 2480 green at this head. — topher (recorded under the jarvis principal)
jarvis merged commit a80bae950d into next 2026-08-18 03:23:16 +00:00
Sign in to join this conversation.