feat(ms-ai-architect): Spor 1 — insertHeaderFields + surgical normalizeStaleVerified (3 dialekter, pipe-safe, ---aware, TDD) [skip-docs]
This commit is contained in:
parent
f8e420c773
commit
6b58afda3b
2 changed files with 338 additions and 0 deletions
|
|
@ -24,6 +24,8 @@ import {
|
|||
buildToc,
|
||||
composeKbFile,
|
||||
insertToc,
|
||||
insertHeaderFields,
|
||||
normalizeStaleVerified,
|
||||
stampVerifiedMeta,
|
||||
} from '../../scripts/kb-update/lib/transform.mjs';
|
||||
import {
|
||||
|
|
@ -494,3 +496,215 @@ test('transform.mjs imports NO write-utils (pure transformer, never writes)', ()
|
|||
assert.doesNotMatch(importLines, /from\s+'[^']*atomic-write[^']*'/);
|
||||
assert.doesNotMatch(importLines, /from\s+'[^']*\/backup\.mjs'/);
|
||||
});
|
||||
|
||||
// --- insertHeaderFields: Spor 1 migration primitive (backfill Type/Source) -------
|
||||
// Unlike buildKbHeader (which emits a COMPLETE new header), insertHeaderFields inserts
|
||||
// only the missing Port-1 field(s) into an EXISTING legacy file's top-region meta block,
|
||||
// immediately after the last line of the first contiguous run of bold-label meta lines
|
||||
// (language-agnostic across the 3 dialects), never before the first `## ` section, never
|
||||
// past the 500-byte scan window. Body byte-identical; per-field idempotent.
|
||||
|
||||
// Dialect A — **Category:** (English labels), with a `---` header rule.
|
||||
const HDR_CATEGORY =
|
||||
'# MLOps Fundamentals\n\n' +
|
||||
'**Last updated:** 2026-06-19\n' +
|
||||
'**Status:** GA\n' +
|
||||
'**Category:** MLOps & GenAIOps\n\n' +
|
||||
'---\n\n' +
|
||||
'## Introduksjon\n\nBrødtekst.\n';
|
||||
|
||||
// Dialect B — **Kategori:** (Norwegian labels), with a `---` header rule.
|
||||
const HDR_KATEGORI =
|
||||
'# Feedback Loops\n\n' +
|
||||
'**Kategori:** MLOps & GenAIOps\n' +
|
||||
'**Sist oppdatert:** 2026-06\n\n' +
|
||||
'---\n\n' +
|
||||
'## Introduksjon\n\nBrødtekst.\n';
|
||||
|
||||
// Dialect C — pipe-delimited meta row, NO `---` rule (the ai-center-of-excellence shape).
|
||||
const HDR_PIPE =
|
||||
'# AI Center of Excellence\n\n' +
|
||||
'**Kategori:** Responsible AI & Governance\n' +
|
||||
'**Opprettet:** 2026-04 | **Sist oppdatert:** 2026-06-19\n' +
|
||||
'**Confidence:** HIGH (Microsoft CAF)\n\n' +
|
||||
'## Introduksjon\n\nBrødtekst.\n';
|
||||
|
||||
// A large file (>100 lines) with a category header — for the combined insertToc oracle.
|
||||
const HDR_LARGE =
|
||||
'# Big Ref\n\n' +
|
||||
'**Last updated:** 2026-06\n' +
|
||||
'**Status:** GA\n' +
|
||||
'**Category:** X\n\n' +
|
||||
'---\n\n' +
|
||||
LARGE_BODY;
|
||||
|
||||
const MS_URL = 'https://learn.microsoft.com/azure/machine-learning/concept-mlops';
|
||||
|
||||
test('insertHeaderFields inserts Type+Source after the meta block (category dialect), body byte-identical', () => {
|
||||
const out = insertHeaderFields(HDR_CATEGORY, { type: 'reference', source: MS_URL });
|
||||
assert.equal(parseTypeHeader(out), 'reference');
|
||||
assert.equal(parseSourceHeader(out), MS_URL);
|
||||
// Type/Source sit inside the meta block: after **Category:**, before the `---` rule.
|
||||
assert.ok(out.indexOf('**Category:**') < out.indexOf('**Type:**'));
|
||||
assert.ok(out.indexOf('**Type:**') < out.indexOf('\n---'));
|
||||
// body (from the first ## section) is byte-identical
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(HDR_CATEGORY));
|
||||
});
|
||||
|
||||
test('insertHeaderFields works on the Norwegian **Kategori:** dialect, body byte-identical', () => {
|
||||
const out = insertHeaderFields(HDR_KATEGORI, { type: 'reference', source: MS_URL });
|
||||
assert.equal(parseTypeHeader(out), 'reference');
|
||||
assert.equal(parseSourceHeader(out), MS_URL);
|
||||
assert.ok(out.indexOf('**Sist oppdatert:**') < out.indexOf('**Type:**'));
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(HDR_KATEGORI));
|
||||
});
|
||||
|
||||
test('insertHeaderFields works on the pipe-delimited dialect without a `---` rule, body byte-identical', () => {
|
||||
const out = insertHeaderFields(HDR_PIPE, { type: 'reference', source: MS_URL });
|
||||
assert.equal(parseTypeHeader(out), 'reference');
|
||||
assert.equal(parseSourceHeader(out), MS_URL);
|
||||
// inserted after the last meta line (**Confidence:**), before the first ## section
|
||||
assert.ok(out.indexOf('**Confidence:**') < out.indexOf('**Type:**'));
|
||||
assert.ok(out.indexOf('**Type:**') < out.indexOf('## Introduksjon'));
|
||||
// the pipe meta row is untouched (siblings preserved)
|
||||
assert.match(out, /\*\*Opprettet:\*\* 2026-04 \| \*\*Sist oppdatert:\*\* 2026-06-19/);
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(HDR_PIPE));
|
||||
});
|
||||
|
||||
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');
|
||||
assert.equal(parseSourceHeader(out), null);
|
||||
assert.doesNotMatch(out, /\*\*Source:\*\*/);
|
||||
});
|
||||
|
||||
test('insertHeaderFields is per-field idempotent (a re-run inserts nothing)', () => {
|
||||
const once = insertHeaderFields(HDR_CATEGORY, { type: 'reference', source: MS_URL });
|
||||
const twice = insertHeaderFields(once, { type: 'reference', source: MS_URL });
|
||||
assert.equal(twice, once);
|
||||
assert.equal((once.match(/\*\*Type:\*\*/g) || []).length, 1);
|
||||
assert.equal((once.match(/\*\*Source:\*\*/g) || []).length, 1);
|
||||
});
|
||||
|
||||
test('insertHeaderFields adds only the missing field when Type is already present', () => {
|
||||
const hasType =
|
||||
'# T\n\n**Status:** GA\n**Category:** X\n**Type:** reference\n\n---\n\n## A\n\ntekst\n';
|
||||
const out = insertHeaderFields(hasType, { type: 'reference', source: MS_URL });
|
||||
assert.equal((out.match(/\*\*Type:\*\*/g) || []).length, 1); // not duplicated
|
||||
assert.equal(parseSourceHeader(out), MS_URL); // Source backfilled
|
||||
});
|
||||
|
||||
test('insertHeaderFields keeps an existing **Source:** (the 7 pre-sourced files)', () => {
|
||||
const hasSource =
|
||||
'# T\n\n**Status:** GA\n**Type:** reference\n' +
|
||||
'**Source:** https://learn.microsoft.com/existing\n\n---\n\n## A\n\ntekst\n';
|
||||
const out = insertHeaderFields(hasSource, { type: 'reference', source: MS_URL });
|
||||
assert.equal(parseSourceHeader(out), 'https://learn.microsoft.com/existing');
|
||||
assert.equal((out.match(/\*\*Source:\*\*/g) || []).length, 1);
|
||||
});
|
||||
|
||||
test('insertHeaderFields rejects an unknown type', () => {
|
||||
assert.throws(() => insertHeaderFields(HDR_CATEGORY, { type: 'blogpost' }), /type/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);
|
||||
assert.equal(parseTypeHeader(out), 'reference');
|
||||
assert.equal(parseSourceHeader(out), MS_URL);
|
||||
const n4 = checkN4([{ path: 'skills/x/references/y/z.md', content: out }]);
|
||||
assert.equal(n4.largeFiles, 1);
|
||||
assert.equal(n4.withToc, 1);
|
||||
assert.equal(n4.pass, true);
|
||||
assert.equal((out.match(/^##\s+Innhold/gm) || []).length, 1);
|
||||
// body from the first real section is byte-identical to the original body
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(HDR_LARGE));
|
||||
});
|
||||
|
||||
// --- 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.
|
||||
|
||||
const VERIFIED_STALE =
|
||||
'# T\n\n**Last updated:** 2026-06-19\n**Verified:** MCP 2026-06-19\n' +
|
||||
'**Status:** GA\n**Category:** X\n\n---\n\n## A\n\ntekst.\n';
|
||||
|
||||
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.
|
||||
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' +
|
||||
'## Introduksjon\n\ntekst.\n';
|
||||
|
||||
// The ai-center-of-excellence-setup.md shape: Verified is the last token of a
|
||||
// pipe-delimited meta row.
|
||||
const VERIFIED_PIPE =
|
||||
'# AI Center of Excellence\n\n**Kategori:** Responsible AI & Governance\n' +
|
||||
'**Opprettet:** 2026-04 | **Sist oppdatert:** 2026-06-19 | **Verified:** MCP 2026-06-19\n' +
|
||||
'**Confidence:** HIGH (Microsoft CAF)\n\n## Introduksjon\n\ntekst.\n';
|
||||
|
||||
test('normalizeStaleVerified removes a standalone stale **Verified:** MCP header line (parseVerifiedHeader → null)', () => {
|
||||
const out = normalizeStaleVerified(VERIFIED_STALE);
|
||||
assert.equal(parseVerifiedHeader(out), null);
|
||||
assert.doesNotMatch(out, /\*\*Verified:\*\*/);
|
||||
// siblings preserved
|
||||
assert.match(out, /\*\*Last updated:\*\* 2026-06-19/);
|
||||
assert.match(out, /\*\*Status:\*\* GA/);
|
||||
// body untouched
|
||||
const tail = (s) => s.slice(s.indexOf('## A'));
|
||||
assert.equal(tail(out), tail(VERIFIED_STALE));
|
||||
});
|
||||
|
||||
test('normalizeStaleVerified leaves a clean YYYY-MM(-DD) Verified date untouched', () => {
|
||||
assert.equal(normalizeStaleVerified(VERIFIED_CLEAN), VERIFIED_CLEAN);
|
||||
assert.equal(parseVerifiedHeader(VERIFIED_CLEAN), '2026-06');
|
||||
});
|
||||
|
||||
test('normalizeStaleVerified removes the header **Verified:** but never the body-duplicate below ---', () => {
|
||||
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
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(VERIFIED_BODY_DUP));
|
||||
});
|
||||
|
||||
test('normalizeStaleVerified on a pipe row removes only the Verified token, preserving siblings', () => {
|
||||
const out = normalizeStaleVerified(VERIFIED_PIPE);
|
||||
assert.equal(parseVerifiedHeader(out), null);
|
||||
assert.match(out, /\*\*Opprettet:\*\* 2026-04/);
|
||||
assert.match(out, /\*\*Sist oppdatert:\*\* 2026-06-19/);
|
||||
assert.doesNotMatch(out, /\*\*Verified:\*\*/);
|
||||
// no dangling separator left at the row end
|
||||
assert.doesNotMatch(out, /2026-06-19 \|\s*$/m);
|
||||
const tail = (s) => s.slice(s.indexOf('## Introduksjon'));
|
||||
assert.equal(tail(out), tail(VERIFIED_PIPE));
|
||||
});
|
||||
|
||||
test('normalizeStaleVerified is idempotent', () => {
|
||||
const once = normalizeStaleVerified(VERIFIED_STALE);
|
||||
assert.equal(normalizeStaleVerified(once), once);
|
||||
const oncePipe = normalizeStaleVerified(VERIFIED_PIPE);
|
||||
assert.equal(normalizeStaleVerified(oncePipe), oncePipe);
|
||||
const onceDup = normalizeStaleVerified(VERIFIED_BODY_DUP);
|
||||
assert.equal(normalizeStaleVerified(onceDup), onceDup);
|
||||
});
|
||||
|
||||
test('normalizeStaleVerified is a no-op when there is no header Verified', () => {
|
||||
const clean = '# T\n\n**Status:** GA\n\n---\n\n## A\n\ntekst\n';
|
||||
assert.equal(normalizeStaleVerified(clean), clean);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue