From a3965fb372c9667b5521b5bdd1bc28bf8da0b894 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Fri, 3 Jul 2026 13:45:14 +0200 Subject: [PATCH] =?UTF-8?q?docs(plan):=20m=C3=A5lbilde=20+=20gated=20sesjo?= =?UTF-8?q?nsplan=20for=20ingest-programmet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Program-planleggingssesjon per brief 2026-07-03: alle brief-premisser verifisert mot ground truth (retrieval-forbudet sitert ordrett), planen adversarial-reviewet x2 (2 blockere + 8 majors innarbeidet: verdict-lag- reservasjon, lag-separasjon ved re-ingest, deterministisk timestamp, guard-dekning, D7/HTTP-ærlighet, gatede spec-endringer). I1 er GATET på operatør-godkjenning av målbildet. Kun dokumenter — ingen kode-, shared- eller søskenrepo-endring; suite 157/4 grønn. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01AaQCFnfsh3tfq1VfzdJpoi --- docs/plan/2026-07-03-maalbilde-ingest-lag.md | 214 +++++++++++++++++++ docs/plan/2026-07-03-sesjonsplan-ingest.md | 142 ++++++++++++ 2 files changed, 356 insertions(+) create mode 100644 docs/plan/2026-07-03-maalbilde-ingest-lag.md create mode 100644 docs/plan/2026-07-03-sesjonsplan-ingest.md diff --git a/docs/plan/2026-07-03-maalbilde-ingest-lag.md b/docs/plan/2026-07-03-maalbilde-ingest-lag.md new file mode 100644 index 0000000..3f7f0d3 --- /dev/null +++ b/docs/plan/2026-07-03-maalbilde-ingest-lag.md @@ -0,0 +1,214 @@ +# Målbilde — ingest-laget (tools og konnektorer mot reelle datakilder) + +> **Status:** KONSENSUS-forslag skrevet 2026-07-03 fra +> [program-briefen](2026-07-03-program-brief-ingest-konnektorer.md) — blir **frossen +> nordstjerne** for ingest-programmet når operatøren godkjenner det. Endres deretter *bevisst*, +> aldri ved drift (samme regime som [hovednordstjernen](2026-06-26-maalbilde-agentic-loop.md)). +> Fase-nivået er [sesjonsplanen for ingest](2026-07-03-sesjonsplan-ingest.md). +> +> **Provenance:** arkitekturvalgene her (svarene på briefens §7-spørsmål) er AI-anbefalinger, +> adversarial-reviewet i planleggingssesjonen 2026-07-03; de er ikke bindende før +> operatør-godkjenning og kan overstyres punkt for punkt. + +--- + +## 0. Hva dette dokumentet er (og ikke er) + +Målbildet for hva ingest-laget skal *være* når det er sant — ikke en faseplan. Det definerer +«ferdig» for programmet; sesjonsplanen sekvenserer veien dit. Ingest-laget er et **tillegg +foran** den eksisterende 8-stegs-loopen: ingenting i dette dokumentet endrer metode-spec-en, +golden-fasiten eller agent-atferden. + +## 1. Behovet + +Begge stackene (MAF + D7/Claude Agent SDK) er bevist på kuraterte OKF-bundles +(`shared/examples/bygg-energi-mikro/`). Praktisk anvendbarhet krever at fageksperter kan: + +1. koble rammeverket til reelle datakilder (økonomisystem, prosjektdatabase, FDV-system, + energimålere, dokumentarkiv), og +2. definere *hvilke spørringer* som henter underlaget per kjøring — som konfig, ikke kode. + +## 2. Arkitektur — ingest-steget kjører FØR optimalisereren + +Metode-spec-en (§3 Steg 1) forbyr eksplisitt query-time retrieval mot bundelen: + +> *«never via a query-time retrieval tool pointed at the bundle (which would re-leak the +> verdict layer)»* + +Konsekvensen er arkitektur-definerende: **data når modellen KUN via OKF-bundles.** Konnektorer +lever derfor i et **deterministisk ingest-steg som kjører før optimalisereren** og +materialiserer uttrekket som en OKF-bundle. Ikke RAG, ikke live-oppslag i agent-løkka, ingen +retrieval-tools i kjørestien. + +``` +manifest → konnektor → mapping → OKF-bundle (inkl. index-generering) → [eksisterende loop, uendret] +``` + +**Index-generering er del av kontrakten.** En bundle uten `index.md` er en feil, og +navigasjonen følger KUN index-cross-links (metode-spec Steg 1) — en generert konseptfil uten +index-lenke er unåbar. Konnektoren genererer/oppdaterer derfor `index.md` (sammendrag + én +lenke per generert fil); navigerbarhet er et load-bearing-krav (§9), ikke en detalj. + +```mermaid +flowchart LR + subgraph SRC["KILDESYSTEMER · aldri i agent-løkka"] + ERP["Økonomisystem"] + DB["Prosjektdatabase"] + FDV["FDV / energimålere"] + DOC["Dokumentarkiv"] + end + + MAN["Ingest-manifest
kilde + spørringer + mapping
KONFIG, skjema-validert fail-fast"] + + subgraph ING["INGEST-STEG · deterministisk · kjøres eksplisitt (HITL-gate)"] + CONN["Konnektor
filkatalog/CSV · SQL · (HTTP/MCP)"] + MAT["Materialisering
provenance-frontmatter + index-generering"] + CONN --> MAT + end + + BUNDLE["OKF-bundle
generert lag (ingest-eid)
+ kuratert/promotert lag (urørt)"] + + LOOP["8-STEGS-LOOPEN
uendret — leser bundelen
via navigasjon, aldri retrieval"] + + SRC --> CONN + MAN --> CONN + MAT --> BUNDLE + BUNDLE --> LOOP +``` + +## 3. Lag-separasjon i bundelen (ufravikelig) + +Bundelen er ikke bare input — den er også wikien Steg 8 promoterer godkjent kunnskap inn i. +To regler holder ingest og læringssløyfe adskilt: + +- **Verdict-laget er RESERVERT.** Manifest-mapping MÅ IKKE produsere `type: verdict`-filer + eller filnavn i `promoted-verdict-*`-navnerommet. Promoterings-gaten (metode-spec §6) er + ENESTE vei inn i verdict-laget; Steg 1 seeder hver `type: verdict`-fil inn i store med + decision-default `approved`, så en ingest som kunne skrive verdict-typede filer ville + injisere maskingenererte «godkjente» dommer utenom gaten — nøyaktig selv-forurensningen + gaten finnes for å hindre. Håndheves fail-fast i manifest-valideringen + load-bearing test. +- **Ingest eier kun sine egne filer.** Re-materialisering erstatter NØYAKTIG filene som bærer + ingest-stempelet (`generated: true` + `ingest_manifest`-ref) og rører ALDRI kuraterte eller + promoterte filer. Index-oppdatering er idempotent og bevarer kuraterte lenker (gjenbruker + `link_in_index`-mønsteret i `okf.py`). Load-bearing: re-ingest over en bundle med promotert + verdict → verdicten og dens index-lenke overlever. + +## 4. Ingest-manifestet (kontrakten) + +Ekspertens kobling til en kilde er ett JSON-manifest: **kilde** (type + tilkoblingsreferanse), +**spørring(er)**, **mapping → OKF-typer** (minus de reserverte, §3) og **provenance-krav**. +Skjema-validert fail-fast à la `contracts.py` — et malformet manifest starter aldri en +kjøring. Spørringene er KONFIG, ikke kode. + +**Credentials aldri i manifestet (svar på åpent spm. 3):** manifestet bærer kun en referanse +ved navn (env var / keychain-mønsteret); hemmeligheten slås opp ved kjøretid. Manifestet er +dermed versjonerbart og delbart uten hemmeligheter. + +Skjemaet designes polymorft for de tre kildetypene (filkatalog/CSV, SQL, HTTP/MCP) i én +spec-runde — HTTP/MCP-delen holdes til et minimum (nok til at extension-point-demoen ikke +trenger spec-endring, ikke mer) — slik at implementasjonsøktene ikke utløser spec-endringer. + +## 5. Provenance — eget lag, ubrutt kjede (svar på åpent spm. 2) + +Ingest-provenance er et **eget frontmatter-lag** på genererte konseptfiler — IKKE en utvidelse +av metode-spec §9: + +```yaml +source_system: +source_query: +ingested_at: +ingest_manifest: +generated: true +``` + +Begrunnelse: §9 er proposal-provenance (forslag → bundle-fil + span); ingest-provenance er +neste ledd i kjeden (bundle-fil → kildesystem). To separate kontrakter som aldri blandes — +samme disiplin som de to falsifisererne. OKF-spec-en garanterer at egendefinerte felt bevares +av konsumenter (verifisert mot eksisterende `okf.py` med syntetisk bundle, 2026-07-03). + +- **Timestamp-regelen:** `ingested_at` er et EKSPLISITT PÅKREVD argument til materialiseringen + — ingen wall-clock-default (speiler promoterings-gatens regel, metode-spec §6). Dermed er + golden-uttrekk bit-deterministiske. +- **Kjede-integritet:** kjeden ekspert → forslag → bundle-fil+span → kilde+spørring+tidspunkt + holder GITT versjonerte bundles (OKF-premisset: kuratert, versjonskontrollert). En + re-materialisering er en ny bundle-versjon, og bundelen bærer materialiserings-stempelet + (manifest-hash + `ingested_at`), slik at en kjørings citations kan knyttes til den konkrete + materialiseringen. Versjonering av bundles er en dokumentert deployer-forutsetning — vi + påstår ikke «ubrutt» utover den. +- **Ærlighets-regelen (§1):** en maskingenerert bundle MERKES som det (`generated: true` + + manifest-ref) overalt der den presenteres. + +## 6. Sikkerhetsrammer + +- **Lokal-only default, ingen stille egress.** Nettverkskilder krever et eksplisitt + opt-in-flagg per kjøring; uten flagg nekter konnektoren fail-fast. +- **Kildekall logges** (hvilken kilde, når, radantall) — samme disiplin som D6. +- **Tak på uttrekksstørrelse** (fail-fast ved overskridelse — aldri stille trunkering). +- DPIA/ROS/behandlingsformål eies fortsatt av deployer (rent teknisk rammeverk). + +## 7. HITL-gate for manifestet (svar på åpent spm. 5) + +MVP-mekanikken er to lag: + +1. **Prosessuelt:** ingest kjøres ALDRI automatisk — alltid en eksplisitt operatør-/ + ekspert-kommando med manifest-sti. Ingen scheduler, ingen implisitt re-ingest. +2. **Teknisk:** fail-fast skjemavalidering før noe kildekall + nettverkskilder nekter uten + eksplisitt flagg (§6). + +Rikere godkjenningsmekanikk (signert `approved_by`, godkjennings-register e.l.) er et +extension point — ikke MVP (90 %-prinsippet). + +## 8. Re-ingest og versjonering (svar på åpent spm. 4) + +MVP = **full re-materialisering av de ingest-eide filene** per kjøring — deterministisk gitt +samme kilde + manifest + timestamp, idempotent, og innenfor lag-separasjonen i §3 (kuratert og +promotert innhold overlever ALLTID). Bundelen stemples med manifest-hash + timestamp. +Inkrementell re-ingest er et extension point, ikke MVP. + +## 9. Determinisme og testbarhet (svar på åpent spm. 6) + +Konnektorer testes KUN mot fixtures/golden-uttrekk — aldri mot levende kilder. Golden-formatet +er: fixture-kilde + fast timestamp → forventet bundle, bit-deterministisk. Suitene i begge +repo kjører fortsatt uten nøkkel og uten nettverk. + +Load-bearing-krav (testen MÅ bli rød når sømmen detaches — metode-spec §11-regimet): + +1. Provenance-stempling detached → rød. +2. Generert bundle er navigerbar via uendret `okf.py` (inkl. index-lenkene) → rød hvis ingest + genererer noe OKF-koden ikke tåler. +3. Verdict-reservasjonen (§3): manifest som mapper til `type: verdict` → avvist; rød uten + reservasjonen. +4. Re-ingest bevarer promotert innhold (§3) → rød hvis re-materialisering sletter wikien. +5. Golden-uttrekk per kildetype → rød ved enhver drift i materialiseringen. + +## 10. Spec-plassering (svar på åpent spm. 1) + +Kontrakten bor i en **egen spec: `shared/ingest-spec.md`** i commons — IKKE som ny § i +`method-spec.md`. Begrunnelse: metode-spec-en er normativ på loopen, frosset og beskyttet av +spec-integrity-testen; ingest er et separat steg FORAN loopen; en egen fil holder frysingen +intakt og lar begge stackene konsumere kontrakten uavhengig. Skrives i commons-repoet og +subtree-pulles (PULL-ONLY-regimet står). Framework-guardene i BEGGE repo må EKSPLISITT utvides +til å dekke den nye fila — verifisert 2026-07-03: dagens guard itererer kun metode-spec-en + +skill-treet og dekker IKKE en ny spec-fil automatisk. + +## 11. Stack-mapping (ærlighets-avgrenset) + +- **Delt (commons):** ingest-spec + golden-uttrekk. Ren data/spec — framework-nøytral. +- **Implementert i BEGGE stacker:** filkatalog/CSV og SQL (sqlite-fixture). MAF gjenbruker + `contracts.py`-mønsteret + `okf.py`-skriverne; D7 bygger egen impl mot samme spec. +- **HTTP/MCP: demonstrert som extension point KUN på MAF-siden** (mot lokal mock, gated bak + nettverksflagget). D7s tekniske kroker (`create_sdk_mcp_server`, verifisert i D7-S5) + dokumenteres som pekere — ingen D7-HTTP-økt planlegges. +- **Ingen live-kilde forekommer noensinne i programmet.** Briefens «første live kilde»-gate + forblir ukonsumert — reservert deployer/framtidig arbeid. Sies eksplisitt her for at ingen + artefakt skal kunne påstå live-integrasjon. + +## 12. Utenfor scope + +- Ingen endring i agent-atferd eller nye modellkall — ingest er deterministisk (null + modellkall i hele programmet). +- Ikke query-time retrieval/RAG (forbudt av metode-spec-en, sitert i §2). +- DPIA/ROS/behandlingsformål eies av deployer. +- Ingen endring i golden-fasiten eller eksisterende suite-invarianter. +- Ingen scheduler/orkestrering av ingest-kjøringer (deployers ansvar). +- Ingen live-kilder (§11). diff --git a/docs/plan/2026-07-03-sesjonsplan-ingest.md b/docs/plan/2026-07-03-sesjonsplan-ingest.md new file mode 100644 index 0000000..0b21f2d --- /dev/null +++ b/docs/plan/2026-07-03-sesjonsplan-ingest.md @@ -0,0 +1,142 @@ +# Sesjonsplan — ingest-programmet (2026-07-03) + +> **Hva dette er:** Program-nivåets øktkart for ingest-laget, avledet av +> [målbildet for ingest](2026-07-03-maalbilde-ingest-lag.md) (nordstjernen dette planverket +> realiserer) og [program-briefen](2026-07-03-program-brief-ingest-konnektorer.md). Målbildet +> definerer «ferdig»; denne planen sekvenserer veien. Hver økt er scoped til å **fullføres +> innenfor én sesjon**. Programmet starter først etter operatør-godkjenning av målbildet. + +## Rammer (gjelder alle økter) + +- **Modell:** Fable 5 med xhigh reasoning effort — global default; 2026-07-02-planens + Opus-direktiv var scoped til dén planen og gjelder ikke her. +- **Én økt = én lukket leveranse:** grønn suite, STATE.md overskrevet, commit + push til + Forgejo før økta slutter. Aldri broken state over en øktgrense. +- **Kode-økter:** stram Plan-modus + TDD (Iron Law: ingen produksjonskode uten rød test + først). Hver økt får egen `/trekbrief` som kan re-scope innenfor «én økt = én lukket + leveranse». +- **Kostnadsdisiplin (D6):** ALT offline — null modellkall i hele programmet (ingest er + deterministisk; konnektorer testes kun mot fixtures/golden-uttrekk). +- **Commons PULL-ONLY:** spec-endringer skrives i commons-repoet og subtree-pulles. **Enhver + commons-/spec-endring utover I1 er en egen GATET runde — aldri foldet inn i en impl-økt.** +- **Operatør-gates:** I1 (spec-/commons-endring), I3 og I5 (søskenrepoet røres), I6 + (nettverks-kapabilitet innføres). S12 (release) er uavhengig av dette programmet og forblir + gated på egne vilkår. + +## Avhengigheter + +I1 → I2 → I3 → I4 → I5 → I6 → I7. (I6 avhenger teknisk kun av I2, men kjøres lineært etter I5 +— enklere statehåndtering. I7 sist, avhenger av alle.) + +--- + +## I1 — Ingest-spec i commons **[GATET: spec-/commons-endring]** + +**Mål:** Den framework-nøytrale kontrakten eksisterer i commons og er guardet i dette repoet — +begge stackene kan implementere fra spec alene. + +**Innhold:** +1. I COMMONS-repoet: forfatt `shared/ingest-spec.md` (framework-nøytral prosa — samme regel + som method-spec): polymorft manifest-skjema for alle tre kildetyper (HTTP/MCP-delen som + minimum, jf. målbildet §4), credential-referanse-regelen, verdict-lag-reservasjonen + + lag-separasjonen (målbildet §3), provenance-frontmatter-kontrakten inkl. eksplisitt + timestamp-argument (§5), index-genereringskravet (§2), golden-uttrekk-formatet (§9); + kryss-sjekk-tabell felter ↔ avsnitt. +2. I DETTE repoet: `git subtree pull --prefix=shared commons main --squash` + utvid + framework-guarden (`tests/test_method_spec_loadbearing.py`) til å dekke den nye fila. + +**Verifisering:** guard-utvidelsen bevist RØD mot en throwaway-kopi med framework-navn +injisert · begge repos suiter grønne etter pull (søskenets pull kan tas i I3 hvis søskenrepoet +ikke røres i I1 — da gjelder «begge grønne» fra I3) · kryss-sjekk-tabellen komplett · +`uv run ruff check .` + `mypy` grønne. + +## I2 — MAF-referanseimplementasjon: filkatalog/CSV (offline) + +**Mål:** Første implementasjonsøkt er offline-kildetypen (brief-krav): manifest → CSV-konnektor +→ materialisert OKF-bundle, hele veien load-bearing-testet. Lukker nøkkelantakelse 2. + +**Innhold:** manifest-kontrakt (pydantic, fail-fast, uten nettverk), CSV-/filkatalog-konnektor, +materialisering → OKF-bundle med provenance-frontmatter + index-generering. TDD. + +**Verifisering:** golden-uttrekk-test (fixture + fast timestamp → forventet bundle, +bit-deterministisk) · load-bearing: provenance-detach → rød; generert bundle navigerbar via +UENDRET `okf.py` → rød ellers (varig versjon av planleggingsøktas ad hoc-bevis); manifest som +mapper til `type: verdict` → avvist (rød uten reservasjonen); re-ingest over bundle med +promotert verdict → verdicten + index-lenken overlever (rød ellers) · suite grønn uten +nøkkel/nettverk · mypy/ruff grønne. + +## I3 — D7-speil: filkatalog/CSV **[GATET: annet repo]** + +**Mål:** Samme kontrakt konsumert uendret fra commons i søskenrepoet +(`/Users/ktg/repos/portfolio-optimiser-claude`) — beviser at ingest-spec-en faktisk er delt. + +**Innhold:** forankres i søskenets STATE + egen `/trekbrief`. Commons-pull der; egen impl mot +samme spec; speiltester av I2s load-bearing-sett; søskenets framework-guard utvides +tilsvarende. Re-verifiser SDK-kroker søk-først (API-drift-risiko). + +**Verifisering:** golden-uttrekk bit-identisk konsumert · speiltester røde ved detach · +søskensuite grønn uten nøkkel/nettverk. + +## I4 — SQL-kilde MAF (sqlite-fixture, null nettverk) + +**Mål:** Andre kildetype på MAF-siden, mot I1-skjemaet uten spec-endring. + +**Innhold:** sqlite-konnektor mot det polymorfe manifest-skjemaet. Ingen spec-endring +forventet; hvis drift likevel oppdages: egen GATET commons-runde FØR økta fortsetter +(ramme-regelen). + +**Verifisering:** som I2 for SQL: golden-uttrekk (fixture-db + fast timestamp → +bit-deterministisk bundle) · load-bearing-settet · suite grønn uten nøkkel/nettverk. + +## I5 — SQL-kilde D7-speil **[GATET: annet repo, som I3]** + +**Mål/Innhold:** speiler I4 i søskenrepoet. + +**Verifisering:** som I3 for SQL. + +## I6 — HTTP/MCP som demonstrert extension point, MAF-only **[GATET: nettverks-kapabilitet innføres — lokal mock, ingen live-kilde]** + +**Mål:** Extension-point-mønsteret demonstrert ærlig: HTTP/MCP-konnektor mot LOKAL mock, +gated bak opt-in-nettverksflagget. Ingen live-kilde — briefens «første live kilde»-gate +forblir ukonsumert i hele programmet (målbildet §11). + +**Innhold:** lokal mock i test (in-process/localhost, bak flagget); dokumentér mønsteret i +`docs/extending.md` med D7-krok-pekere (`create_sdk_mcp_server`). + +**Verifisering:** uten flagg → fail-fast nekt (rød hvis gaten detaches) · suite grønn HELT +uten nettverk · ingen artefakt påstår live-integrasjon (grep). + +## I7 — Program-avslutning: dokumentasjon + statusrapport + +**Mål:** Alt dokumentert sannferdig; programmet lukket med rapport. + +**Innhold:** README/`docs/extending.md`-oppdatering i begge repo — der D7-omtalen AVGRENSES +til det D7 faktisk har (CSV + SQL; HTTP/MCP kun pekere); kort norsk statusrapport (hva er +bevist / ikke bevist — ærlighets-regelen). + +**Verifisering:** verifiseringslogg i rapporten (hver påstand → kommando/kilde) · grep-sjekk: +ingen artefakt påstår HTTP/MCP-støtte i D7 eller live-kilde-integrasjon · begge repos suiter +grønne. + +--- + +## Nøkkelantakelser (med eksplisitt test) + +1. **Maskingenerert bundle passerer eksisterende OKF-kode** → testet ad hoc 2026-07-03 + (syntetisk bundle med provenance-frontmatter gjennom `navigate_bundle`/`bundle_context`: + ukjente felt bevart, kontekst rendret). Efemert bevis — den VARIGE load-bearing-testen + skrives i I2. +2. **Ingest-manifest kan valideres fail-fast uten nettverk** → antakelse med belegg + (`contracts.py`-mønsteret er ren in-process), merket RISIKO til I2 lukker den med varig + test (rød på malformet manifest, null nettverk). +3. **Commons-subtree-flyten fungerer** → bevist i S4 (PULL-ONLY-regimet etablert og dokumentert). +4. **D7s tekniske kroker dekker behovet** (`@tool`/`create_sdk_mcp_server`) → verifisert i + D7-S5 per briefen; re-verifiseres søk-først i I3 (API-drift-risiko). + +## Verifisering (planen som helhet) + +- Ingen økt erklæres ferdig uten at øktas verifiseringskriterier er kjørt og grønne. +- Program-sluttkriterium: begge stacker materialiserer identiske golden-uttrekk fra delt spec + (CSV + SQL); HTTP/MCP demonstrert MAF-only mot mock; alle load-bearing-krav i målbildet §9 + bevist røde ved detach; begge repos suiter grønne uten nøkkel/nettverk — og ingen artefakt + påstår mer enn koden gjør (live-kilder, D7-HTTP, LLM-atferd).