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:
parent
667b7037a1
commit
85143be7b1
2 changed files with 98 additions and 3 deletions
|
|
@ -35,9 +35,23 @@ export const OKF_VERSION = '0.1';
|
|||
export const OKF_LAYOUT = 'kb-layout-2026-06';
|
||||
|
||||
// Upstream-versjoner er numerisk punktnotasjon (`0.1`). Alt annet i et
|
||||
// `okf_version`-felt er en layout-verdi fra foer splitten.
|
||||
// `okf_version`-felt er en layout-verdi fra foer splitten. Testes ALLTID mot en
|
||||
// unquotet verdi -- se unquote().
|
||||
const UPSTREAM_VERSION_RE = /^\d+(?:\.\d+)+$/;
|
||||
|
||||
// En markoerverdi kan vaere sitert: upstreams eget kanoniske eksempel
|
||||
// (`okf/SPEC.md:773`) skriver `okf_version: "0.2"`. Anfoerselstegnene er
|
||||
// YAML-strengsyntaks, ikke del av verdien, saa de maa vekk FOER verdien tolkes
|
||||
// (UPSTREAM_VERSION_RE) og foer den emitteres -- ellers leses en gyldig
|
||||
// upstream-versjon som en layout-verdi og migreres til feil markoer.
|
||||
// KUN et matchende par strippes: en halv anfoerselstegn-sekvens er en ugyldig
|
||||
// verdi som skal bevares uroert, ikke gjettes paa.
|
||||
function unquote(s) {
|
||||
const q = s[0];
|
||||
if ((q === '"' || q === "'") && s.length >= 2 && s.endsWith(q)) return s.slice(1, -1);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Drop-zone (raa innboks-filer) + skjulte kataloger (.cache osv.) er ikke nivaaer:
|
||||
// de skal verken faa egen index.md eller listes som underkatalog-peker. Maa
|
||||
// filtreres i BEGGE enumererings-steder (subdir-listing + rekursjon).
|
||||
|
|
@ -66,9 +80,9 @@ function parseExistingIndex(path) {
|
|||
result.heading = line.slice(2).trim();
|
||||
}
|
||||
const ver = line.match(/^okf_version:\s*(.+)$/);
|
||||
if (ver) result.okfVersion = ver[1].trim();
|
||||
if (ver) result.okfVersion = unquote(ver[1].trim());
|
||||
const lay = line.match(/^okf_layout:\s*(.+)$/);
|
||||
if (lay) result.okfLayout = lay[1].trim();
|
||||
if (lay) result.okfLayout = unquote(lay[1].trim());
|
||||
const entry = line.match(/^\*\s*\[([^\]]*)\]\(([^)]+)\)(?:\s*-\s*(.*))?$/);
|
||||
if (entry) {
|
||||
if (!(entry[2] in result.descByLink)) result.linkOrder.push(entry[2]);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue