397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
37 lines
1.7 KiB
JavaScript
37 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* judge-anchor (§9.3 / §11.1) — механическая граница «находка vs призрак».
|
|
* Возражение указывает ЯКОРЬ на конкретику; анкерованное МОЖЕТ блокировать,
|
|
* безъякорное авто-демотится в СОВЕТ (не блокирует, но и не глушится — в нём
|
|
* бывают зёрна, §13). Работает в обе стороны: голос-призрак с безъякорным «НЕТ»
|
|
* не клинит ворота. Качество мысли не судим — только наличие опоры на факт.
|
|
*/
|
|
export const ANCHOR_KINDS = Object.freeze([
|
|
'spec_section', // § спеки
|
|
'card_need', // нужда карточки навыка
|
|
'test_name', // имя теста
|
|
'failed_criterion', // проваленный критерий приёмки
|
|
'observation', // конкретное наблюдение (напр. строка кода)
|
|
]);
|
|
|
|
function isAnchored(objection) {
|
|
const a = objection && objection.anchor;
|
|
if (!a || typeof a !== 'object') return false;
|
|
if (!ANCHOR_KINDS.includes(a.kind)) return false;
|
|
return typeof a.ref === 'string' && a.ref.trim().length > 0;
|
|
}
|
|
|
|
export function classifyObjection(objection) {
|
|
const anchored = isAnchored(objection);
|
|
return { anchored, disposition: anchored ? 'block' : 'advice' };
|
|
}
|
|
|
|
export function partitionObjections(objections = []) {
|
|
const blocking = [];
|
|
const advisory = [];
|
|
for (const o of objections) {
|
|
(classifyObjection(o).disposition === 'block' ? blocking : advisory).push(o);
|
|
}
|
|
return { blocking, advisory };
|
|
}
|