fix(fleet): enforce exact comms authority (#787)
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

This commit was merged in pull request #787.
This commit is contained in:
2026-07-16 00:32:23 +00:00
parent c1aecfabe9
commit adad486b6f
22 changed files with 3534 additions and 859 deletions

View File

@@ -1,30 +1,43 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import {
chmodSync,
mkdtempSync,
mkdirSync,
writeFileSync,
rmSync,
readFileSync,
symlinkSync,
} from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { parseFleetRosterV1, type FleetRoster, type FleetAgent } from './fleet-roster-v1.js';
import {
parseRosterAgents,
buildFleetCommsBlock,
renderPeerReach,
readFleetCommsBlock,
resolveCommsBlock,
type CommsPeer,
resolvePeerCommand,
renderToolsContractStatus,
} from './comms-onboarding.js';
const ROSTER = [
'version: 1',
'transport: tmux',
'tmux:',
' socket_name: mosaic-fleet',
'agents:',
' - name: orchestrator',
' runtime: claude',
' class: orchestrator',
' host: w-jarvis',
' - name: enhancer',
' runtime: claude',
' class: enhancer',
' host: w-jarvis',
' - name: coder0',
' runtime: pi',
' class: implementer',
' # a manually-listed cross-host peer (pre-federation stopgap)',
' host: w-jarvis',
' - name: coder0-0',
' runtime: claude',
' class: implementer',
@@ -33,206 +46,687 @@ const ROSTER = [
'',
].join('\n');
describe('parseRosterAgents', () => {
it('parses name + class + optional host/ssh', () => {
const peers = parseRosterAgents(ROSTER);
expect(peers.map((p) => p.name)).toEqual(['orchestrator', 'enhancer', 'coder0', 'coder0-0']);
expect(peers.find((p) => p.name === 'coder0')).toMatchObject({ className: 'implementer' });
expect(peers.find((p) => p.name === 'coder0-0')).toMatchObject({
className: 'implementer',
function roster(source = ROSTER): FleetRoster {
return parseFleetRosterV1(source, 'yaml');
}
describe('shared fleet roster v1 resolver', () => {
it('resolves comms fields and the global socket through the canonical roster contract', () => {
const resolved = roster();
expect(resolved.tmux.socketName).toBe('mosaic-fleet');
expect(resolved.agents.find((agent) => agent.name === 'coder0-0')).toMatchObject({
className: 'code',
host: '10.1.10.37',
ssh: 'jwoltje@10.1.10.37',
});
// local agents have no host/ssh
expect(peers.find((p) => p.name === 'orchestrator')!.host).toBeUndefined();
});
it('parses an optional per-agent socket', () => {
const peers = parseRosterAgents(
['agents:', ' - name: a', ' class: worker', ' socket: mosaic-fleet'].join('\n'),
it('rejects unknown fields instead of leniently constructing a second roster view', () => {
expect(() => parseFleetRosterV1(`${ROSTER}\nunknown: value\n`, 'yaml')).toThrow(
/unknown field/i,
);
expect(peers[0]).toMatchObject({ name: 'a', socket: 'mosaic-fleet' });
});
it('stops at the next top-level key', () => {
const peers = parseRosterAgents(
['agents:', ' - name: a', ' class: worker', 'defaults:', ' working_directory: ~'].join(
'\n',
it('rejects an unsupported independent per-agent socket instead of targeting a nonexistent session', () => {
expect(() =>
roster(
ROSTER.replace(
' host: w-jarvis\n - name: coder0',
' host: w-jarvis\n socket: other-socket\n - name: coder0',
),
),
);
expect(peers.map((p) => p.name)).toEqual(['a']);
).toThrow(/independent per-agent sockets are not supported/i);
});
it('rejects unsafe operational targeting values', () => {
expect(() =>
roster(ROSTER.replace(' ssh: jwoltje@10.1.10.37', ' ssh: host;touch-owned')),
).toThrow(/unsupported targeting characters/i);
});
it('normalizes matching connector settings for YAML and JSON rosters', () => {
const yamlSource = `${ROSTER}connector:\n kind: discord\n discord:\n channel_id: "123"\n`;
const jsonSource = JSON.stringify({
version: 1,
transport: 'tmux',
agents: [{ name: 'a', runtime: 'claude', class: 'worker' }],
connector: {
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: '@a:example',
room_id: '!room:example',
},
},
});
expect(parseFleetRosterV1(yamlSource, 'yaml').connector).toEqual({
kind: 'discord',
discord: { channelId: '123' },
});
expect(parseFleetRosterV1(jsonSource, 'json').connector).toEqual({
kind: 'matrix',
matrix: {
homeserverUrl: 'https://matrix.example',
userId: '@a:example',
roomId: '!room:example',
},
});
});
it.each([
['discord channel_id', { kind: 'discord', discord: { channel_id: '' } }],
['discord channel_id whitespace', { kind: 'discord', discord: { channel_id: ' ' } }],
[
'matrix homeserver_url',
{
kind: 'matrix',
matrix: { homeserver_url: '', user_id: '@a:example', room_id: '!room:example' },
},
],
[
'matrix homeserver_url whitespace',
{
kind: 'matrix',
matrix: { homeserver_url: '\t', user_id: '@a:example', room_id: '!room:example' },
},
],
[
'matrix user_id',
{
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: '',
room_id: '!room:example',
},
},
],
[
'matrix user_id whitespace',
{
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: ' ',
room_id: '!room:example',
},
},
],
[
'matrix room_id',
{
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: '@a:example',
room_id: '',
},
},
],
[
'matrix room_id whitespace',
{
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: '@a:example',
room_id: '\n',
},
},
],
])(
'rejects empty or whitespace-only parser-required connector string: %s',
(_label, connector) => {
expect(() =>
parseFleetRosterV1(
JSON.stringify({
version: 1,
transport: 'tmux',
agents: [{ name: 'a', runtime: 'claude', class: 'worker' }],
connector,
}),
'json',
),
).toThrow(/required/i);
},
);
it.each([
['tmux with discord settings', { kind: 'tmux', discord: { channel_id: '123' } }],
['discord without discord settings', { kind: 'discord' }],
[
'discord with matrix settings',
{ kind: 'discord', discord: { channel_id: '123' }, matrix: {} },
],
['matrix without matrix settings', { kind: 'matrix' }],
[
'matrix with discord settings',
{
kind: 'matrix',
matrix: {
homeserver_url: 'https://matrix.example',
user_id: '@a:example',
room_id: '!room:example',
},
discord: { channel_id: '123' },
},
],
])('rejects connector kind/settings mismatch: %s', (_label, connector) => {
expect(() =>
parseFleetRosterV1(
JSON.stringify({
version: 1,
transport: 'tmux',
agents: [{ name: 'a', runtime: 'claude', class: 'worker' }],
connector,
}),
'json',
),
).toThrow();
});
it.each([
['tmux socket', ['tmux', 'socket_name'], ['tmux', 'socketName'], 'same', 'different'],
['tmux holder', ['tmux', 'holder_session'], ['tmux', 'holderSession'], 'same', 'different'],
[
'defaults working directory',
['defaults', 'working_directory'],
['defaults', 'workingDirectory'],
'same',
'different',
],
[
'runtime reset command',
['runtimes', 'claude', 'reset_command'],
['runtimes', 'claude', 'resetCommand'],
'same',
'different',
],
[
'agent working directory',
['agents', 0, 'working_directory'],
['agents', 0, 'workingDirectory'],
'same',
'different',
],
[
'agent model hint',
['agents', 0, 'model_hint'],
['agents', 0, 'modelHint'],
'same',
'different',
],
[
'agent reasoning level',
['agents', 0, 'reasoning_level'],
['agents', 0, 'reasoningLevel'],
'same',
'different',
],
[
'agent tool policy',
['agents', 0, 'tool_policy'],
['agents', 0, 'toolPolicy'],
'same',
'different',
],
[
'agent persistent persona',
['agents', 0, 'persistent_persona'],
['agents', 0, 'persistentPersona'],
true,
false,
],
[
'agent reset between tasks',
['agents', 0, 'reset_between_tasks'],
['agents', 0, 'resetBetweenTasks'],
true,
false,
],
[
'agent kickstart template',
['agents', 0, 'kickstart_template'],
['agents', 0, 'kickstartTemplate'],
'same',
'different',
],
] as const)(
'rejects conflicting %s aliases and accepts identical aliases',
(_label, snake, camel, same, different) => {
const base: Record<string, unknown> = {
version: 1,
transport: 'tmux',
tmux: {},
defaults: {},
runtimes: { claude: {} },
agents: [{ name: 'a', runtime: 'claude', class: 'worker' }],
};
const assign = (
root: Record<string, unknown>,
path: readonly (string | number)[],
value: unknown,
) => {
let cursor: unknown = root;
for (const segment of path.slice(0, -1)) {
cursor = (cursor as Record<string | number, unknown>)[segment];
}
(cursor as Record<string | number, unknown>)[path.at(-1)!] = value;
};
assign(base, snake, same);
assign(base, camel, different);
expect(() => parseFleetRosterV1(JSON.stringify(base), 'json')).toThrow(
/aliases .* conflict/i,
);
assign(base, camel, same);
expect(() => parseFleetRosterV1(JSON.stringify(base), 'json')).not.toThrow();
},
);
});
describe('renderPeerReach — same-host vs cross-host', () => {
describe('renderPeerReach — exact same-host/cross-host/socket targeting', () => {
const send = '/home/u/.config/mosaic/tools/tmux/agent-send.sh';
const base: FleetAgent = {
name: 'peer',
runtime: 'claude',
className: 'worker',
};
it('renders the short form for a same-host peer', () => {
const peer: CommsPeer = { name: 'enhancer', className: 'enhancer' };
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(`${send} -s enhancer -m "…"`);
});
it('renders the -H form for a cross-host peer using ssh', () => {
const peer: CommsPeer = {
name: 'coder0-0',
className: 'implementer',
host: '10.1.10.37',
ssh: 'jwoltje@10.1.10.37',
};
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(
`${send} -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`,
it('renders the global named socket and omits -H for a same-host peer', () => {
expect(renderPeerReach(base, 'w-jarvis', 'w-jarvis', 'mosaic-fleet', send)).toBe(
`${send} -L mosaic-fleet -s peer -m "…"`,
);
});
it('falls back to host when a cross-host peer has no ssh', () => {
const peer: CommsPeer = { name: 'x', className: 'worker', host: '10.0.0.9' };
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(`${send} -H 10.0.0.9 -s x -m "…"`);
});
it('treats a peer whose host equals the fleet host as same-host', () => {
const peer: CommsPeer = { name: 'y', className: 'worker', host: 'w-jarvis' };
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(`${send} -s y -m "…"`);
});
it('emits NO -L for an unset/default socket', () => {
const peer: CommsPeer = { name: 'lead', className: 'orchestrator' };
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(`${send} -s lead -m "…"`);
});
it('emits -L <socket> for a named socket', () => {
const peer: CommsPeer = { name: 'coder0', className: 'implementer', socket: 'mosaic-fleet' };
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(
`${send} -L mosaic-fleet -s coder0 -m "…"`,
);
});
it('combines -L (named socket) and -H (cross-host) in order', () => {
const peer: CommsPeer = {
it('uses only the explicit roster ssh target for a cross-host peer', () => {
const peer: FleetAgent = {
...base,
name: 'coder0-0',
className: 'implementer',
host: '10.1.10.37',
ssh: 'jwoltje@10.1.10.37',
socket: 'mosaic-fleet',
};
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(
expect(renderPeerReach(peer, 'w-jarvis', 'w-jarvis', 'mosaic-fleet', send)).toBe(
`${send} -L mosaic-fleet -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`,
);
});
it('fails closed when a cross-host peer has no explicit roster ssh target', () => {
const peer: FleetAgent = { ...base, name: 'x', host: '10.0.0.9' };
expect(() => renderPeerReach(peer, 'w-jarvis', 'w-jarvis', 'mosaic-fleet', send)).toThrow(
/explicit roster ssh target/i,
);
});
it('renders only the fleet-wide supported socket', () => {
const peer: FleetAgent = { ...base, socket: 'mosaic-fleet' };
expect(renderPeerReach(peer, 'w-jarvis', 'w-jarvis', 'mosaic-fleet', send)).toBe(
`${send} -L mosaic-fleet -s peer -m "…"`,
);
});
it('resolves hostless peers against the stable fleet-host baseline, not the viewer host', () => {
const peer: FleetAgent = { ...base, ssh: 'fleet-user@w-jarvis' };
expect(renderPeerReach(peer, 'remote-host', 'w-jarvis', 'mosaic-fleet', send)).toBe(
`${send} -L mosaic-fleet -H fleet-user@w-jarvis -s peer -m "…"`,
);
});
it('shell-quotes an exact helper path that contains spaces', () => {
expect(
renderPeerReach(base, 'w-jarvis', 'w-jarvis', 'mosaic-fleet', '/home/test user/send.sh'),
).toBe(`'/home/test user/send.sh' -L mosaic-fleet -s peer -m "…"`);
});
it('omits -L only for the literal default socket', () => {
expect(renderPeerReach(base, 'w-jarvis', 'w-jarvis', '', send)).toBe(`${send} -s peer -m "…"`);
});
});
describe('buildFleetCommsBlock', () => {
const send = '/h/.config/mosaic/tools/tmux/agent-send.sh';
const agents = parseRosterAgents(ROSTER);
it('excludes self, lists peers, flags the orchestrator, and emits both address forms', () => {
it('renders authoritative identity, exact rows, generation, and no operational metavariables', () => {
const block = buildFleetCommsBlock({
selfName: 'enhancer',
agents,
fleetHost: 'w-jarvis',
roster: roster(),
localHost: 'ignored-process-host',
agentSendPath: send,
});
expect(block).toContain('# Fleet Comms');
expect(block).toContain('You are **enhancer**');
// criterion 1: agent's own [host:session] identity
expect(block).toContain('`[w-jarvis:enhancer]`');
// self excluded
expect(block).toContain('Host: `w-jarvis`');
expect(block).toContain('Agent/session: `enhancer`');
expect(block).toContain('tmux socket: `mosaic-fleet`');
expect(block).toContain(`Helper: \`${send}\``);
expect(block).toMatch(/Comms generation: `[a-f0-9]{64}`/);
expect(block).not.toMatch(/\|\s*enhancer\s*\|/);
// peers present
expect(block).toContain('| orchestrator |');
expect(block).toContain('point of contact');
// same-host peer short form
expect(block).toContain(`${send} -s coder0 -m "…"`);
// cross-host peer -H form + host annotation
expect(block).toContain(`${send} -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`);
expect(block).toContain('host `10.1.10.37`');
// conventions
expect(block).toContain('FLIP the preamble');
expect(block).toContain('ACCEPTED');
expect(block).toContain(`${send} -L mosaic-fleet -s orchestrator -m "…"`);
expect(block).toContain(`${send} -L mosaic-fleet -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`);
expect(block).toContain(`mosaic agent comms-block enhancer`);
expect(block).toMatch(/Never invent, substitute, or fuzzy-match/i);
expect(block).not.toMatch(
/<(?:user@host|src_host|src_session|dst_host|dst_session|target-session)>/,
);
expect(block).not.toContain('FLIP the preamble');
});
it('returns empty when the agent has no peers', () => {
expect(
it('changes the generation when a rendered peer role changes', () => {
const generation = (block: string) => block.match(/Comms generation: `([a-f0-9]{64})`/)?.[1];
const before = buildFleetCommsBlock({
selfName: 'enhancer',
roster: roster(),
localHost: 'w-jarvis',
agentSendPath: send,
});
const changedRoster = roster(ROSTER.replace('class: implementer', 'class: reviewer'));
const after = buildFleetCommsBlock({
selfName: 'enhancer',
roster: changedRoster,
localHost: 'w-jarvis',
agentSendPath: send,
});
expect(generation(before)).toMatch(/^[a-f0-9]{64}$/);
expect(generation(after)).not.toBe(generation(before));
});
it('fails closed when any rendered cross-host row lacks ssh', () => {
const bad = roster(ROSTER.replace(' ssh: jwoltje@10.1.10.37\n', ''));
expect(() =>
buildFleetCommsBlock({
selfName: 'solo',
agents: [{ name: 'solo', className: 'orchestrator' }],
fleetHost: 'h',
selfName: 'enhancer',
roster: bad,
localHost: 'w-jarvis',
agentSendPath: send,
}),
).toBe('');
).toThrow(/explicit roster ssh target/i);
});
it('still renders authoritative local identity when the agent has no peers', () => {
const solo = roster(
[
'version: 1',
'transport: tmux',
'agents:',
' - name: solo',
' runtime: claude',
' class: orchestrator',
].join('\n'),
);
const block = buildFleetCommsBlock({
selfName: 'solo',
roster: solo,
localHost: 'h',
agentSendPath: send,
});
expect(block).toContain('Host: `h`');
expect(block).toContain('Agent/session: `solo`');
expect(block).toContain('Role/class: `orchestrator`');
expect(block).toMatch(/Comms generation: `[a-f0-9]{64}`/);
expect(block).toContain('This roster has no peers');
expect(block).toContain('## Solo authority boundaries');
expect(block).toContain('no peer, orchestrator, or remote communication authority');
expect(block).toContain('Do not send, infer a target, or claim fleet coordination');
});
});
describe('readFleetCommsBlock — situational (the context a spawned agent gets)', () => {
describe('resolvePeerCommand', () => {
const send = '/h/.config/mosaic/tools/tmux/agent-send.sh';
it('returns one exact known-peer row', () => {
const result = resolvePeerCommand(roster(), 'enhancer', 'coder0-0', 'w-jarvis', send);
expect(result.ok).toBe(true);
expect(result.command).toContain('-H jwoltje@10.1.10.37 -s coder0-0');
});
it('fails closed for an unknown peer with exact-name discovery guidance', () => {
const result = resolvePeerCommand(roster(), 'enhancer', 'invented-host', 'w-jarvis', send);
expect(result.ok).toBe(false);
expect(result.command).toBe('');
expect(result.error).toContain('invented-host');
expect(result.error).toContain('orchestrator, coder0, coder0-0');
expect(result.error).toContain('mosaic agent comms-block enhancer');
expect(result.error).not.toContain('tmux ls');
});
});
describe('readFleetCommsBlock — spawned-agent context', () => {
let home: string;
beforeEach(() => {
home = mkdtempSync(join(tmpdir(), 'mosaic-comms-'));
mkdirSync(join(home, 'fleet'), { recursive: true });
mkdirSync(join(home, 'tools', 'tmux'), { recursive: true });
writeFileSync(join(home, 'fleet', 'roster.yaml'), ROSTER);
const helper = join(home, 'tools', 'tmux', 'agent-send.sh');
writeFileSync(helper, '#!/bin/sh\n');
chmodSync(helper, 0o755);
});
afterEach(() => rmSync(home, { recursive: true, force: true }));
it('builds the cheat-sheet with correct peer addresses for a fleet member', () => {
const block = readFleetCommsBlock(home, 'orchestrator', 'w-jarvis');
expect(block).toContain('# Fleet Comms');
expect(block).toContain('| enhancer |');
expect(block).toContain(`${join(home, 'tools', 'tmux', 'agent-send.sh')} -s coder0 -m "…"`);
expect(block).toContain('-H jwoltje@10.1.10.37 -s coder0-0');
expect(block).not.toMatch(/\|\s*orchestrator\s*\|/); // self excluded
it('uses the authoritative self host and global socket from the shared roster resolver', () => {
const result = readFleetCommsBlock(home, 'enhancer', 'process-host-must-not-win');
expect(result.ok).toBe(true);
expect(result.output).toContain('Host: `w-jarvis`');
expect(result.output).toContain('tmux socket: `mosaic-fleet`');
expect(result.output).toContain('-L mosaic-fleet -s orchestrator');
});
it('returns empty when MOSAIC_AGENT_NAME is unset, no roster, or agent not a member', () => {
expect(readFleetCommsBlock(home, undefined, 'w-jarvis')).toBe('');
expect(readFleetCommsBlock(home, 'stranger', 'w-jarvis')).toBe('');
expect(readFleetCommsBlock(mkdtempSync(join(tmpdir(), 'noroster-')), 'orchestrator')).toBe('');
it('fails closed for a requested fleet identity that is absent', () => {
const result = readFleetCommsBlock(home, 'stranger', 'w-jarvis');
expect(result.ok).toBe(false);
expect(result.output).toBe('');
expect(result.error).toContain('Known exact names');
});
it('resolves a supported JSON-only installed roster', () => {
rmSync(join(home, 'fleet', 'roster.yaml'));
writeFileSync(
join(home, 'fleet', 'roster.json'),
JSON.stringify({
version: 1,
transport: 'tmux',
tmux: { socket_name: 'mosaic-fleet' },
agents: [
{ name: 'enhancer', runtime: 'claude', class: 'enhancer', host: 'w-jarvis' },
{ name: 'orchestrator', runtime: 'claude', class: 'orchestrator', host: 'w-jarvis' },
],
}),
);
const result = readFleetCommsBlock(home, 'enhancer', 'process-host-must-not-win');
expect(result.ok).toBe(true);
expect(result.output).toContain('-L mosaic-fleet -s orchestrator');
});
it('fails closed on a YAML I/O error instead of falling back to JSON', () => {
rmSync(join(home, 'fleet', 'roster.yaml'));
mkdirSync(join(home, 'fleet', 'roster.yaml'));
writeFileSync(
join(home, 'fleet', 'roster.json'),
JSON.stringify({
version: 1,
transport: 'tmux',
agents: [{ name: 'enhancer', runtime: 'claude', class: 'enhancer' }],
}),
);
const result = readFleetCommsBlock(home, 'enhancer', 'w-jarvis');
expect(result.ok).toBe(false);
expect(result.error).toContain('invalid fleet roster at');
expect(result.error).toContain('roster.yaml');
});
it.each([
['missing', () => rmSync(join(home, 'tools', 'tmux', 'agent-send.sh'))],
[
'directory',
() => {
rmSync(join(home, 'tools', 'tmux', 'agent-send.sh'));
mkdirSync(join(home, 'tools', 'tmux', 'agent-send.sh'));
},
],
[
'symlink',
() => {
const helper = join(home, 'tools', 'tmux', 'agent-send.sh');
rmSync(helper);
writeFileSync(join(home, 'real-send.sh'), '#!/bin/sh\n');
symlinkSync(join(home, 'real-send.sh'), helper);
},
],
['non-executable', () => chmodSync(join(home, 'tools', 'tmux', 'agent-send.sh'), 0o644)],
])('fails closed for a %s helper with deterministic repair guidance', (_case, mutate) => {
mutate();
const result = readFleetCommsBlock(home, 'enhancer', 'w-jarvis');
expect(result.ok).toBe(false);
expect(result.output).toBe('');
expect(result.error).toContain('mosaic update --repair-tools');
expect(result.error).toContain('no active context or session was rewritten');
});
it('does not rewrite the roster while resolving context', () => {
const path = join(home, 'fleet', 'roster.yaml');
const before = readFileSync(path, 'utf8');
readFleetCommsBlock(home, 'enhancer', 'w-jarvis');
expect(readFileSync(path, 'utf8')).toBe(before);
});
});
describe('resolveCommsBlock — `mosaic fleet comms-block <role>` emitter semantics', () => {
// The emitter wraps readFleetCommsBlock but must NEVER print an empty string silently:
// an unknown role / missing roster has to fail loud (caller maps !ok → stderr + exit 1)
// so `mosaic fleet comms-block bogus` is a visible error, not a confusing no-op. The
// success path returns the block verbatim for `mosaic fleet comms-block <peer>` previews.
describe('renderToolsContractStatus — non-mutating install drift', () => {
let home: string;
beforeEach(() => {
home = mkdtempSync(join(tmpdir(), 'mosaic-tools-status-'));
mkdirSync(join(home, 'defaults'), { recursive: true });
writeFileSync(
join(home, 'defaults', 'TOOLS.md'),
'# authoritative tools\n<!-- fleet-comms-contract: 1 -->\n',
);
});
afterEach(() => rmSync(home, { recursive: true, force: true }));
it('uses the supported repair command when installed TOOLS.md is missing', () => {
const status = renderToolsContractStatus(home);
expect(status).toContain('mosaic update --repair-tools');
expect(status).not.toContain('--reseed');
expect(status).toContain('authorized operator');
});
it('reports stale preserved content without rewriting it', () => {
const path = join(home, 'TOOLS.md');
const stale = '# customized tools\n';
writeFileSync(path, stale);
const status = renderToolsContractStatus(home);
expect(status).toContain('fleet-comms-contract: 1');
expect(status).toContain('digest-qualified backup');
expect(status).toContain('mosaic update --repair-tools');
expect(status).toContain('active context was not rewritten');
expect(readFileSync(path, 'utf8')).toBe(stale);
});
it('does not accept marker-only customized content as current', () => {
const path = join(home, 'TOOLS.md');
writeFileSync(path, '<!-- fleet-comms-contract: 1 -->\ncorrupt\n');
expect(renderToolsContractStatus(home)).toContain('does not byte-match');
});
it('rejects markerless byte-equal source and installed content', () => {
const content = '# markerless but equal\n';
writeFileSync(join(home, 'defaults', 'TOOLS.md'), content);
writeFileSync(join(home, 'TOOLS.md'), content);
const status = renderToolsContractStatus(home);
expect(status).toContain('source contract');
expect(status).toContain('does not declare the expected');
});
it.each([
['source', join('defaults', 'TOOLS.md')],
['installed', 'TOOLS.md'],
])('rejects a wrong contract version in %s content', (_case, relativePath) => {
const current = '# authoritative tools\n<!-- fleet-comms-contract: 1 -->\n';
writeFileSync(join(home, 'TOOLS.md'), current);
writeFileSync(join(home, 'defaults', 'TOOLS.md'), current);
writeFileSync(join(home, relativePath), current.replace('contract: 1', 'contract: 2'));
expect(renderToolsContractStatus(home)).not.toBe('');
});
it('treats installed TOOLS.md symlinks as stale without following or rewriting them', () => {
const external = join(home, 'external-tools.md');
const externalContent = '# external\n<!-- fleet-comms-contract: 1 -->\n';
writeFileSync(external, externalContent);
symlinkSync(external, join(home, 'TOOLS.md'));
const status = renderToolsContractStatus(home);
expect(status).toContain('unavailable');
expect(status).toContain('mosaic update --repair-tools');
expect(readFileSync(external, 'utf8')).toBe(externalContent);
});
it('treats source TOOLS.md symlinks as unavailable without following them', () => {
const external = join(home, 'external-source.md');
const content = '# authoritative tools\n<!-- fleet-comms-contract: 1 -->\n';
writeFileSync(external, content);
rmSync(join(home, 'defaults', 'TOOLS.md'));
symlinkSync(external, join(home, 'defaults', 'TOOLS.md'));
writeFileSync(join(home, 'TOOLS.md'), content);
const status = renderToolsContractStatus(home);
expect(status).toContain('source contract');
expect(status).toContain('unavailable');
expect(readFileSync(external, 'utf8')).toBe(content);
});
it('accepts byte-equal bounded source and installed contracts', () => {
const source = readFileSync(join(home, 'defaults', 'TOOLS.md'), 'utf8');
writeFileSync(join(home, 'TOOLS.md'), source);
expect(renderToolsContractStatus(home)).toBe('');
});
});
describe('resolveCommsBlock — mosaic agent comms-block', () => {
let home: string;
beforeEach(() => {
home = mkdtempSync(join(tmpdir(), 'mosaic-commsblk-'));
mkdirSync(join(home, 'fleet'), { recursive: true });
mkdirSync(join(home, 'tools', 'tmux'), { recursive: true });
writeFileSync(join(home, 'fleet', 'roster.yaml'), ROSTER);
const helper = join(home, 'tools', 'tmux', 'agent-send.sh');
writeFileSync(helper, '#!/bin/sh\n');
chmodSync(helper, 0o755);
});
afterEach(() => rmSync(home, { recursive: true, force: true }));
it('returns ok + the cheat-sheet for a roster member', () => {
const res = resolveCommsBlock(home, 'orchestrator', 'w-jarvis');
expect(res.ok).toBe(true);
expect(res.output).toContain('# Fleet Comms');
expect(res.output).toContain('| enhancer |');
expect(res.error).toBeUndefined();
it('returns the exact contract for a roster member', () => {
const result = resolveCommsBlock(home, 'enhancer');
expect(result.ok).toBe(true);
expect(result.output).toContain('Host: `w-jarvis`');
expect(result.error).toBeUndefined();
});
it('fails loud (not ok + error naming the role) for a non-member — never silently empty', () => {
const res = resolveCommsBlock(home, 'stranger', 'w-jarvis');
expect(res.ok).toBe(false);
expect(res.output).toBe('');
expect(res.error).toContain('stranger');
it('fails loud and lists known exact names for a non-member', () => {
const result = resolveCommsBlock(home, 'stranger');
expect(result.ok).toBe(false);
expect(result.output).toBe('');
expect(result.error).toContain('stranger');
expect(result.error).toContain('orchestrator');
expect(result.error).toContain('enhancer');
});
it('fails loud when no roster exists at the mosaic home', () => {
it('fails loud when no roster exists', () => {
const noRoster = mkdtempSync(join(tmpdir(), 'mosaic-noroster-'));
const res = resolveCommsBlock(noRoster, 'orchestrator', 'w-jarvis');
expect(res.ok).toBe(false);
expect(res.error).toBeTruthy();
mkdirSync(join(noRoster, 'tools', 'tmux'), { recursive: true });
const helper = join(noRoster, 'tools', 'tmux', 'agent-send.sh');
writeFileSync(helper, '#!/bin/sh\n');
chmodSync(helper, 0o755);
const result = resolveCommsBlock(noRoster, 'orchestrator');
expect(result.ok).toBe(false);
expect(result.error).toContain('no fleet roster');
rmSync(noRoster, { recursive: true, force: true });
});
it('fails loud for a missing role argument', () => {
const res = resolveCommsBlock(home, undefined, 'w-jarvis');
expect(res.ok).toBe(false);
expect(res.error).toBeTruthy();
});
it('honors a host override so a peer can preview its own cross-host view', () => {
// coder0-0 viewing with its own host → its self-identity line uses that host.
const res = resolveCommsBlock(home, 'coder0-0', '10.1.10.37');
expect(res.ok).toBe(true);
expect(res.output).toContain('`[10.1.10.37:coder0-0]`');
const result = resolveCommsBlock(home, undefined);
expect(result.ok).toBe(false);
expect(result.error).toContain('requires');
});
});