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>
40 lines
2.1 KiB
JavaScript
40 lines
2.1 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { buildObjectionFeedback, buildDegradedFeedback } from './objection-delivery.mjs';
|
|
|
|
describe('buildObjectionFeedback', () => {
|
|
it('собирает полный текст замечания с пометкой стороны (наставник)', () => {
|
|
const out = buildObjectionFeedback({ side: 'mentor', text: 'пункт 2 плохой' });
|
|
expect(out).toContain('наставник');
|
|
expect(out).toContain('пункт 2 плохой');
|
|
});
|
|
it('пометка судьи для side=judge', () => {
|
|
const out = buildObjectionFeedback({ side: 'judge', text: 'шаг 4 трогает порог' });
|
|
expect(out).toContain('судья');
|
|
expect(out).toContain('шаг 4 трогает порог');
|
|
});
|
|
it('пустой текст → безопасная заглушка, не пусто', () => {
|
|
expect(buildObjectionFeedback({ side: 'judge', text: '' })).toMatch(/судья/);
|
|
});
|
|
it('не обрезает длинный текст замечания', () => {
|
|
const long = 'A'.repeat(5000);
|
|
expect(buildObjectionFeedback({ side: 'mentor', text: long })).toContain(long);
|
|
});
|
|
});
|
|
|
|
describe('buildDegradedFeedback (спека §9 — degraded ИИ информирует контроллера, не тишина)', () => {
|
|
it('наставник degraded → «не смог дозвониться» + причина, помечен наставник', () => {
|
|
const out = buildDegradedFeedback({ side: 'mentor', reason: 'timeout' });
|
|
expect(out).toContain('наставник');
|
|
expect(out).toMatch(/не смог дозвониться|недоступен/i);
|
|
expect(out).toContain('timeout');
|
|
});
|
|
it('судья degraded → помечен судья, печати нет', () => {
|
|
const out = buildDegradedFeedback({ side: 'judge', reason: 'no_key' });
|
|
expect(out).toContain('судья');
|
|
expect(out).toMatch(/печат/i);
|
|
});
|
|
it('пустая причина → безопасная заглушка, не пусто', () => {
|
|
expect(buildDegradedFeedback({ side: 'mentor' })).toMatch(/наставник/);
|
|
});
|
|
});
|