From da8606f9f6352a628f7367e345ac677132a29d72 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Tue, 30 Jun 2026 21:55:39 +0200 Subject: [PATCH] =?UTF-8?q?feat(ms-ai-architect):=20G2=20LUKKET=20?= =?UTF-8?q?=E2=80=94=20adoptert=20v3.1-judge=20wired=20inn=20i=20pipeline?= =?UTF-8?q?=20(JUDGE=5FVERSION=202=E2=86=92'3.1',=20TDD,=20suite=20641)=20?= =?UTF-8?q?[skip-docs]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- commands/generate-skills.md | 8 ++++---- commands/kb-update.md | 2 +- docs/ref-kb-correctness-program-2026-06.md | 6 +++++- scripts/kb-update/lib/transform.mjs | 12 +++++++++--- scripts/kb-update/transform-prompt.md | 6 +++--- tests/kb-update/test-transform.test.mjs | 4 ++-- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/commands/generate-skills.md b/commands/generate-skills.md index 8e6e613..6fefa43 100644 --- a/commands/generate-skills.md +++ b/commands/generate-skills.md @@ -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 diff --git a/commands/kb-update.md b/commands/kb-update.md index c073b28..6cb0447 100644 --- a/commands/kb-update.md +++ b/commands/kb-update.md @@ -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: , lastUpdated: }, verdict, )` — 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: , lastUpdated: }, verdict, )` — 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). diff --git a/docs/ref-kb-correctness-program-2026-06.md b/docs/ref-kb-correctness-program-2026-06.md index f7fe6f1..02aac51 100644 --- a/docs/ref-kb-correctness-program-2026-06.md +++ b/docs/ref-kb-correctness-program-2026-06.md @@ -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`, R1–R8) 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). diff --git a/scripts/kb-update/lib/transform.mjs b/scripts/kb-update/lib/transform.mjs index 1635dba..482081e 100644 --- a/scripts/kb-update/lib/transform.mjs +++ b/scripts/kb-update/lib/transform.mjs @@ -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` 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' diff --git a/scripts/kb-update/transform-prompt.md b/scripts/kb-update/transform-prompt.md index 33a7270..5d502aa 100644 --- a/scripts/kb-update/transform-prompt.md +++ b/scripts/kb-update/transform-prompt.md @@ -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 + diff --git a/tests/kb-update/test-transform.test.mjs b/tests/kb-update/test-transform.test.mjs index 6d62691..188d0d4 100644 --- a/tests/kb-update/test-transform.test.mjs +++ b/tests/kb-update/test-transform.test.mjs @@ -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 -------------