feat(okr): okf-check leser okf_version fra frontmatter og broedtekst

This commit is contained in:
Kjell Tore Guttormsen 2026-08-02 21:11:58 +02:00
commit 049259d9a6
2 changed files with 155 additions and 11 deletions

View file

@ -899,3 +899,119 @@ test('okf-check: rot-index uten okf_layout ekkoer MANGLER for den, ikke for okf_
rmSync(dir, { recursive: true, force: true });
}
});
// --- D8 steg 20: okf-check leser markoerene fra BEGGE plasseringene ---
// Beslutning 6 flytter `okf_version` til rot-indeksens frontmatter (steg 21),
// mens `okf_layout` blir staaende i broedteksten. Bundles migrerer IKKE
// samtidig -- en bundle skrevet av en eldre okf-index baerer fortsatt begge i
// broedteksten -- saa LESINGEN maa tolerere begge former gjennom migrasjonen.
// Presedens: frontmatter foerst, deretter broedteksten UNDER frontmatter-blokken.
// Fortsatt ren ekko (ingen verdivalidering) og fortsatt ingen PRESENCE-krav.
//
// De tre casene er valgt for aa DISKRIMINERE de to lagene. S49-laerdommen:
// en assertion som ikke kan skille HVILKET lag som fanget gjoer en tolagsvakt
// til en ettlagsvakt uten at noe blir roedt. Her roedner hvert lag for seg:
// (20a) kun frontmatter -> roedner naar frontmatter-laget fjernes
// (20b) frontmatter UTEN noekkelen, verdi i -> roedner naar broedtekst-laget fjernes
// broedteksten (den naive "har fila frontmatter?
// bruk kun den"-regresjonen)
// (20c) begge, ULIKE verdier -> pinner presedensen; roedner naar
// rekkefoelgen snus
// Uten (20b) ville steg 20 bestaatt UTEN kodeendring: dagens rootMarkers()
// regex-scanner raa filtekst med `m`-flagg og treffer allerede frontmatter-
// linjer -- foerste treff vinner, og frontmatter staar oeverst.
// Rot-index med VILKAARLIG innhold (helleren writeRootIndex laaser formen).
function writeRawRootIndex(dir, content) {
mkdirSync(dir, { recursive: true });
writeFileSync(join(dir, 'index.md'), content);
}
test('(20a) okf-check: okf_version i rot-indeksens FRONTMATTER leses', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
writeRawRootIndex(dir, '---\nokf_version: 0.1\n---\n\n# Bundle\n\nokf_layout: kb-layout-2026-06\n');
const r = checkBundle(dir);
assert.equal(r.okfVersion, '0.1', 'frontmatter-plassert okf_version skal leses');
assert.equal(r.okfLayout, 'kb-layout-2026-06', 'broedtekst-plassert okf_layout skal fortsatt leses');
assert.equal(runCheck(dir).status, 0, 'migrert form skal gi exit 0');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('(20b) okf-check: frontmatter UTEN okf_version faller tilbake til broedteksten', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
// Umigrert bundle som likevel har en frontmatter-blokk: verdien staar i
// broedteksten. En lesing som slaar seg til ro med "fila HAR frontmatter"
// mister markoeren her -- det er regresjonen dette steget er likest til.
writeRawRootIndex(dir, '---\ntitle: Bundle\n---\n\n# Bundle\n\nokf_version: 0.1\nokf_layout: kb-layout-2026-06\n');
const r = checkBundle(dir);
assert.equal(r.okfVersion, '0.1', 'broedtekst-verdien skal finnes selv naar frontmatter finnes uten noekkelen');
assert.equal(r.okfLayout, 'kb-layout-2026-06');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('(20c) okf-check: staar markoeren BEGGE steder, vinner frontmatter', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
// Overgangstilstand: en delvis migrert index kan baere begge. Frontmatter er
// maalformen, saa den er den autoritative -- broedteksten er restene.
writeRawRootIndex(dir, '---\nokf_version: 0.9\n---\n\n# Bundle\n\nokf_version: 0.1\nokf_layout: kb-layout-2026-06\n');
const r = checkBundle(dir);
assert.equal(r.okfVersion, '0.9', 'frontmatter skal ha presedens over broedteksten');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('(20d) okf-check: sitert okf_version i frontmatter unquotes som paa produsent-siden', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
// Upstreams eget kanoniske eksempel (SPEC.md:773) er sitert. Samme fil skal
// ikke gi to lesninger avhengig av hvor markoeren staar.
writeRawRootIndex(dir, '---\nokf_version: "0.2"\n---\n\n# Bundle\n');
assert.equal(checkBundle(dir).okfVersion, '0.2', 'anfoerselstegn er YAML-syntaks, ikke del av verdien');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('(20e) okf-check: markoer helt fravaerende gir fortsatt exit 0 (ingen PRESENCE-krav)', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
writeRawRootIndex(dir, '---\ntitle: Bundle\n---\n\n# Bundle\n');
const r = checkBundle(dir);
assert.equal(r.okfVersion, null, 'fravaerende markoer skal vaere null');
assert.equal(r.okfLayout, null);
assert.equal(runCheck(dir).status, 0, 'okf_version er MAY i specen -- fravaer er ikke en feil');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('(20f) okf-check: frontmatter-markoer tolkes som YAML -- trailing kommentar lekker ikke inn i verdien', () => {
const dir = tmpRoot();
try {
buildCleanIngest(dir);
// Dette er caset som SKILLER de to lagene, og det eneste som roedner uten
// kodeendring: frontmatter ER YAML, saa ` # ...` er en kommentar og ikke del
// av verdien (lib/frontmatter.mjs:39, comment-leak-fiksen). Broedtekst-
// markoeren er IKKE YAML -- der er unquote() alene fortsatt riktig regel.
// Uten denne casen kunne steg 20 «bestaa» med dagens ettlags-regex, som
// scanner raa filtekst og ikke vet hva en frontmatter-blokk er.
writeRawRootIndex(dir, '---\nokf_version: 0.1 # upstream OKF-versjon\n---\n\n# Bundle\n');
assert.equal(checkBundle(dir).okfVersion, '0.1', 'YAML-kommentaren skal strippes i frontmatter');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});