ms-ai-architect/tests/kb-update/test-full-pass-worklist.test.mjs

246 lines
11 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-full-pass-worklist.test.mjs
// Spor 3 Port 3 (kadens-judge) — PERIODIC full-pass WORKLIST (P3d).
//
// The incremental pass (P3a) only re-judges files whose source sitemap_lastmod
// moved past **Verified:** — it catches lastmod-VISIBLE drift. The full-pass
// catches the class staleness misses (base-rate showed staleness-recall 0/40):
// MS can change a page without bumping its sitemap lastmod. So the full-pass is
// deliberately LASTMOD-INDEPENDENT — it gates on the Port 1 frontmatter contract
// (type:reference + a Source URL to anchor against) and on cadence age of the
// **Verified:** stamp, NOT on lastmod. buildFileSourceMap (which skips sources
// without a lastmod) is reused only to ANNOTATE entries, never to gate them.
//
// classifyFullPassDue is PURE (mirrors classifyVerifiedStaleness): no disk, today
// + cadence injected. The operator-chosen design is a WORKLIST (not an inline
// judge): this produces the ranked list of files due for re-judge; the operator
// kicks off the actual judging separately (§5 "ikke auto-lansert", §4c "aldri
// auto-fiks", and the honest ~2700-fetch/multi-session cost forecloses inline).
import { test } from 'node:test';
import assert from 'node:assert/strict';
import {
classifyFullPassDue,
buildFullPassReport,
} from '../../scripts/kb-update/lib/full-pass-worklist.mjs';
import { normalizeStaleVerified } from '../../scripts/kb-update/lib/transform.mjs';
import {
parseTypeHeader,
parseSourceHeader,
parseVerifiedHeader,
} from '../../scripts/kb-update/lib/kb-headers.mjs';
const TODAY = '2026-06-29';
const MAX_AGE = 90; // threshold = 2026-03-31 (verified strictly before → cadence-due)
const f = (over) => ({
path: 'skills/x/references/a.md',
type: 'reference',
source: 'https://learn.microsoft.com/x',
verified: '2026-06-01',
newestSourceLastmod: null,
...over,
});
const opts = { today: TODAY, maxAgeDays: MAX_AGE };
// --- classifyFullPassDue: core scope + cadence classification ---
test('reference + source + never verified → due, reason never-verified', () => {
const out = classifyFullPassDue([f({ verified: null })], opts);
assert.equal(out.worklist.length, 1);
assert.equal(out.worklist[0].reason, 'never-verified');
assert.equal(out.worklist[0].ageDays, null);
assert.equal(out.counts.neverVerified, 1);
assert.equal(out.counts.due, 1);
});
test('reference + source + verified OLDER than cadence window → due, reason cadence-due', () => {
const out = classifyFullPassDue([f({ verified: '2026-01-01' })], opts);
assert.equal(out.worklist.length, 1);
assert.equal(out.worklist[0].reason, 'cadence-due');
assert.equal(out.worklist[0].ageDays, 179); // 2026-01-01 → 2026-06-29
assert.equal(out.counts.cadenceDue, 1);
assert.equal(out.counts.due, 1);
});
test('reference + source + verified WITHIN cadence window → fresh, not in worklist', () => {
const out = classifyFullPassDue([f({ verified: '2026-06-01' })], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.fresh, 1);
});
test('verified EXACTLY at threshold (today maxAgeDays) → fresh (strict <, mirrors incremental)', () => {
// 2026-06-29 minus 90 days = 2026-03-31
const out = classifyFullPassDue([f({ verified: '2026-03-31' })], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.fresh, 1);
});
test('verified one day before threshold → cadence-due', () => {
const out = classifyFullPassDue([f({ verified: '2026-03-30' })], opts);
assert.equal(out.worklist.length, 1);
assert.equal(out.worklist[0].reason, 'cadence-due');
});
test('reference declared but NO source → unsourced (cannot anchor full-pass), counted not listed', () => {
const out = classifyFullPassDue([f({ source: null, verified: null })], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.unsourced, 1);
});
test('template / methodology / regulatory → out-of-scope, never listed', () => {
const out = classifyFullPassDue([
f({ type: 'template', source: null, verified: null }),
f({ type: 'methodology', source: null, verified: null }),
f({ type: 'regulatory', source: null, verified: null }),
], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.outOfScope, 3);
});
test('no Type header (legacy corpus) → unmigrated, counted but not listed (Spor 1 territory)', () => {
const out = classifyFullPassDue([f({ type: null, source: null, verified: null })], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.unmigrated, 1);
});
test('YYYY-MM verified normalizes to -01 for the cadence boundary', () => {
// 2026-03 → 2026-03-01, which is before the 2026-03-31 threshold → due
const out = classifyFullPassDue([f({ verified: '2026-03' })], opts);
assert.equal(out.worklist.length, 1);
assert.equal(out.worklist[0].reason, 'cadence-due');
});
test('worklist entry carries path, reason, verified, ageDays, source for the human', () => {
const out = classifyFullPassDue([
f({ path: 'skills/s/references/p.md', verified: '2026-02-01', source: 'https://learn.microsoft.com/p' }),
], opts);
const e = out.worklist[0];
assert.equal(e.path, 'skills/s/references/p.md');
assert.equal(e.reason, 'cadence-due');
assert.equal(e.verified, '2026-02-01');
assert.equal(e.source, 'https://learn.microsoft.com/p');
assert.equal(typeof e.ageDays, 'number');
});
test('ranking: never-verified before cadence-due; within cadence-due oldest verified first', () => {
const out = classifyFullPassDue([
f({ path: 'b-recent-stale.md', verified: '2026-02-01' }), // cadence-due, 148d
f({ path: 'a-never.md', verified: null }), // never-verified
f({ path: 'c-oldest-stale.md', verified: '2026-01-01' }), // cadence-due, 179d
], opts);
assert.deepEqual(out.worklist.map((e) => e.path), ['a-never.md', 'c-oldest-stale.md', 'b-recent-stale.md']);
});
test('mixed corpus aggregates counts; total = input length; due = worklist length', () => {
const out = classifyFullPassDue([
f({ verified: '2026-01-01' }), // cadence-due
f({ verified: null }), // never-verified
f({ verified: '2026-06-20' }), // fresh
f({ source: null, verified: null }), // unsourced
f({ type: 'template', source: null, verified: null }), // out-of-scope
f({ type: null, source: null, verified: null }), // unmigrated
], opts);
assert.equal(out.counts.total, 6);
assert.equal(out.counts.cadenceDue, 1);
assert.equal(out.counts.neverVerified, 1);
assert.equal(out.counts.fresh, 1);
assert.equal(out.counts.unsourced, 1);
assert.equal(out.counts.outOfScope, 1);
assert.equal(out.counts.unmigrated, 1);
assert.equal(out.counts.due, 2);
assert.equal(out.worklist.length, 2);
});
test('empty input → empty worklist, zeroed counts', () => {
const out = classifyFullPassDue([], opts);
assert.equal(out.worklist.length, 0);
assert.equal(out.counts.total, 0);
assert.equal(out.counts.due, 0);
});
// --- buildFullPassReport: assemble the report (pure; corpus paths + reader injected) ---
const SOURCE_MAP = new Map([
['due.md', '2026-06-15'], // annotation only — does NOT affect due-ness
['fresh.md', '2026-01-01'],
]);
const PATHS = ['due.md', 'fresh.md', 'gone.md', 'legacy.md'];
const READER = (p) => ({
'due.md': { type: 'reference', source: 'https://learn.microsoft.com/due', verified: '2026-01-01' },
'fresh.md': { type: 'reference', source: 'https://learn.microsoft.com/fresh', verified: '2026-06-20' },
'gone.md': null, // deleted on disk
'legacy.md': { type: null, source: null, verified: null },
}[p] ?? null);
test('buildFullPassReport — stamps metadata, joins headers, classifies by cadence', () => {
const r = buildFullPassReport(PATHS, READER, SOURCE_MAP, opts);
assert.equal(r.generated_at, TODAY);
assert.equal(r.cadence_max_age_days, MAX_AGE);
assert.equal(r.counts.due, 1);
assert.equal(r.counts.fresh, 1);
assert.equal(r.counts.unmigrated, 1);
assert.equal(r.worklist.length, 1);
assert.equal(r.worklist[0].path, 'due.md');
assert.equal(r.worklist[0].reason, 'cadence-due');
});
test('buildFullPassReport — annotates worklist entry with newestSourceLastmod from the source map', () => {
const r = buildFullPassReport(PATHS, READER, SOURCE_MAP, opts);
assert.equal(r.worklist[0].newestSourceLastmod, '2026-06-15');
});
test('buildFullPassReport — deleted files (reader null) skipped entirely, not counted', () => {
const r = buildFullPassReport(PATHS, READER, SOURCE_MAP, opts);
assert.equal(r.counts.total, 3); // gone.md skipped
assert.ok(!r.worklist.some((e) => e.path === 'gone.md'));
});
test('buildFullPassReport — no source map still works (annotation null)', () => {
const r = buildFullPassReport(['due.md'], READER, new Map(), opts);
assert.equal(r.worklist.length, 1);
assert.equal(r.worklist[0].newestSourceLastmod, null);
});
// --- Spor 1 acceptance: worklist ACTIVATION + the **Verified:** MCP poison it fixes ---
test('acceptance — migrated reference headers (type+source, verified:null) land in never-verified; unmigrated===0', () => {
const reader = (p) => ({
'm1.md': { type: 'reference', source: 'https://learn.microsoft.com/1', verified: null },
'm2.md': { type: 'reference', source: 'https://learn.microsoft.com/2', verified: null },
}[p] ?? null);
const r = buildFullPassReport(['m1.md', 'm2.md'], reader, new Map(), opts);
assert.equal(r.counts.neverVerified, 2);
assert.ok(r.counts.due > 0, 'the worklist activates — due>0');
assert.equal(r.counts.unmigrated, 0, 'no legacy no-Type files remain');
assert.ok(r.worklist.every((e) => e.reason === 'never-verified'));
});
// The poison, exercised through the REAL parser + normalizer (not a hand-forged
// header value): a header-region `**Verified:** MCP <date>` parses to the non-date
// token 'MCP', which the cadence classifier reads as a recent verification and drops
// the file to `fresh` — omitted from the worklist AND falsely "verified". This is the
// exact failure mode normalizeStaleVerified removes.
const POISONED =
'# Poisoned Ref\n\n**Status:** GA\n**Verified:** MCP 2026-06\n**Type:** reference\n' +
'**Source:** https://learn.microsoft.com/x\n\n---\n\n## A\n\ntekst\n';
const hdr = (c) => ({ type: parseTypeHeader(c), source: parseSourceHeader(c), verified: parseVerifiedHeader(c) });
test('acceptance — **Verified:** MCP poison drops a never-verified ref to fresh (the bug the normalizer fixes)', () => {
assert.equal(parseVerifiedHeader(POISONED), 'MCP'); // the poison: a non-date token read as "verified"
const r = buildFullPassReport(['p.md'], (p) => ({ 'p.md': hdr(POISONED) }[p] ?? null), new Map(), opts);
assert.equal(r.counts.fresh, 1, 'wrongly counted fresh');
assert.equal(r.worklist.length, 0, 'omitted from the worklist — the poison');
assert.equal(r.counts.unmigrated, 0);
});
test('acceptance — normalizeStaleVerified restores the poisoned file to a due never-verified entry', () => {
const fixed = normalizeStaleVerified(POISONED);
assert.equal(parseVerifiedHeader(fixed), null); // stale token stripped
assert.equal(parseTypeHeader(fixed), 'reference'); // Type/Source untouched
assert.equal(parseSourceHeader(fixed), 'https://learn.microsoft.com/x');
const r = buildFullPassReport(['p.md'], (p) => ({ 'p.md': hdr(fixed) }[p] ?? null), new Map(), opts);
assert.equal(r.worklist.length, 1);
assert.equal(r.worklist[0].reason, 'never-verified');
assert.ok(r.counts.due > 0);
});