feat(ms-ai-architect): Spor 1 — Port-1-substrat migrert på 4 ikke-advisor-skills (243 Source + 327 Type + 325 TOC + stale-verified poison fjernet) [skip-docs]

Steg 9 (R4): unified migrate-corpus.mjs --write over engineering/governance/
infrastructure/security. 327 filer mutert, verified=null, prosa byte-identisk
(fra første ## seksjon), advisor urørt (0 endringer).

To applier-fixes oppdaget under kjøring (TDD, RED→GREEN):
- insertHeaderFields: anker faller nå tilbake når en meta-linje selv passerer
  500B (2 filer pakket et avsnitt i **Status:** → Type/Source landet utenfor
  scan-vinduet, applierens post-write-assertion fanget + restaurerte).
- normalizeStaleVerified: fjerner nå ALLE stale non-date **Verified:** i
  500B-vinduet, inkl. stray body-dup rett under --- (9 mlops-genaiops-filer var
  ellers falskt "verified"/fresh, droppet fra worklist). Operatør-godkjent
  utvidelse av carve-out; kun stray metadata-linjer, aldri prosa.

test-transform-criterion: precondition oppdatert til post-migrasjons-sannhet
(fila bærer nå Source). Suite 728/728 grønn.
This commit is contained in:
Kjell Tore Guttormsen 2026-07-04 10:19:11 +02:00
commit ddce43d8b2
330 changed files with 4643 additions and 83 deletions

View file

@ -62,9 +62,11 @@ test('regenerate 1 real file → valid, dated, source-anchored, body preserved,
const original = readFileSync(join(PLUGIN_ROOT, refRel), 'utf8');
const body = splitBody(original);
// The pre-lag-4 file has no **Source:** header — the 0%-coverage failure mode.
assert.ok(validateKbFile(original).missing.includes('source'),
'expected the pre-lag-4 file to lack a header Source');
// Post-migration (Spor 1 lag 4) this real file now carries a **Source:** header — the
// 0%-coverage failure mode is closed. Regeneration below re-stamps the full Port-1
// contract (source + verified) and preserves the body verbatim.
assert.ok(!validateKbFile(original).missing.includes('source'),
'post-migration the real file should already carry a header Source');
// category key + filename from the real path: skills/<skill>/references/<category>/<file>
const parts = refRel.split('/');

View file

@ -574,6 +574,33 @@ test('insertHeaderFields works on the pipe-delimited dialect without a `---` rul
assert.equal(tail(out), tail(HDR_PIPE));
});
// Dialect A' — a meta line (Status) whose single line is itself >500 bytes (real corpus:
// agentic-rag-patterns.md, gpt5-gpt41-pricing-models.md pack a paragraph into **Status:**).
// The anchor must back off to the last meta line that still leaves room in the 500-byte
// window, so the inserted Type/Source stay parseable — never anchor PAST the giant line.
const HDR_GIANT_META =
'# Agentic RAG Patterns — Agent-styrt retrieval\n\n' +
'**Last updated:** 2026-06-19\n' +
'**Status:** ' + 'GA; '.repeat(140) + 'slutt\n' + // single meta line ~560 bytes
'**Category:** RAG Architecture\n\n' +
'---\n\n' +
'## Introduksjon\n\nBrødtekst.\n';
test('insertHeaderFields keeps Type+Source inside the 500-byte window when a meta line is itself >500B (anchor backs off, does not overshoot)', () => {
// Guard: the fixture really does have a Status line that alone crosses the window.
assert.ok(HDR_GIANT_META.indexOf('**Category:**') > 500, 'fixture must push Category past 500B');
const out = insertHeaderFields(HDR_GIANT_META, { type: 'reference', source: MS_URL });
// The whole point: both fields must survive the top-500-byte scan.
assert.equal(parseTypeHeader(out), 'reference', 'Type fell outside the 500-byte window');
assert.equal(parseSourceHeader(out), MS_URL, 'Source fell outside the 500-byte window');
// They landed BEFORE the giant Status line (after Last updated), not after it.
assert.ok(out.indexOf('**Last updated:**') < out.indexOf('**Type:**'));
assert.ok(out.indexOf('**Type:**') < out.indexOf('**Status:**'));
// body (from the first ## section) is byte-identical
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
assert.equal(tail(out), tail(HDR_GIANT_META));
});
test('insertHeaderFields for a non-reference type emits Type only, never Source', () => {
const out = insertHeaderFields(HDR_KATEGORI, { type: 'methodology', source: MS_URL });
assert.equal(parseTypeHeader(out), 'methodology');
@ -626,10 +653,13 @@ test('insertToc(insertHeaderFields(large)) → Type+Source+TOC, passes real chec
});
// --- normalizeStaleVerified: surgical carve-out for the 14 `**Verified:** MCP` files ---
// Acts ONLY on the first header-region **Verified:** (the one parseVerifiedHeader reads),
// ONLY when its value is not a clean YYYY-MM(-DD) date. Never touches at/below the first
// `---` (body-duplicate preserved). Pipe-safe: on a pipe row it removes only the Verified
// token + one adjacent ` | `, keeping siblings. Idempotent.
// Acts on EVERY stale (non-date) **Verified:** that falls inside the 500-byte scan window —
// exactly what parseVerifiedHeader reads as the file's verified value, whether it sits in
// the header block OR as a stray duplicate just below the first `---` (a corpus artifact
// that still poisons the read). A clean YYYY-MM(-DD) date at the first position is left
// untouched, and anything past the 500-byte window is genuine body content and never
// touched. Pipe-safe: on a pipe row it removes only the Verified token + one adjacent ` | `,
// keeping siblings. Idempotent.
const VERIFIED_STALE =
'# T\n\n**Last updated:** 2026-06-19\n**Verified:** MCP 2026-06-19\n' +
@ -639,7 +669,8 @@ const VERIFIED_CLEAN =
'# T\n\n**Last updated:** 2026-06\n**Verified:** 2026-06\n**Status:** GA\n\n---\n\n## A\n\ntekst\n';
// The mlops-fundamentals-overview.md shape: a stale header Verified AND a duplicate
// below the `---` rule (line-10 shape). The normalizer removes the header one only.
// below the `---` rule (line-10 shape). Both sit inside the 500-byte scan window, so both
// poison parseVerifiedHeader — the normalizer removes BOTH (the blessed body-dup carve-out).
const VERIFIED_BODY_DUP =
'# MLOps Fundamentals\n\n**Last updated:** 2026-06-19\n**Verified:** MCP 2026-06-19\n' +
'**Status:** GA\n**Category:** MLOps\n\n---\n\n**Verified:** MCP 2026-06-19\n\n' +
@ -669,16 +700,15 @@ test('normalizeStaleVerified leaves a clean YYYY-MM(-DD) Verified date untouched
assert.equal(parseVerifiedHeader(VERIFIED_CLEAN), '2026-06');
});
test('normalizeStaleVerified removes the header **Verified:** but never the body-duplicate below ---', () => {
test('normalizeStaleVerified removes BOTH the header **Verified:** and the stray duplicate below --- within the 500B window', () => {
const out = normalizeStaleVerified(VERIFIED_BODY_DUP);
// exactly one **Verified:** remains …
assert.equal((out.match(/\*\*Verified:\*\*/g) || []).length, 1);
// … and it is the body one, below the `---` rule
const ruleIdx = out.indexOf('\n---');
assert.ok(ruleIdx !== -1 && out.indexOf('**Verified:**') > ruleIdx, 'surviving Verified must be below ---');
// header meta above the rule is intact
assert.match(out.slice(0, ruleIdx), /\*\*Last updated:\*\* 2026-06-19/);
// body from ## Introduksjon byte-identical
// both the header AND the body-dup are stale MCP within 500B → both gone
assert.equal((out.match(/\*\*Verified:\*\*/g) || []).length, 0);
assert.equal(parseVerifiedHeader(out), null, 'no stale Verified may survive in the scan window');
// header meta is intact
assert.match(out, /\*\*Last updated:\*\* 2026-06-19/);
assert.match(out, /\*\*Status:\*\* GA/);
// prose from ## Introduksjon is byte-identical — only the stray metadata line was removed
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
assert.equal(tail(out), tail(VERIFIED_BODY_DUP));
});