ms-ai-architect/scripts/kb-update/strip-stale-verified-pipe.mjs
Kjell Tore Guttormsen 712a143e58 fix(ms-ai-architect): RX-KB1 strip stale plain-Verified pipe-tails (87) + audit-deteksjon [skip-docs]
De 87 referansefilene bar en plain-text `| Verified: <dato>`-hale på **Last updated:**-linjen
i 500B-header-vinduet — usynlig for den bold-only kontrakt-stacken (kb-headers.mjs / audit
RE_VERIFIED), og claimet en verifisering judgen aldri gjorde (samme poison-klasse som de 14
bold **Verified:** MCP Spor 1 fjernet). Uhåndtert springer den også dual-Verified-fellen: R7s
insertVerifiedFields ville stemplet en bold-verdi ved siden av den plain → to motstridende
provenance-claims per fil.

- ny driver strip-stale-verified-pipe.mjs: frosset 87-manifest (18 advisor + 45 eng + 8 gov +
  16 sec), pure verdi-bevarende strip (kun ` | Verified: …`-halen; **Last updated:**-dato
  byte-eksakt), hard per-fil-invariant (linjeantall uendret, body byte-identisk, dato bevart),
  idempotent, atomicWriteSync (RX-OPS2 recovery-kontrakt).
- audit-corpus-headers.mjs: ny plain-Verified-deteksjon (RE_PLAIN_VERIFIED + plainVerifiedPipe)
  — gjør M4-blindheten synlig så en stale plain-hale ikke kan gjenoppstå stille (non-advisor scope).
- 87 filer strippet; plain Verified i vinduet 0/389; live-audit plainVerifiedPipe 0.

Mekanisme: +15 tester (12 strip + 3 audit). Suite 875→890 exit 0. validate-plugin.sh 250/0.

Utsatt → RX-KB1b: footer-dato-avvik + label-whitelist (annen dialekt, flag-to-human).
2026-07-16 20:04:52 +02:00

239 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
// strip-stale-verified-pipe.mjs — RX-KB1 (2026-07-16, FØR R7). Strip the stale plain
// `| Verified: <date>` pipe-tail from the **Last updated:** line on the 87 reference files
// that carry it inside the top-500-byte header window.
//
// WHY. The bold-label frontmatter contract (lib/kb-headers.mjs) and the audit
// (audit-corpus-headers.mjs RE_VERIFIED) recognise provenance ONLY as a bold **Verified:**
// field the judge writes. These 87 files instead carry a PLAIN-TEXT `| Verified: MCP <date>`
// tail appended to the Last updated line — invisible to that stack, and claiming a
// verification the judge never performed. It is the same poison class as the 14 bold
// `**Verified:** MCP` labels Spor 1 removed. Left in place it also springs the "dual-Verified
// trap": R7's insertVerifiedFields would stamp a bold value ALONGSIDE the surviving plain one,
// leaving two contradictory provenance claims per file. Stripping restores an honest
// never-verified state (the judge can later fill a bold field) and preserves the authored
// **Last updated:** date byte-exact, so no freshness fact is lost. Aligns with the contract;
// does not violate it (the plain tail is not a contract-recognised field).
//
// SCOPE. All 87 files that carry the tail (ground truth 2026-07-16): 18 advisor + 45
// engineering + 8 governance + 16 security. NB: this deliberately INCLUDES the 18 advisor
// files — the false-provenance claim is equally dishonest there, and this is a value-neutral
// honesty fix, not a header-contract mutation (advisor stays out of the audit's mutation/scan
// scope, a separate pre-existing design choice). The audit's plain-Verified DETECTION added in
// this same session stays within its existing non-advisor scope.
//
// The dual dialect in the corpus: 85× `| Verified: MCP <date>`, 2× `| Verified: <date>`.
// Verified is always the final tail on the line (nothing follows it), so the strip removes
// from the ` | Verified:` separator to end-of-line.
//
// INVARIANT (asserted per file BEFORE any write; throws → aborts the whole run, writes nothing):
// - exactly one `| Verified:` tail existed in the header and is gone
// - `**Last updated:**` survives with its date byte-exact
// - total line count unchanged (the line is edited in place, never removed)
// - the body (from the first `## `/`---`) is byte-identical
// Idempotent: a re-run finds no tail and is a no-op. Value-preserving: no date is derived,
// rewritten, or reconciled — only the unverifiable claim is dropped.
//
// Recovery contract: writes are crash-safe (atomicWriteSync tmp+rename — a reader sees the old
// file or the new one, never a partial); an interrupted run is recovered by re-running
// (idempotent, per-file, no cross-file state).
//
// Usage: node scripts/kb-update/strip-stale-verified-pipe.mjs [--dry]
import { readFileSync, existsSync, realpathSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { atomicWriteSync } from './lib/atomic-write.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const PLUGIN_ROOT = join(__dirname, '..', '..');
// Header region = lines above the first `## `/`---` (mirrors transform.mjs headerEndIndex /
// dedup-plain-header.mjs). Confines the edit to the header so a body "Verified:" is never hit.
function splitHeaderBody(content) {
const lines = content.split('\n');
let i = 0;
for (; i < lines.length; i++) {
if (/^##\s/.test(lines[i]) || /^---\s*$/.test(lines[i])) break;
}
return { header: lines.slice(0, i).join('\n'), body: lines.slice(i).join('\n') };
}
// The pipe-tail on the **Last updated:** line: from the ` | ` separator through end of line.
// Lazy capture of the Last updated prefix so group 1 stops at the separator; `[ \t]*` eats the
// space before the pipe so the result has no trailing whitespace.
const RE_TAIL = /^(\*\*Last updated:\*\*.*?)[ \t]*\|[ \t]*Verified:[^\n]*$/im;
/**
* Strip the stale plain Verified pipe-tail from the Last updated line. Pure — no I/O.
* Operates only on the header region; the body is returned unchanged.
* @param {string} content
* @returns {string}
*/
export function stripVerifiedPipe(content) {
const { header, body } = splitHeaderBody(content);
const newHeader = header.replace(RE_TAIL, '$1');
if (newHeader === header) return content; // idempotent / no tail
return newHeader + (body ? '\n' + body : '');
}
// Assert the hard per-file invariant. Throws (aborting the run) on any breach.
function assertInvariant(rel, oldC, newC) {
const o = oldC.split('\n');
const n = newC.split('\n');
if (n.length !== o.length) {
throw new Error(`ABORT ${rel}: line count changed (was ${o.length}, now ${n.length}) — tail strip must edit in place`);
}
const oldH = splitHeaderBody(oldC);
const newH = splitHeaderBody(newC);
if (oldH.body !== newH.body) throw new Error(`ABORT ${rel}: body not byte-identical`);
if (/\bVerified:/.test(newH.header)) throw new Error(`ABORT ${rel}: a Verified label remains in the header`);
// The Last updated date must survive byte-exact.
const dateOf = (h) => (/\*\*Last updated:\*\*\s*([\d-]+)/i.exec(h) || [])[1] || null;
const oldDate = dateOf(oldH.header);
const newDate = dateOf(newH.header);
if (!newDate || newDate !== oldDate) {
throw new Error(`ABORT ${rel}: Last updated date not preserved (was ${JSON.stringify(oldDate)}, now ${JSON.stringify(newDate)})`);
}
// Only the tail was removed: newC must be oldC with exactly the matched tail excised.
if (!oldC.startsWith(newH.header)) {
// The header shrank only by the tail; everything else identical.
const reOld = oldH.header.replace(RE_TAIL, '$1');
if (reOld !== newH.header) throw new Error(`ABORT ${rel}: header changed beyond the Verified tail`);
}
}
function run({ dry }) {
const planned = [];
const skipped = [];
const missing = [];
for (const rel of MANIFEST) {
const abs = join(PLUGIN_ROOT, rel);
if (!existsSync(abs)) { missing.push(rel); continue; }
const old = readFileSync(abs, 'utf8');
const out = stripVerifiedPipe(old);
if (out === old) { skipped.push(rel); continue; } // idempotent: already stripped
assertInvariant(rel, old, out);
planned.push({ rel, out });
}
if (missing.length) {
console.error(`ABORT — ${missing.length} manifest target(s) not found (corpus drift):`);
missing.forEach((m) => console.error(' ' + m));
process.exit(1);
}
if (planned.length + skipped.length !== MANIFEST.length) {
throw new Error(`ABORT — accounted ${planned.length + skipped.length} ≠ manifest ${MANIFEST.length}`);
}
console.log(`Manifest: ${MANIFEST.length} | to strip: ${planned.length} | already stripped (skipped): ${skipped.length}`);
if (dry) {
console.log('\n(dry run — no writes)');
for (const p of planned) console.log(` ~ ${p.rel}`);
return;
}
for (const p of planned) atomicWriteSync(join(PLUGIN_ROOT, p.rel), p.out);
console.log(`\nWrote ${planned.length} files.`);
}
// Frozen manifest — the 87 reference files carrying a plain `| Verified: <date>` tail on the
// **Last updated:** line within the top-500-byte header window (ground truth 2026-07-16,
// re-measured at session start per the premiss-verification duty). Sorted, diff-stable.
export const MANIFEST = [
'skills/ms-ai-advisor/references/architecture/security.md',
'skills/ms-ai-advisor/references/copilot-extensibility/adaptive-cards-copilot-responses.md',
'skills/ms-ai-advisor/references/copilot-extensibility/copilot-api-rate-limiting-resilience.md',
'skills/ms-ai-advisor/references/copilot-extensibility/copilot-connectors-design-patterns.md',
'skills/ms-ai-advisor/references/copilot-extensibility/copilot-extensibility-security-patterns.md',
'skills/ms-ai-advisor/references/copilot-extensibility/copilot-orchestration-multi-agent.md',
'skills/ms-ai-advisor/references/copilot-extensibility/copilot-studio-localization-globalization.md',
'skills/ms-ai-advisor/references/copilot-extensibility/declarative-agents-fundamentals.md',
'skills/ms-ai-advisor/references/copilot-extensibility/declarative-agents-grounding-strategies.md',
'skills/ms-ai-advisor/references/copilot-extensibility/m365-copilot-plugins-ecosystem.md',
'skills/ms-ai-advisor/references/copilot-extensibility/mcp-protocol-copilot-studio.md',
'skills/ms-ai-advisor/references/copilot-extensibility/power-automate-copilot-integration.md',
'skills/ms-ai-advisor/references/copilot-extensibility/sharepoint-copilot-agents.md',
'skills/ms-ai-advisor/references/prompt-engineering/error-handling-and-fallback-prompting.md',
'skills/ms-ai-advisor/references/prompt-engineering/few-shot-learning-techniques.md',
'skills/ms-ai-advisor/references/prompt-engineering/multimodal-prompt-design.md',
'skills/ms-ai-advisor/references/prompt-engineering/real-time-reasoning-performance.md',
'skills/ms-ai-advisor/references/prompt-engineering/role-playing-and-persona-techniques.md',
'skills/ms-ai-engineering/references/agent-orchestration/agent-autonomy-and-control-governance.md',
'skills/ms-ai-engineering/references/agent-orchestration/agent-evaluation-testing-frameworks.md',
'skills/ms-ai-engineering/references/agent-orchestration/agent-memory-and-context-management.md',
'skills/ms-ai-engineering/references/agent-orchestration/agent-to-agent-a2a-protocol.md',
'skills/ms-ai-engineering/references/agent-orchestration/agent-to-agent-communication.md',
'skills/ms-ai-engineering/references/agent-orchestration/computer-using-agents-cua.md',
'skills/ms-ai-engineering/references/agent-orchestration/foundry-workflows-visual-orchestration.md',
'skills/ms-ai-engineering/references/agent-orchestration/multi-agent-orchestration-patterns.md',
'skills/ms-ai-engineering/references/agent-orchestration/semantic-kernel-agents-implementation.md',
'skills/ms-ai-engineering/references/agent-orchestration/tool-use-and-function-calling-patterns.md',
'skills/ms-ai-engineering/references/azure-ai-services/ai-services-api-best-practices.md',
'skills/ms-ai-engineering/references/azure-ai-services/ai-services-enterprise-architecture.md',
'skills/ms-ai-engineering/references/azure-ai-services/ai-services-monitoring-logging.md',
'skills/ms-ai-engineering/references/azure-ai-services/ai-services-networking-security.md',
'skills/ms-ai-engineering/references/azure-ai-services/ai-services-vs-foundry-tools-selection.md',
'skills/ms-ai-engineering/references/azure-ai-services/azure-ai-vision-image-analysis.md',
'skills/ms-ai-engineering/references/azure-ai-services/azure-ai-vision-ocr-processing.md',
'skills/ms-ai-engineering/references/azure-ai-services/content-understanding-multimodal-analysis.md',
'skills/ms-ai-engineering/references/azure-ai-services/document-intelligence-prebuilt-models.md',
'skills/ms-ai-engineering/references/azure-ai-services/language-services-custom-text-classification.md',
'skills/ms-ai-engineering/references/azure-ai-services/language-services-question-answering.md',
'skills/ms-ai-engineering/references/azure-ai-services/language-services-text-analytics.md',
'skills/ms-ai-engineering/references/azure-ai-services/speech-services-speech-to-text.md',
'skills/ms-ai-engineering/references/azure-ai-services/speech-services-text-to-speech.md',
'skills/ms-ai-engineering/references/azure-ai-services/translator-document-translation.md',
'skills/ms-ai-engineering/references/rag-architecture/agentic-rag-patterns.md',
'skills/ms-ai-engineering/references/rag-architecture/azure-ai-search-setup.md',
'skills/ms-ai-engineering/references/rag-architecture/citation-tracking.md',
'skills/ms-ai-engineering/references/rag-architecture/contextual-retrieval.md',
'skills/ms-ai-engineering/references/rag-architecture/graphrag-knowledge-graphs.md',
'skills/ms-ai-engineering/references/rag-architecture/hierarchical-rag-patterns.md',
'skills/ms-ai-engineering/references/rag-architecture/hybrid-search-configuration.md',
'skills/ms-ai-engineering/references/rag-architecture/metadata-management-filtering.md',
'skills/ms-ai-engineering/references/rag-architecture/multi-index-federation.md',
'skills/ms-ai-engineering/references/rag-architecture/multimodal-rag.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-caching-optimization.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-context-windows.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-core-patterns.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-document-preprocessing.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-hallucination-mitigation.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-iterative-refinement.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-query-understanding.md',
'skills/ms-ai-engineering/references/rag-architecture/rag-security-rbac.md',
'skills/ms-ai-engineering/references/rag-architecture/semantic-ranker-reranking.md',
'skills/ms-ai-engineering/references/rag-architecture/vector-indexing-techniques.md',
'skills/ms-ai-governance/references/monitoring-observability/custom-dashboards-ai-operations.md',
'skills/ms-ai-governance/references/monitoring-observability/model-performance-drift-detection.md',
'skills/ms-ai-governance/references/monitoring-observability/response-quality-metrics-rag.md',
'skills/ms-ai-governance/references/norwegian-public-sector-governance/copyright-ai-training-data-norway.md',
'skills/ms-ai-governance/references/responsible-ai/bias-detection-mitigation-strategies.md',
'skills/ms-ai-governance/references/responsible-ai/content-safety-implementation.md',
'skills/ms-ai-governance/references/responsible-ai/responsible-ai-policy-development.md',
'skills/ms-ai-governance/references/responsible-ai/stakeholder-communication-ai-decisions.md',
'skills/ms-ai-security/references/ai-security-engineering/ai-incident-response-procedures.md',
'skills/ms-ai-security/references/ai-security-engineering/ai-threat-modeling-stride.md',
'skills/ms-ai-security/references/ai-security-engineering/data-leakage-prevention-ai.md',
'skills/ms-ai-security/references/ai-security-engineering/defender-threat-protection-ai-services.md',
'skills/ms-ai-security/references/ai-security-engineering/entra-agent-id-zero-trust.md',
'skills/ms-ai-security/references/ai-security-engineering/output-validation-grounding-verification.md',
'skills/ms-ai-security/references/ai-security-engineering/owasp-llm-top10-azure-mitigations.md',
'skills/ms-ai-security/references/ai-security-engineering/security-copilot-integration.md',
'skills/ms-ai-security/references/cost-optimization/multi-model-strategy-costs.md',
'skills/ms-ai-security/references/cost-optimization/observability-cost-reduction.md',
'skills/ms-ai-security/references/performance-scalability/async-processing-patterns.md',
'skills/ms-ai-security/references/performance-scalability/connection-pooling-patterns.md',
'skills/ms-ai-security/references/performance-scalability/gpu-compute-sizing.md',
'skills/ms-ai-security/references/performance-scalability/model-distillation-performance.md',
'skills/ms-ai-security/references/performance-scalability/rate-limit-management.md',
'skills/ms-ai-security/references/performance-scalability/regional-deployment-latency.md',
];
const isMain = (() => {
try {
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
} catch {
return false;
}
})();
if (isMain) run({ dry: process.argv.includes('--dry') });