feat(ms-ai-architect): C3.6 — SessionStart-surfacing av kurs-leads (summarizeCourses) → C3 kurs-spor komplett (TDD)

Siste C3-fase. `summarizeCourses(report)` ren one-liner i detection-schedule.mjs
(«Kurs-signaler: N nye / M endrede kurs i dekkede produkter»; null ved
0/skipped/error/removed-only/malformed — removed er informasjons-signal, aldri
surfacet lead, spec §4.2). Speiler summarizeSkillLifecycle.

Wiring i session-start-context.mjs: read-only, leser
scripts/kb-update/data/course-detection-report.json, foreslår /architect:kb-update,
speiler skill-signaler-blokka. Hooken spawner ingenting for kurs-sporet.

docs/development.md: ny C3-workflow-seksjon (to-stegs: Claude-fri deteksjon →
SessionStart-surfacing → operatør-gate §3c). CLAUDE.md hook-tabell oppdatert.

Tester (+6): summarizeCourses — new+updated one-liner, only-new/only-updated,
zero→null, removed-only→null, skipped/error→null, missing/partial→null.
kb-update 307→313, validate 239/0, kb-eval 100/0, hooks 11/11, discovery 13/13.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-06-23 15:00:40 +02:00
commit f4dd4d3fb6
5 changed files with 120 additions and 1 deletions

View file

@ -66,6 +66,27 @@ Legacy (deprecated):
bash scripts/kb-staleness-check.sh # mtime-basert, upålitelig etter git clone
```
### Kurs-deteksjon (Spor C / C3 — Learn Platform API, opt-in)
Et parallelt, uavhengig spor fra sitemap-discoveren: oppdage at Microsoft har publisert **nye** eller **endrede** treningskurs (modules + learning paths) i produktene KB-en dekker, slik at operatøren kan vurdere om temaet bør dekkes. Et kurs er et *signal*, ikke en doc-side — det auto-ingestes aldri. Full spec: [`c3-course-detection-plan.md`](c3-course-detection-plan.md).
**To-stegs-mønster (samme invariant som `discover-new-urls`):**
1. **Deteksjon (Claude-fri, opt-in, Node-script).** `detect-courses.mjs` leser tre Entra-creds fra macOS Keychain, henter token, paginerer Platform API (`/api/v1/modules` + `/learning-paths`) med produkt- og `updatedAt.gt`-filter, diff-er mot `data/course-registry.json` (detektorens egen sporings-state), og skriver **kun** to private filer: `data/course-detection-report.json` (kandidater) + oppdatert `course-registry.json`. Importerer **aldri** `saveDecisions` — skriver hverken `skills/` eller `decisions.json`.
```bash
node scripts/kb-update/detect-courses.mjs # default data-dir
node scripts/kb-update/detect-courses.mjs --data-dir DIR # omdiriger IO (tester)
```
Fail-soft: mangler creds → `status:"skipped"` + exit 0; vedvarende nettverksfeil → `status:"error"` + exit 0. Opt-in inni opt-in: steget kjøres kun av scheduleren når `include_course_detection: true` (default `false`) — sett nøkkelen manuelt i `~/.claude/ms-ai-architect/ms-ai-architect.local.md`.
2. **SessionStart-surfacing (read-only).** `session-start-context.mjs` leser `course-detection-report.json` og viser en one-liner via `summarizeCourses` («Kurs-signaler: N nye / M endrede kurs i dekkede produkter. Kjør /architect:kb-update») — speiler skill-signaler-blokka. `removed` er kun et informasjonssignal i rapporten, aldri en surfacet lead (spec §4.2). Hooken spawner ingenting for kurs-sporet.
3. **Gate (operatør, Claude-i-loop).** `/architect:kb-update` §3c leser rapporten, presenterer nye/endrede leads, og skriver godkjente leads til den UID-nøklede `courses`-kolleksjonen i `decisions.json` (via `recordCourseLead`). `--dry-run` viser leads uten å skrive. **Strukturell invariant:** ingen apply-path leser `courses` → et godkjent kurs-lead trigger aldri fetch/transform/KB-skriving.
Slug→skill-mapping er config i `domain-taxonomy.json` (`course_products`), ikke hardkoding. `last_full_enum`-kadens (≥30 d) styrer når `removed` beregnes (kun full-enumerering — aldri inkrementelt).
### E2E-regresjonstester
```bash
# Kjør alle E2E-suiter