test(ms-ai-architect): Spor 1 — akseptansetester (residual scoped, worklist-aktivering, CT5/N4, poison-doc) [skip-docs]
This commit is contained in:
parent
cec98b5cb5
commit
ed92d65385
3 changed files with 134 additions and 1 deletions
|
|
@ -22,6 +22,12 @@ 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)
|
||||
|
|
@ -195,3 +201,46 @@ test('buildFullPassReport — no source map still works (annotation null)', () =
|
|||
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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@
|
|||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { validatePaths } from '../../scripts/kb-update/validate-kb-file.mjs';
|
||||
import { buildKbHeader } from '../../scripts/kb-update/lib/transform.mjs';
|
||||
import {
|
||||
buildKbHeader,
|
||||
insertHeaderFields,
|
||||
validateKbFile,
|
||||
} from '../../scripts/kb-update/lib/transform.mjs';
|
||||
import { parseTypeHeader, parseSourceHeader } from '../../scripts/kb-update/lib/kb-headers.mjs';
|
||||
|
||||
const GOOD = buildKbHeader({
|
||||
title: 'Azure AI Search - Hybrid Retrieval',
|
||||
|
|
@ -78,3 +83,44 @@ test('validatePaths — no paths → ok:true (nothing to gate)', () => {
|
|||
assert.equal(r.ok, true);
|
||||
assert.deepEqual(r.results, []);
|
||||
});
|
||||
|
||||
// --- Spor 1 acceptance: the residual criterion after the substrate migration ---
|
||||
// These generate the migrated file through the REAL Session-2 primitive
|
||||
// (insertHeaderFields), then assert the create-guard's residual — proving the
|
||||
// substrate closes the worklist-relevant fields (type+source) even where base
|
||||
// fields lag. `verified`/`verified_by` stay open by design (the judge fills them,
|
||||
// next brief), so the residual for a conformant file is EXACTLY those two.
|
||||
|
||||
// A base-field-CONFORMANT legacy file: title + English **Last updated:** + **Status:**,
|
||||
// small (no TOC required). Migrated → Type + Source stamped, still no Verified.
|
||||
const LEGACY_CONFORMANT =
|
||||
'# Azure AI Foundry\n\n**Last updated:** 2026-06\n**Status:** GA\n\n---\n\n## Oversikt\n\ntekst\n';
|
||||
// A base-field-INCOMPLETE legacy file: Norwegian **Sist oppdatert:** (RE_LAST_UPDATED is
|
||||
// English-only) + **Kategori:** but NO **Status:**. Migrated → Type + Source stamped.
|
||||
const LEGACY_INCOMPLETE =
|
||||
'# Copilot Studio\n\n**Kategori:** Styring\n**Sist oppdatert:** 2026-06\n\n---\n\n## Oversikt\n\ntekst\n';
|
||||
|
||||
test('acceptance — a migrated base-field-conformant reference has residual EXACTLY [verified, verified_by]', () => {
|
||||
const migrated = insertHeaderFields(LEGACY_CONFORMANT, {
|
||||
type: 'reference',
|
||||
source: 'https://learn.microsoft.com/azure/ai-foundry',
|
||||
});
|
||||
assert.equal(parseTypeHeader(migrated), 'reference');
|
||||
assert.equal(parseSourceHeader(migrated), 'https://learn.microsoft.com/azure/ai-foundry');
|
||||
assert.deepEqual(validateKbFile(migrated).missing, ['verified', 'verified_by']);
|
||||
});
|
||||
|
||||
test('acceptance — a migrated base-field-incomplete reference has residual ⊆ the 4-set, with type+source present', () => {
|
||||
const migrated = insertHeaderFields(LEGACY_INCOMPLETE, {
|
||||
type: 'reference',
|
||||
source: 'https://learn.microsoft.com/power-platform/copilot',
|
||||
});
|
||||
const { missing } = validateKbFile(migrated);
|
||||
const FOUR_SET = ['last_updated', 'status', 'verified', 'verified_by'];
|
||||
assert.ok(missing.every((m) => FOUR_SET.includes(m)), `residual ${JSON.stringify(missing)} ⊆ 4-set`);
|
||||
// The substrate DID complete the worklist-relevant fields — type + source are present,
|
||||
// never in the residual, even though base fields (Norwegian date / no Status) lag.
|
||||
assert.ok(!missing.includes('source'));
|
||||
assert.equal(parseTypeHeader(migrated), 'reference');
|
||||
assert.equal(parseSourceHeader(migrated), 'https://learn.microsoft.com/power-platform/copilot');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue