Files
brain/tools/objection-format.mjs
T

40 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* objection-format — дословные сводки возражений для блок-сообщений (П1).
* Чистые форматтеры (презентация, не логика гейта): судья и наставник.
* Fail-safe: мусор/нет возражений → пустая строка.
*/
/**
* Дословная сводка возражений судьи. Две формы:
* - результат runJudge — блокирующие в `blocking[{anchor:{ref},severity}]` (приоритет);
* - сырой parseJudgeResponse — `objections[{anchor:{ref},severity}]` (fallback).
*/
export function formatJudgeObjection(verdict) {
const blocking = verdict && Array.isArray(verdict.blocking) ? verdict.blocking : null;
const objs = (blocking && blocking.length) ? blocking
: (verdict && Array.isArray(verdict.objections) ? verdict.objections : []);
const lines = objs
.filter((o) => o && o.anchor && o.anchor.ref)
.map((o) => `— [${o.severity || 'light'}] ${o.anchor.ref}`);
return lines.join('\n');
}
/** Дословная сводка замечания наставника (результат onPlanWrite {ok,wired,reason,verdict}).
* Р7/мерж: NO-GO = decision==='NO-GO' ИЛИ сломанный вердикт (ok!==true). Доносит СУТЬ —
* recommendation (что править) + reasoning (разбор) + plan_points_addressed (по пунктам,
* включая скил-конкретику) + reason сбоя. GO → пустая строка (не заворот). */
export function formatMentorObjection(r) {
if (!r || r.wired !== true) return '';
const v = r.verdict || {};
const isNoGo = v.decision === 'NO-GO' || r.ok !== true;
if (!isNoGo) return '';
const lines = ['Замечание наставника:'];
if (typeof v.recommendation === 'string' && v.recommendation.trim()) lines.push(`Что править: ${v.recommendation.trim()}`);
if (typeof v.reasoning === 'string' && v.reasoning.trim()) lines.push(`Разбор: ${v.reasoning.trim()}`);
const pts = Array.isArray(v.plan_points_addressed) ? v.plan_points_addressed.filter((p) => typeof p === 'string' && p.trim()) : [];
if (pts.length) lines.push('По пунктам:', ...pts.map((p) => `${p}`));
if (typeof r.reason === 'string' && r.reason.trim()) lines.push(`(${r.reason.trim()})`);
return lines.length > 1 ? lines.join('\n') : '';
}