Files
portal/tools/enforce-supreme-gate-bootstrap.test.mjs
T
Дмитрий b739d5adad feat(mentor): мерж роутера в наставника — единый рецензент (спека+план+скилы) + decision GO/NO-GO
Болезни B (роутер в пустоту) + A (наставник не заворачивал) — лечение Р7/Р8 (Подход 1):
наставник — единый мозг-рецензент, зовёт classify() как функцию (3 слоя + граф nodes.yaml +
карточки — код не тронут, новый вызыватель), судит спеку+план+выбор скилов, заворачивает NO-GO.

- validateMentorVerdict + промпты (план/спека): явное decision GO|NO-GO (поглощённый Р7)
- plan-skills.mjs: parsePlanSkills (skills-json) + extractPlanGoal (зеркало extractGoal судьи)
- mentor-seam: renderSkillContext; onPlanWrite зовёт classifyImpl (fail-safe: сбой → без скил-сверки)
- decideMentorObjection: заворот на decision=NO-GO ИЛИ сломанный вердикт; mentor-GO только на чистом GO
- formatMentorObjection доносит суть (recommendation + reasoning + plan_points), GO -> пусто
- enforce-mentor main: loadRegistry + classify; счётчик L1 decision-aware (Р7/§3.4)
- скил-сверка — только план (gate2); спека (gate1) — по сути + decision
- включает redesign согласования L1->L2 (Фазы 0-6, способ B: наставник->судья->печать)
- регрессия tools-only 3901 passed + 2 skip (база 3877, +24 теста, 0 регрессий)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 11:38:09 +03:00

28 lines
1.9 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { isAuthoringWrite, decideMode } from './enforce-supreme-gate.mjs';
const newFile = { existsImpl: () => false }; // файла ещё нет на диске
describe('M7 Ф8 bootstrap-карвут: авторская запись нового плана/спеки', () => {
it('Write нового .md в specs/ или plans/ → true', () => {
expect(isAuthoringWrite({ name: 'Write', input: { file_path: 'docs/superpowers/specs/2026-06-12-x.md' } }, newFile)).toBe(true);
expect(isAuthoringWrite({ name: 'Write', input: { file_path: 'docs/superpowers/plans/2026-06-12-x.md' } }, newFile)).toBe(true);
});
it('перезапись существующего файла → false', () => {
expect(isAuthoringWrite({ name: 'Write', input: { file_path: 'docs/superpowers/plans/x.md' } }, { existsImpl: () => true })).toBe(false);
});
it('код / чужой путь / не-Write → false', () => {
expect(isAuthoringWrite({ name: 'Write', input: { file_path: 'tools/enforce-supreme-gate.mjs' } }, newFile)).toBe(false);
expect(isAuthoringWrite({ name: 'Write', input: { file_path: 'app/Foo.php' } }, newFile)).toBe(false);
expect(isAuthoringWrite({ name: 'Edit', input: { file_path: 'docs/superpowers/plans/x.md' } }, newFile)).toBe(false);
});
it('decideMode без плана + авторская запись нового файла → allow', () => {
const r = decideMode({ toolUse: { name: 'Write', input: { file_path: 'docs/superpowers/plans/__nonexistent_bootstrap_test__.md' } }, frozenPlan: null, key: 'k' });
expect(r.decision).toBe('allow');
});
it('decideMode без плана + запись в код → по-прежнему block (регрессия)', () => {
const r = decideMode({ toolUse: { name: 'Write', input: { file_path: 'app/Foo.php' } }, frozenPlan: null, key: 'k' });
expect(r.decision).toBe('block');
});
});