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).
239 lines
15 KiB
JavaScript
239 lines
15 KiB
JavaScript
#!/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') });
|