Files
stack/packages/mosaic/src/commands/brain-store.spec.ts
T
2026-08-05 17:19:51 -05:00

1160 lines
40 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, describe, expect, it } from 'vitest';
import {
existsSync,
lstatSync,
mkdtempSync,
mkdirSync,
readFileSync,
readdirSync,
renameSync,
rmSync,
symlinkSync,
writeFileSync,
} from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
/**
* Red-first contract checks for stack #1051 / MB-BRAIN-01.
*
* These checks are committed before the implementation. They bind to the
* MC-CRED v1.5 terminal classes and stable reason codes, not to the currently
* deployed resolver behavior. Live grant and read/write round-trip tests remain
* gated on MC-CRED-01; these fixtures contain no credential values.
*/
interface BrainTarget {
readonly estate: string;
readonly host: string;
readonly owner: string;
readonly repo: string;
readonly cloneUrl: string;
}
interface CredentialAssessment {
readonly outcome: 'ok' | 'refused' | 'error' | 'indeterminate';
readonly exitCode: 0 | 10 | 20 | 30;
readonly reasonCode: string;
readonly diagnostic: string;
}
interface ResolverParityAssessment extends CredentialAssessment {
readonly gitReasonCode: string;
readonly apiReasonCode: string;
}
interface MigrationOwnerResolution {
readonly verdict: 'resolved' | 'refused' | 'not-measured';
readonly reasonCode: string;
readonly principal: {
readonly name: string;
readonly kind:
| 'active-lane'
| 'durable-team'
| 'durable-human'
| 'durable-queue'
| 'mission-seat';
} | null;
readonly authority: {
readonly system: 'gitea' | 'glpi' | 'mosaic-mission-state';
readonly endpoint: string;
readonly contentType: 'application/json';
} | null;
}
interface MigrationCandidate {
readonly source: string;
readonly destination: string;
readonly archive: string;
readonly kind: 'lane' | 'seat';
}
interface MigrationPlan {
readonly status: 'ready' | 'blocked';
readonly candidates: readonly MigrationCandidate[];
readonly reported: readonly { path: string; reason: string }[];
readonly owner: MigrationOwnerResolution['principal'];
}
interface MigrationPublishEvidence {
readonly commit: string;
readonly remoteHead: string;
readonly reachable: boolean;
}
interface MigrationResult {
readonly status: 'migrated' | 'reported' | 'failed';
readonly migrated: readonly MigrationCandidate[];
readonly reported: readonly { path: string; reason: string }[];
readonly publish: MigrationPublishEvidence | null;
}
interface BrainDoctorObservation {
readonly rootExists: boolean;
readonly rootPrivate: boolean;
readonly gitRepository: boolean;
readonly remote: string | null;
readonly branch: string | null;
readonly worktreeState: 'clean' | 'dirty' | 'unmeasurable';
readonly access: CredentialAssessment | null;
}
interface BrainDoctorFinding {
readonly code: string;
readonly repairable: boolean;
readonly reasonCode: string | null;
}
interface BrainDoctorAction {
readonly program: 'git' | 'mosaic';
readonly args: readonly string[];
readonly findingCode: string;
}
interface BrainWritePolicy {
readonly allowed: boolean;
readonly mode: 'append-only' | 'single-writer' | 'seat-writer' | 'refused';
readonly reason: string;
}
interface BrainStoreModule {
deriveBrainTarget(
registrySource: string,
targetGitUrl: string,
brainNamespace: string,
): BrainTarget;
createBrainSkeleton(root: string): { readonly created: readonly string[] };
assessCredentialResult(source: string): CredentialAssessment;
assessResolverParity(gitSource: string, apiSource: string): ResolverParityAssessment;
discoverBrainMigration(
input: {
readonly sourceRoot: string;
readonly brainRoot: string;
readonly seat: string;
readonly lane: string;
readonly laneActive: boolean;
},
resolveOwner?: (lane: string) => MigrationOwnerResolution,
approveContent?: (path: string, content: Uint8Array) => boolean,
): MigrationPlan;
migrateBrainState(
plan: MigrationPlan,
publish: (
brainRoot: string,
entries: readonly { readonly path: string; readonly content: Uint8Array }[],
) => MigrationPublishEvidence,
brainRoot: string,
hooks?: {
readonly beforeDestinationWrite?: (destination: string) => void;
readonly beforeSourceCleanup?: (source: string) => void;
},
): MigrationResult;
evaluateBrainDoctor(
observation: BrainDoctorObservation,
expectedRemote: string,
): readonly BrainDoctorFinding[];
planBrainDoctorFix(input: {
readonly findings: readonly BrainDoctorFinding[];
readonly target: BrainTarget;
readonly identity: string;
readonly root: string;
}): readonly BrainDoctorAction[];
classifyBrainWrite(input: {
readonly path: string;
readonly actor: string;
readonly seat: string;
readonly boardWriter?: string;
}): BrainWritePolicy;
}
const MODULE_PATH = './brain-store.js';
const tempRoots: string[] = [];
async function loadSut(requirement: string): Promise<BrainStoreModule> {
try {
return (await import(MODULE_PATH)) as BrainStoreModule;
} catch (error: unknown) {
const detail = error instanceof Error ? error.message : String(error);
throw new Error(`${requirement}: brain-store implementation is absent (${detail})`);
}
}
function tempRoot(): string {
const root = mkdtempSync(join(tmpdir(), 'mosaic-brain-contract-'));
tempRoots.push(root);
return root;
}
function registry(): string {
return JSON.stringify({
version: 1,
estates: [
{
name: 'homelab',
readOnlyControlIdentity: 'homelab-read-control',
hosts: [
{
host: 'git.mosaicstack.dev',
provider: 'gitea',
apiBaseUrl: 'https://git.mosaicstack.dev',
tokenPrefix: 'gitea-mosaicstack',
},
],
},
{
name: 'usc',
readOnlyControlIdentity: 'usc-read-control',
hosts: [
{
host: 'git.uscllc.com',
provider: 'gitea',
apiBaseUrl: 'https://git.uscllc.com',
tokenPrefix: 'gitea-usc',
},
],
},
],
});
}
function credentialResult(
outcome: CredentialAssessment['outcome'],
reasonCode: string,
message = 'non-secret diagnostic',
providerLogin: string | null = outcome === 'ok'
? 'external-seat'
: reasonCode === 'provider-identity-mismatch'
? 'Mos'
: null,
): string {
const exits = { ok: 0, refused: 10, error: 20, indeterminate: 30 } as const;
return JSON.stringify({
schemaVersion: 1,
operation: 'validate',
outcome,
exitCode: exits[outcome],
retryable: false,
subject: {
identity: 'external-seat',
estate: 'homelab',
host: 'git.mosaicstack.dev',
repo: 'mosaicstack/mosaic-brain',
},
mutation: 'none',
reason: { code: reasonCode, message },
evidence: {
providerIdentity:
providerLogin === null
? null
: {
login: providerLogin,
endpoint: 'GET /api/v1/user',
contentType: 'application/json',
},
repositoryPermission:
outcome === 'ok'
? {
requested: 'write',
effective: 'write',
endpoint: 'GET /api/v1/repos/mosaicstack/mosaic-brain',
contentType: 'application/json',
}
: null,
writeDifferential:
outcome === 'ok'
? {
state: 'can-write',
credentialBinding: 'same-resolution',
transportPrincipal: 'external-seat',
authenticatedReceivePack: 'advertised',
readOnlyControl: {
identity: 'homelab-read-control',
providerPermission: 'read',
receivePack: 'refused',
},
unauthenticatedReceivePack: 'refused',
artifactCreated: false,
proves: 'non-secret evidence',
doesNotProve: 'branch update acceptance',
}
: null,
},
audit: { journalId: 'opaque', state: 'sealed' },
});
}
afterEach((): void => {
for (const root of tempRoots.splice(0)) {
rmSync(root, { recursive: true, force: true });
}
});
describe('R2/Q1 — estate and brain discovery have one authority', (): void => {
it('derives the estate from the configured target git host and the brain owner from that target URL', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-02 target-host estate derivation');
expect(
sut.deriveBrainTarget(
registry(),
'https://git.mosaicstack.dev/mosaicstack/stack.git',
'durable-owner',
),
).toEqual({
estate: 'homelab',
host: 'git.mosaicstack.dev',
owner: 'durable-owner',
repo: 'durable-owner/mosaic-brain',
cloneUrl: 'https://git.mosaicstack.dev/durable-owner/mosaic-brain.git',
});
});
it('fails closed for an unmapped target host instead of consulting machine or ambient estate values', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-02 unmapped host fail-closed');
const previous = process.env['MOSAIC_ESTATE'];
process.env['MOSAIC_ESTATE'] = 'homelab';
try {
expect(() =>
sut.deriveBrainTarget(
registry(),
'https://unmapped.example.invalid/acme/stack.git',
'durable-owner',
),
).toThrow(/estate-host-unmapped/);
} finally {
if (previous === undefined) delete process.env['MOSAIC_ESTATE'];
else process.env['MOSAIC_ESTATE'] = previous;
}
});
});
describe('R6 — brain layout refuses secret material', (): void => {
it('creates the durable layout and exact required gitignore exclusions', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 exact secret exclusions');
const root = tempRoot();
sut.createBrainSkeleton(root);
for (const directory of ['agents', 'lanes', 'board', 'specs', 'methods', 'archives']) {
expect(existsSync(join(root, directory)), directory).toBe(true);
expect(
existsSync(join(root, directory, '.gitkeep')),
`${directory} tracked placeholder`,
).toBe(true);
}
const rules = readFileSync(join(root, '.gitignore'), 'utf8').trim().split('\n');
expect(rules).toEqual(
expect.arrayContaining([
'*.token',
'*.key',
'*.pem',
'.env',
'credentials.json',
'*.TOKEN',
'*.KEY',
'*.PEM',
'.env.*',
'credentials.*',
'secrets.*',
'id_rsa',
'id_ed25519',
]),
);
});
it('creates the brain root and memory directories owner-only under a permissive umask', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 owner-only brain checkout');
const brain = join(tempRoot(), 'brain');
const previousUmask = process.umask(0o022);
try {
sut.createBrainSkeleton(brain);
} finally {
process.umask(previousUmask);
}
for (const path of [
brain,
...['agents', 'lanes', 'board', 'specs', 'methods', 'archives'].map((name) =>
join(brain, name),
),
]) {
expect(lstatSync(path).mode & 0o077, path).toBe(0);
}
});
it('refuses existing noncanonical gitignore content instead of publishing it', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 unapproved gitignore content');
const root = tempRoot();
const ignore = join(root, '.gitignore');
writeFileSync(ignore, '# token=fixture-value\n*.token\n');
expect(() => sut.createBrainSkeleton(root)).toThrow(/brain-layout-ignore-content-unsafe/);
expect(readFileSync(ignore, 'utf8')).toBe('# token=fixture-value\n*.token\n');
});
it('refuses a symlinked layout directory without writing a tracked placeholder outside the brain', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 no-follow brain layout');
const root = tempRoot();
const brain = join(root, 'brain');
const outside = join(root, 'outside');
mkdirSync(brain);
mkdirSync(outside);
symlinkSync(outside, join(brain, 'agents'));
expect(() => sut.createBrainSkeleton(brain)).toThrow(/brain-layout-directory-unsafe/);
expect(existsSync(join(outside, '.gitkeep'))).toBe(false);
});
it('refuses a symlinked gitignore instead of reading and tracking its external target', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 no-follow gitignore');
const root = tempRoot();
const brain = join(root, 'brain');
const outside = join(root, 'outside-secret');
mkdirSync(brain);
writeFileSync(outside, 'DO-NOT-TRACK\n');
symlinkSync(outside, join(brain, '.gitignore'));
expect(() => sut.createBrainSkeleton(brain)).toThrow(/brain-layout-ignore-unsafe/);
expect(readFileSync(outside, 'utf8')).toBe('DO-NOT-TRACK\n');
});
it('never relays broker reason messages that may contain secret-bearing text', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 secret-free error path');
const secretMarker = 'DO-NOT-EMIT-CREDENTIAL-MARKER';
const result = sut.assessCredentialResult(
credentialResult('error', 'insecure-credential-source', secretMarker),
);
expect(JSON.stringify(result)).not.toContain(secretMarker);
expect(result.diagnostic).toContain('insecure-credential-source');
});
});
describe('credential caller contract v1.5 terminal classes', (): void => {
it.each([
['ok', 0, 'validation-verified'],
['refused', 10, 'no-token-for-identity'],
['refused', 10, 'provider-identity-mismatch'],
['error', 20, 'estate-registry-invalid'],
['indeterminate', 30, 'provider-unavailable'],
['indeterminate', 30, 'identity-not-visible'],
['indeterminate', 30, 'identity-not-measured'],
['refused', 10, 'credential-rejected'],
] as const)(
'preserves %s/%i and stable reason %s without parsing prose',
async (outcome, exitCode, reasonCode): Promise<void> => {
const sut = await loadSut(`AC-MB-01 terminal class ${outcome}/${exitCode}`);
const result = sut.assessCredentialResult(credentialResult(outcome, reasonCode));
expect(result.outcome).toBe(outcome);
expect(result.exitCode).toBe(exitCode);
expect(result.reasonCode).toBe(reasonCode);
},
);
it('makes a missing or inconsistent decision field indeterminate rather than success or refusal', async (): Promise<void> => {
const sut = await loadSut('AC-MB-01 malformed broker result fail-closed');
const malformed = JSON.parse(credentialResult('ok', 'validation-verified')) as Record<
string,
unknown
>;
malformed['exitCode'] = 10;
const result = sut.assessCredentialResult(JSON.stringify(malformed));
expect(result.outcome).toBe('indeterminate');
expect(result.exitCode).toBe(30);
expect(result.reasonCode).toBe('unexpected-provider-shape');
});
it('makes an apparent write ok indeterminate when the side-effect-free differential is absent', async (): Promise<void> => {
const sut = await loadSut('AC-MB-01 required write differential');
const raw = JSON.parse(credentialResult('ok', 'validation-verified')) as {
evidence: { writeDifferential: unknown };
};
raw.evidence.writeDifferential = null;
const result = sut.assessCredentialResult(JSON.stringify(raw));
expect(result).toMatchObject({
outcome: 'indeterminate',
exitCode: 30,
reasonCode: 'readback-missing',
});
});
it('rejects the superseded indeterminate/credential-rejected pairing from before the v1.4 correction', async (): Promise<void> => {
const sut = await loadSut('AC-MB-01 credential-rejected stable class');
const legacy = JSON.parse(credentialResult('indeterminate', 'provider-unavailable')) as Record<
string,
unknown
>;
legacy['reason'] = {
code: 'credential-rejected',
message: 'superseded classification',
};
const result = sut.assessCredentialResult(JSON.stringify(legacy));
expect(result.outcome).toBe('indeterminate');
expect(result.exitCode).toBe(30);
expect(result.reasonCode).toBe('unexpected-provider-shape');
});
it('preserves scope-limited identity as not-measured rather than a dead credential refusal', async (): Promise<void> => {
const sut = await loadSut('AC-MB-01 scope-limited identity is not dead credential');
const result = sut.assessCredentialResult(
credentialResult('indeterminate', 'identity-not-measured'),
);
expect(result).toMatchObject({
outcome: 'indeterminate',
exitCode: 30,
reasonCode: 'identity-not-measured',
});
});
it('refuses an apparent ok whose provider /user read-back names a different principal', async (): Promise<void> => {
const sut = await loadSut('AC-MB-01 provider identity MISMATCH is first-class');
const result = sut.assessCredentialResult(
credentialResult('ok', 'validation-verified', 'looks successful', 'Mos'),
);
expect(result.outcome).toBe('refused');
expect(result.exitCode).toBe(10);
expect(result.reasonCode).toBe('provider-identity-mismatch');
});
});
describe('R5 — out-of-estate refusal must agree on both resolver axes', (): void => {
it('accepts refusal evidence only when Git and API return the same authoritative refusal', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-05 both-axis refusal');
const refusal = credentialResult('refused', 'no-token-for-identity');
const result = sut.assessResolverParity(refusal, refusal);
expect(result.outcome).toBe('refused');
expect(result.exitCode).toBe(10);
expect(result.reasonCode).toBe('no-token-for-identity');
expect(result.gitReasonCode).toBe('no-token-for-identity');
expect(result.apiReasonCode).toBe('no-token-for-identity');
});
it.each([
[
credentialResult('refused', 'no-token-for-identity'),
credentialResult('ok', 'validation-verified'),
],
[
credentialResult('refused', 'no-token-for-identity'),
credentialResult('refused', 'cross-estate-resolution'),
],
[
credentialResult('refused', 'no-token-for-identity'),
credentialResult('indeterminate', 'provider-unavailable'),
],
])('turns axis disagreement into indeterminate failure', async (git, api): Promise<void> => {
const sut = await loadSut('MB-REQ-05 resolver-axis disagreement');
const result = sut.assessResolverParity(git, api);
expect(result.outcome).toBe('indeterminate');
expect(result.exitCode).toBe(30);
expect(result.reasonCode).toBe('permission-evidence-disagrees');
});
});
describe('R7 — migration is non-destructive, append-only, and explicit', (): void => {
const activeLaneOwner = (): MigrationOwnerResolution => ({
verdict: 'resolved',
reasonCode: 'active-lane-owner-verified',
principal: { name: 'lane:lane-a', kind: 'active-lane' },
authority: {
system: 'mosaic-mission-state',
endpoint: 'file:///var/lib/mosaic/missions/lane-a.json',
contentType: 'application/json',
},
});
it('uses an injected authoritative owner resolver for unit mechanics without claiming live owner validation', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 injected owner-resolver seam');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
mkdirSync(join(sourceRoot, 'agents', 'seat-a'), { recursive: true });
writeFileSync(join(sourceRoot, 'lanes', 'lane-a', 'finding.md'), 'lane finding\n');
writeFileSync(join(sourceRoot, 'agents', 'seat-a', 'STATE.md'), 'seat state\n');
writeFileSync(join(sourceRoot, 'orphan-state.md'), 'must be reported\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
expect(plan.status).toBe('ready');
expect(plan.owner).toEqual({ name: 'lane:lane-a', kind: 'active-lane' });
expect(plan.candidates.map((candidate) => candidate.kind).sort()).toEqual(['lane', 'seat']);
expect(plan.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({ path: join(sourceRoot, 'orphan-state.md') }),
]),
);
});
it('retains and reports otherwise-benign legacy content when no approved scanner is available', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 approved scanner required');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
const source = join(sourceRoot, 'lanes', 'lane-a', 'finding.md');
writeFileSync(source, 'ordinary finding\n');
const plan = sut.discoverBrainMigration(
{
sourceRoot,
brainRoot: join(root, 'brain'),
seat: 'seat-a',
lane: 'lane-a',
laneActive: true,
},
activeLaneOwner,
);
expect(plan.candidates).toHaveLength(0);
expect(plan.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: source,
reason: expect.stringMatching(/scanner|approval/i),
}),
]),
);
});
it('ignores a caller-asserted owner string/validated flag and leaves the gate blocking', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-09 caller owner assertion cannot satisfy gate');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
mkdirSync(join(sourceRoot, 'lanes', 'closed-lane'), { recursive: true });
writeFileSync(join(sourceRoot, 'lanes', 'closed-lane', 'finding.md'), 'finding\n');
const callerAssertion = {
sourceRoot,
brainRoot: join(root, 'brain'),
seat: 'seat-a',
lane: 'closed-lane',
laneActive: false,
owner: { name: 'some-string', kind: 'durable-team', validated: true },
};
const plan = sut.discoverBrainMigration(callerAssertion);
expect(plan.status).toBe('blocked');
expect(plan.candidates).toHaveLength(0);
expect(plan.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({ reason: expect.stringMatching(/durable owner/i) }),
]),
);
});
it.each([
['mission seat', { name: 'user:be-coder-07', kind: 'mission-seat' }],
['unicode dash', { name: 'team:platformmaintainers', kind: 'durable-team' }],
['padded', { name: ' team:platform-maintainers ', kind: 'durable-team' }],
['dot presentation', { name: 'team:platform.maintainers', kind: 'durable-team' }],
['space presentation', { name: 'team:platform maintainers', kind: 'durable-team' }],
] as const)(
'rejects %s owner evidence through the injected resolver allowlist',
async (_caseName, principal): Promise<void> => {
const sut = await loadSut('MB-REQ-09 durable-owner allowlist');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
mkdirSync(join(sourceRoot, 'lanes', 'closed-lane'), { recursive: true });
writeFileSync(join(sourceRoot, 'lanes', 'closed-lane', 'finding.md'), 'finding\n');
let resolverCalls = 0;
const plan = sut.discoverBrainMigration(
{
sourceRoot,
brainRoot: join(root, 'brain'),
seat: 'seat-a',
lane: 'closed-lane',
laneActive: false,
},
(): MigrationOwnerResolution => {
resolverCalls += 1;
return {
verdict: 'resolved',
reasonCode: 'owner-verified',
principal,
authority: {
system: 'gitea',
endpoint: 'GET /api/v1/teams/1',
contentType: 'application/json',
},
};
},
);
expect(resolverCalls).toBe(1);
expect(plan.status).toBe('blocked');
expect(plan.candidates).toHaveLength(0);
},
);
it('reports secret-shaped legacy files without ever copying them into the brain', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-06 migration secret exclusion');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const laneRoot = join(sourceRoot, 'lanes', 'lane-a');
const brainRoot = join(root, 'brain');
mkdirSync(laneRoot, { recursive: true });
const secretNames = [
'access.token',
'private.key',
'client.pem',
'CLIENT.PEM',
'.env',
'.env.local',
'.env.production',
'credentials.json',
'credentials.yaml',
'id_rsa',
'secrets.txt',
];
for (const name of secretNames) {
writeFileSync(join(laneRoot, name), 'DO-NOT-MIGRATE\n');
}
const nestedSecretPaths = [
join('.env.d', 'database.txt'),
join('credentials.d', 'token.txt'),
join('secrets', 'private.txt'),
];
for (const path of nestedSecretPaths) {
mkdirSync(join(laneRoot, path, '..'), { recursive: true });
writeFileSync(join(laneRoot, path), 'NESTED-SECRET-MARKER\n');
}
const embeddedSecrets = new Map([
['benign-auth.md', 'Authorization: Bearer NESTED-CONTENT-SECRET-MARKER-1234567890\n'],
['benign-token.md', 'token=fixture-value\n'],
['benign-aws.md', 'AWS_SECRET_ACCESS_KEY=fixture-value\n'],
['benign-header.md', 'X-Api-Key: fixture-value\n'],
['benign-jwt.md', 'session=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJmaXh0dXJlIn0.signature\n'],
]);
for (const [name, content] of embeddedSecrets) writeFileSync(join(laneRoot, name), content);
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
expect(plan.status).toBe('ready');
expect(plan.candidates).toHaveLength(0);
expect(plan.reported).toHaveLength(
secretNames.length + nestedSecretPaths.length + embeddedSecrets.size,
);
expect(plan.reported.every((entry) => /secret/i.test(entry.reason))).toBe(true);
expect(JSON.stringify(plan)).not.toMatch(/NESTED-(?:CONTENT-)?SECRET-MARKER/);
expect(existsSync(brainRoot)).toBe(false);
});
it('publishes collision-safe append-only copies, retains the source explicitly, and never overwrites a finding', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 append-only publish-before-archive migration');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
writeFileSync(join(sourceRoot, 'lanes', 'lane-a', 'finding.md'), 'new finding\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
const candidate = plan.candidates[0];
expect(candidate).toBeDefined();
if (candidate === undefined) return;
mkdirSync(join(brainRoot, 'lanes', 'lane-a', 'findings', 'imports'), { recursive: true });
const preexisting = join(
brainRoot,
'lanes',
'lane-a',
'findings',
'imports',
'existing-finding.md',
);
writeFileSync(preexisting, 'older independent finding\n');
let publishedPaths: readonly string[] = [];
const result = sut.migrateBrainState(
plan,
(_publishedRoot, entries): MigrationPublishEvidence => {
publishedPaths = entries.map((entry): string => entry.path);
return { commit: 'a'.repeat(40), remoteHead: 'a'.repeat(40), reachable: true };
},
brainRoot,
);
expect(result.status).toBe('reported');
expect(readFileSync(preexisting, 'utf8')).toBe('older independent finding\n');
expect(readFileSync(candidate.destination, 'utf8')).toBe('new finding\n');
expect(readFileSync(candidate.archive, 'utf8')).toBe('new finding\n');
expect(existsSync(candidate.source)).toBe(true);
expect(result.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: candidate.source,
reason: expect.stringMatching(/retained/i),
}),
]),
);
expect(publishedPaths).toContain(candidate.destination);
expect(publishedPaths).toContain(candidate.archive);
});
it.each(['modified', 'replaced'] as const)(
'retains and reports a source that is %s while its published snapshot is in flight',
async (change): Promise<void> => {
const sut = await loadSut('MB-REQ-07 source identity before cleanup');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
const source = join(sourceRoot, 'lanes', 'lane-a', 'finding.md');
writeFileSync(source, 'published snapshot\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
const result = sut.migrateBrainState(
plan,
(): MigrationPublishEvidence => {
if (change === 'replaced') rmSync(source);
writeFileSync(source, 'new concurrent state\n');
return { commit: 'a'.repeat(40), remoteHead: 'a'.repeat(40), reachable: true };
},
brainRoot,
);
expect(result.status).toBe('reported');
expect(readFileSync(source, 'utf8')).toBe('new concurrent state\n');
expect(readFileSync(plan.candidates[0]!.destination, 'utf8')).toBe('published snapshot\n');
expect(result.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: source,
reason: expect.stringMatching(/retained|cleanup/i),
}),
]),
);
},
);
it('holds the destination directory while a concurrent actor replaces its ancestor with a symlink', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 destination descriptor race');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
const outside = join(root, 'outside');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
mkdirSync(join(brainRoot, 'lanes', 'lane-a'), { recursive: true });
mkdirSync(outside);
const source = join(sourceRoot, 'lanes', 'lane-a', 'finding.md');
writeFileSync(source, 'lane state\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
let swapped = false;
let publishCalls = 0;
const result = sut.migrateBrainState(
plan,
(): MigrationPublishEvidence => {
publishCalls += 1;
return { commit: 'a'.repeat(40), remoteHead: 'a'.repeat(40), reachable: true };
},
brainRoot,
{
beforeDestinationWrite: (): void => {
if (swapped) return;
swapped = true;
renameSync(join(brainRoot, 'lanes', 'lane-a'), join(brainRoot, 'lanes', 'lane-a-held'));
symlinkSync(outside, join(brainRoot, 'lanes', 'lane-a'));
},
},
);
expect(result.status).toBe('failed');
expect(readFileSync(source, 'utf8')).toBe('lane state\n');
expect(readdirSync(outside)).toEqual([]);
expect(publishCalls).toBe(0);
});
it('refuses nested symlink destinations without copying a migration outside the brain', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 migration destination no-follow');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
const outside = join(root, 'outside');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
mkdirSync(join(brainRoot, 'lanes'), { recursive: true });
mkdirSync(outside);
const source = join(sourceRoot, 'lanes', 'lane-a', 'finding.md');
writeFileSync(source, 'lane state\n');
symlinkSync(outside, join(brainRoot, 'lanes', 'lane-a'));
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
let publishCalls = 0;
const result = sut.migrateBrainState(
plan,
(): MigrationPublishEvidence => {
publishCalls += 1;
return { commit: 'a'.repeat(40), remoteHead: 'a'.repeat(40), reachable: true };
},
brainRoot,
);
expect(result.status).toBe('failed');
expect(readFileSync(source, 'utf8')).toBe('lane state\n');
expect(readdirSync(outside)).toEqual([]);
expect(publishCalls).toBe(0);
});
it('never path-unlinks a source when identity-aware unlink is unavailable', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 no path-based source unlink');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
mkdirSync(join(sourceRoot, 'lanes', 'lane-a'), { recursive: true });
const source = join(sourceRoot, 'lanes', 'lane-a', 'finding.md');
writeFileSync(source, 'published snapshot\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
let cleanupHookCalled = false;
const result = sut.migrateBrainState(
plan,
(): MigrationPublishEvidence => ({
commit: 'a'.repeat(40),
remoteHead: 'a'.repeat(40),
reachable: true,
}),
brainRoot,
{
beforeSourceCleanup: (): void => {
cleanupHookCalled = true;
rmSync(source);
writeFileSync(source, 'replacement must survive\n');
},
},
);
expect(cleanupHookCalled).toBe(true);
expect(result.status).toBe('reported');
expect(readFileSync(source, 'utf8')).toBe('replacement must survive\n');
expect(result.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({ path: source, reason: expect.stringMatching(/retained/i) }),
]),
);
});
it('retains every source and reports failure when remote reachability is not established', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 failed-publish source preservation');
const root = tempRoot();
const sourceRoot = join(root, 'local-memory');
const brainRoot = join(root, 'brain');
mkdirSync(join(sourceRoot, 'agents', 'seat-a'), { recursive: true });
const source = join(sourceRoot, 'agents', 'seat-a', 'STATE.md');
writeFileSync(source, 'seat state\n');
const plan = sut.discoverBrainMigration(
{ sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true },
activeLaneOwner,
(): boolean => true,
);
const result = sut.migrateBrainState(
plan,
(): MigrationPublishEvidence => ({
commit: 'a'.repeat(40),
remoteHead: 'b'.repeat(40),
reachable: false,
}),
brainRoot,
);
expect(result.status).toBe('failed');
expect(readFileSync(source, 'utf8')).toBe('seat state\n');
expect(plan.candidates[0]).toBeDefined();
expect(existsSync(plan.candidates[0]!.destination)).toBe(true);
expect(existsSync(plan.candidates[0]!.archive)).toBe(true);
expect(result.reported).toEqual(
expect.arrayContaining([
expect.objectContaining({ reason: expect.stringMatching(/reachab/i) }),
]),
);
});
});
describe('R8 — doctor diagnoses defects and fixes only through approved seams', (): void => {
it('surfaces missing clone, wrong remote, absent write evidence, and uncommitted state as distinct defects', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-08 doctor defect classes');
const expected = 'https://git.mosaicstack.dev/mosaicstack/mosaic-brain.git';
const missing = sut.evaluateBrainDoctor(
{
rootExists: false,
rootPrivate: false,
gitRepository: false,
remote: null,
branch: null,
worktreeState: 'unmeasurable',
access: sut.assessCredentialResult(credentialResult('refused', 'no-token-for-identity')),
},
expected,
);
expect(missing.map((finding) => finding.code)).toEqual(
expect.arrayContaining(['brain-clone-missing', 'brain-write-access-refused']),
);
const defects = sut.evaluateBrainDoctor(
{
rootExists: true,
rootPrivate: true,
gitRepository: true,
remote: 'https://git.uscllc.com/usc/mosaic-brain.git',
branch: 'main',
worktreeState: 'dirty',
access: sut.assessCredentialResult(
credentialResult('indeterminate', 'credential-rejected'),
),
},
expected,
);
expect(defects.map((finding) => finding.code)).toEqual(
expect.arrayContaining([
'brain-remote-mismatch',
'brain-write-access-indeterminate',
'brain-uncommitted-state',
]),
);
});
it('plans clone/remote/grant repair with git and mosaic cred only and never emits a token lookup', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-08 approved doctor fix seam');
const target = sut.deriveBrainTarget(
registry(),
'https://git.mosaicstack.dev/mosaicstack/stack.git',
'durable-owner',
);
const findings: BrainDoctorFinding[] = [
{ code: 'brain-clone-missing', repairable: true, reasonCode: null },
{ code: 'brain-remote-mismatch', repairable: true, reasonCode: null },
{ code: 'brain-write-access-refused', repairable: true, reasonCode: 'permission-denied' },
{ code: 'brain-uncommitted-state', repairable: false, reasonCode: null },
];
const actions = sut.planBrainDoctorFix({
findings,
target,
identity: 'seat-a',
root: '/home/test/.mosaic',
});
const rendered = JSON.stringify(actions);
expect(actions.map((action) => action.program)).toEqual(['mosaic', 'git', 'git']);
expect(actions[0]?.findingCode).toBe('brain-write-access-refused');
expect(actions[1]?.findingCode).toBe('brain-clone-missing');
expect(rendered).toContain('cred');
expect(rendered).toContain('grant');
expect(rendered).toContain('--estate');
expect(rendered).toContain('homelab');
expect(rendered).not.toMatch(/token|authorization|password/i);
expect(actions.some((action) => action.findingCode === 'brain-uncommitted-state')).toBe(false);
});
it('does not reinterpret error or indeterminate evidence as grantable refusal', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-08 non-refusal fail-closed fix planning');
const target = sut.deriveBrainTarget(
registry(),
'https://git.mosaicstack.dev/mosaicstack/stack.git',
'durable-owner',
);
for (const finding of [
{
code: 'brain-write-access-error',
repairable: false,
reasonCode: 'estate-registry-invalid',
},
{
code: 'brain-write-access-indeterminate',
repairable: false,
reasonCode: 'provider-unavailable',
},
]) {
expect(
sut.planBrainDoctorFix({
findings: [finding],
target,
identity: 'seat-a',
root: '/home/test/.mosaic',
}),
).toHaveLength(0);
}
});
});
describe('Q2/Q3 doctrine — writes and retention are structurally constrained', (): void => {
it('makes lane findings append-only, board writes single-writer, and seat state seat-owned', async (): Promise<void> => {
const sut = await loadSut('MB-REQ-07 write policy');
expect(
sut.classifyBrainWrite({
path: 'lanes/lane-a/findings/new.md',
actor: 'seat-a',
seat: 'seat-a',
}),
).toMatchObject({ allowed: true, mode: 'append-only' });
expect(
sut.classifyBrainWrite({
path: 'board/assignments.json',
actor: 'tl-mosaic',
seat: 'seat-a',
boardWriter: 'tl-mosaic',
}),
).toMatchObject({ allowed: true, mode: 'single-writer' });
expect(
sut.classifyBrainWrite({
path: 'board/assignments.json',
actor: 'seat-a',
seat: 'seat-a',
boardWriter: 'tl-mosaic',
}),
).toMatchObject({ allowed: false, mode: 'refused' });
expect(
sut.classifyBrainWrite({
path: 'agents/other-seat/STATE.md',
actor: 'seat-a',
seat: 'seat-a',
}),
).toMatchObject({ allowed: false, mode: 'refused' });
});
});