b739d5adad
Болезни 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>
62 lines
3.3 KiB
JavaScript
62 lines
3.3 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { formatJudgeObjection, formatMentorObjection } from './objection-format.mjs';
|
|
|
|
describe('formatJudgeObjection', () => {
|
|
it('склеивает дословные возражения (anchor.ref + severity)', () => {
|
|
const v = { objections: [
|
|
{ verdict: 'NO', anchor: { kind: 'failed_criterion', ref: 'шаг 3 не проверяемый исход' }, severity: 'heavy' },
|
|
], slots: {} };
|
|
const s = formatJudgeObjection(v);
|
|
expect(s).toContain('шаг 3 не проверяемый исход');
|
|
expect(s).toContain('heavy');
|
|
});
|
|
it('несколько возражений — все в выводе', () => {
|
|
const v = { objections: [{ anchor: { ref: 'A' }, severity: 'fatal' }, { anchor: { ref: 'B' }, severity: 'light' }] };
|
|
const s = formatJudgeObjection(v);
|
|
expect(s).toContain('A');
|
|
expect(s).toContain('B');
|
|
});
|
|
it('нет возражений → пустая строка', () => {
|
|
expect(formatJudgeObjection({ objections: [], slots: {} })).toBe('');
|
|
});
|
|
it('мусорный вердикт не роняет', () => {
|
|
expect(formatJudgeObjection(null)).toBe('');
|
|
expect(formatJudgeObjection({ objections: 'x' })).toBe('');
|
|
});
|
|
it('возражение без anchor.ref пропускается', () => {
|
|
expect(formatJudgeObjection({ objections: [{ severity: 'heavy' }] })).toBe('');
|
|
});
|
|
it('читает блокирующие возражения судьи из поля blocking (форма runJudge, Фаза 1)', () => {
|
|
const v = { decision: 'NO-GO', blocking: [{ verdict: 'NO', anchor: { kind: 'spec_section', ref: '§4 порог' }, severity: 'heavy' }], advice: [], slots: {} };
|
|
const s = formatJudgeObjection(v);
|
|
expect(s).toContain('§4 порог');
|
|
expect(s).toContain('heavy');
|
|
});
|
|
});
|
|
|
|
describe('formatMentorObjection', () => {
|
|
it('собирает дословный reason + суть вердикта (recommendation)', () => {
|
|
const s = formatMentorObjection({ ok: false, wired: true, reason: 'шаг 2 склеен', verdict: { decision: 'NO-GO', recommendation: 'разбей шаг 2' } });
|
|
expect(s).toContain('шаг 2 склеен');
|
|
expect(s).toContain('разбей шаг 2');
|
|
});
|
|
it('ok=true → пустая строка (нет замечания)', () => {
|
|
expect(formatMentorObjection({ ok: true, wired: true })).toBe('');
|
|
});
|
|
it('не wired → пустая строка ($0, наставник не судил)', () => {
|
|
expect(formatMentorObjection({ ok: false, wired: false })).toBe('');
|
|
});
|
|
it('мусор не роняет', () => { expect(formatMentorObjection(null)).toBe(''); });
|
|
it('содержательный NO-GO → суть: recommendation + reasoning + пункты', () => {
|
|
const r = { ok: true, wired: true, verdict: { decision: 'NO-GO', recommendation: 'добавь systematic-debugging',
|
|
reasoning: 'это отладка бага', plan_points_addressed: ['шаг 2: скил не тот'] } };
|
|
const s = formatMentorObjection(r);
|
|
expect(s).toMatch(/systematic-debugging/);
|
|
expect(s).toMatch(/отладка бага/);
|
|
expect(s).toMatch(/шаг 2/);
|
|
});
|
|
it('GO → пустая строка (не заворот)', () => {
|
|
expect(formatMentorObjection({ ok: true, wired: true, verdict: { decision: 'GO' } })).toBe('');
|
|
});
|
|
});
|