portfolio-optimiser/.claude/projects/2026-07-04-i7-program-avslutning/plan.md
Kjell Tore Guttormsen 3957354408 docs(i7): trekbrief + trekplan for program-avslutning — execute parked (fresh session)
Brief (framing=preserve, 0 research, validator PASS, brief-reviewer PROCEED) +
plan (3 steg, v1.7 strict PASS). plan-critic fanget 1 BLOCKER (README real-source
overclaim) → adressert; scope-guardian ALIGNED. Execute parkert til fersk økt på
20% kontekst. README/extending URØRT denne økta.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJET4jzpqykqEaQKQDqbS6
2026-07-04 20:41:02 +02:00

286 lines
19 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.

# I7 — Program-avslutning (ingest): dokumentasjon + felles statusrapport
> **Plan quality: APPROVE_WITH_NOTES** — plan-critic ga REVISE (73/C) pre-revisjon på 1 blocker
> (README real-source-overclaim); blocker + alle 2 major/4 minor adressert (se Revisions). Scope-
> guardian ALIGNED (0 creep). Post-revisjon utførbar.
>
> Generated by trekplan v5.9.1 on 2026-07-04 — `plan_version: 1.7`
## Context
Ingest-programmet (I1I6) er levert: den framework-nøytrale spec-en i commons, file/CSV (I2/I3)
og SQL (I4/I5) på begge stacker med bit-identiske golden-uttrekk, og HTTP demonstrert som
extension point MAF-only mot lokal mock (I6). I7 er det planlagte avslutningssteget (sesjonsplan
§I7): gjøre dokumentasjonen sannferdig og lukke programmet med én ærlig norsk statusrapport av
hva som er bevist — og ikke bevist. Motivasjonen er tillit (brief Intent): rammeverket publiseres
på Forgejo for alle som har MAF, og en artefakt som overselger eroderer tilliten. Bindende føring
er ærlighets-regelen (målbilde §11 «Stack-mapping (ærlighets-avgrenset)» + §0). Ground-truth-
utforsking avdekket at README-status er STALE («ingest specified but not yet implemented») og at
en presis to-akset «live»-distinksjon må inn i rapporten (live data-kilde vs live modell-kjøring).
## Architecture Diagram
```mermaid
graph TD
subgraph "I7 — docs-only, MAF-repo + felles rapport"
R[README.md<br/>fiks stale ingest-status] -->|honest status| OUT[Ingen overselgende artefakt]
E[docs/extending.md<br/>skjerp D7-grense: CSV+SQL bygget,<br/>HTTP/MCP MAF-only + peker] -->|SC1 grep-gate| OUT
REP[docs/rapport/2026-07-04-<br/>program-statusrapport-ingest.md<br/>NY: exec-sammendrag + bevist/ikke-bevist<br/>+ verifiseringslogg] -->|SC2/SC3| OUT
EV[Evidens read-only:<br/>pytest/ruff/mypy MAF · D7-suite · D7 S10-live-run] -.cites.-> REP
end
style REP fill:#2d5,color:#000
style EV fill:#eee,color:#000
```
## Codebase Analysis
- **Tech stack:** Python ≥3.10, MAF, `uv`, pytest/ruff/mypy. Docs i markdown.
- **Key patterns:** ærlighets-avgrenset dokumentasjon (målbilde §0/§11); named markdown-lenker;
norsk for leder-/forretningsdocs, engelsk for README/utviklerdocs (docs-språkregel).
- **Relevant files (verifisert under utforsking):**
- `README.md` — Status-blokka (linje 913) sier «The ingest layer (real data sources) is
specified but **not yet implemented**»; linje 9092 sier «will materialize» (futurum). Begge
STALE etter I1I6.
- `docs/extending.md` — har allerede http-familien (linje 55101) + D7-MCP-peker
(`create_sdk_mcp_server`, linje 92101) fra I6. D7-grensa kan skjerpes (eksplisitt «CSV+SQL
bygget; HTTP/MCP MAF-only demo, ikke shipped D7-connector»).
- `docs/rapport/2026-07-03-sammenligningsrapport.md` — eksisterende stack-sammenligning
(refereres, dupliseres ikke).
- `docs/plan/2026-07-03-sesjonsplan-ingest.md` (§I7) + `docs/plan/2026-07-03-maalbilde-ingest-lag.md`
(§0/§11) — kilder for scope + ærlighets-regel.
- **Reusable code:** ingen kode — docs-økt. Gjenbruker eksisterende rapport-mønster
(sammenligningsrapporten) + verifiseringslogg-formen fra KTG-verifiseringsplikten.
- **External tech (researched):** ingen (brief: 0 research-topics).
- **Recent git activity:** I6 lukket på `72cb15f` (review WARN akseptert). I1I6-commits
`e4ee8bd..696f19a` (CSV/SQL/HTTP + golden + load-bearing). Ren tree ved oppstart.
### D7-søsken-fakta (read-only, grunner rapporten — INGEN skriving/commit der)
- `/Users/ktg/repos/portfolio-optimiser-claude/README.md` sier: **programmets ene budsjetterte
live *modell*-kjøring (S10) er utført + validert 2026-07-03** (linje 13, 76, 121125), og at
http-kilden er «an optional extension point, **not built in** [...] this repo ships no network
connector and no live-source integration» (linje 114118). D7 har CSV+SQL-connectorer (I3/I5).
- D7 har **ingen `docs/rapport/`-mappe** → bekrefter «én felles rapport her» (brief-valg).
## Implementation Plan
Docs-økt: ingen tester (`Test first` utelatt), `Verify` er konkrete grep/kjør-kommandoer. TDD
Iron Law gjelder produksjonskode, ikke dokumentasjon (brief Non-Goal).
### Step 1: Fiks stale ingest-status i README (specified→implementert, uten overclaim)
- **Files:** `README.md`
- **Changes:** Oppdater Status-blokka (linje 913): erstatt «The ingest layer (real data sources)
is specified but not yet implemented» med en formulering som skiller **kapabilitet-implementert**
fra **kjørt-mot-ekte-kilde**: ingest-laget er implementert — file/CSV og SQL på begge stacker
(bit-identiske golden-uttrekk fra delt spec), HTTP som **MAF-only demonstrert extension point mot
en lokal mock** — og **kun øvd mot committede fixtures/golden; ingen bundle er materialisert fra
en live-kilde**. Behold «no live-model run yet» for MAF-siden (fortsatt sant — offline skriptet
sim). **(BLOCKER-fiks, plan-critic):** linje 9092 — IKKE endre «will materialize» til et bart
«materializes … today» (det ville motsi «hand-curated today» og overselge: bundelene er fortsatt
hand-curated, connectorene har kun kjørt mot fixtures). Skriv i stedet en reconciled, ærlig
setning: de medfølgende eksemplene er hand-curated; ingest-laget som materialiserer en bundle fra
en kilde (file/CSV + SQL, HTTP som MAF-only demonstrert extension point) via et deterministisk,
schema-validert manifest FØR loopen er **implementert og øvd mot committede fixtures — ingen
bundle er ennå materialisert fra en live-kilde**. Ikke rør Karpathy/OKF-seksjonene. Ingen påstand
om at D7 har HTTP/MCP. Sibling-presiseringen «file/CSV and SQL mirror the MAF stack» er valgfri —
ta den KUN med hvis den ikke trigger Step 1s egen `(claude).{0,40}(http|mcp)`-grep (den gjør den
ikke: ingen http/mcp-nærhet).
- **Reuses:** eksisterende Status-blockquote-stil i `README.md`; ærlighets-formuleringen fra
`docs/extending.md` linje 8890 («local mock — no live source»).
- **Verify:** `grep -c "not yet implemented" README.md``0`; `grep -c "local mock" README.md`
`≥1`; `grep -niE '(d7|claude).{0,40}(http|mcp).{0,20}(support|støtte|built)' README.md`
ingen treff som påstår D7 HTTP/MCP-støtte. **Honesty-gate (major, plan-critic):**
`grep -niE '(materializ|materialiser)[^.]{0,40}(real|live|ekte)[^.]{0,20}(source|kilde)' README.md`
→ ingen treff som påstår materialisering fra ekte/live kilde som gjort; gjennomlesning bekrefter
«no bundle … materialized from a live source»-klausulen er til stede (kapabilitet ≠ live-bruk).
- **On failure:** revert — `git checkout -- README.md`
- **Checkpoint:** `git commit -m "docs(i7): refresh stale README ingest status — implemented (CSV+SQL both stacks, HTTP MAF-only demo)"`
- **Manifest:**
```yaml
manifest:
expected_paths:
- README.md
min_file_count: 1
commit_message_pattern: "^docs\\(i7\\): refresh stale README ingest status"
bash_syntax_check: []
forbidden_paths:
- docs/extending.md
must_contain:
- path: README.md
pattern: "local mock"
```
### Step 2: Skjerp D7-grensa i extending.md (CSV+SQL bygget; HTTP/MCP MAF-only + peker)
- **Files:** `docs/extending.md`
- **Changes:** I «D7 sibling hook»-underseksjonen (linje 92101), gjør grensa eksplisitt per
målbilde §11: D7 bygde **file/CSV og SQL**-connectorene (speiler I3/I5); **HTTP/MCP er
demonstrert KUN på MAF-siden** mot lokal mock, og `create_sdk_mcp_server` er en **dokumentert
krok** en deployer ville brukt — **ikke en shipped D7-connector**; ingen D7-HTTP-økt planlagt.
Legg til «MAF-only» eksplisitt der HTTP/MCP nevnes for D7. Ikke endre http-manifest-avsnittene
(linje 5590) — de er korrekte fra I6.
- **Reuses:** eksisterende D7-hook-avsnitt (linje 92101); målbilde §11-formuleringen verbatim
som kilde.
- **Verify:** `grep -c "MAF-only" docs/extending.md` → `≥1`;
`grep -niE 'D7.{0,30}(built|shipped|implement).{0,20}(http|mcp)' docs/extending.md` → ingen
treff som påstår D7 bygde HTTP/MCP.
- **On failure:** revert — `git checkout -- docs/extending.md`
- **Checkpoint:** `git commit -m "docs(i7): sharpen D7 boundary in extending.md — CSV+SQL built, HTTP/MCP MAF-only"`
- **Manifest:**
```yaml
manifest:
expected_paths:
- docs/extending.md
min_file_count: 1
commit_message_pattern: "^docs\\(i7\\): sharpen D7 boundary"
bash_syntax_check: []
forbidden_paths:
- README.md
must_contain:
- path: docs/extending.md
pattern: "MAF-only"
- path: docs/extending.md
pattern: "create_sdk_mcp_server"
```
### Step 3: Skriv felles norsk program-statusrapport (hybrid, verifiseringslogg)
- **Files:** `docs/rapport/2026-07-04-program-statusrapport-ingest.md` (new file)
- **Changes:** Skriv rapporten på norsk i hybrid form:
1. **Executive-sammendrag** (KI-seksjon/ledelse): hva ble bygget (ingest-lag på begge stacker),
hva er bevist, hva gjenstår — kort, uten salgsspråk.
2. **Bevist / ikke bevist** (ærlighets-regel, målbilde §11). MÅ inneholde den **to-aksede
«live»-distinksjonen**: (a) **live data-KILDE** (http mot ekte endpoint) — ALDRI gjort,
ingen stack; «første live kilde»-gaten ukonsumert. (b) **live MODELL-kjøring** (ekte LLM) —
IKKE på MAF (offline skriptet sim beviser plumbing + deterministisk ryggrad, ikke levende
LLM-atferd), **DONE én gang på D7 (S10, budsjettert, validert 2026-07-03)**. Per connector:
CSV+SQL bevist begge stacker (golden bit-identisk); HTTP MAF-only demo mot mock; MCP kun
dokumentert krok.
3. **Verifiseringslogg**: tabell der HVER påstand → kjørbar kommando ELLER fil-/commit-sitering.
Kjør og fang faktisk output for: MAF-suite (`uv run pytest`), `uv run ruff check .`,
`uv run mypy src`, SC1-grep-gaten, og D7-suite **read-only** i søsknet
(`cd /Users/ktg/repos/portfolio-optimiser-claude && uv run pytest`; skill «suite rød» fra
«kunne ikke kjøres offline» hvis ikke `uv sync`-et). Siter D7 S10-live-run fra D7s egen
README (read-only). Referér `sammenligningsrapport.md` (ikke dupliser).
- Ingen salgsspråk (KTG-verifiseringsplikt): unngå «fullt ut», «uten unntak». Named
markdown-lenker til lokale filer.
- **Reuses:** rapport-mønster fra `docs/rapport/2026-07-03-sammenligningsrapport.md`;
verifiseringslogg-formen fra KTG-global «Verifiseringsplikt».
- **Verify:** fila finnes;
`grep -c "Verifiseringslogg" docs/rapport/2026-07-04-program-statusrapport-ingest.md` → `≥1`;
`grep -ciE "ikke bevist" docs/rapport/2026-07-04-program-statusrapport-ingest.md` → `≥1`;
`grep -niE '(live)[^.]{0,40}(kilde|source|integrasjon)' docs/rapport/2026-07-04-program-statusrapport-ingest.md`
→ hvert treff er negasjon («ingen live-kilde»), ingen påstand om live-kilde-integrasjon;
gjennomlesning: 0 rader i verifiseringsloggen uten kommando/kilde. **SC5 per-steg (minor):** kjør
og fang `uv run ruff check .` (exit 0) + `uv run mypy src` (exit 0) her, siter faktiske exit-koder
i loggen (ikke bare i ende-til-ende-sjekken).
- **On failure:** revert — `git checkout -- docs/rapport/2026-07-04-program-statusrapport-ingest.md` (slett fila hvis untracked).
**Circuit breaker (minor, plan-critic):** hvis MAF-suiten (SC4) er RØD ved evidens-innsamling —
STOPP og eskaler; skriv ALDRI en rapport som påstår «grønn offline» over en rød suite. (D7 rød/
ikke-kjørbar er derimot forventet-håndtert: rapporteres som «ikke bevist» per SC6, ikke en stopp.)
- **Checkpoint:** `git commit -m "docs(i7): program status report — bevist/ikke-bevist + verifiseringslogg (I7)"`
- **Manifest:**
```yaml
manifest:
expected_paths:
- docs/rapport/2026-07-04-program-statusrapport-ingest.md
min_file_count: 1
commit_message_pattern: "^docs\\(i7\\): program status report"
bash_syntax_check: []
forbidden_paths:
- README.md
- docs/extending.md
- src/portfolio_optimiser/okf.py
must_contain:
- path: docs/rapport/2026-07-04-program-statusrapport-ingest.md
pattern: "Verifiseringslogg"
- path: docs/rapport/2026-07-04-program-statusrapport-ingest.md
pattern: "S10"
```
## Alternatives Considered
| Approach | Pros | Cons | Why rejected |
|----------|------|------|--------------|
| Full 7-agent exploration-swarm | Prosess-symmetri | Analyserer Python-arkitektur irrelevant for docs; token-sløsing | /trekplan hard rule «Adaptive/Honesty» — docs-økt, målrettet utforsking i stedet |
| Egen D7-lokal rapport + MAF-rapport | Polyrepo-symmetri | Dupliserer «bevist»-narrativ, tråding mellom to | Operatør valgte «én felles rapport her» (brief) |
| Slå README+extending sammen til én commit | Færre commits | Blander to distinkte finpuss; svakere headless-revert | To steg = to rene reverts + tydeligere manifest-gate |
| Skriv rapport FØR docs-fiks | — | Rapporten ville sitert ustabile/stale docs | Rapport sist (Step 3): siterer ferdig-finpusset README/extending |
## Test Strategy
- **Framework:** ingen nye tester — docs-økt. Eksisterende suite er regresjonsvernet.
- **Existing patterns:** load-bearing-tester (I1I6) forblir grønne; I7 rører ikke `src/`,
`okf.py` eller `shared/`.
- **New tests in this plan:** 0. Verifikasjon er grep-gater + suite-grønn-sjekk (brief SC1SC6).
- **Manuell verifisering:** SC1/SC3 har en menneskelig klassifiseringssteg (docs-prosa) med
bundet objektiv proxy (grep + hver logg-rad har kilde) — akseptert av brief-reviewer.
## Risks and Mitigations
| Priority | Risk | Location | Impact | Mitigation |
|----------|------|----------|--------|------------|
| Medium | D7-suite ikke `uv sync`-et → pytest feiler av miljøgrunn | søsken-repo | «D7 rød» feilrapporteres | SC6: skill «rød» fra «kunne ikke kjøres offline» eksplisitt i rapporten |
| Medium | Conflate live-kilde vs live-modell-kjøring | rapport §bevist | Ærlighets-brudd (over- eller under-claim) | Eksplisitt to-akset distinksjon påkrevd i Step 3; D7 S10 sitert fra D7-README |
| Low | Utilsiktet endring i søsken-repo | D7 | Polyrepo-grensebrudd | Hard rule: D7 er READ-ONLY; ingen commit/write der; forbidden i scope-fence |
| Low | README-edit rører OKF/Karpathy-prosa | README.md | Scope-drift | Step 1 Changes avgrenser eksakt til Status-blokk + linje 9092 |
| Low | Premiss «237/4» sitert uverifisert | rapport | Feil tall i logg | Step 3 kjører `uv run pytest` og fanger FAKTISK output (premiss-verifisering) |
## Assumptions
| # | Assumption | Why unverifiable | Impact if wrong |
|---|-----------|-----------------|-----------------|
| 1 | D7-suiten er grønn offline (uv-synced) | Ikke kjørt ennå (execute-tid) | SC6 rapporterer «ikke bevist» framfor å fikse — dekket |
| 2 | Sammenligningsrapporten dekker stack-sammenligning | Antatt fra tittel/størrelse | Rapport må evt. si mer selv; leses i execute før referanse |
| 3 | README/extending trenger finpuss, ikke omskriving | Bekreftet: I6 la http+D7-peker | Ingen — begge filer lest, delta bekreftet |
## Verification
*Ende-til-ende integrasjonssjekker på tvers av steg (per-steg manifest kjøres av trekexecute).*
- [ ] `grep -c "not yet implemented" README.md` → `0` (SC1: stale-status fjernet)
- [ ] **SC1-grep (a), briefens fulle scope** `grep -rniE '(d7|claude[- ]?sdk).{0,60}(http|mcp)' README.md docs/` → manuell klassifisering: HVERT treff er enten (i) eksplisitt «MAF-only / demonstrert extension point», (ii) ren D7-krok-peker (`create_sdk_mcp_server`), eller (iii) plan-/målbilde-prosa som FORBYR/negerer D7-HTTP (§11, sesjonsplan) — INGEN treff påstår D7 HTTP/MCP-*støtte* som bygget
- [ ] **SC1-grep (b), live-source, briefens verbatim** `grep -rniE '(live|produksjon|production).{0,30}(kilde|source|integrasjon|integration)' README.md docs/rapport/ docs/extending.md` → hvert treff er negasjon/forbud («ingen live-kilde», «no live source», «not built in»), INGEN påstand om live-kilde-integrasjon (dekker README + de to ed.-filene, ikke bare rapporten)
- [ ] `test -f docs/rapport/2026-07-04-program-statusrapport-ingest.md` → fila finnes med exec-sammendrag + «bevist/ikke bevist» + «Verifiseringslogg» (SC2)
- [ ] Gjennomlesning: 0 rader i verifiseringsloggen uten kjørbar kommando eller fil-/commit-sitering (SC3)
- [ ] `uv run pytest` → exit 0, 0 failed (uten nøkkel/nettverk) (SC4)
- [ ] `uv run ruff check .` exit 0 og `uv run mypy src` exit 0 (SC5)
- [ ] `cd /Users/ktg/repos/portfolio-optimiser-claude && uv run pytest` → exit 0 offline, sitert read-only, INGEN commit der (SC6)
## Estimated Scope
- **Files to modify:** 2 (`README.md`, `docs/extending.md`)
- **Files to create:** 1 (`docs/rapport/2026-07-04-program-statusrapport-ingest.md`)
- **Complexity:** low (docs-økt; ingen kode, ingen nye tester; hovedrisiko = ærlighets-presisjon)
## Plan Quality Score
| Dimension | Weight | Score | Notes |
|-----------|--------|-------|-------|
| Structural integrity | 0.15 | 92 | 3 steg, ren avhengighet (1,2 → 3), ≤5 så ingen Execution Strategy |
| Step quality | 0.20 | 90 | Kirurgiske changes, eksakte linjer, manifest per steg |
| Coverage completeness | 0.20 | 94 | SC1SC6 alle sporet til steg + Verification |
| Specification quality | 0.15 | 90 | Konkrete grep/kjør-kommandoer, ingen placeholders |
| Risk & pre-mortem | 0.15 | 90 | Live-akse-conflate + D7-miljø fanget |
| Headless readiness | 0.10 | 90 | On failure + Checkpoint per steg |
| Manifest quality | 0.05 | 88 | Gyldige manifester; innholds-absens dekkes av Verify (grep -c 0) |
| **Weighted total** | **1.00** | **91** | **Grade: A** |
**Adversarial review:**
- **Plan critic:** REVISE (pre-revisjon 73/C) — 1 blocker, 2 major, 4 minor. Blocker (README
real-source-overclaim) + alle major/minor adressert i Revisions under. Post-revisjon: blocker lukket.
- **Scope guardian:** ALIGNED — 0 creep, 2 minor (SC1-dekning). Adressert (Rev 3). Polyrepo-grense
(D7 read-only) bekreftet respektert.
## Revisions
| # | Finding (severity) | Kilde | Resolution |
|---|--------------------|-------|------------|
| 1 | README linje 9092 «materializes today» overselger real-source, motsier «hand-curated» (**blocker**) | plan-critic | Step 1 Changes omskrevet: skill kapabilitet-implementert fra kjørt-mot-ekte-kilde; reconciled setning «implementert og øvd mot committede fixtures — ingen bundle materialisert fra live-kilde». Ikke bar nåtid. |
| 2 | Grep-gater dekker ikke live-*bruk*-overclaim-vektoren (**major**) | plan-critic | Step 1 Verify: ny honesty-gate-grep (`materializ…real/live…source` → 0) + gjennomlesnings-sjekk på «no live source»-klausul. |
| 3 | SC1 narrowet fra briefens `docs/` til 3 filer; live-source-grep manglet i top-level Verification (**major/minor ×3**) | plan-critic + scope-guardian | Verification: begge SC1-grep gjenopprettet verbatim fra brief (hele `docs/`-treet + live-source over README/extending/rapport), med manuell klassifiserings-regel. |
| 4 | Step 3 Verify `<fil>`-placeholder ikke headless-kjørbar (**minor**) | plan-critic | Erstattet med literal sti i alle tre grep. |
| 5 | Ingen circuit breaker hvis MAF-suite rød ved Step 3 (**minor**) | plan-critic | Step 3 On failure: STOPP+eskaler hvis MAF-suite rød; aldri «grønn»-rapport over rød suite. |
| 6 | SC5 (ruff/mypy) kun ende-til-ende, ikke per-steg (**minor**) | plan-critic | Step 3 Verify: kjør + siter faktiske exit-koder i loggen. |
| 7 | Step 1 valgfri sibling-CSV+SQL-claim = scope-nudge (**minor**) | plan-critic | Step 1 Changes: markert valgfri, betinget av at den ikke trigger egen http/mcp-grep. |