feat(ms-ai-architect): R20 — Category-backfill på 25 kategorisløse ref-filer via insertMetaField [skip-docs]

Ny testet primitiv transform.insertMetaField (anker + 500B-back-off som insertHeaderFields, idempotent på eksakt label, body byte-identisk; 6 tester) + backfill-category.mjs (deterministisk folder->category-regel, hard per-fil-invariant, insert-only, aborterer for skriving ved avvik).

Fordeling: 14 Solution Architecture & Advisory (architecture/), 6 Microsoft AI Platforms (platforms/+development/), 4 Responsible AI & Governance, 1 MLOps & GenAIOps. Label = engelsk Category (322 vs 42 Kategori). Eksisterende recommended-mcp-servers/rag-maturity-model urort.

Roadmap: R20 done + R21 (Status/Last-updated not-due) encoded. Verifisering: 0 kategorislose filer (var 25); diff +25/-0; idempotent re-run; suite 764/764 exit 0.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-06 07:39:54 +02:00
commit a583599ab1
29 changed files with 262 additions and 1 deletions

View file

@ -25,6 +25,7 @@ import {
composeKbFile,
insertToc,
insertHeaderFields,
insertMetaField,
insertVerifiedFields,
normalizeStaleVerified,
stampVerifiedMeta,
@ -690,6 +691,81 @@ test('insertHeaderFields rejects an unknown type', () => {
assert.throws(() => insertHeaderFields(HDR_CATEGORY, { type: 'blogpost' }), /type/i);
});
// --- insertMetaField: the R20/R21 base-field backfill primitive ------------------
// Inserts ONE bold-label meta line (**<Label>:** <value>) into an EXISTING file that
// lacks it, using the same anchor + 500-byte back-off discipline as insertHeaderFields
// (last line of the first contiguous meta run that fits the window; title fallback for
// the "None" dialect). Body byte-identical; idempotent on the exact label. Serves R20
// (**Category:**) and R21 (**Status:**, **Last updated:**).
// A file with a meta run but NO **Category:** (the R20 target shape).
const NOCAT =
'# Decision Trees\n\n' +
'**Last updated:** 2026-06-19\n' +
'**Status:** Established Practice\n\n' +
'---\n\n' +
'## Introduksjon\n\nBrødtekst.\n';
// The "None" dialect: a platform ref with NO bold-label meta line at all.
const NOMETA =
'# Azure AI Foundry\n\n' +
'Foundry er Microsofts plattform.\n\n' +
'## Oversikt\n\nBrødtekst.\n';
test('insertMetaField inserts **Category:** after the meta run, before the rule, body byte-identical', () => {
const out = insertMetaField(NOCAT, 'Category', 'Solution Architecture & Advisory');
assert.match(out, /\*\*Category:\*\* Solution Architecture & Advisory/);
// lands inside the meta run: after Status, before the `---` rule
assert.ok(out.indexOf('**Status:**') < out.indexOf('**Category:**'));
assert.ok(out.indexOf('**Category:**') < out.indexOf('\n---'));
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
assert.equal(tail(out), tail(NOCAT));
});
test('insertMetaField anchors on the title for the "None" dialect (no meta lines), before the first ## section', () => {
const out = insertMetaField(NOMETA, 'Category', 'Microsoft AI Platforms');
assert.match(out, /\*\*Category:\*\* Microsoft AI Platforms/);
assert.ok(out.indexOf('# Azure AI Foundry') < out.indexOf('**Category:**'));
assert.ok(out.indexOf('**Category:**') < out.indexOf('## Oversikt'));
const tail = (s) => s.slice(s.indexOf('## Oversikt'));
assert.equal(tail(out), tail(NOMETA));
});
test('insertMetaField is idempotent on the exact label (a re-run inserts nothing)', () => {
const once = insertMetaField(NOCAT, 'Category', 'Solution Architecture & Advisory');
const twice = insertMetaField(once, 'Category', 'Solution Architecture & Advisory');
assert.equal(twice, once);
assert.equal((once.match(/\*\*Category:\*\*/g) || []).length, 1);
});
test('insertMetaField keeps the field inside the 500-byte window when a meta line is itself >500B (anchor backs off)', () => {
const giant =
'# Big\n\n' +
'**Status:** ' + 'GA; '.repeat(140) + 'slutt\n\n' + // single meta line ~560 bytes
'---\n\n' +
'## A\n\ntekst\n';
const out = insertMetaField(giant, 'Category', 'X');
// backed off to the title anchor — Category lands BEFORE the giant Status line, in-window
assert.ok(out.indexOf('# Big') < out.indexOf('**Category:**'));
assert.ok(out.indexOf('**Category:**') < out.indexOf('**Status:**'));
assert.ok(out.indexOf('**Category:**') < 500, 'Category fell outside the 500-byte window');
const tail = (s) => s.slice(s.indexOf('## A'));
assert.equal(tail(out), tail(giant));
});
test('insertMetaField preserves a pipe-delimited meta row (siblings untouched)', () => {
const out = insertMetaField(HDR_PIPE, 'Type', 'reference');
assert.match(out, /\*\*Opprettet:\*\* 2026-04 \| \*\*Sist oppdatert:\*\* 2026-06-19/);
assert.ok(out.indexOf('**Confidence:**') < out.indexOf('**Type:**'));
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
assert.equal(tail(out), tail(HDR_PIPE));
});
test('insertMetaField rejects a blank label or blank value', () => {
assert.throws(() => insertMetaField(NOCAT, '', 'x'), /label/i);
assert.throws(() => insertMetaField(NOCAT, 'Category', ' '), /value/i);
});
test('insertToc(insertHeaderFields(large)) → Type+Source+TOC, passes real checkN4, body byte-identical except header + one ## Innhold', () => {
const withHdr = insertHeaderFields(HDR_LARGE, { type: 'reference', source: MS_URL });
const out = insertToc(withHdr);