feat(fleet): brain-home split — fleet state under ~/.mosaic, templates stay config-home (#1298)
ci/woodpecker/push/publish Pipeline failed
ci/woodpecker/push/publish Pipeline failed
Co-authored-by: Jason Woltje <[email protected]>
This commit was merged in pull request #1298.
This commit is contained in:
@@ -349,3 +349,90 @@ describe('registerRuntimeLaunchers — claudex (EXPERIMENTAL overlay)', () => {
|
||||
expect(mockExit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Seat harness homes (MOSAIC-D-002, brain-home split) ────────────────────
|
||||
|
||||
import { activeSeatDir, seatPersonaOverlay } from './launch.js';
|
||||
|
||||
describe('activeSeatDir — per-agent harness home resolution', () => {
|
||||
let root: string;
|
||||
const savedAgentName = process.env['MOSAIC_AGENT_NAME'];
|
||||
const savedBrainHome = process.env['MOSAIC_BRAIN_HOME'];
|
||||
|
||||
beforeEach(() => {
|
||||
root = mkdtempSync(join(tmpdir(), 'mosaic-seat-home-'));
|
||||
delete process.env['MOSAIC_BRAIN_HOME'];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
if (savedAgentName === undefined) {
|
||||
delete process.env['MOSAIC_AGENT_NAME'];
|
||||
} else {
|
||||
process.env['MOSAIC_AGENT_NAME'] = savedAgentName;
|
||||
}
|
||||
if (savedBrainHome !== undefined) {
|
||||
process.env['MOSAIC_BRAIN_HOME'] = savedBrainHome;
|
||||
} else {
|
||||
delete process.env['MOSAIC_BRAIN_HOME'];
|
||||
}
|
||||
});
|
||||
|
||||
it('resolves the seat dir when MOSAIC_BRAIN_HOME carries the seat', () => {
|
||||
const seat = join(root, 'brain', 'fleet', 'agents', 'coder0');
|
||||
mkdirSync(seat, { recursive: true });
|
||||
process.env['MOSAIC_AGENT_NAME'] = 'coder0';
|
||||
process.env['MOSAIC_BRAIN_HOME'] = join(root, 'brain');
|
||||
|
||||
expect(activeSeatDir(join(root, 'config', 'mosaic'))).toBe(seat);
|
||||
});
|
||||
|
||||
it('returns undefined without an agent name (bare launches stay shared)', () => {
|
||||
delete process.env['MOSAIC_AGENT_NAME'];
|
||||
expect(activeSeatDir(join(root, 'config', 'mosaic'))).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined when the seat dir does not exist in the brain', () => {
|
||||
process.env['MOSAIC_AGENT_NAME'] = 'ghost';
|
||||
process.env['MOSAIC_BRAIN_HOME'] = join(root, 'brain');
|
||||
mkdirSync(join(root, 'brain', 'fleet', 'agents'), { recursive: true });
|
||||
|
||||
expect(activeSeatDir(join(root, 'config', 'mosaic'))).toBeUndefined();
|
||||
});
|
||||
|
||||
it.each(['../escape', 'a/b', '.hidden-start', '', 'spaced name'])(
|
||||
'rejects unsafe agent name %j (path traversal cannot leave the seat store)',
|
||||
(name: string) => {
|
||||
process.env['MOSAIC_AGENT_NAME'] = name;
|
||||
process.env['MOSAIC_BRAIN_HOME'] = join(root, 'brain');
|
||||
|
||||
expect(activeSeatDir(join(root, 'config', 'mosaic'))).toBeUndefined();
|
||||
},
|
||||
);
|
||||
|
||||
it('seatPersonaOverlay renders the seat SOUL.md as an overlay block', () => {
|
||||
const seat = join(root, 'brain', 'fleet', 'agents', 'coder0');
|
||||
mkdirSync(seat, { recursive: true });
|
||||
writeFileSync(join(seat, 'SOUL.md'), '# coder0 — code seat persona\n\nShips tested code.\n');
|
||||
process.env['MOSAIC_AGENT_NAME'] = 'coder0';
|
||||
process.env['MOSAIC_BRAIN_HOME'] = join(root, 'brain');
|
||||
|
||||
const overlay = seatPersonaOverlay(join(root, 'config', 'mosaic'));
|
||||
expect(overlay).toContain('## Seat Persona');
|
||||
expect(overlay).toContain('coder0 — code seat persona');
|
||||
});
|
||||
|
||||
it('seatPersonaOverlay is empty when the seat carries no SOUL.md', () => {
|
||||
const seat = join(root, 'brain', 'fleet', 'agents', 'coder0');
|
||||
mkdirSync(seat, { recursive: true });
|
||||
process.env['MOSAIC_AGENT_NAME'] = 'coder0';
|
||||
process.env['MOSAIC_BRAIN_HOME'] = join(root, 'brain');
|
||||
|
||||
expect(seatPersonaOverlay(join(root, 'config', 'mosaic'))).toBe('');
|
||||
});
|
||||
|
||||
it('seatPersonaOverlay is empty when no agent name is set', () => {
|
||||
delete process.env['MOSAIC_AGENT_NAME'];
|
||||
expect(seatPersonaOverlay(join(root, 'config', 'mosaic'))).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user