#!/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 };
}
