397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.8 KiB
JavaScript
32 lines
1.8 KiB
JavaScript
// tools/m2-supreme-invariants.test.mjs
|
|
import { describe, it, expect } from 'vitest';
|
|
import { freezePlan, verifyFrozenPlan } from './plan-lock.mjs';
|
|
import { decide, isSeed } from './enforce-supreme-gate.mjs';
|
|
|
|
const KEY = 'm2-key';
|
|
const steps = [{ n: 1, op: 'Write', object: 'tools/foo.mjs', intent: 'i' }];
|
|
|
|
describe('Машина 2 — инварианты стены', () => {
|
|
it('без замороженного плана любое мутирующее действие блокируется', () => {
|
|
const r = decide({ toolUse: { name: 'Write', input: { file_path: 'tools/foo.mjs' } }, frozenPlan: null, key: KEY });
|
|
expect(r.decision).toBe('block');
|
|
});
|
|
it('подмена шага в плане ломает печать → блок', () => {
|
|
const p = freezePlan({ steps, key: KEY, nowMs: 1 });
|
|
const tampered = { ...p, steps: [{ ...p.steps[0], object: 'tools/evil.mjs' }] };
|
|
expect(verifyFrozenPlan(tampered, KEY)).toBe(false);
|
|
const r = decide({ toolUse: { name: 'Write', input: { file_path: 'tools/evil.mjs' } }, frozenPlan: tampered, key: KEY });
|
|
expect(r.decision).toBe('block');
|
|
});
|
|
it('семя загрузки проходит без плана (стену можно построить)', () => {
|
|
expect(isSeed({ name: 'Skill', input: { skill: 'writing-plans' } })).toBe(true);
|
|
const r = decide({ toolUse: { name: 'Skill', input: { skill: 'writing-plans' } }, frozenPlan: null, key: KEY });
|
|
expect(r.decision).toBe('allow');
|
|
});
|
|
it('действие строго по шагу валидного плана проходит', () => {
|
|
const p = freezePlan({ steps, key: KEY, nowMs: 1 });
|
|
const r = decide({ toolUse: { name: 'Write', input: { file_path: 'tools/foo.mjs' } }, frozenPlan: p, key: KEY });
|
|
expect(r.decision).toBe('allow');
|
|
});
|
|
});
|