feat(ms-ai-architect): G3 gull-intern-konsistens-lint + G4 build-instruks-policy — §8 gap-lukk [skip-docs]

This commit is contained in:
Kjell Tore Guttormsen 2026-06-30 09:55:15 +02:00
commit 9b147b470f
6 changed files with 256 additions and 5 deletions

View file

@ -20,6 +20,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { parseLastUpdated, fileLastmodChanged } from './lib/base-rate.mjs';
import { lintGoldConsistency } from './lib/gold-consistency.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..', '..');
@ -86,12 +87,39 @@ const goldSet = {
raw_returns: 'fase0-returns/batch-*.json',
note_evidence_quote:
'Per-claim evidence_quote omitted here to bound size; full verbatim quotes live in the session transcript. notes + evidence_url capture each verdict basis.',
// G4 (programdok §8 / §3-kjennelse 2026-06-30): nedre-grense-policy for
// subagenter som bygger fremtidig gull. En nedre-grense-påstand («100+»,
// «200k+») teller som FEIL (outdated/wrong) hvis den GROVT understater
// (>~2x, beslutnings-endrende) den sanne verdien; en STRAM nedre grense (sann
// verdi i samme størrelsesorden) blir stående correct. Anvendt på FN2 (Spor 2b).
lower_bound_policy:
'Lower-bound claims (e.g. "100+", "200k+"): verdict=outdated/wrong if the bound grossly understates (>~2x, decision-changing) the true value; a tight bound (true value within the same order of magnitude) stays correct.',
// G3 (programdok §8): gull-intern-konsistens. Et verdict=correct-claim hvis
// egen `notes` innrømmer at verdien ikke er bekreftet mot kilden («uverifisert
// / illustrativ / ikke i kilden») MÅ enten relabel-es ELLER bære et
// `consistency_waiver` med begrunnelse. Håndhevet av lint-gold-consistency.mjs.
consistency_policy:
'verdict=correct claims whose notes admit the value is unverified/illustrative/not-in-source must be relabeled OR carry a consistency_waiver. Enforced by lint-gold-consistency.mjs.',
claim_count: claims.length,
},
claims,
};
// G3 (programdok §8): gull fødes konsistent. Hard gate kun på --write — et
// nybygget gull med uwaived selvmotsigende correct-claims (verdict=correct mens
// noten innrømmer ikke-bekreftet: «uverifisert/illustrativ/ikke i kilden») nektes
// SKREVET; relabel eller waiver først. Dry-run forhåndsviser (advarer, blokkerer
// ikke). Escape-hatch --allow-inconsistent (samme idiom som
// run-judge-bakeoff --allow-incomplete) for bevisst override.
const consistency = lintGoldConsistency(goldSet);
if (process.argv.includes('--write')) {
if (!consistency.ok && !process.argv.includes('--allow-inconsistent')) {
console.error(`error: ${consistency.flagged.length} uwaived selvmotsigende correct-claim(s) — gull nektes skrevet (G3):`);
for (const f of consistency.flagged) console.error(` - ${f.id} [${f.markers.join(', ')}]: ${f.notes}`);
console.error('Resolver hver (relabel ELLER consistency_waiver), eller --allow-inconsistent for å overstyre.');
process.exit(2);
}
const out = path.join(DATA, 'gold-correctness-set.json');
fs.writeFileSync(out, JSON.stringify(goldSet, null, 2) + '\n');
console.log(`wrote ${out} (${claims.length} claims)`);
@ -101,5 +129,11 @@ if (process.argv.includes('--write')) {
const filesUnknown = Object.entries(fileMeta).filter(([, m]) => m.lastmod_changed === null).length;
console.log(`claims: ${claims.length} | files: ${Object.keys(fileMeta).length}`);
console.log(`file lastmod_changed: true=${filesWithChange} false=${filesNoChange} unknown(null date)=${filesUnknown}`);
if (consistency.ok) {
console.log('G3 gull-konsistens: OK (0 uwaived selvmotsigende correct-claims)');
} else {
console.log(`G3 gull-konsistens: ⚠ ${consistency.flagged.length} uwaived selvmotsigende correct-claim(s) — --write vil nektes:`);
for (const f of consistency.flagged) console.log(` - ${f.id} [${f.markers.join(', ')}]`);
}
console.log('(dry run — pass --write to persist gold-correctness-set.json)');
}

View file

@ -3451,7 +3451,8 @@
"evidence_url": "https://learn.microsoft.com/azure/reliability/reliability-ai-search",
"lastmod_changed": false,
"file_last_updated": "2026-02-01",
"notes": "AI Search single-region; manuell multi-region matcher MS-veiledning. RTO 15 min illustrativ."
"notes": "AI Search single-region; manuell multi-region matcher MS-veiledning. RTO 15 min illustrativ.",
"consistency_waiver": "G3: 'RTO 15 min illustrativ' er en note-aside om et tidstall utenfor den vurderte claim-en (claim = 'ingen built-in cross-region', grunnet mot reliability-ai-search). Kapabiliteten korrekt; ikke FP1."
},
{
"id": "ms-ai-infrastructure/bcdr/service-level-documentation-dr.md#5",
@ -3477,7 +3478,8 @@
"evidence_url": "https://learn.microsoft.com/azure/cosmos-db/continuous-backup-restore-introduction",
"lastmod_changed": false,
"file_last_updated": "2026-02-01",
"notes": "Multi-write reell active-active; ~0-tall illustrative men kapabiliteten korrekt."
"notes": "Multi-write reell active-active; ~0-tall illustrative men kapabiliteten korrekt.",
"consistency_waiver": "G3/FP5 (Spor 2b reconciled): multi-region-write active-active grunnet (cosmos-db/distribute-data-globally); '~0'-RTO/RPO-tall illustrative, ikke kilde-siterte. Kapabilitet korrekt — behold correct."
},
{
"id": "ms-ai-infrastructure/bcdr/service-level-documentation-dr.md#7",
@ -4296,7 +4298,8 @@
"evidence_url": "https://learn.microsoft.com/azure/cost-management-billing/reservations/azure-openai",
"lastmod_changed": false,
"file_last_updated": "2026-06-01",
"notes": "Cross-model-sharing + per-time matching bekreftet. 'mai 2025' ikke i kilden."
"notes": "Cross-model-sharing + per-time matching bekreftet. 'mai 2025' ikke i kilden.",
"consistency_waiver": "G3: kjerne-kapabilitet (cross-model PTU-deling + per-minutt pro-rata matching) bekreftet live mot Foundry PTU-reservasjons-siden 2026-06-30; 'mai 2025'-ikrafttredelsesdato IKKE i kilden (ikke-materiell, ikke beslutnings-endrende). Behold correct; fjern/merk datoen i .md = Spor 0/1-fil-fiks."
},
{
"id": "ms-ai-security/cost-optimization/reserved-capacity-planning.md#6",

View file

@ -0,0 +1,62 @@
// lib/gold-consistency.mjs — G3 (programdok §8): deterministisk gull-intern-
// konsistens-vakt. Fanger FP1-klassen (Spor 2b): et claim med verdict=correct
// hvis egen `notes` innrømmer at den påståtte verdien ikke er bekreftet mot
// kilden («uverifisert / illustrativ / ikke i kilden»). Verdikten sier «matcher
// kilden»; noten sier det motsatte — en selvmotsigende annotasjon.
//
// Tripwire-design: brede markører for recall, presisjon via en eksplisitt
// `consistency_waiver`-escape-hatch (menneske-i-loop §4c). Linten klassifiserer
// ikke — den surfacer kandidater et menneske enten relabel-er eller waiver-er
// med begrunnelse. Ren funksjon, ingen I/O; testet i tests/kb-eval/.
// Markører som — i en note festet til et verdict=correct-claim — innrømmer at
// den påståtte verdien IKKE er bekreftet mot den siterte kilden. Holdt brede med
// vilje (recall); falske positive absorberes av waiver-hatchen, ikke av en
// perfekt regex. Hver er en delstreng matchet case-insensitivt.
export const CONTRADICTION_MARKERS = [
'uverifisert',
'ikke verifiser', // ikke verifisert / ikke verifiserbar
'kan ikke verifiser',
'illustrativ', // illustrativt / illustrative
'ikke i kilden',
'ikke nevnt i kild',
'kilden oppgir ikke',
'ikke bekreftet',
'ubekreftet',
'source_silent',
'plassholder',
'placeholder',
'eksempel-tall',
'eksempeltall',
];
// Verdikter som hevder samsvar med dagens kilde. Kun disse kan motsi en
// «ikke bekreftet»-note: outdated/wrong/unsourced anerkjenner allerede ikke-match.
const ASSERTS_SOURCE_MATCH = new Set(['correct']);
export function findContradictionMarkers(notes) {
if (!notes || typeof notes !== 'string') return [];
const lc = notes.toLowerCase();
return CONTRADICTION_MARKERS.filter((m) => lc.includes(m));
}
function hasWaiver(claim) {
return typeof claim.consistency_waiver === 'string' && claim.consistency_waiver.trim().length > 0;
}
// Returnerer { ok, flagged: [{ id, verdict, notes, markers }] }.
// Et claim flagges når: verdikten hevder kilde-samsvar, noten bærer en
// motsigelses-markør, og det ikke finnes et ikke-tomt consistency_waiver.
export function lintGoldConsistency(goldSet) {
const claims = (goldSet && goldSet.claims) || [];
const flagged = [];
for (const c of claims) {
if (!ASSERTS_SOURCE_MATCH.has(c.verdict)) continue;
if (hasWaiver(c)) continue;
const markers = findContradictionMarkers(c.notes);
if (markers.length) {
flagged.push({ id: c.id, verdict: c.verdict, notes: c.notes, markers });
}
}
return { ok: flagged.length === 0, flagged };
}

View file

@ -0,0 +1,47 @@
#!/usr/bin/env node
// lint-gold-consistency.mjs — G3 (programdok §8) CLI: kjør gull-intern-
// konsistens-vakten over gold-correctness-set.json. Tynn wiring; all logikk i
// testet lib/gold-consistency.mjs (samme form som run-judge-bakeoff.mjs).
//
// Flagger verdict=correct-claims hvis egen `notes` innrømmer at verdien ikke er
// bekreftet mot kilden («uverifisert / illustrativ / ikke i kilden») og mangler
// et `consistency_waiver`. Exit 1 hvis noen uwaived → hard gate for gull-bygg.
//
// Usage:
// node scripts/kb-eval/lint-gold-consistency.mjs [--gold <path>] [--json]
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { lintGoldConsistency } from './lib/gold-consistency.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DATA = path.join(__dirname, 'data');
function flag(name) {
const i = process.argv.indexOf(name);
return i >= 0 ? process.argv[i + 1] : undefined;
}
const goldPath = flag('--gold') || path.join(DATA, 'gold-correctness-set.json');
if (!fs.existsSync(goldPath)) {
console.error(`error: ${goldPath} not found`);
process.exit(2);
}
const gold = JSON.parse(fs.readFileSync(goldPath, 'utf8'));
const r = lintGoldConsistency(gold);
if (process.argv.includes('--json')) {
console.log(JSON.stringify(r, null, 2));
} else if (r.ok) {
console.log(`gull-konsistens OK — 0 uwaived selvmotsigende correct-claims (${(gold.claims || []).length} claims)`);
} else {
console.error(`gull-konsistens FEIL — ${r.flagged.length} uwaived selvmotsigende correct-claim(s):`);
for (const f of r.flagged) {
console.error(` - ${f.id} [${f.markers.join(', ')}]`);
console.error(` notes: ${f.notes}`);
}
console.error('\nResolver hver: relabel verdikten ELLER legg til et consistency_waiver med begrunnelse (menneske-i-loop §4c).');
}
process.exit(r.ok ? 0 : 1);