Operator ratifiserte utvidelsen 2026-08-11. Beslutning #17 (én klasse-entry) og grunnen bak #14 (ingen lokator usynlig for gaten) var begge ekte og kolliderte i skjemaet. De kolliderer ikke lenger. SKJEMAET: et anker er enten en ordrett STRENG, sjekket mot entry.file som foer, eller et { file, text }-PAR sjekket mot SIN EGEN fil. Bakoverkompatibelt — alle 47 eksisterende entries er uroert. Et misformet par er en schema-feil, ikke et anker som stille matcher ingenting. TDD, og testene maatte skjerpes foer de var ekte: fem tester skrevet og kjoert FOERST. To av dem PASSERTE mot gammel kode — av feil grunn: den gamle koden stringify-er ankerobjektet inn i drift-meldingen, saa /other\.md/ traff tilfeldig. En test som ikke kan feile beviser ingenting. Begge fikk en diskriminator (meldingen skal IKKE navne entry.file) og feilet deretter. 5 feilende -> implementasjon -> 20/20 i fila, 1052/1052 i suiten. idx-26an: 42 { file, text }-ankere, ett per medlem, hvert re-verifisert ordrett OG unikt i sin egen fil med split-telling foer skriving. MEKANISMEN ER BEVIST, IKKE ANTATT: kjoert mot den ekte validatoren med ett medlems anker fjernet i en lesestubb — ok=false, ett anchor_drift, riktig entry-id, og meldingen navner agent-evaluation-testing-frameworks.md. Det er nettopp garantien #14 fantes for, naa baaret av én entry i stedet for 42. MAALT HASARD BOKFOERT I ENTRYEN: to av de 42 ankertekstene er strenge prefikser av andre medlemmers ankere («**Total MCP calls:** 6» i ai-services-cost-optimization.md, «**MCP Calls:** 3» i reserved-capacity-planning.md). Hver er unik i SIN fil, saa koen er trygg — en kryss-fil search-and-replace er det ikke. Slett per fil, og rest-soek etter hver edit. Koen: 47 -> 48 entries (28 open, 20 resolved). Bokfoeringen av #17 er dermed komplett: 1 klasse-entry + 16 individuelle = 17. Ingen korpusfil roert.
192 lines
8.2 KiB
JavaScript
192 lines
8.2 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);
|
|
});
|
|
|
|
// A class-wide entry books ONE finding that lives in many files. Booking it as a
|
|
// single-file entry was measured to hide 41 of 42 locators from the gate — the
|
|
// 795d494 failure, a locator alive only in prose while both gates go green. So an
|
|
// anchor may also be a { file, text } pair, checked against ITS OWN file.
|
|
test('a { file, text } anchor is checked against its own file, not entry.file', () => {
|
|
const e = { ...okEntry(), anchors: [{ file: 'skills/x/references/other.md', text: 'over here' }] };
|
|
const r = validateQueue(
|
|
[e],
|
|
stub({ 'skills/x/references/y.md': 'nothing matching', 'skills/x/references/other.md': 'aaa over here bbb' }),
|
|
);
|
|
assert.equal(r.ok, true);
|
|
assert.deepEqual(r.findings, []);
|
|
});
|
|
|
|
test('a { file, text } anchor absent from its own file DRIFTS, and the finding names that file', () => {
|
|
const e = { ...okEntry(), anchors: [{ file: 'skills/x/references/other.md', text: 'over here' }] };
|
|
const r = validateQueue(
|
|
[e],
|
|
stub({ 'skills/x/references/y.md': 'over here', 'skills/x/references/other.md': 'empty' }),
|
|
);
|
|
assert.equal(r.ok, false);
|
|
assert.equal(r.findings[0].kind, 'anchor_drift');
|
|
assert.match(r.findings[0].message, /other\.md/);
|
|
// Discriminating: entry.file DOES contain the text, so a message blaming y.md
|
|
// would mean the anchor was looked up in the wrong file. Without this line the
|
|
// test passes against the old code, which serialises the object into the
|
|
// message and matches /other\.md/ by accident.
|
|
assert.doesNotMatch(r.findings[0].message, /y\.md/);
|
|
});
|
|
|
|
test('string and { file, text } anchors mix in one entry, and BOTH are checked', () => {
|
|
const e = { ...okEntry(), anchors: ['the exact text', { file: 'skills/x/references/other.md', text: 'gone' }] };
|
|
const r = validateQueue(
|
|
[e],
|
|
stub({ 'skills/x/references/y.md': 'the exact text', 'skills/x/references/other.md': 'not it' }),
|
|
);
|
|
assert.equal(r.ok, false);
|
|
assert.equal(r.findings.length, 1);
|
|
assert.match(r.findings[0].message, /gone/);
|
|
// Discriminating, for the same reason: the surviving string anchor is present
|
|
// in entry.file, so the drift must be reported against other.md.
|
|
assert.match(r.findings[0].message, /other\.md/);
|
|
assert.doesNotMatch(r.findings[0].message, /y\.md/);
|
|
});
|
|
|
|
test('an unreadable per-anchor file is reported, not thrown, and names that file', () => {
|
|
const e = { ...okEntry(), anchors: [{ file: 'skills/x/references/missing.md', text: 'whatever' }] };
|
|
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'the exact text' }));
|
|
assert.equal(r.ok, false);
|
|
assert.equal(r.findings[0].kind, 'file_unreadable');
|
|
assert.match(r.findings[0].message, /missing\.md/);
|
|
});
|
|
|
|
// Without this, a typo'd anchor object would be checked against nothing and the
|
|
// entry would pass — a defect leaving the programme unnoticed, which is the one
|
|
// outcome the queue exists to prevent.
|
|
test('a malformed anchor object is a schema fault, never a silent pass', () => {
|
|
const e = { ...okEntry(), anchors: [{ file: 'skills/x/references/other.md' }] };
|
|
const r = validateQueue([e], stub({ 'skills/x/references/y.md': 'x', 'skills/x/references/other.md': 'x' }));
|
|
assert.equal(r.ok, false);
|
|
assert.equal(r.findings[0].kind, 'schema');
|
|
assert.match(r.findings[0].message, /anchor/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);
|
|
});
|