feat(ms-ai-architect): G2 LUKKET — adoptert v3.1-judge wired inn i pipeline (JUDGE_VERSION 2→'3.1', TDD, suite 641) [skip-docs]

This commit is contained in:
Kjell Tore Guttormsen 2026-06-30 21:55:39 +02:00
commit da8606f9f6
6 changed files with 24 additions and 14 deletions

View file

@ -136,11 +136,11 @@ Format (STRENGT — alle seksjoner påkrevd):
Filen skal være *født verifisert*: ingen reference-fil forlater agenten uten at de
maskin-verifiserbare påstandene er bekreftet mot `Source`-URLen.
1. Kjør den gjeldende claim-judgen (`scripts/kb-eval/judge-claim-prompt-v2.md`) over
1. Kjør den gjeldende claim-judgen (`scripts/kb-eval/judge-claim-prompt-v3.1.md`) over
filens maskin-verifiserbare påstander (sku/version/tpm/status/region/taxonomy) mot
`Source`-URLen du hentet i Steg 1.
2. **Hvis alle påstander er `grounded`:** sett i headeren
`**Verified:** {dagens dato, YYYY-MM-DD}` og `**Verified by:** judge-v2`.
`**Verified:** {dagens dato, YYYY-MM-DD}` og `**Verified by:** judge-v3.1`.
3. **Hvis noen påstand IKKE er grounded:** IKKE stempl `Verified`. Rett påstanden mot
kilden og kjør judgen på nytt, eller — hvis verdien er maskin-uverifiserbar (pris/
JS-rendret) — merk den eksplisitt og la filen gå til menneske-gaten (den blir IKKE
@ -302,9 +302,9 @@ Bruk Edit-verktøyet (IKKE Write) for å:
berørt fil skal forlate oppdateringen kontrakt-kompatibel — inkrementell Spor 1).
## Steg 2.5: Født-verifisert (judge FØR du returnerer)
Kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v2.md`) over de oppdaterte maskin-
Kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v3.1.md`) over de oppdaterte maskin-
verifiserbare påstandene mot `Source`. Alle `grounded` ⇒ sett `**Verified:** {dagens dato}`
+ `**Verified by:** judge-v2`. Ikke grounded ⇒ IKKE stempl; rett mot kilde og kjør på nytt,
+ `**Verified by:** judge-v3.1`. Ikke grounded ⇒ IKKE stempl; rett mot kilde og kjør på nytt,
eller send til menneske-gaten (fila committes ikke; se batch-gaten). Aldri stempl spekulativt.
## Steg 3: Returner kvittering

View file

@ -127,7 +127,7 @@ saveDecisions(led);
d. **For `approved`:** registrér URLen i `url-registry` (gated) så den fanges av polling heretter — via `lib/registry-io.mjs` `saveRegistry`. Bruk `suggested_skill`/`suggested_category` fra kandidaten. Deretter kjør **transformasjonslaget (lag 4)** for å lage KB-fila:
1. `microsoft_docs_fetch` på den godkjente URLen → kildedokument.
2. Destillér via `scripts/kb-update/transform-prompt.md` (doc→KB-fil; status-påstander holdes eksplisitte). Multi-agent parallell fan-out foreslås i produksjon (roadmap §71), speilet på `generate-skills`-mønsteret.
3. **Født-verifisert (Spor 3 Port 2):** kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v2.md`) over brødtekstens maskin-verifiserbare påstander mot den godkjente URLen → `verdict = {pass}`. Så `meta = stampVerifiedMeta({title, status, category, source: <godkjent URL>, lastUpdated: <YYYY-MM>}, verdict, <i dag>)` — stempler `type='reference'` + `verified` + `verified_by='judge-v2'` **kun** ved `pass`; ellers KASTER (ingen fil, flagg for menneske). Deretter `content = composeKbFile(meta, body)` (`lib/transform.mjs`) — header + (store filer >100 linjer) en deterministisk `## Innhold`-TOC + brødtekst. **`Status` + `Source` + `Verified` + `Verified by` er obligatoriske** — `Source` i header-blokka (øverste 500 bytes) er det som lar lag 3 backfille `authority_source`. TOC-en fødes inn så regenerering ikke stripper den (Fase 1c).
3. **Født-verifisert (Spor 3 Port 2):** kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v3.1.md`) over brødtekstens maskin-verifiserbare påstander mot den godkjente URLen → `verdict = {pass}`. Så `meta = stampVerifiedMeta({title, status, category, source: <godkjent URL>, lastUpdated: <YYYY-MM>}, verdict, <i dag>)` — stempler `type='reference'` + `verified` + `verified_by='judge-v3.1'` **kun** ved `pass`; ellers KASTER (ingen fil, flagg for menneske). Deretter `content = composeKbFile(meta, body)` (`lib/transform.mjs`) — header + (store filer >100 linjer) en deterministisk `## Innhold`-TOC + brødtekst. **`Status` + `Source` + `Verified` + `Verified by` er obligatoriske** — `Source` i header-blokka (øverste 500 bytes) er det som lar lag 3 backfille `authority_source`. TOC-en fødes inn så regenerering ikke stripper den (Fase 1c).
4. `validateKbFile(content)` MÅ være `valid: true` (title + Last updated + Status + Source + **Verified + Verified by**; **store filer også TOC**) før noe gates videre (ellers be modellen fylle manglende felt).
5. For hver status-/load-bearing-påstand: `buildChange({...})`**lag 5** `classifyChange(...)` (samme gate som §4 c2). Status-påstander er alltid `flagged`.
6. `resolveTargetPath(tax, category, filename)` → eierskill-sti via taksonomien (`null` = ukjent kategori → flagg for operatør, ikke skriv).

View file

@ -97,7 +97,7 @@ Status-nøkkel: 🔴 ikke startet · 🟡 pågår · 🟢 lukket.
| # | Gap (mekanismen mangler) | Forhindrer feilklasse | Lukke-fase | Status | MÅ lukkes før |
|---|---|---|---|---|---|
| **G1** | Judgen er ikke herdet mot de 8 dokumenterte feilmodusene (`source_silent`-maskerer-fravær, legacy-rad-match, ramme-skifte-tall-overlever, nedre-grense-understatement, eksakt-streng-pedanteri, taksonomi-nyanse, kapabilitet-bom) | Judge-FN/FP påvist i Spor 2b (8 mål, se `ref-kb-gold-reconciliation-2026-06.md`) | **Spor 2a** — judge-prompt-v3, MÅLT single vs v3/ensemble på herdet gull; adopter kun ved målt forbedring (ad-hoc-patch overfitter + bytter P/R) | 🟢 **LUKKET 2026-06-30 — v3.1 MÅLT + ADOPTERT.** 45-veis fan-out kjørt (255 claims, 45 Opus-4.8-xhigh-subagenter, live MS Learn, én per fil) → deterministisk re-score mot G5b-korrigert gull: **v3.1 = P 100,0 % / R 100,0 % / 0 FP / 0 FN** (TP 39→42: fanget alle 3 gjenstående FN; TN 198 + FP 0 uendret). Forhåndsregistrert gate (hold P=100 ∧ løft R>92,9) **klarert****v3.1 adoptert som judge**. Se lukke-logg. | Spor 1 korpus-pass (judgen brukes i ~2700 fetches) |
| **G2** | Herdet judge er ikke wired inn i Port 2 (born-verified create-guard) + Port 3 (kadens) — uten innplugging binder ikke hardningen mekanisk | Re-introdusert drift ved nye/regenererte filer + kadens-bom | Del av Spor 2a→3: bytt ut v2 med v3 i `transform.mjs`-judge-passet + kadens-runneren | 🟡 **AVBLOKKERT (G1 lukket 2026-06-30) — v3.1 = adoptert prompt å wire** inn i `transform.mjs`-judge-passet (Port 2 born-verified) + kadens-runner (Port 3). Ikke startet. | Spor 1 |
| **G2** | Herdet judge er ikke wired inn i Port 2 (born-verified create-guard) + Port 3 (kadens) — uten innplugging binder ikke hardningen mekanisk | Re-introdusert drift ved nye/regenererte filer + kadens-bom | Del av Spor 2a→3: bytt ut v2 med v3 i `transform.mjs`-judge-passet + kadens-runneren | 🟢 **LUKKET 2026-06-30 — v3.1 wired (TDD).** `JUDGE_VERSION 2 → '3.1'` (label-streng, provenance navner adoptert judge eksakt); prompt-/command-sites (`transform-prompt.md`, `kb-update.md` Port 2+Port 3, `generate-skills.md`) byttet `judge-claim-prompt-v2.md → -v3.1.md`. Suite 641/641. Se lukke-logg. | Spor 1 |
| **G3** | Ingen deterministisk gull-intern-konsistens-vakt (`verdict=correct` mens egen `notes` sier «uverifisert/illustrativ») | Gull-labeling-feil av FP1-klassen (selvmotsigende annotasjon) | Liten TDD-lint over `gold-correctness-set.json` (+ kjøres på fremtidige gull-bygg) | 🟢 **lukket 2026-06-30** | Spor 1 (nytt gull bygges) / §7 friskt utvalg |
| **G4** | Nedre-grense-policyen lever kun i prosa (denne dok + reconciliation-logg) — ikke kodet i judge-prompt ELLER `build-gold-set`-instruks | Re-introdusert nedre-grense-ambivalens i fremtidige gull-bygg + judge-kjøringer | Kod policyen inn i judge-prompt-v3 (G1) + build-gold-set-instruks | 🟢 **kodet 2026-06-30** (build-instruks + v3 R1); håndheving rir på G1/G2-adopsjon | Spor 1 / §7 friskt utvalg |
| **G5** | Gull-fasiten kan aldre — ingen friskhets-/re-adjuderings-vakt på selve svarnøkkelen. v3-målingen avdekket at flere judge-«feil» trolig er *utdatert gull*, ikke judge-feil (`genaiops-llm-specific#2`: claim «1600+», live=1900 ⇒ 1,19× tett nedre grense, R1 sier korrekt `grounded`, gull sier `outdated` — gull-standarden er her for streng) | Feil adopsjonsbeslutning bygd på aldrende baseline; falsk feilrate i §7-nordstjernen | Friskhets-mikropass: re-adjuder de ~5 omstridte v3-vs-v2-claims mot live MS Learn (avgjør gull-feil vs judge-feil) + periodisk gull-re-adjudering knyttet til §7 friskt utvalg | 🟢 **lukket 2026-06-30** (G5: 2 gull-feil rettet, 3 judge-feil bekreftet, **reverserte adopsjonsbeslutningen**; **G5b: completeness-caveat lukket** — de 4 v3-FP re-sjekket, ALLE 4 stale gull, v3 → P 100 % / R 92,9 % / 0 FP — se lukke-logg) | v3.1-adopsjon (baseline må være til å stole på FØR ny prompt måles mot den) |
@ -139,3 +139,7 @@ Status-nøkkel: 🔴 ikke startet · 🟡 pågår · 🟢 lukket.
- **FP-risiko avkreftet (R1s dobbeltegg holdt):** R1-«+»-floor-flaggene over full populasjon (`rag-context-windows#2` «200k+»→1M, `ai-services-vs-foundry#5` «100+»→1900) er begge gull=`outdated`**TP, ikke FP**; tette floors (`genaiops#2` «1600+»→1900, `reserved-capacity#3` «enkelte 100+») holdt `grounded`, gull=`correct` → TN. R1s magnitude-skille (>~2× decision-changing vs tett) sporet fasiten i begge retninger over de 255 — ingen ny FP innført.
- **Forhåndsregistrert gate klarert:** «adopter v3.1 KUN hvis P=100 OG R>92,9» → P=100 ✓ ∧ R=100>92,9 ✓ → **v3.1 ADOPTERT**. v3.1 (`judge-claim-prompt-v3.1.md`, R1R8) er nå inngangen til G2.
- **Metode-note (portabelt mønster, [[showcase-reusable-patterns]]):** `build-judge-payloads.mjs` (deterministisk payload-generator) + per-payload-splitt + inkrementell per-fil-persistering (resume-trygg mot kvote-stopp) gjorde fan-outen reproduserbar og avbruddssikker. Artefakter: `judge-bakeoff-results-v3.1.json`, `judge-bakeoff-report-v3.1.{json,md}` (committet); payloads gitignored.
- **G2 🟢 LUKKET (2026-06-30) — adoptert v3.1-judge wired inn i pipelinen (TDD).** RED→GREEN: testene `test-transform.test.mjs:200` (default-stempel) + `:235` (ende-til-ende) flippet `judge-v2 → judge-v3.1`, så feile, så `scripts/kb-update/lib/transform.mjs:44` `JUDGE_VERSION = 2 → '3.1'`.
- **Designvalg — version-label-streng, ikke integer (`judge-v3` forkastet):** v3 er en distinkt, målt, *forkastet* versjon (R 92,9 / 3 FN) med eget navn i programmets artefakter; et `judge-v3`-stempel ville navne feil judge og kollidere. Streng `'3.1'` lar provenance navne adoptert judge eksakt. Blast-radius null: `verified_by` lagres/parses kun som `\S+`-token + presence-sjekk (`parseVerifiedByHeader`), ingen kode trekker ut integeren; parseren tar `judge-v3.1` uendret (ende-til-ende-testen bekrefter det gjennom `composeKbFile`). Default-stien interpolerer strengen direkte (utenom `Number.isInteger`-guarden), så integer-override-stien (`judgeVersion:3 → judge-v3`) består.
- **Prompt-/command-wiring:** `transform-prompt.md` (46/101/105), `commands/kb-update.md` (130 — BÅDE Port 2 born-verified OG Port 3-kadens-inngang), `commands/generate-skills.md` (139/143/305/307) byttet `judge-claim-prompt-v2.md → -v3.1.md` + `judge-v2 → judge-v3.1`. `generate-skills.md`: kun kirurgisk judge-ref (Cosmo-heading urørt — «gjøres sist» per [[cosmo-persona-deprecated]]). Suite **641/641** (kun 2 eksisterende tester flippet, ingen lagt til).
- **Restgap (guard-minor-nit, §8-oppfølging):** stempel-guarden (`transform.mjs:165`) honorerer *integer*-override men ikke en minor-bærende streng-override (`judgeVersion:'3.2'` faller tilbake til default pga `Number.isInteger`). Harmløst — pipelinen bruker alltid default ('3.1'); en fremtidig judge-revisjon som vil *overstyre* til en minor må generalisere guarden til en version-label-regex. Logget her, ikke lukket (utenfor G2-scope; ingen failing behov i dag).

View file

@ -39,9 +39,11 @@ const DEFAULT_TYPE = 'reference';
// drift-introducing failure mode the create-guard exists to stop.
const REQUIRED_REFERENCE_META = ['source', 'verified', 'verified_by'];
// The current GATE-PASS claim judge (judge-claim-prompt-v2). stampVerifiedMeta records
// The current GATE-PASS claim judge (judge-claim-prompt-v3.1, adopted G1 2026-06-30).
// A version *label string* — integer major + optional minor — so provenance names the
// adopted judge exactly (v3 was a distinct, rejected version). stampVerifiedMeta records
// `verified_by: judge-v<JUDGE_VERSION>` unless the caller overrides or marks `human`.
const JUDGE_VERSION = 2;
const JUDGE_VERSION = '3.1';
// A Microsoft Learn / docs authority URL — a non-reference file may NOT carry one.
const MS_LEARN_RE = /\b(?:learn|docs)\.microsoft\.com/i;
@ -143,7 +145,7 @@ export function buildKbHeader(meta) {
* meta IFF the judge verdict passed otherwise REFUSE (throw). This encodes
* "nytt/regenerert innhold kjøres gjennom judgen FØR commit født verifisert; ellers
* ingen fil". transform.mjs never calls the judge itself (pure lib); the command runs
* the v2 claim judge, aggregates per-claim results into `{pass}`, and calls this. A
* the v3.1 claim judge, aggregates per-claim results into `{pass}`, and calls this. A
* failing verdict means no file is born.
*
* @param {object} baseMeta the reference meta (title/status/category/source/lastUpdated)
@ -159,6 +161,10 @@ export function stampVerifiedMeta(baseMeta, verdict, today) {
if (!DATE_RE.test(String(today ?? ''))) {
throw new Error(`stampVerifiedMeta: invalid today date '${today}' (expected YYYY-MM[-DD])`);
}
// Default stamp = the current JUDGE_VERSION label ('3.1'). An explicit integer override
// is still honoured (judgeVersion:3 → judge-v3); a minor-bearing string override is not
// yet (falls back to default) — tracked as a §8 follow-up, harmless since the pipeline
// always uses the default.
const verifiedBy =
verdict.by === 'human'
? 'human'

View file

@ -43,7 +43,7 @@ Headeren ser slik ut og MÅ stå først:
**Type:** reference
**Source:** {{SOURCE_URL}}
**Verified:** {{VERIFIED_DATE}}
**Verified by:** judge-v2
**Verified by:** judge-v3.1
---
```
@ -98,11 +98,11 @@ Ingen innledning eller avslutningskommentar — kun markdown-brødteksten.
## Etter destillasjon (caller, gated)
1. **Født-verifisert judge (FØR commit):** kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v2.md`)
1. **Født-verifisert judge (FØR commit):** kjør claim-judgen (`scripts/kb-eval/judge-claim-prompt-v3.1.md`)
over brødtekstens maskin-verifiserbare påstander mot `{{SOURCE_URL}}`. Aggreger til `verdict = {pass}`
(alle maskin-verifiserbare påstander `grounded``pass: true`).
2. `meta = stampVerifiedMeta({title, status, category, source, lastUpdated}, verdict, today)`
stempler `type='reference'` + `verified=today` + `verified_by='judge-v2'` **kun** ved `pass: true`;
stempler `type='reference'` + `verified=today` + `verified_by='judge-v3.1'` **kun** ved `pass: true`;
ellers KASTER den (ingen fil fødes). Deretter `content = composeKbFile(meta, body)`
header + (store filer) `## Innhold`-TOC + brødtekst.
3. `validateKbFile(content)` → må være `valid: true` (title + Last updated + Status + Source +

View file

@ -197,7 +197,7 @@ test('stampVerifiedMeta stamps verified=today + verified_by=judge-vN on a passin
const m = stampVerifiedMeta(base, { pass: true }, '2026-06-29');
assert.equal(m.type, 'reference');
assert.equal(m.verified, '2026-06-29');
assert.equal(m.verified_by, 'judge-v2'); // current GATE-PASS judge
assert.equal(m.verified_by, 'judge-v3.1'); // current GATE-PASS judge (v3.1 adopted G1)
});
test('stampVerifiedMeta honours an explicit judgeVersion', () => {
@ -232,7 +232,7 @@ test('stampVerifiedMeta → composeKbFile is a complete born-verified file (end-
const file = composeKbFile(stamped, '## Introduksjon\n\nKort.\n');
assert.equal(validateKbFile(file).valid, true);
assert.equal(parseVerifiedHeader(file), '2026-06-29');
assert.equal(parseVerifiedByHeader(file), 'judge-v2');
assert.equal(parseVerifiedByHeader(file), 'judge-v3.1'); // default stamp parses back (dotted minor survives)
});
// --- validateKbFile: catches files missing the mandatory contract -------------