feat(ms-ai-architect): C3.5 — courses-kolleksjon i decisions-io.mjs (UID-nøklet, Spor C) + kb-update §3c kurs-gate (TDD) [skip-docs]
Tredje ledger-kolleksjon (courses), additivt ved siden av decisions (URL,
Spor A) og actions (skill, Spor B). De tre rene helperne speiler
recordAction-trioen 1:1:
- recordCourseLead(led, uid, lead) (ren, UID-nøklet)
- setCourseLeadStatus(led, uid, status, at) (ren transisjon, kaster på ukjent UID)
- isCourseLeadDecided(led, uid) (dedup policy A: any status)
createLedger()->courses:{}; loadDecisions backfiller courses ??= {} (bakoverkompat).
Strukturell ingen-ingest-invariant: apply-pathene leser ALDRI courses
(apply-skill-op.mjs->kun actions, discover-new-urls.mjs->kun decisions),
så et godkjent kurs-lead trigger aldri fetch/transform/KB-skriving.
commands/kb-update.md §3c: operatør-gate som leser course-detection-report.json,
dedup'er via isCourseLeadDecided, skriver godkjente leads via recordCourseLead
(--dry-run viser leads uten å skrive).
Tester (+16): test-decisions-courses.test.mjs. Eksisterende test-decisions-io
+ test-decisions-actions URØRT grønne (ikke-regresjons-bevis, samme mønster
som Spor B). kb-update 291->307 · validate 239/0 · kb-eval 100/0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2e69e69326
commit
e0d2d05dbb
3 changed files with 352 additions and 8 deletions
|
|
@ -135,6 +135,43 @@ d. **For `approved`:** registrér URLen i `url-registry` (gated) så den fanges
|
|||
|
||||
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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue