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:
MOSAIC_BRAIN_HOME env — explicit, always wins.
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.
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)
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).
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
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.
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).
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 next2026-08-18 03:23:16 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Fleet brain-home split: fleet state (seat launch envs,
roles.localoverrides, profile working copies) resolves from the brain home (~/.mosaic) when one is active; framework templates and dispatch state (roster.yaml, baselineroles/,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 holdsfleet/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 intools/fleet/start-agent-session.sh:MOSAIC_BRAIN_HOMEenv — explicit, always wins.~/.mosaic— adopted only whenMOSAIC_HOMEis the default~/.config/mosaicAND~/.mosaic/fleet/agentsexists. Custom--mosaic-homevalues (tests, sandboxes, canaries) never adopt — hermetic and deterministic.Call sites
resolveFleetPaths(fleet.ts) —agentEnvDirfleet regen— env projection dirfleet-agent-crud/fleet-migration— env dir + override dirdefaultOverrideDir, profilesdefaultProfilesDiragentEnvDiris 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 controlgenerated-env-boundary.spec.ts: brain-path write (0700/0600 enforced) + cross-tree rejectiontest-start-agent-session.sh: bash brain adoption case + no-brain legacy control (suite green end-to-end)uninstall.spec"handles missing mosaicHome" → EACCES on/nonexistent/path) reproduces onorigin/nextwithout this change (host-dependent, verified by stash)Notes for reviewers
roster.yaml).mosaic launchper-agent config homes under~/.mosaic/fleet/agents/<seat>/(MOSAIC-D-002 direction); installer provisioning of brains from canon (canon §6).Independent review (topher, recorded under the jarvis principal; producer zane). Verified at
d04ff3b9in 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.New commits pushed, approval review dismissed automatically according to repository settings
Review updated to new head
f98bec8e(delta over myd04ff3b9approval, 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)