ms-ai-architect/commands/kb-update.md
Kjell Tore Guttormsen 89dcd80cbc feat(ms-ai-architect): Layer B ingestion-gate — deterministisk adversariell-innhold-skann før skriving/commit (G6 §8 / R6 punkt d, TDD) [skip-docs]
Load-bearing gaten i den to-lags ingestion-sikkerheten: en deterministisk,
alltid-på node-skann (unicode/injection/base64, prosa + fenced code blocks) over
kandidat skills/**/*.md, wiret inn som sibling til validate-kb-file.mjs ved det
ENESTE skrive-chokepunktet — dekker kb-update + generate-skills + fremtidig R7.

- lib/adversarial-scan.mjs: ren disposition-kjerne (provenance-tiering + BLOCK/
  WARN-matrise). Ortogonal til korrekthets-judgen.
- lib/adversarial-detect.mjs: bro til de DELTE llm-security-detektorene
  (scanForInjection-lexikon + unicode-scanner + base64/entropi) — ingen kopi av
  lexikonet. Fail-closed hvis llm-security fraværende.
- scan-adversarial-content.mjs: CLI (speiler validate-kb-file.mjs); exit 1=BLOCK
  (aldri skriv), 2=WARN (flagg → menneske), 0=ren.
- 30 tester (19 kjerne + 7 CLI + 4 integrasjon mot ekte llm-security). Suite 692/0.

Premiss-verifisert mot live kode: research/research-agent skriver ingenting
(kun Layer A); R7-judge re-bruker samme create-guard; CLI-scan alene misset
injection+base64 for markdown → importerer rene primitiver i stedet.
2026-07-04 07:13:43 +02:00

243 lines
22 KiB
Markdown
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.

---
name: architect:kb-update
description: Manuell oppdatering av kunnskapsbasen — poller Microsoft Learn-sitemaps, sammenligner mot lokale `Last updated`-headere, oppdaterer endrede filer og oppdager nye relevante URLer
argument-hint: "[valgfritt: --skip-discover | --priorities critical,high,medium,low | --dry-run]"
allowed-tools: Bash, Read, Edit, Write, Glob, Grep, mcp__microsoft-learn__microsoft_docs_search, mcp__microsoft-learn__microsoft_docs_fetch, mcp__microsoft-learn__microsoft_code_sample_search
model: opus
---
# /architect:kb-update — Manuell KB-oppdatering
Holder Microsoft AI-kunnskapsbasen i `skills/*/references/` ferskt ved å sammenligne lokale referansefiler mot Microsoft Learn-sitemaps.
**Apply (oppdatering av KB-filer) er alltid manuell og kjøres in-session** — den bruker Claude og forblir under operatør-gate. **Deteksjon** (poll → rapport → discovery → skill-livssyklus) er ren node som aldri kontakter Claude/Anthropic, og kan **valgfritt schceduleres** (se «Scheduled deteksjon» under). Skillet er ToS-forankret: Consumer Terms §3.7 begrenser automatisert tilgang til Anthropics tjenester — ikke kjøring av lokale scripts som ikke rører Claude.
## Hva kommandoen gjør
1. **Polle sitemaps:** kjører `node scripts/kb-update/run-weekly-update.mjs --force` for å hente fersk `<lastmod>` for hver Microsoft Learn-URL i registeret
2. **Optional discovery:** med default `--discover` finner nye relevante URLer i sitemap som ikke er i registeret (`scripts/kb-update/discover-new-urls.mjs --limit 500`). Discovery **leser beslutnings-ledgeren** (`data/decisions.json`, lag 2) og utelater alt operatøren allerede har tatt stilling til (policy A: approved/rejected/pending) — så de samme kandidatene drukner ikke gaten kjøring etter kjøring
3. **Generere endringsrapport:** `report-changes.mjs` produserer `data/change-report.json` med per-fil prioritering (critical/high/medium/low) basert på antall endrede kilder + alder på lokal fil
4. **Vise rapporten:** lese rapport, presentere oppsummering til bruker, vente på `go`
5. **Oppdatere filer:** for hver fil i valgt prioritetsbøtte (default: critical + high):
- Hente fersk innhold fra alle endrede kildene via `microsoft_docs_fetch`
- Oppdatere relevante seksjoner i den lokale `.md`-fila
- Oppdatere `Last updated:`-header til dagens dato
6. **Committe:** én git-commit per fil med `chore(ms-ai-architect): refresh KB <fil> [skip-docs]`-format (eller én samlet commit om brukeren foretrekker det)
## Argumenter
| Flagg | Effekt |
|-------|--------|
| `--skip-discover` | Hopp over discovery-passet (raskere, ingen nye URLer oppdages) |
| `--priorities <list>` | Komma-separert subset av `critical,high,medium,low`. Default: `critical,high` |
| `--dry-run` | Generer rapport, men ikke oppdater filer eller committ |
| `--single-commit` | Samle alle filendringer i én commit i stedet for én per fil |
## Scheduled deteksjon (opt-in, Spor C / C1)
Deteksjonen kan kjøre automatisk i bakgrunnen ved sesjonsstart — **av som default**. Den er frivillig å sette opp, men virker når aktivert.
**Slik aktiverer du den:** opprett `ms-ai-architect.local.md` i plugin-roten (gitignored) med:
```yaml
---
scheduled_detection:
enabled: true # default false — ingenting kjører før dette er true (Tier 1)
interval_days: 7 # kjør deteksjon på nytt når det er ≥ N dager siden sist poll
include_skill_lifecycle: true # ta med skill-livssyklus-deteksjon (overlapp/gap/bloat)
os_scheduler_cadence: daily # Tier 2: daily (poll hver dag) | interval (throttle på interval_days)
---
```
### Tier 1 — sesjonsforankret (SessionStart-hook)
Når `enabled: true` og det er ≥ `interval_days` siden sist poll, spawner SessionStart-hooken `scripts/kb-update/run-detection.mjs` i bakgrunnen. Den kjører **kun deteksjon** (poll → rapport → discovery → skill-livssyklus) og skriver JSON-rapporter til `data/`**aldri** til `skills/`, og kaller **aldri** Claude. Ferske signaler surfaces ved neste sesjonsstart («KB: …» + «Skill-signaler: …»), og du kjører `/architect:kb-update` manuelt for å gjennomgå + apply-e gjennom gaten. **Begrensning:** Tier 1 kjører bare når en Claude-sesjon *starter* — starter du aldri en sesjon, kjører deteksjonen aldri.
### Tier 2 — lokal launchd-scheduler (ekte bakgrunn mellom sesjoner)
For deteksjon som kjører *uavhengig av sesjoner*, installer en lokal **launchd LaunchAgent** som fyrer samme Claude-frie entrypoint daglig (kl. 03:00):
```bash
node scripts/kb-update/scheduler.mjs install # skriv plist til ~/Library/LaunchAgents + last agenten
node scripts/kb-update/scheduler.mjs status # er den lastet?
node scripts/kb-update/scheduler.mjs run-now # kjør én gang nå (verifiser uten å vente til 03:00)
node scripts/kb-update/scheduler.mjs print # vis plisten uten å skrive noe (alias --dry-run)
node scripts/kb-update/scheduler.mjs uninstall # avlast + fjern plist
```
- **Kadens (`os_scheduler_cadence`):** `daily` (default) poller hver dag; `interval` throttler til `interval_days` via samme staleness-gate som Tier 1. (Onboarding setter dette senere; daglig er fornuftig default — poll av Microsoft Learn-sitemaps er billig og read-only.)
- **Pause = uninstall.** LaunchAgenten kjører uansett `enabled:`-flagget (det styrer *kun* Tier 1/hooken). Vil du stoppe Tier 2, kjør `uninstall` — det er pause-knappen.
- **Etter en major `brew upgrade node`:** kjør `install` på nytt. Node-stien bakes inn ved install-tid (launchd har minimalt `PATH`); plistens `PATH` inkluderer `/usr/local/bin` så barneprosessenes `node` overlever, men det er ryddigst å re-installere.
- **launchd, ikke cron:** Apple anbefaler launchd; cron krever Full Disk Access og er «not recommended». Vil du heller bruke cron/systemd/CI, peker du den på samme `node scripts/kb-update/run-detection.mjs`.
**ToS-garanti (strukturell, begge tiers):** entrypointet (`run-detection.mjs`, og `scheduler.mjs run` som delegerer til det) spawner kun `node` på de allow-listede deteksjons-scriptene + `launchctl` for agent-styring; det kan ikke invokere `claude`. Apply (det eneste Claude-steget) forblir manuelt og in-session. Kjør `node scripts/kb-update/run-detection.mjs --dry-run` (eller `scheduler.mjs print`) for å se hva som ville kjørt uten å kjøre noe.
## Instruksjoner til assistenten
### 1. Pre-flight
- `pwd` — bekreft at du står i `plugins/ms-ai-architect/` (eller delegere via absolutt sti)
- `git status --porcelain | grep -E '\.md$' && echo "WARN: ucommittede skill-endringer — kommandoen vil blande dem inn"` — advar bruker hvis det finnes lokale skill-endringer
- Parse argumenter
### 2. Kjør pollingsfasen
```bash
node scripts/kb-update/run-weekly-update.mjs --force${ARG_DISCOVER}
```
Hvor `${ARG_DISCOVER}` er `--discover` med mindre `--skip-discover` ble gitt.
Output forventes å skrive `data/change-report.json` og evt. nye registry-entries hvis discovery kjørte.
### 3. Vis rapport-oppsummering
```bash
node scripts/kb-update/report-changes.mjs | head -40
```
Presenter til bruker:
- Antall filer per prioritet
- Hvilke prioriteter som blir behandlet (default: critical + high)
- Estimert antall `microsoft_docs_fetch`-kall (≈ sum av endrede kilder per fil)
- Spør: "Fortsett med oppdatering? (y/n)"
Hvis `--dry-run`: stopp her, ikke oppdater filer.
### 3b. Discovery-gate — nye URLer via decision-ledger (lag 2)
Kjørte discovery (default), lukk løkken her. Dette er **operatør-gaten** — det eneste stedet beslutninger om nye URLer skrives.
a. **Les kandidatene:** `data/discovery-report.json``candidates[]`. Listen er allerede dedupet av scriptet mot både registry og `data/decisions.json`, så alt her er genuint ubesluttet. Feltet `deduped_by_ledger` viser hvor mange tidligere beslutninger som ble utelatt.
b. **Presenter for operatør**, gruppert per `suggested_skill` (vis `url`, `suggested_category`, `lastmod`). For hver kandidat (eller batch): **approve** (ta inn i KB), **reject** (irrelevant — ikke vis igjen), eller **utsett** (`pending` — ikke avgjort, vises i pending-bøtta men re-foreslås ikke).
c. **Skriv beslutningene til ledgeren — ENESTE skrivevei.** Bruk `lib/decisions-io.mjs` (ikke håndskriv JSON):
```
import { loadDecisions, recordDecision, saveDecisions } from './scripts/kb-update/lib/decisions-io.mjs';
let led = loadDecisions();
led = recordDecision(led, url, { status: 'rejected', decided_at: '<i dag>', suggested_skill, suggested_category, note });
// ...én recordDecision per beslutning...
saveDecisions(led);
```
`decided_at` settes til dagens dato (caller-injisert — `recordDecision` er ren). `decisions.json` er tracket i git (overlever, til forskjell fra de genererte rapportene).
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-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).
7. **Create-guard FØR skriving (to sibling-gater):** kjør BEGGE (exit ≠0 på noen av dem ⇒ ikke skriv):
- `node scripts/kb-update/validate-kb-file.mjs <sti>` — kontrakt (Source/født-verifisert/TOC).
- `node scripts/kb-update/scan-adversarial-content.mjs <sti>`**Layer B ingestion-gate (G6 §8 / R6 punkt d):** deterministisk adversariell-innhold-skann (unicode/injection/base64, prosa + fenced code blocks) via de delte llm-security-detektorene. **exit 1 = BLOCK** (aldri skriv — karantene, operatør adjudiserer); **exit 2 = WARN** (flagg → samme menneske-i-loop som en status-påstand; ikke auto-committ). Gaten er ortogonal til korrekthets-judgen: en faktakorrekt men forgiftet fil blokkeres likevel.
Først etter operatør-gate + BEGGE create-guards grønne: atomisk skriving (`lib/atomic-write.mjs` + `lib/backup.mjs`). **`transform.mjs` skriver aldri selv** — verifisert av `tests/kb-update/test-transform.test.mjs` (import-invariant). Kriterium verifisert av `tests/kb-eval/test-transform-criterion.test.mjs` (regenerer 1 fil → eval ≥ baseline). Layer B verifisert av `tests/kb-update/test-adversarial-scan.test.mjs` + `test-scan-adversarial-content.test.mjs` + `test-adversarial-detect-integration.test.mjs`.
e. **Invariant:** `discover-new-urls.mjs` (deteksjon) skriver **aldri** ledgeren — den kun leser. Bare denne gaten skriver. Verifisert av `tests/kb-update/test-discover-invariant.test.mjs`.
### 3c. Kurs-deteksjon-gate — nye/endrede kurs via decision-ledger (courses-kolleksjon, Spor C / C3)
Operatør-gaten for kurs-sporet. **Et kurs-lead er et *signal* om at et tema finnes — aldri en doc-side som ingestes.** Å godkjenne et lead **henter/transformerer/skriver ingen KB-fil** (det ville vært auto-ingest, et eksplisitt ikke-mål) — det registrerer kun operatørens beslutning i den UID-nøklede `courses`-kolleksjonen. Dette er ENESTE skrivevei for kurs-beslutninger.
a. **Sjekk rapporten:** `data/course-detection-report.json`. Produsert av den Claude-frie detektoren (`detect-courses.mjs`) — enten schedulert (Tier 1/2) eller manuelt: `node scripts/kb-update/detect-courses.mjs`. Mangler fila, eller `status:"skipped"` (Keychain-creds mangler — C3 er opt-in inni opt-in): **hopp over denne gaten stille**. `status:"error"`: rapportér kort og hopp over.
b. **Les leads:** `new[]` + `updated[]` (hver `{uid, title, url, products, suggested_skill, suggested_category, updated_at}`). `removed[]` er **kun et informasjonssignal** — vis det som en notis, aldri som en beslutning (et retirert kurs er ikke et tema å dekke; spec §4.2).
c. **Dedup mot ledgeren (policy A):** utelat leads operatøren allerede har tatt stilling til. Bruk `isCourseLeadDecided` (UID er den stabile nøkkelen — URL kan endres):
```
import { loadDecisions, isCourseLeadDecided } from './scripts/kb-update/lib/decisions-io.mjs';
const led = loadDecisions();
const fresh = [...report.new, ...report.updated].filter((l) => !isCourseLeadDecided(led, l.uid));
```
d. **Presenter `fresh`** for operatør, gruppert per `suggested_skill` (vis `title`, `url`, `products`, `kind` new/updated). For hvert lead (eller batch): **approve** (relevant — verdt å dekke i KB-en), **reject** (ikke relevant — ikke vis igjen), eller **utsett** (`pending` — ikke avgjort).
Hvis `--dry-run`: stopp etter presentasjonen — **ikke skriv ledgeren**.
e. **Skriv beslutningene til ledgeren — ENESTE skrivevei.** Bruk `recordCourseLead` (ikke håndskriv JSON):
```
import { loadDecisions, recordCourseLead, saveDecisions } from './scripts/kb-update/lib/decisions-io.mjs';
let led = loadDecisions();
led = recordCourseLead(led, uid, {
kind, status: 'approved', title, url, products, suggested_skill, suggested_category,
updated_at, detected_at, decided_at: '<i dag>', note,
});
// ...én recordCourseLead per beslutning...
saveDecisions(led);
```
`decided_at` settes til dagens dato (caller-injisert — `recordCourseLead` er ren). `decisions.json` er tracket i git.
f. **Ingen ingest — strukturell invariant.** Et godkjent kurs-lead blir værende i `courses`-kolleksjonen og leses av **ingen** av apply-pathene: `apply-skill-op.mjs` leser kun `actions`, `discover-new-urls.mjs` kun `decisions`. En kurs-beslutning trigger derfor **aldri** fetch/transform/KB-skriving. Skal et kurs' tema faktisk dekkes med en KB-side, er det en **separat, bevisst** doc-discovery-handling gjennom §3b (finn doc-URLen) — ikke en automatisk konsekvens av å godkjenne kurset. Et godkjent kurs surfaces ved sesjonsstart (C3.6: «N nye / M endrede kurs i dekkede produkter») som en påminnelse til operatøren.
### 4. Per-fil oppdatering (etter brukerens `y`)
For hver fil i valgte prioriteter:
a. **Les nåværende fil:** `Read` på filstien
b. **Hent oppdaterte kilder:** for hver URL i `change-report.json[file].changed_urls`, kjør `microsoft_docs_fetch` på URLen
c. **Identifiser endringer:** sammenlign hentet markdown mot eksisterende seksjoner i fila. Fokuser på faktuelle endringer (ny info, oppdaterte features, deprecation-varsler) — ikke små formuleringsendringer
c1. **Autoritetskilde-binding (lag 3) — header-as-truth.** `authority_source = resolveAuthority(<fil-innhold>)` (`lib/authority.mjs`) — fila sin `**Source:**`-header ER den utpekte autoriteten for dens påstander. `null` hvis fila mangler headeren (vokser etter hvert som lag 4 regenererer filer). Dette er inngangsdataen til lag-5 regel 3 (autoritets-mismatch): er en status-/load-bearing-endrings `source_url``authority_source`, flagges den. Aldri gjett en autoritet fra fila sine siterte URLer (251/303 filer siterer 410 → ville vært gjetning).
c2. **Verifisering-ut (lag 5) — FØR du skriver.** Hver kandidat-endring fra (c) går gjennom `lib/verify-out.mjs` `classifyChange({field, old_value, new_value, source_url, authority_source, refutations})` med `authority_source` fra (c1). Dette fanger regresjons-klassen (en status-påstand «korrigert» mot en tilfeldig sitert side og stille auto-applyet — agentic-retrieval-regresjonen):
- **`flagged`** → IKKE auto-skriv. Vis endringen til operatør med `reasons[]`; operatør avgjør om den tas inn. **Status-påstander (GA/preview/versjon/pris) er ALLTID `flagged`** (spec §21) — uansett hvor sikker kilden ser ut.
- **`auto-applied`** → trygt å ta inn i (d) (benign, ikke-status, ingen motbevis, autoritets-match).
- **Adversarial motbevis-panel (LLM-runtime):** for status-/load-bearing-påstander, kjør et lite panel som *prøver å motbevise* `new_value` mot den utpekte `authority_source`, og mat resultatene inn som `refutations[]` (`[{refuted, reason}]`). Multi-agent foreslås når lag 4/5 kjøres i produksjon (roadmap §71).
- **Invariant:** `verify-out.mjs` skriver aldri — den returnerer kun en verdict. Selve skrivingen skjer i (d), gated. Verifisert av `tests/kb-update/test-verify-out.test.mjs`.
d. **Oppdater fila:** `Edit` med endringer som er `auto-applied` eller eksplisitt godkjent av operatør i (c2). Behold "For Cosmo"-seksjonen og overordnet struktur. Oppdater `Last updated: YYYY-MM-DD`-header til dagens dato. **Lag-4-kontrakt:** kjør `validateKbFile(<ny fil-innhold>)` (`lib/transform.mjs`) før skriving — den skal være `valid: true`. Mangler fila et `**Source:**`-header, legg det til i header-blokka med den utpekte autoritets-URLen for hovedkilden — da fanger lag 3 (`resolveAuthority` + `build-registry`) den som `authority_source`, og lag-5 regel 3 blir virksom for fila. Mangler en **stor fil (>100 linjer)** en `## Innhold`-TOC, generer den med `buildToc(<brødtekst>)` og legg den inn rett etter header-`---``validateKbFile` krever den nå for store filer, så in-place-oppdateringer backfiller TOC inkrementelt (Fase 1c).
d1. **Layer B FØR skriving/commit (ingestion-gate, G6 §8):** kjør `node scripts/kb-update/scan-adversarial-content.mjs <fil>` på den oppdaterte fila. exit 1 (BLOCK) ⇒ ikke skriv/committ — karantene, operatør adjudiserer; exit 2 (WARN) ⇒ flagg for operatør, ikke auto-committ. Deterministisk adversariell-innhold-skann via delte llm-security-detektorer; ortogonal til korrekthets-gatene i (c1/c2).
e. **Committ:** kjør create-guardene (`validate-kb-file.mjs` + `scan-adversarial-content.mjs`) grønne på fila, deretter `git add <fil>` + `git commit -m "chore(ms-ai-architect): refresh KB $(basename <fil>) [skip-docs]"` med mindre `--single-commit` ble gitt
### 5. Single-commit modus
Hvis `--single-commit`: skip committer per fil, og lag én samlet commit til slutt. **Layer B FØR commit (ingestion-gate, G6 §8):** skann alle endrede `skills/**/*.md` — en BLOCK (exit 1) tas ut av staging (aldri committet, karantene); en WARN (exit 2) flagges for operatør før commit:
```bash
node scripts/kb-update/scan-adversarial-content.mjs $(git diff --name-only --diff-filter=AM -- 'skills/**/*.md')
git add skills/
git commit -m "chore(ms-ai-architect): refresh KB — N files [skip-docs]"
```
### 6. Push (om bruker bekrefter)
Spør: "Push til Forgejo origin/main? (y/n)". Per global push-policy er direkte main-push pre-autorisert, men spør likevel her siden dette er en bulk-operasjon.
```bash
git push origin main
```
### 7. Oppsummering
Rapporter:
- Antall filer oppdatert per prioritet
- Antall commits laget
- Hvis discovery kjørte: antall nye URLer oppdaget og lagt til registry
- Eventuelle filer som ble hoppet over (f.eks. ingen reelle endringer i hentet innhold)
- `data/change-report.json` blir værende på disk for diagnose
## Fallgruver
- **Sitemap-coverage:** ~69% av URLene matche mot sitemap. ~31% (mest `azure/ai-foundry/openai/`) finnes ikke pga. URL-restrukturering på Microsofts side. Disse rapporteres som "always stale" og må vurderes manuelt
- **Microsoft_docs_fetch latency:** hver fetch tar 2-5 sek. 9 critical + 44 high filer × ~1.5 kilder hver = ~80 fetches = ~3-7 minutter
- **Modellvalg:** Opus brukes fordi diff-resonnering + tekst-syntese krever nyanse. For enklere "just refresh dates"-oppdateringer er Sonnet tilstrekkelig — bruker kan overstyre med eksplisitt `--model claude-sonnet-4-6` i Claude Code config
- **MCP-tilgjengelighet:** kommandoen krever at `microsoft-learn` MCP-serveren er aktiv. Sjekk med `claude mcp list` ved første kjøring
## Når kjøre
- **Anbefalt:** ukentlig eller månedlig, avhengig av hvor sensitive prosjektene dine er for KB-ferskhet
- **Før viktig vurdering:** kjør med `--priorities critical,high,medium` før en stor `/architect:utredning` eller `/architect:adr`
- **Etter Microsoft-events:** Build, Ignite, eller annen større Microsoft-konferanse → forvent mange endringer
## Schedulering
Pluginen schedulerer **ingenting før du selv aktiverer det** (alt er opt-in). Du har tre nivåer, alle Claude-frie i deteksjonsfasen:
- **Tier 1 (sesjonsstart):** `scheduled_detection.enabled: true` i `ms-ai-architect.local.md` — se «Scheduled deteksjon» over.
- **Tier 2 (lokal launchd, ekte bakgrunn):** `node scripts/kb-update/scheduler.mjs install` — se «Scheduled deteksjon» over.
- **Egen scheduler:** vil du heller bruke cron / systemd timer / CI, pek den på `node scripts/kb-update/run-detection.mjs` (eller `run-weekly-update.mjs --force --discover` for den eldre poll-flyten) og la den varsle deg om å kjøre `/architect:kb-update` i en interaktiv sesjon.
Apply-fasen (oppdatere filer + committe) kan ikke automatiseres innenfor denne pluginen — den krever LLM-resonnering på endringene og menneskelig vurdering, og er bevisst designet for kjøring fra en åpen Claude Code-sesjon.