feat(ms-ai-architect): Spor 3 Port 2 — create-time-guard (born-verified contract) [skip-docs]

Type-aware create-guard for reference-filer (Spor 3 Port 1/Port 2):

- kb-headers.mjs: parseTypeHeader/parseVerifiedHeader/parseVerifiedByHeader
  (samme top-500-byte bold-label-skann som parseSourceHeader).
- transform.mjs: buildKbHeader er type-aware (reference krever
  source+verified+verified_by; non-reference kaster pa MS-Learn-source) +
  emitterer Type/Verified/Verified by; validateKbFile type-aware;
  stampVerifiedMeta = fodt-verifisert-gate (stempler KUN ved bestatt
  judge-verdikt, ellers kaster).
- validate-kb-file.mjs (ny): kjorbar gate generatorer kaller for commit
  (exit != 0 ved kontraktbrudd).
- generate-skills.md + kb-update.md + transform-prompt.md: wiret til
  fodt-verifisert kontrakt (header-felt + judge-steg + create-guard-gate).

Suite 586/586 (33 nye + 1 invariant). Plugin-validering 239/0/0.

Utenfor scope (flagget): generate-skills.sh legacy (sonnet/Cosmo/no-source),
Cosmo-persona i generatorene (S-Cosmo), korpus-migrering av 306 filer (Spor 1).
This commit is contained in:
Kjell Tore Guttormsen 2026-06-29 10:36:21 +02:00
commit 5a0ba1fc9e
10 changed files with 621 additions and 54 deletions

View file

@ -10,6 +10,21 @@ const SOURCE_PATTERNS = [
/\*\*Primary source:\*\*\s*(\S+)/i,
];
// Spor 3 Port 1 frontmatter contract: these live in the SAME top-500-byte bold-label
// region as **Source:**, so build-registry and the create-guard read one header format.
// `Verified:` and `Verified by:` are distinct labels — the date pattern below is
// anchored on the colon right after "Verified" so it never swallows the "by:" line.
const TYPE_PATTERN = /\*\*Type:\*\*\s*(\S+)/i;
const VERIFIED_PATTERN = /\*\*Verified:\*\*\s*(\S+)/i;
const VERIFIED_BY_PATTERN = /\*\*Verified by:\*\*\s*(\S+)/i;
/** Scan only the header region for the first capture of `pattern`, trimmed. */
function scanHeader(content, pattern) {
if (!content || typeof content !== 'string') return null;
const match = content.slice(0, HEADER_REGION_BYTES).match(pattern);
return match ? match[1].trim() : null;
}
/**
* Extract the declared authority source URL from a KB reference file's header.
* @param {string} content full file content (only the first 500 bytes are scanned)
@ -24,3 +39,32 @@ export function parseSourceHeader(content) {
}
return null;
}
/**
* Extract the Port 1 `type` (reference|template|methodology|regulatory), lowercased.
* @param {string} content full file content (only the first 500 bytes are scanned)
* @returns {string|null} the declared type, or null if absent
*/
export function parseTypeHeader(content) {
const t = scanHeader(content, TYPE_PATTERN);
return t === null ? null : t.toLowerCase();
}
/**
* Extract the Port 1 `verified` date (when the file was last confirmed against source).
* Anchored on `**Verified:**` so it never matches the `**Verified by:**` line.
* @param {string} content full file content (only the first 500 bytes are scanned)
* @returns {string|null} the verified date (YYYY-MM or YYYY-MM-DD), or null if absent
*/
export function parseVerifiedHeader(content) {
return scanHeader(content, VERIFIED_PATTERN);
}
/**
* Extract the Port 1 `verified_by` field (`judge-vN` / `human`).
* @param {string} content full file content (only the first 500 bytes are scanned)
* @returns {string|null} the verifier, or null if absent
*/
export function parseVerifiedByHeader(content) {
return scanHeader(content, VERIFIED_BY_PATTERN);
}