fix(fleet): enforce exact comms authority
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jarvis
2026-07-15 16:28:03 -05:00
parent 499090508e
commit 0dc47cac92
22 changed files with 3304 additions and 859 deletions

View File

@@ -19,10 +19,17 @@ import { createRequire } from 'node:module';
import { homedir } from 'node:os';
import { join, dirname } from 'node:path';
import type { Command } from 'commander';
import { readFleetCommsBlock } from '../fleet/comms-onboarding.js';
import {
buildResolvedFleetCommsBlock,
renderToolsContractStatus,
resolveFleetIdentity,
} from '../fleet/comms-onboarding.js';
import { readRegularFileSecure } from '../fleet/secure-file.js';
import { readPersonaContractBlock } from '../fleet/persona-contract.js';
import { canonicalizeRoleClass } from './fleet-personas.js';
const MOSAIC_HOME = process.env['MOSAIC_HOME'] ?? join(homedir(), '.config', 'mosaic');
const MAX_INSTALLED_TOOLS_BYTES = 256 * 1024;
type RuntimeName = 'claude' | 'codex' | 'opencode' | 'pi';
@@ -185,6 +192,17 @@ function readOptional(path: string): string {
}
}
function readInstalledToolsSecure(mosaicHome: string): string {
try {
return readRegularFileSecure(join(mosaicHome, 'TOOLS.md'), {
root: mosaicHome,
maxBytes: MAX_INSTALLED_TOOLS_BYTES,
}).content.toString('utf8');
} catch {
return '';
}
}
function readJson(path: string): Record<string, unknown> | null {
try {
return JSON.parse(readFileSync(path, 'utf-8')) as Record<string, unknown>;
@@ -361,9 +379,25 @@ For required push/merge/issue-close/release actions, execute without routine con
parts.push('\n\n## Operator Overlay (USER.local.md)\n\n' + userLocal);
}
const fleetIdentity = resolveFleetIdentity(mosaicHome, process.env['MOSAIC_AGENT_NAME']);
if (!fleetIdentity.ok) {
throw new Error(`Fleet communications contract unavailable: ${fleetIdentity.error}`);
}
const canonicalMember = fleetIdentity.identity?.member;
if (canonicalMember && process.env['MOSAIC_AGENT_CLASS']?.trim()) {
const ambientClass = canonicalizeRoleClass(process.env['MOSAIC_AGENT_CLASS']).canonicalClass;
if (ambientClass !== canonicalMember.className) {
throw new Error(
`Ambient MOSAIC_AGENT_CLASS resolves to "${ambientClass}" but canonical roster member "${canonicalMember.name}" resolves to "${canonicalMember.className}". Refusing split identity authority.`,
);
}
}
// TOOLS.md
const tools = readOptional(join(mosaicHome, 'TOOLS.md'));
const tools = readInstalledToolsSecure(mosaicHome);
if (tools) parts.push('\n\n# Machine Tools\n\n' + tools);
const toolsContractStatus = renderToolsContractStatus(mosaicHome);
if (toolsContractStatus) parts.push('\n\n' + toolsContractStatus);
// Operator overlays whose base layers are load-on-demand (SOUL, STANDARDS):
// inject only the small `.local` delta by value so the customization reaches
@@ -385,24 +419,23 @@ For required push/merge/issue-close/release actions, execute without routine con
// Runtime-specific contract
parts.push('\n\n# Runtime-Specific Contract\n\n' + readFileSync(runtimeFile, 'utf-8'));
// Persona contract (A3b): when this agent was spawned with a class
// (MOSAIC_AGENT_CLASS, exported into the pane env by A3a), inject its resolved
// role contract so its identity (mandate + boundaries) is resident from the
// first turn. Override-aware via the persona resolver: a user-customized
// persona in fleet/roles.local/ wins over the baseline (AC-NS-7 launch proof).
// Placed BEFORE fleet comms: identity first, then how-to-reach-peers. No-ops
// silently when the class is unset/unknown (mirrors the comms block).
const persona = readPersonaContractBlock(mosaicHome, process.env['MOSAIC_AGENT_CLASS']);
// Fleet launches derive every identity projection from the one canonical roster
// member resolved above. Non-fleet launches retain the legacy ambient persona
// and tool-policy behavior.
const personaClass = canonicalMember?.className ?? process.env['MOSAIC_AGENT_CLASS'];
const persona = readPersonaContractBlock(mosaicHome, personaClass);
if (persona) parts.push('\n\n' + persona);
const toolPolicy = readFleetToolPolicyBlock(process.env['MOSAIC_AGENT_TOOL_POLICY']);
const toolPolicyName = canonicalMember
? canonicalMember.toolPolicy
: process.env['MOSAIC_AGENT_TOOL_POLICY'];
const toolPolicy = readFleetToolPolicyBlock(toolPolicyName);
if (toolPolicy) parts.push('\n\n' + toolPolicy);
// Fleet onboarding: when this is a spawned fleet agent (MOSAIC_AGENT_NAME set
// and present in the roster), inject a comms cheat-sheet + peer roster so it
// knows how to reach the orchestrator and its peers from its first turn.
const fleetComms = readFleetCommsBlock(mosaicHome, process.env['MOSAIC_AGENT_NAME']);
if (fleetComms) parts.push('\n\n' + fleetComms);
if (fleetIdentity.identity) {
const fleetComms = buildResolvedFleetCommsBlock(fleetIdentity.identity);
if (fleetComms) parts.push('\n\n' + fleetComms);
}
return parts.join('\n');
}