#!/usr/bin/env node
/**
 * skeleton-radar (§5.7 ДР-3) — раздел-уровень: grep заголовков → Claude отчитывается по
 * КАЖДОМУ (touched/not-relevant/not-read). Чистое ядро (headers + reports инъектируются).
 * Непрорепорченный ИЛИ невалидно-прорепорченный пункт → not-reported (fail-safe: молчание
 * = «не отчитался», а не «не релевантно»).
 */
export const REPORT_STATUSES = Object.freeze(['touched', 'not-relevant', 'not-read', 'not-reported']);
const VALID = new Set(['touched', 'not-relevant', 'not-read']);

export function buildSkeletonRadar({ headers, reports } = {}) {
  const list = Array.isArray(headers) ? headers : [];
  const rep = (reports && typeof reports === 'object') ? reports : {};
  const items = list.map((h) => {
    const s = Object.prototype.hasOwnProperty.call(rep, h) ? rep[h] : undefined;
    // F-F4 (L2-пол): пункт заморожен — машинная мутация status бросает TypeError;
    // отчёт живёт в reports (вход), не правкой выхода.
    return Object.freeze({ header: h, status: VALID.has(s) ? s : 'not-reported' });
  });
  const unreported = items.filter((i) => i.status === 'not-reported');
  // F-F3: пустой скелет виден (headers:0 ≠ «всё отчитано») — зеркало F-F1 graph-radar.
  return { items, unreported, summary: { headers: list.length, unreported: unreported.length } };
}
