feat(ms-ai-architect): RX-KB1b — deterministisk footer-dato-avvik-deteksjon + label-whitelist i corpus-audit (flag-to-human, 3 flagg) [skip-docs]

This commit is contained in:
Kjell Tore Guttormsen 2026-07-17 03:23:40 +02:00
commit 722a131eb7
2 changed files with 119 additions and 0 deletions

View file

@ -163,3 +163,68 @@ test('auditHeaders — an unreadable file is reported, not thrown', () => {
assert.equal(r.aggregate.files, 1);
assert.equal(r.aggregate.readErrors, 1);
});
// ── RX-KB1b: footer date-conflict + label-whitelist ────────────────────────
// A file that claims one **Last updated:** date in the header and a DIFFERENT date
// under a norsk "Sist oppdatert" footer contradicts itself. Only the last-updated-
// EQUIVALENT label ("Sist oppdatert") is conflict-bearing; "Verifisert"/"Sist
// verifisert" record an independent axis (when content was checked vs source) and are
// whitelisted. Detection is read-only and flag-to-human — the audit never mutates.
// header 2026-06-24, italic footer "Sist oppdatert: 2026-02" — the
// stakeholder-communication-ai-decisions.md shape (genuine self-contradiction).
const FOOTER_CONFLICT =
'# T\n\n**Category:** x\n**Status:** GA\n**Last updated:** 2026-06-24\n\n---\n\n' +
'## A\n\ntekst\n\n*Sist oppdatert: 2026-02 av Cosmo Skyberg (AI Architect Plugin)*\n';
// header and footer agree on the month — no conflict.
const FOOTER_MATCH =
'# T\n\n**Category:** x\n**Status:** GA\n**Last updated:** 2026-02-03\n\n---\n\n' +
'## A\n\ntekst\n\n**Sist oppdatert:** 2026-02-03\n';
// footer carries a DIFFERENT date but under the whitelisted "Sist verifisert" label —
// an independent provenance axis, NOT a conflict.
const FOOTER_VERIFISERT_INDEP =
'# T\n\n**Category:** x\n**Status:** GA\n**Last updated:** 2026-06-24\n\n---\n\n' +
'## A\n\ntekst\n\n**Sist verifisert:** 2026-02-04\n';
// placeholder footer ([Dato]) is template scaffolding, not a real date — never a conflict.
const FOOTER_PLACEHOLDER =
'# T\n\n**Category:** x\n**Status:** GA\n**Last updated:** 2026-06-24\n\n---\n\n' +
'## A\n\n## Versjon og godkjenning\n- **Sist oppdatert:** [Dato]\n';
test('auditHeaders — footer "Sist oppdatert" date ≠ header Last updated is flagged as a conflict', () => {
const r = auditHeaders(['a.md'], reader({ 'a.md': FOOTER_CONFLICT }));
const f = r.files['a.md'];
assert.ok(f.footerConflict, 'conflict object present');
assert.equal(f.footerConflict.headerLastUpdated, '2026-06-24');
assert.deepEqual(f.footerConflict.footerDates, ['2026-02']);
assert.equal(r.aggregate.footerConflicts, 1);
});
test('auditHeaders — footer "Sist oppdatert" matching the header month raises no conflict', () => {
const r = auditHeaders(['b.md'], reader({ 'b.md': FOOTER_MATCH }));
assert.equal(r.files['b.md'].footerConflict, null);
assert.equal(r.aggregate.footerConflicts, 0);
});
test('auditHeaders — a differing "Sist verifisert" footer is whitelisted, not a conflict', () => {
const r = auditHeaders(['c.md'], reader({ 'c.md': FOOTER_VERIFISERT_INDEP }));
assert.equal(r.files['c.md'].footerConflict, null);
assert.equal(r.aggregate.footerConflicts, 0);
});
test('auditHeaders — a placeholder "[Dato]" footer never counts as a conflict', () => {
const r = auditHeaders(['d.md'], reader({ 'd.md': FOOTER_PLACEHOLDER }));
assert.equal(r.files['d.md'].footerConflict, null);
assert.equal(r.aggregate.footerConflicts, 0);
});
test('auditHeaders — footer conflict needs BOTH a header date and a norsk footer date', () => {
// V_NONDATE has a norsk "Sist oppdatert" but no English header Last updated → no conflict.
// V_DATE has an English header date but no norsk footer → no conflict.
const r = auditHeaders(['a.md', 'b.md'], reader({ 'a.md': V_NONDATE, 'b.md': V_DATE }));
assert.equal(r.files['a.md'].footerConflict, null);
assert.equal(r.files['b.md'].footerConflict, null);
assert.equal(r.aggregate.footerConflicts, 0);
});