Files
brain/tools/skeleton-radar.mjs
T

24 lines
1.5 KiB
JavaScript

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