feat(mosaic): WI-2 mutator-class guard for directive-freshness (#837)
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/push/publish Pipeline was successful

WI-2: mutator-class guard for the compaction directive-freshness mechanism — command-position parser (prefix x var-indirection unified) + primitive-anchored invariant backstop + all-tools-hook fail-close. Parser-complete on principle: realistic evasion matrix RED-regression-covered, residual exotic evasions proven backstop-caught (B-tests), lens-convergence reached.

closes #829
This commit was merged in pull request #837.
This commit is contained in:
2026-07-18 05:51:58 +00:00
parent 8ec67a1126
commit abd2791f59
27 changed files with 2579 additions and 46 deletions

View File

@@ -1,5 +1,13 @@
import { describe, it, expect, vi } from 'vitest';
import { mkdtempSync, mkdirSync, symlinkSync, rmSync, lstatSync, writeFileSync } from 'node:fs';
import {
lstatSync,
mkdtempSync,
mkdirSync,
readFileSync,
rmSync,
symlinkSync,
writeFileSync,
} from 'node:fs';
import { tmpdir, homedir } from 'node:os';
import { join } from 'node:path';
import {
@@ -14,6 +22,7 @@ import {
buildClaudexEnv,
buildClaudexBanner,
buildClaudexContractNote,
ensureClaudexMutatorGateSettings,
runClaudexProxyGate,
launchClaudex,
type ClaudexHarnessAdapter,
@@ -36,12 +45,20 @@ function makeReport(overrides: Partial<PreflightReport> = {}): PreflightReport {
};
}
function okAdapter(overrides: Partial<ClaudexHarnessAdapter> = {}): ClaudexHarnessAdapter {
type TestAdapterOverrides = Partial<ClaudexHarnessAdapter> & {
exec?: (cmd: string, args: string[], env: NodeJS.ProcessEnv) => void;
};
function okAdapter(overrides: TestAdapterOverrides = {}): ClaudexHarnessAdapter {
const { exec, ...adapterOverrides } = overrides;
return {
harnessPreflight: () => {},
composePrompt: () => '# Composed Claude contract',
exec: () => {},
...overrides,
execLeaseGated:
adapterOverrides.execLeaseGated ??
((args, env, dangerous) =>
exec?.('claude', dangerous ? ['--dangerously-skip-permissions', ...args] : args, env)),
...adapterOverrides,
};
}
@@ -561,11 +578,51 @@ describe('runClaudexProxyGate', () => {
// ─── launch orchestration (fail-closed ordering) ──────────────────────────────
describe('ensureClaudexMutatorGateSettings', () => {
it('does not accept a lookalike hook and preserves isolated settings', () => {
const root = mkdtempSync(join(tmpdir(), 'claudex-gate-settings-'));
try {
writeFileSync(
join(root, 'settings.json'),
JSON.stringify({
preserved: true,
hooks: {
PreToolUse: [
{
matcher: '.*',
hooks: [{ type: 'command', command: 'echo lease-broker/mutator-gate.py' }],
},
],
},
}),
);
ensureClaudexMutatorGateSettings(root);
const settings = JSON.parse(readFileSync(join(root, 'settings.json'), 'utf8')) as {
preserved: boolean;
hooks: { PreToolUse: Array<{ hooks: Array<{ command: string }> }> };
};
const commands = settings.hooks.PreToolUse.flatMap((entry) =>
entry.hooks.map((hook) => hook.command),
);
expect(settings.preserved).toBe(true);
expect(commands).toContain(
'python3 ~/.config/mosaic/tools/lease-broker/mutator-gate.py --runtime claude',
);
expect(lstatSync(join(root, 'settings.json')).mode & 0o777).toBe(0o600);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
});
describe('launchClaudex', () => {
const baseDeps = {
baseEnv: {},
proxyGate: () => Promise.resolve({ ok: true, report: makeReport(), problems: [] }),
resolveConfigDir: () => '/home/agent/.config/mosaic/claudex/home',
prepareConfig: () => {},
log: () => {},
errorLog: () => {},
fail: (() => {