ms-ai-architect/tests/kb-eval/test-g7-queue.test.mjs
Kjell Tore Guttormsen 59c6c280b1 feat(ms-ai-architect): G7 lukket som mekanisme — navngitt review-kø (form b), valgt på måling
Operatør-ratifisert 2026-08-03. G7 var gapet for korreksjoner som er RIKTIGE
men større enn O2-konvolutten (én lokator + kun-sletting). Uten eier falt de
stille ut: O2-triagen avviser dem, O3 dekker dem ikke, og review-sporet hadde
ingen inngangskø.

Formvalget ble tatt på §9.6-målingen, ikke på preferanse:
- 2 av 4 anvendte subtraksjoner etterlot en rest -> rester er delete-only-
  konvoluttens NORMALE biprodukt, ikke et unntak.
- 2 av 5 medlemmer (idx 17, 33) er ERSTATNINGER, ikke fler-lokator. En
  delete-orientert O4-klasse med egen retur-kontrakt ville ikke fikset dem —
  altså feil dimensjonert mot evidensen. Køen absorberer begge klasser.

Artefakter (TDD, test-først):
- data/g7-review-queue.json — 6 entries, tracked
- lib/g7-queue.mjs — validateQueue, lukkede vokabular
- check-g7-queue.mjs — exit 1 ved drift eller skjemafeil
- tests/kb-eval/test-g7-queue.test.mjs — 15 tester

Kontrakten: ankere er ORDRETTE strenger, aldri linjenummer (line != real_line
i 9 av 17 R11-records). En åpen entry hvis anker slutter å matche gir
anchor_drift og exit 1 — den kan ikke falle stille ut, som er hele hensikten.
En resolved entry MÅ føre resolution, ellers er "resolved" ikke til å skille
fra "stille droppet". Ingenting i køen er maskin-anvendbart per definisjon.

Innhold: 5 åpne (26, 27, 33, 36, 18), 1 lukket (17). idx 27 kom hit ved å
falle ut av O2 på cond 3; idx 26 ved operatørens avvisning av delvis fiks.

Suite 1047/1047. [skip-docs]
2026-08-03 21:10:00 +02:00

128 lines
5 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { validateQueue, ENTRY_CLASSES, ENTRY_STATES } from '../../scripts/kb-eval/lib/g7-queue.mjs';
// A queue entry is the ONLY thing standing between a real defect and silent loss,
// so the checks here are deliberately unforgiving about shape and about anchors
// that no longer exist in the corpus.
const okEntry = () => ({
id: 'idx-99',
file: 'skills/x/references/y.md',
class: 'multi-locator',
status: 'open',
raised: '2026-08-03',
summary: 'Something the file asserts in two places.',
evidence: 'docs/r11-pilot-results.md §9.6',
anchors: ['the exact text'],
});
const stub = (contents) => (p) => {
if (!(p in contents)) throw new Error(`ENOENT ${p}`);
return contents[p];
};
test('a well-formed open entry whose anchor is present passes', () => {
const r = validateQueue([okEntry()], stub({ 'skills/x/references/y.md': 'aaa the exact text bbb' }));
assert.equal(r.ok, true);
assert.deepEqual(r.findings, []);
});
test('vocabularies are closed', () => {
assert.deepEqual([...ENTRY_CLASSES].sort(), ['multi-locator', 'replacement']);
assert.deepEqual([...ENTRY_STATES].sort(), ['open', 'resolved']);
});
test('unknown class is rejected', () => {
const e = { ...okEntry(), class: 'deletion' };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /class/);
});
test('unknown status is rejected', () => {
const e = { ...okEntry(), status: 'wontfix' };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /status/);
});
test('a missing required field is reported by name', () => {
const e = okEntry();
delete e.evidence;
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /evidence/);
});
test('an open entry MUST carry at least one anchor', () => {
const e = { ...okEntry(), anchors: [] };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /anchor/i);
});
// The point of the whole mechanism: a defect must not be able to leave the queue
// just because someone edited the file around it.
test('an open entry whose anchor no longer occurs is a DRIFT finding, not a pass', () => {
const r = validateQueue([okEntry()], stub({ 'skills/x/references/y.md': 'nothing matching here' }));
assert.equal(r.ok, false);
assert.equal(r.findings[0].kind, 'anchor_drift');
assert.match(r.findings[0].message, /the exact text/);
});
test('every anchor is checked, not just the first', () => {
const e = { ...okEntry(), anchors: ['present', 'absent'] };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'present only' }));
assert.equal(r.ok, false);
assert.equal(r.findings.length, 1);
assert.match(r.findings[0].message, /absent/);
});
test('a missing file is reported rather than thrown', () => {
const r = validateQueue([okEntry()], stub({}));
assert.equal(r.ok, false);
assert.equal(r.findings[0].kind, 'file_unreadable');
});
test('a resolved entry MUST record how it was resolved', () => {
const e = { ...okEntry(), status: 'resolved' };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'whatever' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /resolution/);
});
test('a resolved entry is exempt from anchor checking', () => {
const e = { ...okEntry(), status: 'resolved', resolution: 'colon -> period, ratified 2026-08-03' };
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'anchor is long gone' }));
assert.equal(r.ok, true);
});
test('duplicate ids are rejected', () => {
const r = validateQueue([okEntry(), okEntry()], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /duplicate/i);
});
test('findings from several entries are all reported', () => {
const a = { ...okEntry(), id: 'idx-1' };
const b = { ...okEntry(), id: 'idx-2', anchors: ['gone'] };
const r = validateQueue([a, b], stub({ 'skills/x/references/y.md': 'the exact text' }));
assert.equal(r.ok, false);
assert.equal(r.findings.length, 1);
assert.equal(r.findings[0].id, 'idx-2');
});
test('a non-array queue is rejected without throwing', () => {
const r = validateQueue({ entries: [] }, stub({}));
assert.equal(r.ok, false);
assert.match(r.findings[0].message, /array/i);
});
test('the real queue file validates against the live corpus', async () => {
const { readFileSync } = await import('node:fs');
const queue = JSON.parse(readFileSync('scripts/kb-eval/data/g7-review-queue.json', 'utf8'));
const r = validateQueue(queue.entries, (p) => readFileSync(p, 'utf8'));
assert.deepEqual(r.findings, [], `G7 queue drifted: ${JSON.stringify(r.findings, null, 2)}`);
assert.equal(r.ok, true);
});