fix(okr): siterte markoerverdier korrumperte begge rot-markoerene

Upstreams eneste kanoniske eksempel med verdi (okf/SPEC.md:773) skriver
`okf_version: "0.2"` -- sitert. parseExistingIndex fanget anfoerselstegnene
raatt, UPSTREAM_VERSION_RE avviste `"0.2"` som ikke-upstream-form, og
resolveMarkers behandlet den som en layout-verdi fra foer 1.8.1-splitten:

  inn:  okf_version: "0.2"
  ut:   okf_version: 0.1      <- nedgradert til vaar konstant
        okf_layout: "0.2"     <- ekte upstream-versjon i feil markoer

Begge markoerene oedelagt, og dataene ikke gjenopprettelige uten aa kjenne
originalen. Bugen er i released 1.8.1-kode og traff enhver bundle som hadde
skrevet markoeren slik upstream selv viser den.

Fiks: anfoerselstegnene er YAML-strengsyntaks, ikke del av verdien, saa de
strippes ved parse -- foer verdien tolkes og foer den emitteres. Verdien
emitteres normalisert (unquoted), slik at vaar egen utskrift bestaar en
form-sjekk som kjoeres paa raa streng. Unquote er konservativ: kun et
matchende par strippes, en halv sekvens bevares uroert.

Tester: 187 -> 192. Fire nye kjoert roede foer fiksen; den femte
(ubalansert-vakten) mutasjons-verifisert roed mot en graadig unquote.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmXFhc6v9cs4YZ5AWFnQs8
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 17:12:24 +02:00
commit 85143be7b1
2 changed files with 98 additions and 3 deletions

View file

@ -665,6 +665,87 @@ test('okf-index: eksisterende splittet form bevares verbatim (idempotent vedlike
}
});
// --- S38: SITERTE markoerverdier (datakorrumperings-fiks) ---
// Upstreams ENESTE kanoniske eksempel med verdi (`okf/SPEC.md:773`) skriver
// `okf_version: "0.2"` -- SITERT. Anfoerselstegnene er YAML-strengsyntaks, ikke
// del av verdien. Foer denne fiksen fanget parsen dem raatt, UPSTREAM_VERSION_RE
// avviste `"0.2"` som ikke-upstream-form, og migrasjonen flyttet den til
// okf_layout mens okf_version ble nedgradert til vaar konstant -- BEGGE
// markoerene oedelagt, uten gjenoppretting. Verdien tolkes derfor unquoted, og
// emitteres normalisert (unquoted) saa vaar egen utskrift bestaar en form-sjekk
// som kjoeres paa raa streng.
test('okf-index: SITERT upstream-verdi i okf_version migreres IKKE til okf_layout', () => {
const dir = tmpRoot();
try {
writeRootIndex(dir, ['okf_version: "0.2"']);
generateIndexes(dir);
const root = readFileSync(join(dir, 'index.md'), 'utf8');
assert.match(root, /^okf_version: 0\.2$/m, 'sitert upstream-verdi skal bevares, normalisert');
assert.match(root, /^okf_layout: kb-layout-2026-06$/m, 'layout fylles fra konstant');
assert.ok(!/okf_layout: "?0\.2"?$/m.test(root), 'upstream-verdien skal ALDRI havne i okf_layout');
// Idempotent: andre kjoering leser sin egen normaliserte utskrift uendret.
generateIndexes(dir);
assert.equal(readFileSync(join(dir, 'index.md'), 'utf8'), root, 'andre kjoering skal ikke endre noe');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('okf-index: ENKELTSITERT upstream-verdi behandles likt (YAML-syntaks, ikke verdi)', () => {
const dir = tmpRoot();
try {
writeRootIndex(dir, ["okf_version: '0.2'"]);
generateIndexes(dir);
const root = readFileSync(join(dir, 'index.md'), 'utf8');
assert.match(root, /^okf_version: 0\.2$/m);
assert.ok(!/okf_layout: '?0\.2'?$/m.test(root), 'upstream-verdien skal ALDRI havne i okf_layout');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('okf-index: SITERT legacy layout-verdi migreres og emitteres unquoted', () => {
const dir = tmpRoot();
try {
writeRootIndex(dir, ['okf_version: "kb-layout-2025-01"']);
generateIndexes(dir);
const root = readFileSync(join(dir, 'index.md'), 'utf8');
assert.match(root, /^okf_version: 0\.1$/m, 'ekte layout-verdi flyttes fortsatt ut av okf_version');
assert.match(root, /^okf_layout: kb-layout-2025-01$/m, 'verdien flyttes uten anfoerselstegn');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('okf-index: SITERT okf_layout bevares, normalisert', () => {
const dir = tmpRoot();
try {
writeRootIndex(dir, ['okf_version: 0.2', 'okf_layout: "kb-layout-2099-12"']);
generateIndexes(dir);
const root = readFileSync(join(dir, 'index.md'), 'utf8');
assert.match(root, /^okf_version: 0\.2$/m);
assert.match(root, /^okf_layout: kb-layout-2099-12$/m, 'eksisterende layout bevares uten anfoerselstegn');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('okf-index: UBALANSERT anfoerselstegn strippes ikke (konservativ unquote)', () => {
const dir = tmpRoot();
try {
// Kun et MATCHENDE par er YAML-syntaks. En halv anfoerselstegn-sekvens er en
// ugyldig verdi, ikke en upstream-versjon, og faar migrasjonens legacy-vei.
writeRootIndex(dir, ['okf_version: "0.2']);
generateIndexes(dir);
const root = readFileSync(join(dir, 'index.md'), 'utf8');
assert.match(root, /^okf_version: 0\.1$/m, 'ugyldig verdi er ikke upstream-form');
assert.match(root, /^okf_layout: "0\.2$/m, 'verdien flyttes verbatim, uroert');
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
test('okf-index CLI: --okf-layout bumper layout og lar okf_version staa', () => {
const dir = tmpRoot();
try {