fix(okr): okf-check leser OKF-felt paa rot-nivaa (patch-lane #2)

parseFrontmatter.get() er bevisst innrykk-tolerant (`^\s*key:`) fordi nestet
oppslag er load-bearing for inject-okr-context.mjs. Gaten arvet toleransen og
leste en `type:` under `metadata:` som filas type -- en utypet fil passerte
(exit 0). Rot-nivaa-kravet ligger derfor i kalleren; lib/frontmatter.mjs er
uroert.

Ny rootLevelGet() filtrerer bort innrykkede linjer og re-parser visningen med
SAMME lib, saa sitering/kommentar-stripping har fortsatt en implementasjon.
Brukt paa alle OKF-felt i checkBundle (type/title/anbefalte) + paa rootMarkers'
frontmatter-gren, som ellers ga et annet svar enn den rot-ankrede
broedtekst-fallbacken i samme funksjon.

Fire utslag av samme defekt lukket: falsk negativ paa nestet type, nestet type
FOER rot-noekkelen skygget rot-verdien (first-match), falsk positiv naar en
NESTET title bar en lenke, og et nestet anbefalt felt dempet en advarsel.

Tester (N1)-(N5) verifisert roede FOER fiksen; mutasjons-verifisert etterpaa.
Suite 316 -> 321.
This commit is contained in:
Kjell Tore Guttormsen 2026-08-09 14:30:23 +02:00
commit 35a0bb8377
2 changed files with 130 additions and 2 deletions

View file

@ -23,6 +23,26 @@ import { unquote } from './okf-index.mjs';
const RECOMMENDED = ['resource', 'title', 'description', 'timestamp'];
// OKFs konsept-felt er ROT-noekler. parseFrontmatter.get() er derimot bevisst
// innrykk-tolerant (`^\s*key:`, lib/frontmatter.mjs:29) fordi nestet oppslag er
// load-bearing for inject-okr-context.mjs's organisasjon:/program:-lesing. Den
// toleransen hoerer ikke hjemme i denne gaten, saa rot-nivaa-kravet ligger her
// i KALLEREN -- lib-en skal fortsatt tolerere innrykk for sine egne konsumenter.
//
// Uten dette leste gaten en `type:` under `metadata:` som filas type (falsk
// negativ: utypet fil passerte), lot en nestet `type:` FOER rot-noekkelen skygge
// rot-verdien (first-match), felte dokumenter paa en lenke i en NESTET `title:`
// (falsk positiv i strict-ingest) og lot et nestet `description:` dempe en
// advarsel som burde staatt.
//
// Visningen re-parses av SAMME lib, aldri av en kopi av regelen: sitering og
// trailing-kommentar-stripping har fortsatt kun EN implementasjon.
function rootLevelGet(fmRaw) {
if (fmRaw === null) return () => null;
const flat = fmRaw.split('\n').filter((l) => !/^\s/.test(l)).join('\n');
return parseFrontmatter(`---\n${flat}\n---`).get;
}
// Lenke-deteksjon for --strict-ingest: hvert lenke-maal maa vaere en trygg,
// on-disk bundle-root-relativ .md (anti-RAG-poison). B3 (A1): ALLE fire
// standard lenkeformer fanges -- inline, referanse-definisjon, autolink og
@ -84,7 +104,11 @@ function rootMarkers(root) {
const idx = join(root, 'index.md');
if (!existsSync(idx)) return { okfVersion: null, okfLayout: null };
const raw = readFileSync(idx, 'utf8');
const { raw: fmRaw, get: fmGet } = parseFrontmatter(raw);
const { raw: fmRaw } = parseFrontmatter(raw);
// Rot-nivaa ogsaa her: broedtekst-fallbacken under har ALLTID vaert rot-ankret
// (`^key:` uten \s*), saa en innrykk-tolerant frontmatter-gren ga samme fil to
// svar avhengig av hvilket lag som traff foerst.
const fmGet = rootLevelGet(fmRaw);
// Broedteksten = alt UNDER frontmatter-blokken, slik at de to lagene kan feile
// hver for seg (mutasjon M1 roedner (20a)/(20d) NETTOPP fordi fallbacken ikke
// ser frontmatter-linjene).
@ -124,7 +148,7 @@ export function checkBundle(root, { strictIngest = false, files } = {}) {
const strictErrors = [];
for (const f of concepts) {
const raw = readFileSync(f, 'utf8');
const { get } = parseFrontmatter(raw);
const get = rootLevelGet(parseFrontmatter(raw).raw);
const rel = relative(root, f);
const type = get('type');
if (!type) {