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

@ -310,20 +310,25 @@ export function insertHeaderFields(content, meta) {
if (needSource) toInsert.push(`**Source:** ${String(src).trim()}`);
const lines = s.split('\n');
let anchorIdx = -1; // last line of the first contiguous meta run
let anchorIdx = -1; // last line of the first contiguous meta run that fits the window
let titleIdx = -1; // fallback anchor for the "no meta line" dialect
let cum = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (/^##\s/.test(line) || /^---\s*$/.test(line)) break; // reached body / rule
if (titleIdx === -1 && /^#\s+\S/.test(line)) titleIdx = i;
const nextCum = cum + line.length + 1; // byte offset just AFTER this line (= the insertion point)
if (RE_META_LINE.test(line)) {
// Anchor after this meta line ONLY if the insertion point still fits the scan window.
// A meta line whose own length pushes the offset past 500B (a corpus file that packs a
// paragraph into **Status:**) must NOT become the anchor — otherwise the inserted field
// lands past the window and parseTypeHeader/parseSourceHeader miss it. Back off here.
if (nextCum > HEADER_REGION_BYTES) break;
anchorIdx = i; // extend the contiguous meta run
} else if (anchorIdx !== -1) {
break; // first non-meta line after the run — the run is over (contiguous only)
}
cum += line.length + 1;
if (cum > HEADER_REGION_BYTES) break; // never place fields past the scan window
cum = nextCum;
}
// "None" dialect (no bold-label meta): anchor on the title line so the fields still
// land in the header region, before the first section. (-1 → very top if no title.)
@ -333,52 +338,59 @@ export function insertHeaderFields(content, meta) {
}
/**
* Surgically strip a STALE `**Verified:**` value from a legacy KB file's header the
* bounded Spor 1 carve-out for the 14 files carrying `**Verified:** MCP <date>`. That
* non-date value is read by parseVerifiedHeader as a bogus "verified" stamp, which drops
* the file out of the full-pass worklist AND marks it falsely verified; stripping it is
* the OPPOSITE of stamping verified. Acts ONLY on the first header-region `**Verified:**`
* (the exact occurrence parseVerifiedHeader reads) and ONLY when its value is not a clean
* YYYY-MM(-DD) date. It never touches anything at or below the first `---` rule, so a
* body-duplicate survives (removing body content is NOT part of the blessed byte-identity
* carve-out). On a pipe-delimited meta row it removes only the `**Verified:** <value>`
* Surgically strip STALE `**Verified:**` value(s) from a legacy KB file the bounded
* Spor 1 carve-out for the 14 files carrying `**Verified:** MCP <date>`. That non-date
* value is read by parseVerifiedHeader as a bogus "verified" stamp, which drops the file
* out of the full-pass worklist AND marks it falsely verified; stripping it is the OPPOSITE
* of stamping verified. Acts on EVERY stale `**Verified:**` inside the 500-byte scan window
* (the region parseVerifiedHeader actually reads) whose value is not a clean YYYY-MM(-DD)
* date including a stray duplicate sitting just below the first `---` rule, a corpus
* artifact (9 mlops-genaiops files) that still poisons the read once the header copy is
* gone. A clean date at the first scanned position stops the pass (a legitimately verified
* file is left alone), and anything PAST the 500-byte window is genuine body content and is
* never touched. On a pipe-delimited meta row it removes only the `**Verified:** <value>`
* token plus one adjacent ` | ` separator, preserving the sibling tokens
* (**Sist oppdatert:** etc.); on a standalone line it drops the whole line. Idempotent.
* (**Sist oppdatert:** etc.); on a standalone line it drops the whole line. Idempotent
* (each pass removes one match; a re-run finds nothing to strip).
*
* @param {string} content full existing file content
* @returns {string} content with the stale header Verified removed, or unchanged
* @returns {string} content with the stale in-window Verified value(s) removed, or unchanged
*/
export function normalizeStaleVerified(content) {
const s = String(content ?? '');
const head = s.slice(0, HEADER_REGION_BYTES);
const m = /\*\*Verified:\*\*\s*(\S+)/i.exec(head);
if (!m) return s; // no header Verified
if (DATE_RE.test(m[1])) return s; // clean date → leave untouched
const matchStart = m.index; // index of "**Verified:**" in s
// Guard: never act at or below the first `---` rule — body content is off-limits.
const rule = /^---\s*$/m.exec(s);
if (rule && matchStart >= rule.index) return s; // defensive (parser scans header, but be sure)
let s = String(content ?? '');
// Remove every stale (non-date) **Verified:** inside the scan window. Loop because a file
// can carry two (header copy + stray body-dup below ---); each pass drops one, so it
// terminates. A clean date at the first position ends the pass — parseVerifiedHeader reads
// that first occurrence, so a dated first Verified means the file is legitimately verified.
for (;;) {
const head = s.slice(0, HEADER_REGION_BYTES);
const m = /\*\*Verified:\*\*\s*(\S+)/i.exec(head);
if (!m) return s; // nothing stale left in the window
if (DATE_RE.test(m[1])) return s; // clean date at the read position → leave untouched
const matchStart = m.index; // index of "**Verified:**" in s
const lineStart = s.lastIndexOf('\n', matchStart - 1) + 1; // 0 if no preceding newline
let lineEnd = s.indexOf('\n', matchStart);
if (lineEnd === -1) lineEnd = s.length;
const line = s.slice(lineStart, lineEnd);
const lineStart = s.lastIndexOf('\n', matchStart - 1) + 1; // 0 if no preceding newline
let lineEnd = s.indexOf('\n', matchStart);
if (lineEnd === -1) lineEnd = s.length;
const line = s.slice(lineStart, lineEnd);
if (!line.includes(' | ')) {
// Standalone `**Verified:** …` line — drop the whole line, including its newline.
const cutEnd = lineEnd < s.length ? lineEnd + 1 : lineEnd;
return s.slice(0, lineStart) + s.slice(cutEnd);
if (!line.includes(' | ')) {
// Standalone `**Verified:** …` line — drop the whole line, including its newline.
const cutEnd = lineEnd < s.length ? lineEnd + 1 : lineEnd;
s = s.slice(0, lineStart) + s.slice(cutEnd);
continue;
}
// Pipe row: remove only the `**Verified:** <value>` token + one adjacent ` | `.
const nextSepRel = s.slice(matchStart, lineEnd).indexOf(' | ');
const tokenEnd = nextSepRel === -1 ? lineEnd : matchStart + nextSepRel;
if (s.slice(matchStart - 3, matchStart) === ' | ') {
s = s.slice(0, matchStart - 3) + s.slice(tokenEnd); // drop the preceding separator
} else if (nextSepRel !== -1) {
s = s.slice(0, matchStart) + s.slice(tokenEnd + 3); // drop the following separator
} else {
s = s.slice(0, matchStart) + s.slice(tokenEnd); // degenerate — token only
}
}
// Pipe row: remove only the `**Verified:** <value>` token + one adjacent ` | `.
const nextSepRel = s.slice(matchStart, lineEnd).indexOf(' | ');
const tokenEnd = nextSepRel === -1 ? lineEnd : matchStart + nextSepRel;
if (s.slice(matchStart - 3, matchStart) === ' | ') {
return s.slice(0, matchStart - 3) + s.slice(tokenEnd); // drop the preceding separator
}
if (nextSepRel !== -1) {
return s.slice(0, matchStart) + s.slice(tokenEnd + 3); // drop the following separator
}
return s.slice(0, matchStart) + s.slice(tokenEnd); // degenerate — token only
}
const RE_TITLE = /^#\s+\S/m;