docs(ms-ai-architect): R11-flaggformat-spec + valideringstest (judge-output + augmentering) [skip-docs]

This commit is contained in:
Kjell Tore Guttormsen 2026-07-04 23:24:06 +02:00
commit a0283efe84
2 changed files with 151 additions and 0 deletions

View file

@ -170,3 +170,62 @@ test('CLI unknown flag → usage error exit 2', () => {
}
assert.equal(status, 2);
});
// --- R11 flag format (R6 Step 5): the judge-pass → fix-work-list contract -----------
// A flag = a judged claim the pass could not ground. The pass augments the judge output
// {id, judge_verdict, rule, evidence_url, evidence_quote, reason} with {file, line, claim,
// disposition}. Two vocabularies must never be conflated: judge_verdict (grounded/
// not_grounded/source_silent) vs disposition (base-rate VERDICTS; ERROR_VERDICTS = R11 fix
// targets). Spec: docs/r11-flag-format-2026-07.md.
const JUDGE_VERDICTS = ['grounded', 'not_grounded', 'source_silent'];
const DISPOSITIONS = ['correct', 'outdated', 'wrong', 'unsourced']; // mirrors base-rate VERDICTS
const ERROR_DISPOSITIONS = ['outdated', 'wrong']; // mirrors base-rate ERROR_VERDICTS (R11 fix targets)
const FLAG = {
id: 'azure-ai-foundry.md#3', judge_verdict: 'not_grounded', rule: 'R3',
evidence_url: 'https://learn.microsoft.com/azure/ai-foundry/models', evidence_quote: 'GPT-4o mini context 128k',
reason: 'File claims X tokens; source states Y.',
file: 'skills/ms-ai-advisor/references/platforms/azure-ai-foundry.md', line: 42,
claim: 'DeepSeek-R1 131072 tokens', disposition: 'outdated',
};
test('flag record carries the judge output fields + the four augmented fields', () => {
for (const k of ['id', 'judge_verdict', 'rule', 'evidence_url', 'evidence_quote', 'reason', 'file', 'line', 'claim', 'disposition']) {
assert.ok(k in FLAG, `flag record missing '${k}'`);
}
assert.ok(JUDGE_VERDICTS.includes(FLAG.judge_verdict) && FLAG.judge_verdict !== 'grounded', 'a flag is never grounded');
assert.match(FLAG.rule, /^(R[1-8])?$/); // R1-R8 or empty
assert.ok(DISPOSITIONS.includes(FLAG.disposition));
});
test('a flagged ledger record built from a flag validates (Step 4 ↔ Step 5 contract)', () => {
const rec = {
file: FLAG.file, batch: 1, judged_at: '2026-07-04', per_file_verdict: 'flagged',
claim_count: 8, verified: null, verified_by: null, flags: [FLAG],
};
assert.equal(validateManifest(appendJudgedFile(scaffoldManifest(), rec)).valid, true);
});
test('ERROR dispositions (outdated/wrong) are the R11 fix targets; unsourced/correct are not', () => {
assert.deepEqual(ERROR_DISPOSITIONS, ['outdated', 'wrong']);
assert.ok(!ERROR_DISPOSITIONS.includes('unsourced'));
assert.ok(!ERROR_DISPOSITIONS.includes('correct'));
});
test('disposition vocabulary is parity-checked against base-rate.mjs source (no silent drift)', () => {
// base-rate.mjs is the source of truth for the correctness vocabulary; the flag disposition
// reuses it (its enum is module-private, so we assert against the source rather than duplicate
// a live copy). If base-rate's vocabulary changes, this fails → drift is caught.
const src = readFileSync(join(__dirname, '..', '..', 'scripts', 'kb-eval', 'lib', 'base-rate.mjs'), 'utf8');
for (const v of DISPOSITIONS) assert.match(src, new RegExp(`'${v}'`), `base-rate must define '${v}'`);
assert.match(src, /ERROR_VERDICTS\s*=\s*new Set\(\[\s*'outdated'\s*,\s*'wrong'\s*\]\)/);
});
test('the R11 flag-format spec documents judge_verdict + the disposition mapping', () => {
const doc = readFileSync(join(__dirname, '..', '..', 'docs', 'r11-flag-format-2026-07.md'), 'utf8');
assert.match(doc, /judge_verdict/);
assert.match(doc, /not_grounded/);
assert.match(doc, /disposition/);
for (const v of DISPOSITIONS) assert.ok(doc.includes(v), `doc must document disposition '${v}'`);
});