The context sets, the packaged knowledge bases and the example bundles are replaced by one fictitious example set about IT operations in an invented organisation: three context sets (serverrom-2027, driftsavtale-2027 and the two-base drift-og-avtale-2027), two synthetic knowledge bases under src/portfolio_optimiser/data/kunnskapsbaser and two example bundles under src/portfolio_optimiser/data/bundles. Numbers, codes and structural values in tests and fixtures are kept; names, ids and wording change. Dated measurement documents that only recorded runs on the replaced material are deleted. Gate figures measured on the new set are not comparable with earlier ones. The exclusion gate from the previous commit is green: 0 tracked files hit outside the shared/ subtree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
634 lines
48 KiB
Markdown
634 lines
48 KiB
Markdown
# Kunnskapsbasen for én konkret kjøring
|
||
|
||
Dette dokumentet er for **fagpersonen** som skal planlegge en kjøring mot et konkret prosjekt, og
|
||
for **den tekniske personen** som skal bygge kunnskapsbasen den kjøringen leser. Den første jobben
|
||
er alltid den samme: sette sammen en kunnskapsbase som gir riktig kontekst for *nettopp denne*
|
||
kjøringen. Det er den jobben som beskrives her — fra bestillingen til en base som er klar til å
|
||
kjøres.
|
||
|
||
Tre dokumenter står rundt dette:
|
||
|
||
- [knowledge-base-recipe.md](knowledge-base-recipe.md) *(engelsk)* beskriver **prosessen**: de to
|
||
rollene, de fire fasene (inventar → skjelett → frø → iterer) og den ærlige forventningen om at en
|
||
god base tar 1–2 uker. Det gjentas ikke her. Dette dokumentet svarer på det oppskriften ikke
|
||
svarer på: *hvordan går man fra en gitt oppgave til en riktig sammensatt base?*
|
||
- [bestille-en-kjoring.md](bestille-en-kjoring.md) beskriver oppdragsfila — det som kommer **inn**
|
||
til kjøringen. Dette dokumentet møter den i den andre enden: basen oppdraget skal leses mot.
|
||
- [ekspert-svar.md](ekspert-svar.md) beskriver dommen — det som kommer **ut**, og som gjør neste
|
||
base bedre.
|
||
|
||
> **Merkekonvensjon.** Hver teknisk påstand i dokumentet er enten **VERIFISERT** (med filen,
|
||
> linjen eller kommandoen som viser det — samlet i [verifiseringsloggen](#8-verifiseringslogg)
|
||
> nederst) eller **ANTATT** (en tolkning eller en anbefaling som ikke følger av noe målt).
|
||
> Konvensjoner som bare er observert i eksempelbasene, ikke normert i spesifikasjonen, er merket
|
||
> **KONVENSJON**. Ingenting her er en påstand om at en levende modell ville resonnert godt over
|
||
> basen; det er en påstand om hva basen må inneholde for at kjøringen skal kunne starte, lese
|
||
> riktig og dømme mot ekte tall.
|
||
|
||
## Det korte svaret
|
||
|
||
**1. Hvilke kategorier trengs?** Fire, og de skiller seg på *hva de følger*:
|
||
|
||
| Kategori | Følger | Hvem eier den |
|
||
|---|---|---|
|
||
| **Prosjektlaget** | prosjektet / anlegget | prosjekteier og driftsorganisasjon |
|
||
| **Faglaget** | fagområdet (klientpark, kjøling, bygg …) | fagmiljøet |
|
||
| **Erfaringslaget** | organisasjonen, over tid | fagekspertene som avgir dommer |
|
||
| **Kjøringslaget** | denne ene bestillingen | bestilleren |
|
||
|
||
Det er **én kunnskapsbase per prosjekt** (VERIFISERT: `shared/method-spec.md` §2). Prosjekt-,
|
||
fag- og erfaringslaget ligger *i* basen. Kjøringslaget ligger *ved siden av* — det er instruksen
|
||
for én kjøring og lagres aldri som kunnskap. Faglaget deles logisk på tvers av prosjekter i samme
|
||
fagområde, men **kopieres fysisk inn i hver base** — se [§2](#2-kategoriene-hva-følger-hva).
|
||
|
||
**2. Hvilke innholdstyper?** Seks markdown-typer og to tallfiler. Tabellen i
|
||
[§4](#4-innholdstypene) sier for hver av dem hvem som eier den, hvilken form fagpersonen leverer
|
||
den i, hva loopen bruker den til, og hva som skjer hvis den mangler. Den viktigste raden er
|
||
**`cost-baseline.json`**: mangler den, starter kjøringen uten et ord — og validatoren dømmer da bare
|
||
mot tall forslaget selv oppga (VERIFISERT ved kjøring, [§4.1](#41-den-skarpeste-mangelen-cost-baselinejson)).
|
||
|
||
**3. Hvordan ser det ut for et konkret prosjekt?** [§5](#5-klientparken-hos-eksempelvirksomheten-fra-bestilling-til-kjøreklar-base)
|
||
går gjennom klientparken til den oppdiktede Eksempelvirksomheten, fra oppdragsfila til en
|
||
kjøreklar base. Basen det ender i er sjekket inn (VERIFISERT:
|
||
`src/portfolio_optimiser/data/bundles/klientpark-energi/`, den leverte basen demoen leser).
|
||
|
||
## 1. Hva kjøringen leser, og hvorfor det avgjør hva basen må inneholde
|
||
|
||
Hva basen må inneholde er ikke en smakssak. Det følger av hvordan loopen leser den.
|
||
|
||
**Kjøringen navigerer, den søker ikke.** Den starter i `index.md`, følger lenkene derfra, og
|
||
leser hver fil den når. Det som står i brødteksten til `index.md` kommer **først og ordrett** inn
|
||
i det agentene leser; deretter kommer hver lenket fil som en egen seksjon `## <type>: <tittel>`
|
||
med hele brødteksten. Det finnes ingen stikkordssøk og ingen «relevante utdrag» — en fil leses
|
||
helt, eller ikke i det hele tatt (VERIFISERT: `shared/method-spec.md` §3 Steg 1;
|
||
`src/portfolio_optimiser/okf.py` `bundle_context`). Tre konsekvenser for den som bygger basen:
|
||
|
||
- **En fil uten lenke fra `index.md` finnes ikke** for kjøringen. Det gjelder også en fil som
|
||
ligger i riktig mappe med riktig type (VERIFISERT: `shared/ingest-spec.md` §2: «a generated
|
||
concept file without an index link is unreachable»).
|
||
- **En lenke ut av basen følges aldri.** Målet må ligge inne i basens egen mappe; en lenke til en
|
||
nabobase eller et delt fagbibliotek hoppes stille over, uten feilmelding (VERIFISERT:
|
||
method-spec §3 Steg 1, «a target resolving outside the bundle is skipped»). Det er grunnen til
|
||
at faglaget kopieres inn, ikke lenkes til.
|
||
- **Mengde er ikke kvalitet.** Alt som lenkes leses i sin helhet, så ti sider støy koster like mye
|
||
oppmerksomhet som ti sider substans. Hold filene stramme (ANTATT: en anbefaling, ikke et krav i
|
||
koden).
|
||
|
||
**Én type holdes alltid utenfor lesekonteksten: `type: verdict`.** Tidligere dommer kommer aldri
|
||
inn som vanlig tekst. De hentes for seg, nøklet på *kandidaten*, og legges foran hypoteseprompten
|
||
som «tidligere dommer om lignende tiltak» (VERIFISERT: method-spec §3 Steg 1 «Experience fold»;
|
||
`okf.py` `context_files` ekskluderer typen). Kandidaten de nøkles på leses fra
|
||
`validator-input.json` — ikke fra bestillingen, og ikke fra hva agentene ender med å foreslå
|
||
(VERIFISERT: `src/portfolio_optimiser/run.py:634-638`). Det er derfor den fila er påkrevd.
|
||
|
||
**Ved siden av markdown-filene ligger to tallfiler.** `validator-input.json` må finnes — uten den
|
||
nekter kjøringen å starte (VERIFISERT ved kjøring, [§4.1](#41-den-skarpeste-mangelen-cost-baselinejson)).
|
||
`cost-baseline.json` er valgfri, og det er nettopp problemet: uten den starter kjøringen som om alt
|
||
var i orden.
|
||
|
||
**Målt på klientpark-basen:** mappa har 9 filer. Én er `index.md`, én er dommen, to er tallfiler —
|
||
og **5** er det kjøringen faktisk navigerer inn som kontekst (VERIFISERT:
|
||
`tests/golden/demo-transcript.stdout` linje 13, «navigerte konseptfiler (5)»).
|
||
|
||
> **Teknisk note.** Formatet basen bygges i heter Open Knowledge Format (OKF); i koden og
|
||
> spesifikasjonene kalles basen en *bundle*. Hver fil har en frontmatter (`---`-blokk) der
|
||
> `type:` er det ene påkrevde feltet. Koden leser svært få av de andre feltene: `title` (til
|
||
> seksjonsoverskriften og prosjektnavnet), `dimension` (når kjøringen er avgrenset til én
|
||
> kostakse), og på dom-filer `decision`, `description`, `realization_rate`,
|
||
> `expected_actual_saving_nok` samt den valgfrie nøkkel-trioen `affected_codes` /
|
||
> `measure_type` / `claimed_saving_nok`. Felt som `resource`, `measure_id`, `tags`, `gap_source`
|
||
> og `okf_version` i eksemplene leses **ikke** av koden — de er dokumentasjon for mennesker
|
||
> (VERIFISERT: `grep` over `src/portfolio_optimiser/` gir null treff på dem). De er likevel verdt
|
||
> å skrive: de gjør basen lesbar i Obsidian/VS Code, som er lesegrensesnittet i dag.
|
||
|
||
## 2. Kategoriene: hva følger hva
|
||
|
||
| Kategori | Innhold | Følger | Gjenbruk på tvers av prosjekter |
|
||
|---|---|---|---|
|
||
| **Prosjektlaget** | `index.md` · `type: project` · `type: hypothesis` · `validator-input.json` · `cost-baseline.json` | prosjektet | Nei. Skrives per prosjekt, fra prosjektets egne tall. |
|
||
| **Faglaget** | `type: methodology` · `type: reference` | fagområdet | Logisk ja, fysisk nei: **kopieres inn** i hver base og tilpasses. |
|
||
| **Erfaringslaget** | `type: verdict` (frø-dommer og promoterte dommer) · dom-innboksen utenfor basen | organisasjonen, over tid | Ja, gjennom dommene: en dom om et lignende tiltak i et annet prosjekt hentes inn når kandidatene ligner strukturelt. |
|
||
| **Kjøringslaget** | oppdragsfila (`--mandate`) · dimensjonsavgrensning (`--dimension-config`) · eksterne tjenester (`--mcp-config`) · tak (runder/tokens) | denne ene bestillingen | Nei. Instruks for én kjøring; «den lagrer seg ikke som kunnskap» ([bestille-en-kjoring.md](bestille-en-kjoring.md)). |
|
||
|
||
**Deles metode- og litteraturlaget på tvers?** Svaret er todelt, og begge halvdeler er målt.
|
||
|
||
*Logisk* er det samme fagstoff: alle tre eksempelbasene (kontorbygg, klientpark, kjøling i
|
||
driftssenteret) bærer en `metode-ipmvp-a.md`, og alle tre bygger på samme M&V-rammeverk (IPMVP
|
||
Option A). *Fysisk* er det tre ulike filer — målt 2026-08-21 til 40, 81 og 98 linjer — med hver
|
||
sin tittel: «for klientparken — og hvorfor de andre opsjonene er stengt», «for kjølestyring —
|
||
anlegget måler inngangssignalet, ikke energien» (VERIFISERT: `wc -l` + `diff` over de tre). Begge
|
||
de leverte eksempelbasene sier det selv i `index.md`: «metode- og kildelaget er **materialisert
|
||
inn her**, ikke lenket på tvers av bundler».
|
||
|
||
Grunnen er teknisk og ufravikelig: navigasjonen følger aldri en lenke ut av basen
|
||
([§1](#1-hva-kjøringen-leser-og-hvorfor-det-avgjør-hva-basen-må-inneholde)). Men det er også
|
||
faglig riktig: metoden *for klientparken* er ikke metoden *for kjøleanlegget*. I klientparken er
|
||
ex-post stengt fordi anlegget mangler måler; i kjøleanlegget er ex-ante stengt fordi anlegget ble
|
||
bygget før noen målte (VERIFISERT: de to `index.md`-filene). En delt fil ville måttet si begge deler og dermed ingen av
|
||
dem.
|
||
|
||
Praktisk betyr det (ANTATT, anbefaling): fagmiljøet eier en **mal** per fagområde; hver base får
|
||
en **tilpasset kopi**; når malen endres, er det en kjent jobb å gå gjennom kopiene. To kopier
|
||
drifter — det er prisen, og den skal være uttalt, ikke skjult.
|
||
|
||
**Prosjektlaget er det som byttes ut per prosjekt.** Begge de leverte eksempelbasene er fiktive i
|
||
begge lag — prosjektet og kildene tilhører den oppdiktede Eksempelvirksomheten — og sier selv
|
||
hvordan de er ment brukt: «En produksjons-deployer erstatter begge lagene med en ekte
|
||
kunnskapsbase og ekte kilder» (VERIFISERT: begge `index.md`). Kategoriskillet over står likevel:
|
||
prosjektlaget skrives fra det ene prosjektets tall, litteraturlaget fra fagområdets kilder.
|
||
|
||
**Erfaringslaget er reservert.** Ingen automatisk kilde kan skrive en `type: verdict`-fil inn i
|
||
basen; den eneste veien dit er en promotering av en dom et menneske har godkjent, eller en
|
||
håndskrevet frø-dom (VERIFISERT: `shared/ingest-spec.md` §3, «The verdict layer is RESERVED»).
|
||
Grunnen står i spesifikasjonen: hver dom-fil i basen leses som en *godkjent* dom, så en
|
||
datakilde som kunne skrive dem ville sprøytet maskingenererte «godkjenninger» rett inn i
|
||
læringen.
|
||
|
||
### Hvem eier hva
|
||
|
||
| Rolle | Leverer | Leverer ikke |
|
||
|---|---|---|
|
||
| **Prosjekteier / drift** | prosjektlaget: anleggsdata, kostlinjer, rammer, kandidat-tiltak | fag-metoden, dommene |
|
||
| **Fagmiljøet** | faglaget: målemetode, verifisert litteratur, kjente gap-mekanismer | prosjekttall |
|
||
| **Fageksperten(e)** | dommer — frø-dommer før første kjøring, innboks-dommer etter | innhold i basen direkte (de skriver innboksen; systemet leser) |
|
||
| **Bestilleren** | oppdragsfila: hensikt, tilnærminger, suksesskriterium | tall i basen; bestillingen styrer hva som vurderes, aldri hva som godkjennes |
|
||
| **Den tekniske personen** | bygger basen fra det de andre leverer: markdown, lenker, tallfilene, ev. ingest-manifest | fagvurderinger |
|
||
|
||
Fagpersonene leverer **filer i sine egne formater** — regneark, notater, PDF-er — aldri JSON eller
|
||
skjema ([knowledge-base-recipe.md](knowledge-base-recipe.md), «Who does what»). Oversettelsen til
|
||
basens format er den tekniske personens jobb, og i dag er den manuell
|
||
([§6](#6-ærlighetsdelen-hva-som-ikke-finnes-i-dag)).
|
||
|
||
## 3. Avgjørelsesdelen: spørsmålene du stiller fagpersonen
|
||
|
||
Hvert spørsmål avgjør én konkret del av basen. Still dem i denne rekkefølgen; svaret på de fire
|
||
første avgjør om kjøringen i det hele tatt kan starte.
|
||
|
||
**1. Hvilket prosjekt eller anlegg gjelder det, og hva skal det hete?**
|
||
Svaret blir prosjekt-ID-en. Den må være identisk tre steder — kommandolinjen,
|
||
`validator-input.json` og `cost-baseline.json` — ellers nektes kjøringen (VERIFISERT:
|
||
`run.py` `_project_from_bundle`, «bundle project_id … != requested»). Velg en ID uten mellomrom og
|
||
æøå; eksemplene bruker formen `KLIENTPARK-ENERGI` (KONVENSJON).
|
||
*Hvis svaret er «flere anlegg»:* én base per prosjekt. En portefølje er flere baser, kjørt i
|
||
porteføljemodus.
|
||
|
||
**2. Hvilke kostlinjer kan tiltakene komme til å treffe — og har vi faktiske tall for dem?**
|
||
Svaret blir `cost-baseline.json`: én linje per kostkode, med mengde og enhetspris. Hver kostkode
|
||
et forslag viser til må finnes her, og mengden og prisen forslaget oppgir må ligge innenfor
|
||
toleransen (`BASELINE_TOLERANCE_DEFAULT = 0.05`, altså 5 %) rundt baselinens verdi — ellers
|
||
avvises forslaget (VERIFISERT: `src/portfolio_optimiser/validator.py` `_reconcile_against_baseline`).
|
||
Derfor må fila dekke *alle* linjene bestillingens tilnærminger kan treffe, ikke bare den ene
|
||
kandidaten som er projisert.
|
||
*Hvis svaret er «vi har ikke tallene»:* kjøringen går likevel, og det er faren — se
|
||
[§4.1](#41-den-skarpeste-mangelen-cost-baselinejson). Skaff tallene, eller skriv inn i bestillingens
|
||
suksesskriterium at kjøringen er uforankret, så ingen leser et VALIDATED-utfall som mer enn det
|
||
er (ANTATT: en arbeidsregel, ikke noe koden håndhever).
|
||
|
||
**3. Hvilket tiltak er «det ene» vi projiserer?**
|
||
Basen holder én kandidat i `validator-input.json`: tiltaket, kostlinjene det virker på, den
|
||
modellerte besparelsen og usikkerhetsbåndet. Denne kandidaten er **nøkkelen til tidligere
|
||
dommer** — det er dens kostkoder, tiltakstype og beløpsstørrelse som avgjør hvilke dommer fra
|
||
tidligere kjøringer som hentes inn (VERIFISERT: method-spec §3 Steg 1, rangeringsformelen;
|
||
`run.py:634-638`). Den er ikke det som valideres i kjøringen — det er forslaget agentene lager
|
||
(VERIFISERT: `generate.py:491` validerer kandidaten fra modellen).
|
||
*Hvis fagpersonen vil ha flere tiltak vurdert:* det går gjennom bestillingen (spørsmål 5), og
|
||
hvert tiltak bør ha sin egen `type: hypothesis`-fil i basen. Men nøkkelen til tidligere dommer er
|
||
fortsatt den ene projiserte kandidaten — se
|
||
[§6](#6-ærlighetsdelen-hva-som-ikke-finnes-i-dag).
|
||
|
||
**4. Hvilke harde rammer gjelder?**
|
||
Minstekrav som setter et gulv ingen besparelse kan gå under, ting som ikke kan endres, budsjett-
|
||
og anskaffelsesrammer. Svaret skrives inn i `type: project`-fila. Klientpark-eksempelet har fire
|
||
som begrenser tiltakene: ytelseskravene, ytelsesreserven, at nattlig avstenging ikke kan antas,
|
||
og at tiltak vurderes inne i porteføljen (VERIFISERT:
|
||
`src/portfolio_optimiser/data/bundles/klientpark-energi/klientpark-energi.md`, «Rammer»). Agentene leser dem som tekst; koden håndhever dem ikke (ANTATT: det følger av at
|
||
koden bare leser `title` fra fila, men er ikke målt mot en levende modell).
|
||
|
||
**5. Hvilke tilnærminger vil du ha vurdert, og hvorfor?**
|
||
Svaret blir oppdragsfila — se [bestille-en-kjoring.md](bestille-en-kjoring.md). `description`-feltet
|
||
mates ordrett inn til modellen; det er der fagkunnskapen om *hvorfor* tiltaket er verdt å prøve
|
||
gjør en forskjell. Hver tilnærming bør ha et motstykke i basen: en `type: hypothesis`-fil med
|
||
parametere, modellert besparelse og kjent usikkerhet (KONVENSJON: begge de leverte eksempelbasene
|
||
har én hypothesis-fil per kandidat-tiltak; koden krever det ikke).
|
||
|
||
**6. Hvordan måles og verifiseres en besparelse i dette faget?**
|
||
Svaret blir `type: methodology`-fila. Den forteller agentene *hvorfor* modellert og faktisk
|
||
besparelse kan sprike, og hvilken måleopsjon som er åpen for dette anlegget. For klientparken er
|
||
svaret «IPMVP Option A, ved eliminasjon» fordi anlegget mangler måler (VERIFISERT: klientparkens
|
||
`metode-ipmvp-a.md`).
|
||
*Hvis fagmiljøet har en mal:* kopier og tilpass. Tilpasningen er ikke pynt — den delen som
|
||
forklarer hvilke opsjoner som er *stengt for dette anlegget* er prosjektspesifikk.
|
||
|
||
**7. Hva vet litteraturen om gapet mellom modellert og faktisk besparelse her?**
|
||
Svaret blir `type: reference`-fila. Skill skarpt mellom det som er målt på eget anlegg og det
|
||
som er lånt fra andre program — klientpark-eksempelet deler fila i «Del A — materiale om
|
||
klientparken» og «Del B — lånt materiale», og sier hvorfor: «Å blande de to ville gjort et lånt
|
||
tall til en måling av klientparken» (VERIFISERT: `kilder-klientpark-realisering.md`).
|
||
*Hvis svaret er «det finnes ingen måling på eget anlegg»:* skriv det. Et navngitt evidenshull er innhold;
|
||
et oppdiktet tall er forurensning.
|
||
|
||
**8. Finnes det tidligere erfaring med lignende tiltak — en dom noen faktisk har avgitt?**
|
||
Svaret blir en frø-dom: en `type: verdict`-fil med `decision`, en `description` som bærer
|
||
begrunnelsen, og der det finnes, `realization_rate` og `expected_actual_saving_nok`. Det er disse
|
||
feltene som når neste hypotese (VERIFISERT: `verdicts.py` `_verdict_rationale`).
|
||
*Hvis svaret er nei:* det er lovlig å starte med tom erfaring. Demoen starter slik — «fersk
|
||
kunnskapsbase, ingen tidligere dommer» (VERIFISERT: golden-transkriptet linje 11 og 14). Den
|
||
første ekte dommen kommer etter første kjøring, via innboksen.
|
||
|
||
**9. Skal kjøringen avgrenses til én kostakse?**
|
||
Hvis bestillingen gjelder for eksempel *energi* og ikke *vedlikehold*, settes en
|
||
dimensjonsavgrensning (`--dimension-config`). Da leser agentene bare filer som er merket med den
|
||
dimensjonen eller er umerket, og et forslag utenfor aksen avvises (VERIFISERT: `run.py:517-519`,
|
||
`728-740`; `okf.py` `bundle_context`). Filene merkes med `dimension:` i frontmatter.
|
||
*Hvis svaret er nei:* la det være. Ingen av eksempelbasene bruker `dimension:` (VERIFISERT:
|
||
`grep` gir null treff under `shared/examples/`).
|
||
|
||
**10. Ligger kildene som data — regneark, database, tjeneste — eller som dokumenter?**
|
||
Tabelldata kan hentes inn automatisk med et **ingest-manifest**: én JSON-fil som kobler en kilde
|
||
(CSV-katalog, SQL-database, HTTP-endepunkt eller MCP-tjeneste) til basen, og skriver én
|
||
markdown-fil per uttrekk (`ingest-<id>.md`) med provenance-stempel og lenke i `index.md`
|
||
(VERIFISERT: `shared/ingest-spec.md` §2, §4–§7). Manifestet kan aldri skrive en dom-fil, og det
|
||
kan aldri gi seg selv nettverkstilgang — den er et kjøreargument (VERIFISERT: §3, §8).
|
||
*Det ingest IKKE gjør:* skrive `validator-input.json` eller `cost-baseline.json`. Begge er
|
||
håndarbeid (VERIFISERT: [extending.md](extending.md), «An ingested bundle is not yet a runnable
|
||
bundle»). Dokumenter i fri form (PDF, notat) oversettes manuelt til markdown i dag.
|
||
|
||
**11. Hvem skal avgi dommen etterpå — og etter hvilke kostkoder?**
|
||
Svaret blir en innboks-mappe (`--verdict-dir`) eksperten skriver i, og eventuelt en rutingtabell
|
||
som sier hvilken ekspert som får hvilke forslag, etter kostkode-prefiks (VERIFISERT:
|
||
`src/portfolio_optimiser/hitl.py`, `route`). Innboksen skal være en annen mappe enn utboksen
|
||
kjøringen skriver til — de har motsatt eierskap ([ekspert-svar.md](ekspert-svar.md)).
|
||
|
||
## 4. Innholdstypene
|
||
|
||
| Innhold | Eies av | Fagpersonen leverer | Brukes i loopen til | Hvis den mangler |
|
||
|---|---|---|---|---|
|
||
| `index.md` | teknisk person, tekst fra prosjekteier | et avsnitt om hva prosjektet er og hvorfor dette fagområdet er valgt | brødteksten er det **første** agentene leser, ordrett; lenkene bestemmer hva som ellers leses | kjøringen nektes — «a bundle has no entry point without it» (VERIFISERT: method-spec §3 Steg 1) |
|
||
| `type: project` | prosjekteier / drift | anleggsregister, energibaseline, rammer — regneark og notat | kontekst: hva anlegget er, tallene det består av, gulvet ingen besparelse kan gå under | kjøringen starter; prosjektnavnet faller tilbake til ID-en (VERIFISERT: `run.py` `_project_from_bundle`); agentene resonnerer uten rammer (ANTATT) |
|
||
| `type: hypothesis` | prosjekteier + fagmiljø | kandidat-tiltak med parametere, modellert besparelse, hva som er usikkert, hva som er utledet | kontekst: forslagene agentene forbedrer i stedet for å finne opp; «Mapping til validatoren» forklarer tallfilene | kjøringen starter; forslagene står på oppdragsfilas `description` alene (ANTATT) |
|
||
| `type: methodology` | fagmiljøet | målemetode (M&V), hvilke opsjoner som er åpne og stengt for dette anlegget — notat eller mal | kontekst: hvorfor modellert ≠ faktisk, og hva som kan verifiseres etterpå | kjøringen starter; gap-resonnementet mangler i konteksten (ANTATT) |
|
||
| `type: reference` | fagmiljøet | verifisert litteratur med kilde og årstall; eget materiale skilt fra lånt | kontekst: tallgrunnlaget for realiseringsgrad og gap-mekanismer | kjøringen starter; en realiseringskorreksjon har ingenting å forankres i (ANTATT) |
|
||
| `type: verdict` (frø) | fageksperten | en tidligere dom: beslutning, begrunnelse, realiseringsgrad, forventet faktisk besparelse | **ikke** lest som kontekst; hentes som «tidligere dom» og legges foran hypoteseprompten | lovlig: første kjøring har null tidligere dommer (VERIFISERT: golden linje 14) |
|
||
| `validator-input.json` | teknisk person, tall fra prosjekteier | den ene projiserte kandidaten: kostlinjer, modellert besparelse, usikkerhetsbånd | prosjekt-ID-sjekk ved oppstart; nøkkelen tidligere dommer hentes med | **kjøringen nektes**, rc 1: «IR projection not found in bundle» (VERIFISERT ved kjøring, §4.1) |
|
||
| `cost-baseline.json` | prosjekteier / drift | prosjektets faktiske kostlinjer: kode → mengde × enhetspris | validatorens **steg 0**: hvert forslag avstemmes mot ekte linjer FØR noe annet regnes | **kjøringen starter, rc 0, uten melding** — gaten er uforankret (VERIFISERT ved kjøring, §4.1). Finnes fila men er feilformet: kjøringen nektes (VERIFISERT) |
|
||
| oppdragsfila | bestilleren | hensikt, tilnærminger med begrunnelse, suksesskriterium | hva som vurderes; kunngjøring før og oppgjør etter | kjøringen går uten bestilling: systemet foreslår selv; ingen kunngjøring, intet oppgjør per tilnærming |
|
||
| dom-innboksen | fageksperten | én JSON-fil per dom, etter kjøringen | merges inn før neste hypotese; lærer systemet noe | lovlig: ingen læring mellom kjøringene |
|
||
| dimensjonskonfig | bestilleren | hvilken kostakse kjøringen gjelder | avgrenser lesekontekst og avviser forslag utenfor aksen | lovlig: hele basen leses, ingen avvisning på akse |
|
||
| ingest-manifest | teknisk person | — (kobler en datakilde fagpersonen eier til basen) | skriver `ingest-*.md` med provenance før kjøringen | lovlig: alt er håndkuratert |
|
||
| MCP-konfig | bestiller + teknisk person | hvilke interne tjenester agentene får spørre, med navngitte verktøy | oppslag under debatten; alt som kan kontaktes står i kunngjøringen | lovlig: null nettverkskall (VERIFISERT: [bestille-en-kjoring.md](bestille-en-kjoring.md)) |
|
||
|
||
De fire typene `project`, `hypothesis`, `methodology` og `reference` er **KONVENSJON**: de står
|
||
i alle tre eksempelbasene, men ingen av de to spesifikasjonene nevner dem (VERIFISERT: `grep`
|
||
over `shared/method-spec.md` og `shared/ingest-spec.md` gir null treff). Spesifikasjonen normerer
|
||
bare at `type` er påkrevd, at `index.md` er inngangen, og at `verdict` er reservert. En base kan
|
||
bruke andre typenavn; de renderes som `## <type>: <tittel>` uansett. Hold dere til de fire likevel
|
||
— lesbarhet på tvers av baser er verdt mer enn friheten (ANTATT).
|
||
|
||
### 4.1 Den skarpeste mangelen: `cost-baseline.json`
|
||
|
||
Før denne fila fantes resonnerte hver del av validatoren bare om tall forslaget selv oppga, så
|
||
«an internally consistent hallucination passes» (VERIFISERT: `README.md`, «How it is set up»).
|
||
Fila forankrer gaten i prosjektets ekte kostlinjer: hvert forslag avstemmes mot dem i et steg 0
|
||
*før* løseren, og to ting avvises — en kostkode prosjektet ikke har, og en ekte kode med mengde
|
||
eller enhetspris utenfor 5 % av baselinens verdi (VERIFISERT: `validator.py:154-190`, `:210-214`).
|
||
|
||
Men fila er **valgfri** på bundle-stien, og fraværet er stille. Målt 2026-08-21 med
|
||
`--live-dry-run` på fire kopier av den forrige eksempelbasen (samme filsett som klientpark-basen
|
||
i §5), samme kommando, samme oppdragsfil:
|
||
|
||
| Variant | Utfall | rc | Melding |
|
||
|---|---|---|---|
|
||
| intakt | `LIVE-DRY-RUN OK` | 0 | — |
|
||
| uten `validator-input.json` | nektet | 1 | `live-dry-run refused: IR projection not found in bundle: 'validator-input.json'` |
|
||
| **uten `cost-baseline.json`** | **`LIVE-DRY-RUN OK`** | **0** | **`Cost baseline: NONE in the bundle — this run is un-anchored: …`** |
|
||
| korrupt `cost-baseline.json` (`quantity: -1`, `unit_cost` mangler) | nektet | 1 | `live-dry-run refused: 2 validation errors for CostBaseline …` |
|
||
|
||
Kjeden som gir det utfallet: `okf.load_optional_cost_baseline` returnerer `None` når fila mangler
|
||
(VERIFISERT: `okf.py:323-335`), `run.py:516` tar imot `None`, og `validate_proposal` hopper over
|
||
steg 0 når baselinen er `None` (VERIFISERT: `validator.py:213`). Det er med vilje — en base skrevet
|
||
før fila fantes skal fortsatt kjøre byte-identisk (VERIFISERT: `CLAUDE.md`, S4.0-raden).
|
||
|
||
**Fraværet er ikke lenger stille (2026-08-21).** Kjøringen sier det nå på to måter, og begge
|
||
stammer fra den *samme* oppslagsverdien inne i kjøringen — ikke fra en ny lesing av basen:
|
||
|
||
- **Et strukturert felt:** `provenance.cost_baseline_anchored` er `true`/`false`, og følger med
|
||
inn i utboksens `{run_id}-proposal.json`, som dumper hele stempelet (VERIFISERT:
|
||
`tests/test_baseline_visibility_loadbearing.py`, armene (a) og (d)).
|
||
- **Én linje på stdout:** `Cost baseline: NONE in the bundle — this run is un-anchored: …`,
|
||
skrevet av tørrkjøringen, av den fulle enkeltkjøringen og per prosjekt i porteføljemodus. Er
|
||
basen forankret, skrives **ingen linje i det hele tatt** — en linje for noe kjøringen ikke har
|
||
utelates, samme regel som resten av kunngjøringen følger (VERIFISERT: kjørt 2026-08-21 mot to
|
||
kopier av den forrige eksempelbasen; intakt kopi er byte-uendret, kopi uten fila bærer linja).
|
||
|
||
Ankeringen er fortsatt **valgfri** — en base skrevet før fila fantes kjører uendret. Dette er
|
||
synlighet, ikke en ny nekt. Demoen har sin egen, norske formulering
|
||
(«KUNNSKAPSBASE: … — uten kostbaseline», `simulation.py:791-802`): to formuleringer med vilje, fordi
|
||
demoen beskriver hva *basen erklærer* før kjøringen, mens linja over rapporterer hva *kjøringen
|
||
gjorde*.
|
||
|
||
**Konsekvensen for planleggingen:** spørsmål 2 i [§3](#3-avgjørelsesdelen-spørsmålene-du-stiller-fagpersonen)
|
||
er det eneste spørsmålet der et «vet ikke» ikke stopper noe — og derfor det eneste der svaret må
|
||
dokumenteres utenfor systemet. En base uten `cost-baseline.json` bør ikke kalles kjøreklar av
|
||
noen som vet hva fila gjør (ANTATT: en arbeidsregel; koden lar deg kjøre).
|
||
|
||
## 5. Klientparken hos Eksempelvirksomheten: fra bestilling til kjøreklar base
|
||
|
||
Eksempelet følger klientparken — 9 500 stasjonære arbeidsstasjoner — i den oppdiktede
|
||
Eksempelvirksomheten. Basen det ender i er `src/portfolio_optimiser/data/bundles/klientpark-energi/`, som er
|
||
sjekket inn og er den leverte basen demoen leser. Både prosjektlaget og litteraturlaget er
|
||
**fiktive** — porteføljen og kildene finnes ikke (VERIFISERT: basens `index.md`). Skillet
|
||
[§2](#2-kategoriene-hva-følger-hva) handler om er likevel synlig i den: prosjektlaget er skrevet
|
||
fra porteføljens egne tall, litteraturlaget fra fagområdets kilder, og et ekte prosjekt bytter ut
|
||
prosjektlaget.
|
||
|
||
> **Om målingene i dette kapitlet.** Kjøreklar-sjekken og tørrkjøringene i §4.1 ble målt
|
||
> 2026-08-21 på den forrige eksempelbasen, som hadde samme filsett, samme kostlinje og samme tall.
|
||
> Basen er siden skrevet om til klientpark-eksempelet; navnene i utskriftene under er byttet til
|
||
> eksempelets, og målingene er **ikke** gjentatt på den omskrevne basen.
|
||
|
||
### 5.1 Bestillingen
|
||
|
||
En driftsleder i IT-driftsavdelingen vil vite hva utskifting gir på de eldste maskinene, og om
|
||
strømstyring oppå det er verdt noe. Oppdragsfila (VERIFISERT 2026-08-21: en oppdragsfil med samme
|
||
form ble akseptert av kjøringen, og kunngjøringen under er dens utskrift, med eksempelets navn):
|
||
|
||
```json
|
||
{
|
||
"objective": "Redusere energikostnaden i klientparken til Eksempelvirksomheten uten å gå under ytelseskravene, med tiltak som kan bestilles i 2027.",
|
||
"approaches": [
|
||
{
|
||
"id": "pc-trinn-1",
|
||
"label": "Utskifting av de 2 500 eldste stasjonære PC-ene",
|
||
"description": "Drift melder at maskinene på de eldste kontorene er fra før 2015 og byttes hyppig; vi vil vite hva ren maskinutskifting gir før strømstyring vurderes."
|
||
},
|
||
{
|
||
"id": "adaptiv-stromstyring",
|
||
"label": "Adaptiv strømstyring på de utskiftede maskinene",
|
||
"description": "IT-driftshåndboken tillater RF 0,85; vi tror nye maskiner overdimensjoneres og at marginen kan hentes ut med strømsparing, men har ingen måling."
|
||
}
|
||
],
|
||
"allow_own_proposals": true,
|
||
"success_criteria": "Minst ett tiltak som passerer validatoren og som IT-driftsavdelingen kan stå inne for."
|
||
}
|
||
```
|
||
|
||
Bestillingen er den første målingen av basen: hver tilnærming nevner ting basen må kunne svare
|
||
på — maskinalder, ytelsesreserve, ytelseskrav, fravær av måling.
|
||
|
||
### 5.2 Spørsmålene, besvart for dette prosjektet
|
||
|
||
| # | Spørsmål | Svar for klientparken | Lander i |
|
||
|---|---|---|---|
|
||
| 1 | Prosjekt-ID | `KLIENTPARK-ENERGI` — samme streng på kommandolinjen og i begge tallfiler | alle tre |
|
||
| 2 | Kostlinjer med ekte tall | én linje: porteføljens årlige energikostnad, `ENERGI-KLIENTPARK-EL`, 4 386 150 kWh à 1,00 NOK. Investeringskostnad **bevisst utelatt** — ingen kilde gir NOK per arbeidsstasjon | `cost-baseline.json` |
|
||
| 3 | Den ene projiserte kandidaten | PC-utskifting trinn 1 (2 500 maskiner, 114 → 70 W), modellert 445 500 NOK/år | `validator-input.json` |
|
||
| 4 | Harde rammer | ytelseskrav (1,0 s responstid, 5 samtidige applikasjoner), RF ≤ 0,85, nattlig avstenging kan ikke antas, tiltak vurderes inne i porteføljen | `klientpark-energi.md` |
|
||
| 5 | Tilnærminger | de to i oppdragsfila, pluss systemets egne | oppdragsfila + to `hypothesis`-filer |
|
||
| 6 | Målemetode | IPMVP Option A, ved eliminasjon: umålt anlegg stenger B, C og D | `metode-ipmvp-a.md` |
|
||
| 7 | Litteratur om gapet | om klientparken: baseline, normankere og *årsaken* til at gapet ikke kan ses (mangler måler). Lånt: selve realiseringsgraden (virksomhetens etterevalueringer av et annet program, 0,81) | `kilder-klientpark-realisering.md` |
|
||
| 8 | Tidligere erfaring | én frø-dom: godkjent med realiseringskorreksjon, rate 0,81, **merket som lån** | `verdict-klientpark-fro.md` |
|
||
| 9 | Avgrensning til kostakse | nei — porteføljen har én kostlinje | — |
|
||
| 10 | Kilder som data | nei — utstyrsregisteret er levert som tall i et notat; alt er håndkuratert | — |
|
||
| 11 | Hvem dømmer | virksomhetens egen energirådgiver, etter kjøringen, via innboksen | `--verdict-dir` |
|
||
|
||
(Alle svar i kolonnen «Svar» er VERIFISERT mot filene i `src/portfolio_optimiser/data/bundles/klientpark-energi/`; kolonnen
|
||
«Lander i» er VERIFISERT mot filnavnene der.)
|
||
|
||
### 5.3 Hva fagpersonene leverer
|
||
|
||
| Leveranse | Fra | Form de leverer i | Blir til |
|
||
|---|---|---|---|
|
||
| Utstyrsregister: antall arbeidsstasjoner, modell, installert effekt | IT-drift | uttrekk fra utstyrsdatabasen, regneark | `type: project` (energibaseline) + raden i `cost-baseline.json` |
|
||
| Driftstimer og energipris | IT-drift / økonomi | tabellverdi (IT-driftshåndboken) + fakturagrunnlag | samme; prisbåndet i `validator-input.json` |
|
||
| Kravgrunnlag: ytelseskrav, ytelsesreserve | fagmiljø arbeidsflate | henvisning til innkjøpsspesifikasjonen og IT-driftshåndboken | «Rammer» i `type: project` |
|
||
| Kandidat-tiltak med parametere | IT-drift + fagmiljø | notat: før/etter-effekt, antall, hva som er utledet | to `type: hypothesis`-filer |
|
||
| M&V-praksis for umålte anlegg | fagmiljø | mal for IPMVP, tilpasset | `type: methodology` |
|
||
| Litteratur om realiseringsgap, med kilde | fagmiljø | kildeliste med URL og årstall, merket eget anlegg/lånt | `type: reference` |
|
||
| Tidligere vurdering av utskifting i en mindre klientpark | energirådgiver | kort notat: «forvent ~80 % av modellert, fordi …» | `type: verdict` (frø) |
|
||
|
||
Leveranseformene er ANTATT — de er det en slik leveranse rimelig ser ut som, ikke noe
|
||
eksempelbasen dokumenterer. Det som er VERIFISERT er hva hver leveranse *blir til*.
|
||
|
||
### 5.4 Basen som bygges
|
||
|
||
```
|
||
klientpark-energi/
|
||
├── index.md type: index inngangen; lenker til alt under
|
||
├── klientpark-energi.md type: project porteføljen, energibaselinen, rammene
|
||
├── tiltak-pc-utskifting.md type: hypothesis kandidat 1 — den som er projisert
|
||
├── tiltak-adaptiv-stromstyring.md type: hypothesis kandidat 2 — svakere kildebelagt, og merket slik
|
||
├── metode-ipmvp-a.md type: methodology Option A, og hvorfor de andre er stengt
|
||
├── kilder-klientpark-realisering.md type: reference Del A eget anlegg / Del B lånt
|
||
├── verdict-klientpark-fro.md type: verdict frø-dommen — holdes ute av lesekonteksten
|
||
├── validator-input.json den projiserte kandidaten
|
||
└── cost-baseline.json prosjektets ene kostlinje
|
||
```
|
||
|
||
(VERIFISERT: `ls src/portfolio_optimiser/data/bundles/klientpark-energi/` og `grep '^type:'` over filene.)
|
||
|
||
`index.md` gjør to jobber i denne basen. Den første er navigasjon: seks lenker, én per fil, med
|
||
type og én setning hver. Den andre er å si høyt hva som er fiktivt og hva som er ekte, og
|
||
*hvorfor* domenet er valgt — at realiseringsgraden i klientparken er «strukturelt usynlig» fordi
|
||
anlegget mangler måler. Begge deler går ordrett inn som det første agentene leser.
|
||
|
||
### 5.5 De to tallfilene — skrevet fra samme linje
|
||
|
||
Hele basens tallgrunnlag er én linje aritmetikk:
|
||
|
||
> 9 500 arbeidsstasjoner × 114 W × 4 050 t/år ÷ 1 000 = **4 386 150 kWh/år** à 1,00 NOK = 4 386 150 NOK/år
|
||
|
||
`cost-baseline.json` bærer den som `ENERGI-KLIENTPARK-EL: {quantity: 4386150, unit_cost: 1.0}`.
|
||
`validator-input.json` bærer **nøyaktig samme** kode, mengde og pris i `affected_items`, pluss den
|
||
modellerte besparelsen for trinn 1 (2 500 × 44 W × 4 050 t ÷ 1 000 = 445 500 kWh ≈ 445 500 NOK)
|
||
og prisbåndet 0,70–1,40 NOK/kWh til risikosimuleringen (VERIFISERT: begge filene). De to er ikke
|
||
«innenfor toleranse» — de er identiske, fordi begge er skrevet fra samme linje. Det er slik
|
||
toleransen på 5 % skal lukkes: ved konstruksjon, ikke ved avstemming etterpå.
|
||
|
||
**Én beslutning i mappingen er verdt å lære av:** `affected_items` er *hele porteføljens*
|
||
energikostnad, ikke de 2 500 berørte maskinenes eget forbruk. Hadde det vært det siste, ville
|
||
besparelsen vært 38,6 % av linjen — over validatorens 30 %-tak — og det riktige forslaget blitt
|
||
avvist av en gate som målte feil størrelse (VERIFISERT: `tiltak-pc-utskifting.md`, «Mapping til
|
||
validatoren»). Kostlinjen skal være den linjen tiltaket *virker på* i regnskapet.
|
||
|
||
### 5.6 Frø-dommen
|
||
|
||
```yaml
|
||
type: verdict
|
||
decision: approved_with_adjustment
|
||
realization_rate: 0.81
|
||
modelled_saving_nok: 445500
|
||
expected_actual_saving_nok: 360855
|
||
description: "… driftstimene er et internt tabellanslag, ikke en målt kurve, og klientparken
|
||
mangler måler — så avviket kan ikke oppdages i drift. Forventet faktisk besparelse settes til
|
||
81 % av modellert, lånt fra virksomhetens etterevalueringer av belysningsprogrammer og merket
|
||
som lån. …"
|
||
provenance: "frø — AI-forfattet, fiktiv virksomhet. Realiseringsgraden er LÅNT … Det finnes INGEN
|
||
ex-post-måling for klientparken. Erstattes av ekte HITL i produksjon."
|
||
```
|
||
|
||
(Utdrag; VERIFISERT: `verdict-klientpark-fro.md`.) Det som når neste hypotese er `description` pluss
|
||
`[realiseringsgrad=0.81; forventet_faktisk_NOK=360855]` (VERIFISERT: `verdicts.py`
|
||
`_verdict_rationale`). `provenance`-feltet leses ikke av koden — men det er det som gjør at en
|
||
fagperson som åpner basen ser at dommen er et frø og raten et lån. I et ekte prosjekt erstattes
|
||
denne fila av energirådgiverens egen vurdering, i samme form.
|
||
|
||
### 5.7 Kjøreklar-sjekken
|
||
|
||
Det finnes ingen egen «valider basen»-kommando
|
||
([§6](#6-ærlighetsdelen-hva-som-ikke-finnes-i-dag)). Det nærmeste er en tørrkjøring med
|
||
bestillingen på plass:
|
||
|
||
```bash
|
||
uv run python -m portfolio_optimiser.run KLIENTPARK-ENERGI \
|
||
--docs-dir src/portfolio_optimiser/data/bundles/klientpark-energi \
|
||
--bundle-dir src/portfolio_optimiser/data/bundles/klientpark-energi \
|
||
--mandate oppdrag.json \
|
||
--live-dry-run
|
||
```
|
||
|
||
Målt 2026-08-21 på den forrige eksempelbasen (VERIFISERT, rc 0; navnene byttet til eksempelets,
|
||
se notisen øverst i §5):
|
||
|
||
```
|
||
Run mandate for KLIENTPARK-ENERGI
|
||
Objective: Redusere energikostnaden i klientparken til Eksempelvirksomheten uten å gå under ytelseskravene, med tiltak som kan bestilles i 2027.
|
||
Evaluates: 2 expert-proposed approach(es) + the system's own proposals
|
||
1. pc-trinn-1 — Utskifting av de 2 500 eldste stasjonære PC-ene
|
||
2. adaptiv-stromstyring — Adaptiv strømstyring på de utskiftede maskinene
|
||
Stops at: 3 rounds / 100000 tokens
|
||
Contacts: no external services
|
||
Success: Minst ett tiltak som passerer validatoren og som IT-driftsavdelingen kan stå inne for.
|
||
KLIENTPARK-ENERGI: LIVE-DRY-RUN OK (profile=local, models={'proposer': 'qwen3:4b', 'checker': 'qwen3:4b'}, max_rounds=3, max_tokens=100000, top_k=3) — ingen modellkall gjort (stoppet før første debate.run)
|
||
```
|
||
|
||
**Hva `OK` beviser:** basen åpner — `index.md` finnes, `validator-input.json` finnes og bærer
|
||
riktig prosjekt-ID, `cost-baseline.json` *hvis den finnes* er velformet, bestillingen er gyldig,
|
||
modellene er oppløst, takene er satt, og ingen ekstern tjeneste vil bli kontaktet. Alt dette
|
||
skjer før kuttet, uten et eneste modellkall (VERIFISERT: `run.py:513-516` ligger før
|
||
dry-run-returen på `:565-588`).
|
||
|
||
**Hva `OK` sier fra om:** en lenke kjøringen ikke klarte å følge. Tørrkjøringen skriver da én
|
||
blokk under `OK`-linja — én linje per lenke, med filen lenken sto i, lenketeksten ordrett, og
|
||
hvorfor: `missing` (målet ligger inne i basen, men det er ingen lesbar fil der — nesten alltid en
|
||
skrivefeil i lenken) eller `outside-bundle` (målet peker ut av basen). Er alle lenkene fulgt,
|
||
skrives ingen linje i det hele tatt. Målt på en base med begge feilene:
|
||
|
||
```
|
||
Knowledge base: 2 cross-link(s) NOT followed — the agents never read the document(s) behind them:
|
||
- index.md -> metodikk-som-aldri-ble-skrevet.md (missing)
|
||
- index.md -> ../nabobase/index.md (outside-bundle)
|
||
```
|
||
|
||
Selve toleransen er uendret: en brutt lenke stopper ikke kjøringen (OKF SPEC §4 krever det). Det
|
||
som er nytt er at den ikke lenger er taus — før dette var «dokumentet ble aldri skrevet» og «lenken
|
||
til det var feil» umulig å skille utenfra. Den samme blokka skrives på en full kjøring.
|
||
|
||
**Hva `OK` ikke beviser:** at `cost-baseline.json` *finnes* (se [§4.1](#41-den-skarpeste-mangelen-cost-baselinejson)
|
||
— sjekk det med `ls`), at filene faktisk er lenket fra `index.md` (en fil ingen lenker til er
|
||
unåbar, og da finnes det ingen lenke å rapportere), eller at innholdet er godt. `--docs-dir` må oppgis, men leses ikke på bundle-stien (VERIFISERT:
|
||
`run.py:513-530` bruker bare `bundle_dir`; `:1504` krever flagget likevel). Pek den på samme
|
||
mappe.
|
||
|
||
**Det offline ende-til-ende-beviset på denne basen** er demoen:
|
||
`uv run python -m portfolio_optimiser.simulation`. Den kjører nøyaktig `klientpark-energi`, skriver
|
||
«KUNNSKAPSBASE: klientpark-energi — kostbaseline erklært (ENERGI-KLIENTPARK-EL 4386150 x 1)», navigerer
|
||
de fem konseptfilene, og viser at en dom avgitt etter kjøring A når kjøring B (VERIFISERT:
|
||
`tests/golden/demo-transcript.stdout`, linjene 7, 13 og 50). Agent-svarene i demoen er
|
||
skriptede; den beviser dataflyten, ikke modellens dømmekraft.
|
||
|
||
### 5.8 Etter kjøringen
|
||
|
||
Kjør med `--outbox-dir` og `--run-id`, så legger kjøringen igjen én artefakt per vurdert
|
||
tilnærming. `hitl pending` viser hva som venter på dom; energirådgiveren skriver dommen som
|
||
JSON-fil i innboksen etter [ekspert-svar.md](ekspert-svar.md). Neste kjøring med `--verdict-dir`
|
||
leser den inn før hypotesen formes. Godkjennes den for promotering, blir den en ny
|
||
`type: verdict`-fil i basen — og basen er blitt én versjon klokere.
|
||
|
||
## 6. Ærlighetsdelen: hva som ikke finnes i dag
|
||
|
||
Ingenting under er en feil i koden. Det er grensen for hva som er bygget, og det skal stå her
|
||
så dokumentet ikke lover mer enn det som kan leveres.
|
||
|
||
- **Bundle-fabrikken er ikke bygget** (operatørbeslutning D-G / T0). Det finnes ingen verktøy
|
||
som tar fagpersonens regneark og notater og lager en base. Oversettelsen til markdown,
|
||
lenkene i `index.md` og begge tallfilene er den tekniske personens håndarbeid (VERIFISERT:
|
||
[knowledge-base-recipe.md](knowledge-base-recipe.md), «Future / factory-dependent»).
|
||
- **Fri-format-oversettelse av dommer finnes ikke.** Frø-dommer skrives direkte i det strenge
|
||
formatet (VERIFISERT: samme sted). Den tiltenkte flyten — eksperten leverer fri tekst, en
|
||
oversetter lager den strukturerte dommen, som alltid peker tilbake på originalen — er
|
||
beskrevet, ikke bygget.
|
||
- **Ingest har ingen kommandolinje.** `materialize` er et Python-API (VERIFISERT: ingen
|
||
`__main__` i `src/portfolio_optimiser/ingest.py`), og «no bundle has yet been materialized from
|
||
a live source» (VERIFISERT: `README.md`). Det som er målt er fil/CSV, SQL, HTTP og MCP mot
|
||
innsjekkede fixtures.
|
||
- **Tidligere dommer hentes én gang per kjøring, for den projiserte kandidaten** — ikke per
|
||
tilnærming i bestillingen (VERIFISERT: `run.py:634-638`; én `expel_query` for hele
|
||
kjøringen). En bestilling med to tilnærminger mot to ulike kostlinjer får tidligere dommer
|
||
hentet for den kandidaten `validator-input.json` beskriver.
|
||
- **Det finnes ingen «er basen klar?»-kommando.** `--live-dry-run` beviser at basen *åpner*, sier
|
||
fra hvis `cost-baseline.json` mangler, og lister lenkene den ikke klarte å følge
|
||
([§5.7](#57-kjøreklar-sjekken)) — men ingenting om innholdets kvalitet, og ingenting om filer
|
||
ingen lenker til (de er unåbare, så det finnes ingen brutt lenke å rapportere). `preflight`
|
||
sjekker Azure-konfigurasjon, ikke basen (VERIFISERT: `preflight.py` docstring).
|
||
- **Uforankret kjøring er synlig, men ikke summert.** Feltet og linja finnes per kjøring
|
||
([§4.1](#41-den-skarpeste-mangelen-cost-baselinejson)); det finnes ingen rapport som teller opp
|
||
hvor mange kjøringer i et porteføljepass som gikk uforankret.
|
||
- **Eksempelbasene er ikke ekte prosjekter.** Prosjektlaget er fiktivt; realiseringsgraden i
|
||
frø-dommene er lånt fra andre program fordi ingen ex-post-måling av anlegget selv finnes
|
||
(VERIFISERT: `provenance`-feltet i dom-filene).
|
||
- **De fire innholdstypene er konvensjon**, ikke spesifikasjon
|
||
([§4](#4-innholdstypene)).
|
||
- **`docs/extending.md` er utdatert på ett punkt:** den sier at ingen eksempelbase shipper
|
||
`cost-baseline.json`. Det var sant da den ble skrevet (2026-08-05); begge de leverte
|
||
eksempelbasene har fått fila siden (VERIFISERT: `ls`, begge datert 2026-08-09). Rettelsen er ikke gjort her, for
|
||
den hører hjemme i det dokumentet.
|
||
- **1–2 uker.** Oppskriften sier det, og ingenting i dette dokumentet korter det ned. Det som
|
||
står her er hva ukene skal brukes til.
|
||
|
||
## 7. Punktet der utforskningen konkluderte med kode
|
||
|
||
Dokumentet pekte opprinnelig på ett punkt der det ikke holdt å beskrive: en kjøring som går uten
|
||
`cost-baseline.json` burde si det — i kunngjøringen, i `provenance`, eller begge. Demoen gjorde det
|
||
allerede; kjørestien gjorde det ikke.
|
||
|
||
**Det er nå bygget (2026-08-21), med begge deler:** et strukturert `cost_baseline_anchored`-felt på
|
||
provenance-stempelet, og én linje på stdout når kjøringen er uforankret — se
|
||
[§4.1](#41-den-skarpeste-mangelen-cost-baselinejson). Ankeringen forble valgfri, og
|
||
golden-transkriptet er byte-uendret, fordi demoen kjører en base som *har* fila og linja derfor
|
||
ikke fyrer der.
|
||
|
||
## 8. Verifiseringslogg
|
||
|
||
| Påstand | Kilde | Status |
|
||
|---|---|---|
|
||
| Én base per prosjekt | `shared/method-spec.md` §2 («one curated … knowledge bundle per project») | VERIFISERT |
|
||
| Navigasjon fra `index.md`, flat rendering `## type: tittel`, verdict ekskludert | `shared/method-spec.md` §3 Steg 1; `src/portfolio_optimiser/okf.py` `bundle_context`, `context_files` | VERIFISERT |
|
||
| Lenke ut av basen hoppes stille over | method-spec §3 Steg 1 | VERIFISERT |
|
||
| Fil uten index-lenke er unåbar | `shared/ingest-spec.md` §2 | VERIFISERT |
|
||
| Verdict-laget reservert; ingest kan ikke skrive det | ingest-spec §3, §4 (`okf_type` MUST NOT be `verdict`) | VERIFISERT |
|
||
| Tidligere dommer nøkles på `validator-input.json`-kandidaten, én gang per kjøring | `run.py:634-638`; `verdicts.py` `bundle_candidate_features` | VERIFISERT |
|
||
| Det som valideres er modellens forslag, ikke `validator-input.json` | `generate.py:491` | VERIFISERT |
|
||
| Seks `type:`-verdier i drift: index 3 · project 4 · hypothesis 5 · methodology 3 · reference 3 · verdict 3 | `grep -h '^type:' shared/examples/*/*.md \| sort \| uniq -c` (2026-08-21) | VERIFISERT |
|
||
| De fire ikke-reserverte typene er ikke nevnt i noen spesifikasjon | `grep` over `shared/method-spec.md` og `shared/ingest-spec.md` — null treff | VERIFISERT |
|
||
| Metode-filene er tre ulike filer (40 / 81 / 98 linjer), materialisert per base | `wc -l`, `diff`; begge `index.md` («materialisert inn her») | VERIFISERT |
|
||
| Koden leser ikke `resource`, `measure_id`, `gap_source`, `context_key`, `okf_version`, `tags` | `grep` over `src/portfolio_optimiser/*.py` — null treff | VERIFISERT |
|
||
| `dimension:` brukes av ingen eksempelbase | `grep -rn '^dimension:' shared/examples/` — null treff | VERIFISERT |
|
||
| Prosjekt-ID må stemme mellom kommandolinje og `validator-input.json` | `run.py` `_project_from_bundle` | VERIFISERT |
|
||
| Prosjektnavn leses fra `type: project`-filas `title`, ellers ID | samme | VERIFISERT |
|
||
| Steg 0 avviser ukjent kode og avvik > 5 % | `validator.py:154-190`; `BASELINE_TOLERANCE_DEFAULT = 0.05` | VERIFISERT |
|
||
| Manglende `cost-baseline.json` → `None` → steg 0 hoppes over | `okf.py:323-335`; `run.py:516`; `validator.py:213` | VERIFISERT |
|
||
| Fire tørrkjøringer: intakt rc 0 · uten IR rc 1 · uten baseline rc 0 uten melding · korrupt baseline rc 1 | kjørt 2026-08-21 på kopier av den forrige eksempelbasen i scratchpad, kommandoen i §5.7 | VERIFISERT |
|
||
| Ingen artefakt bærer forankret/uforankret | `grep baseline src/portfolio_optimiser/provenance.py src/portfolio_optimiser/outbox.py` — null treff | VERIFISERT |
|
||
| Demoen printer forankringsstatus | `simulation.py:791-802`; golden linje 7 | VERIFISERT |
|
||
| `--live-dry-run` navigerer basen og laster begge tallfiler før kuttet | `run.py:513-516` vs `:565-588` | VERIFISERT |
|
||
| `--docs-dir` påkrevd men ulest på bundle-stien | `run.py:513-530`, `:1504` | VERIFISERT |
|
||
| Demoen kjører `klientpark-energi`, navigerer 5 konseptfiler, henter 0 så 3 dommer | `tests/golden/demo-transcript.stdout` linjene 7, 13, 14, 50 | VERIFISERT |
|
||
| Frø-rationale = `description` + `[realiseringsgrad=…; forventet_faktisk_NOK=…]` | `verdicts.py` `_verdict_rationale` | VERIFISERT |
|
||
| Dom-nøkkel-trioen: alle tre felt eller ingen | `verdicts.py` `_features_from_verdict_frontmatter`; `README.md` | VERIFISERT |
|
||
| Klientpark-tallene: 9 500 × 114 W × 4 050 t = 4 386 150 kWh; 445 500 NOK modellert; 10,2 % av total; 38,6 % av berørte maskiner | `klientpark-energi.md`, `tiltak-pc-utskifting.md`, begge JSON-filer | VERIFISERT |
|
||
| Frø-dommen: rate 0,81, forventet 360 855, lånt | `verdict-klientpark-fro.md` frontmatter | VERIFISERT |
|
||
| Fabrikk og fri-format-oversettelse ikke bygget | `docs/knowledge-base-recipe.md`; `docs/plan/2026-07-14-revisjonspakke-DF-DI.md` §3 | VERIFISERT |
|
||
| Ingest har ingen CLI; ingen base materialisert fra levende kilde | `grep __main__ src/portfolio_optimiser/ingest.py` — null treff; `README.md` «How it is set up» | VERIFISERT |
|
||
| Ingest skriver ikke `validator-input.json` / `cost-baseline.json` | `docs/extending.md`, «Legg til en ingest-kilde» | VERIFISERT |
|
||
| `docs/extending.md` sier ingen eksempelbase shipper `cost-baseline.json` | samme dokument; motbevist av `ls src/portfolio_optimiser/data/bundles/{klientpark-energi,driftssenter-kjoling}/` | VERIFISERT (utdatert) |
|
||
| Leveranseformene i §5.3; anbefalingene merket ANTATT | — | ANTATT |
|