ms-ai-architect/tests/kb-update/test-strip-stale-verified-pipe.test.mjs
Kjell Tore Guttormsen 712a143e58 fix(ms-ai-architect): RX-KB1 strip stale plain-Verified pipe-tails (87) + audit-deteksjon [skip-docs]
De 87 referansefilene bar en plain-text `| Verified: <dato>`-hale på **Last updated:**-linjen
i 500B-header-vinduet — usynlig for den bold-only kontrakt-stacken (kb-headers.mjs / audit
RE_VERIFIED), og claimet en verifisering judgen aldri gjorde (samme poison-klasse som de 14
bold **Verified:** MCP Spor 1 fjernet). Uhåndtert springer den også dual-Verified-fellen: R7s
insertVerifiedFields ville stemplet en bold-verdi ved siden av den plain → to motstridende
provenance-claims per fil.

- ny driver strip-stale-verified-pipe.mjs: frosset 87-manifest (18 advisor + 45 eng + 8 gov +
  16 sec), pure verdi-bevarende strip (kun ` | Verified: …`-halen; **Last updated:**-dato
  byte-eksakt), hard per-fil-invariant (linjeantall uendret, body byte-identisk, dato bevart),
  idempotent, atomicWriteSync (RX-OPS2 recovery-kontrakt).
- audit-corpus-headers.mjs: ny plain-Verified-deteksjon (RE_PLAIN_VERIFIED + plainVerifiedPipe)
  — gjør M4-blindheten synlig så en stale plain-hale ikke kan gjenoppstå stille (non-advisor scope).
- 87 filer strippet; plain Verified i vinduet 0/389; live-audit plainVerifiedPipe 0.

Mekanisme: +15 tester (12 strip + 3 audit). Suite 875→890 exit 0. validate-plugin.sh 250/0.

Utsatt → RX-KB1b: footer-dato-avvik + label-whitelist (annen dialekt, flag-to-human).
2026-07-16 20:04:52 +02:00

111 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// tests/kb-update/test-strip-stale-verified-pipe.test.mjs
// TDD for RX-KB1 — strip the stale plain `| Verified: MCP <date>` pipe-tail from the
// **Last updated:** line across the 87 reference files that carry it in the top-500-byte
// header window. This is the same poison class as the 14 bold `**Verified:** MCP` labels
// Spor 1 already removed: a plain-text "Verified" claim the judge never made, invisible to
// the bold-only contract stack (kb-headers.mjs / audit RE_VERIFIED). "Strip" = remove ONLY
// the ` | Verified: …` tail, preserving `**Last updated:** <date>` byte-exact; the citation,
// the date, and the whole body stay untouched. Value-preserving, idempotent, one line edited
// in place (never removed).
//
// The two dialect variants in the real corpus (ground truth 2026-07-16):
// 85× `**Last updated:** <date> | Verified: MCP <date>`
// 2× `**Last updated:** <date> | Verified: <date>` (no "MCP")
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { stripVerifiedPipe, MANIFEST } from '../../scripts/kb-update/strip-stale-verified-pipe.mjs';
// A reference-shaped fixture: bold header with the plain Verified pipe-tail, then a body that
// itself mentions "Verified:" and even "| Verified:" in prose (must never be touched).
const FIXTURE = [
'# Azure AI Search — RAG Setup',
'**Type:** reference',
'**Last updated:** 2026-06-19 | Verified: MCP 2026-06-19',
'**Category:** RAG',
'',
'---',
'',
'## Innhold',
'',
'A body line mentioning Verified: yesterday and a | Verified: pipe — must be left alone.',
'',
].join('\n');
// ── stripVerifiedPipe (pure) ─────────────────────────────────────────────────
test('stripVerifiedPipe: removes the `| Verified: MCP <date>` tail, keeps Last updated byte-exact', () => {
const out = stripVerifiedPipe(FIXTURE);
const header = out.split('\n---')[0];
assert.ok(header.includes('**Last updated:** 2026-06-19'), 'Last updated + date preserved');
assert.ok(!/Verified:/.test(header), 'no Verified label remains in the header');
assert.ok(!/\|\s*$/.test(header.split('\n')[2]), 'no dangling pipe/whitespace after strip');
assert.equal(header.split('\n')[2], '**Last updated:** 2026-06-19', 'exact stripped line');
});
test('stripVerifiedPipe: strips the non-MCP `| Verified: <date>` variant too', () => {
const nonMcp = FIXTURE.replace('| Verified: MCP 2026-06-19', '| Verified: 2026-06-18');
const out = stripVerifiedPipe(nonMcp);
const header = out.split('\n---')[0];
assert.equal(header.split('\n')[2], '**Last updated:** 2026-06-19', 'non-MCP tail stripped, date kept');
assert.ok(!/Verified:/.test(header), 'no Verified label remains');
});
test('stripVerifiedPipe: one line edited in place — total line count unchanged', () => {
const out = stripVerifiedPipe(FIXTURE);
assert.equal(out.split('\n').length, FIXTURE.split('\n').length, 'no line added or removed');
});
test('stripVerifiedPipe: body is byte-identical (only the header line changes)', () => {
const out = stripVerifiedPipe(FIXTURE);
const bodyOf = (c) => c.slice(c.indexOf('\n---'));
assert.equal(bodyOf(out), bodyOf(FIXTURE), 'body untouched');
});
test('stripVerifiedPipe: never touches a "Verified:" or "| Verified:" in the body', () => {
const out = stripVerifiedPipe(FIXTURE);
assert.ok(out.includes('mentioning Verified: yesterday and a | Verified: pipe'), 'body prose intact');
});
test('stripVerifiedPipe: idempotent — a second pass is a no-op', () => {
const once = stripVerifiedPipe(FIXTURE);
assert.equal(stripVerifiedPipe(once), once);
});
test('stripVerifiedPipe: no pipe-tail present → unchanged (clean Last updated)', () => {
const clean = FIXTURE.replace(' | Verified: MCP 2026-06-19', '');
assert.equal(stripVerifiedPipe(clean), clean);
});
test('stripVerifiedPipe: leaves the citation date byte-exact even if it differs from the Verified date', () => {
// Last updated 2026-06-24, Verified MCP 2026-06 (the drift the review flagged) — the strip
// keeps the authored Last updated date and simply drops the unverifiable Verified claim.
const drift = FIXTURE.replace('**Last updated:** 2026-06-19 | Verified: MCP 2026-06-19',
'**Last updated:** 2026-06-24 | Verified: MCP 2026-06');
const out = stripVerifiedPipe(drift);
assert.equal(out.split('\n')[2], '**Last updated:** 2026-06-24');
});
// ── MANIFEST (frozen ground truth 2026-07-16) ────────────────────────────────
test('MANIFEST: exactly the 87 plain-Verified files, no duplicates', () => {
assert.equal(MANIFEST.length, 87, 'frozen count');
assert.equal(new Set(MANIFEST).size, 87, 'no duplicates');
});
test('MANIFEST: per-skill breakdown 18/45/8/16 (advisor/engineering/governance/security)', () => {
const bySkill = (skill) => MANIFEST.filter((p) => p.startsWith(`skills/${skill}/`)).length;
assert.equal(bySkill('ms-ai-advisor'), 18);
assert.equal(bySkill('ms-ai-engineering'), 45);
assert.equal(bySkill('ms-ai-governance'), 8);
assert.equal(bySkill('ms-ai-security'), 16);
});
test('MANIFEST: every entry is a plugin-relative references .md path', () => {
for (const p of MANIFEST) {
assert.match(p, /^skills\/ms-ai-[a-z]+\/references\/.+\.md$/, `bad path: ${p}`);
}
});
test('MANIFEST: sorted (deterministic, diff-stable)', () => {
const sorted = [...MANIFEST].sort();
assert.deepEqual(MANIFEST, sorted, 'manifest must be sorted');
});