This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 18:37:48 +02:00
commit 2d91943fab
29 changed files with 2712 additions and 21 deletions

View file

@ -0,0 +1,530 @@
# Amendment-underlag — hva frossen tekst sier i dag, per køpunkt
**Status:** underlag. Spec-en er IKKE endret, og dette dokumentet foreslår INGEN ny tekst.
Ny tekst er pakken operatøren ratifiserer, og den eies oppstrøms (`portfolio-optimiser`,
sammen med `portfolio-optimiser-claude`s tekstforslag). Dette dokumentet svarer bare på
spørsmålet commons kan svare på uten å foregripe ratifiseringen: **hvilke seksjoner røres,
hva står der i dag (fil + linje), og hva koster endringen mot fasit-bundelen.**
**Foranledning:** `portfolio-optimiser` klarerte 2026-07-25 (05:09Z, punkt 3) generelt
underlag som trygt arbeid som ikke invalideres av at pakken deres holdes: *«preparing GENERAL
underlag (which spec sections those five stories touch, what the frozen text says today) is
safe work that will not be invalidated»*. Dette er det arbeidet.
**Grunnlag:** commons HEAD `a67a243`. Normativ spec-tekst er uendret siden `bfa5a9b`
(ingest-spec, D1-stempelmodellen) / `9801d35` (method-spec §3 Steg 1, Q3-navigasjonen) /
`b641741` (nav-golden-fixtures) — alle 2026-07-21. Hver sitat-blokk under er hentet fra HEAD
og linjeankeret verifisert, ikke gjengitt fra hukommelse.
> **Leseanvisning for konsumenter (tilføyd 2026-07-26).** Alle linjeankere i dette dokumentet
> gjelder **commons HEAD**. Konsumentene er pinnet på eldre `shared/`-subtrær, og et
> linjenummer overlever ikke en pull-grense: `portfolio-optimiser-claude` står på `7aa53fc`,
> der `method-spec.md` er 441 linjer og §12 begynner på `:413` — mot 464 linjer og `:436` her.
> **Sitér seksjon + ordrett tekst; linjenummeret er en bekvemmelighet, aldri ankeret.** Et
> linjenummer sitert over en pull-grense er et *premiss*, ikke et faktum (metodenote fra
> `portfolio-optimiser-claude`, 2026-07-26 — de fant den på dette dokumentets egne sitater).
---
## 0. Køen, avstemt
To korreksjoner fra `portfolio-optimiser` (16:11Z) er **godtatt**, begge verifisert:
1. **Tittel-whitespace er ikke et eget punkt** — det ER amendment-innholdet i S3.5. Vår
telling dobbeltførte det. (Deres kø-linje `(a) commons-amendment tittel-whitespace → S3.5`
ble lest som «punkt ved siden av», ikke «innholdet i».)
2. **B1 er ute av pakken** — commons-eid, ingen adferds-interesse oppstrøms. Bæres separat
(§8 her).
Én korreksjon går **tilbake** oppstrøms, og den er grunnen til at underlaget er verdt å
skrive før pakken lukkes:
3. **De to oppstrøms-enumerasjonene er ikke den samme mengden.** `portfolio-optimiser`
teller fem *stories* (S2.7 / S2.22.4 / S3.2 / S3.5 / S4.0); `portfolio-optimiser-claude`
teller fem *D-A-punkter*. Bare tre par binder (S2.7 = D-A#1, S3.2 = D-A#4, S4.0 = D-A#2).
De to gjenstående D-A-punktene har **ingen story-etikett** oppstrøms:
- **D-A#3 (ledende `/`)** — trenger ingen amendment i det hele tatt. Frossen tekst i
commons HEAD sier allerede det punktet ber om (§3 under). **Årsaken er repo-avhengig**
(begge konsumenter svarte, med hver sin — begge er sanne): drift over pull-grensen hos
`portfolio-optimiser-claude`, målt konformitetsgap i `okf.py` hos `portfolio-optimiser`.
Anbefalingen er den samme uansett hvilken som gjelder hvor.
- **D-A#5 (hovedbok-projeksjoner)** — er reell og har ingen tekst å endre (§6 under), men
mangler story-etikett. Ratifiserer operatøren «pakken» slik `portfolio-optimiser`
beskriver den, faller D-A#5 utenfor.
Netto, fra commons' side: pakken er deres seks **pluss** hovedbok-kontrakten = **sju
ratifiserbare punkter**, med D-A#3 strøket som amendment. B1 utenfor, som avtalt.
Tallet er ikke poenget — membership er.
**S2.22.4 (D-B)** var det ene punktet commons ikke kunne ankre. **Substansen kom 2026-07-26**
og er ført i §7.17.2: D-B er en *scope*-beslutning, ikke spec-tekst. **To av de tre gatede
storiene viste seg UGATED** — S2.2 fordi §4s `http`-punkt normativt plasserer MCP-konnektorer i
`http`-familien (MUST på samme kontrakter), S2.4 fordi berikelsen holder seg innenfor §8s tre
felt. **Kun S2.3 (`doc`) krever amendment.** Begge frigjøringene kom av ankring i frossen tekst,
ingen av dem av en endring.
---
## 1. S2.7 / D-A#1 — nominal feasibility skal GATE, + IR-invariant `low ≤ unit_cost ≤ high`
**Seksjoner:** `method-spec.md` §3 Steg 4 (`:150-166`), §7.1 (`:335-346`), §7.2 (`:348-365`),
§12 (`:458`).
**Hva frossen tekst sier i dag.** Den nominale grensen *beregnes*, og bare `p90` *blokkerer*:
> **`method-spec.md:157-160`** (§3 Steg 4, punkt 2)
> 2. **Feasibility bound:** the maximum feasible saving is capped at a policy fraction
> (0.30) of the affected items' total cost. *(reference: computed with an LP solve whose
> closed form here is `0.30 × Σ quantity·unit_cost`; a missing solver MUST escalate, never
> silently fall back.)*
> **`method-spec.md:163-166`** (§3 Steg 4, punkt 4)
> 4. **Structural block:** a claim above the optimistic feasible bound (`p90`) yields a
> **rejection that is a distinct type from a validated proposal**
Punkt 2 sier `capped at`, men gir ingen avvisningsregel; punkt 4 er den ENESTE blokkeringen
og bruker `p90`. Påstanden «beregnes, men bare p90 blokkerer» holder altså mot teksten.
§7.2 sier det samme eksplisitt om hva assertionen betyr:
> **`method-spec.md:356-358`** (§7.2)
> … The meaningful assertion is `validates` = true (claimed ≤ `p90`); the frozen numbers are
> the regression net.
`nominal_feasible` er et frosset felt (`:352-356`, kryssjekk `:458`) — det er allerede
normativt *rapportert*, bare ikke *gatende*.
**IR-invarianten finnes ikke.** §7.1 har én construction-time-invariant, og den handler om
noe annet:
> **`method-spec.md:343-344`** (§7.1)
> - Construction-time invariant: the claimed saving MUST NOT exceed the affected items' own
> total (`Σ quantity·unit_cost`); violation is a schema error, not a validator rejection.
`assumptions` er definert som band per kostkode (`:341-342`), men ingenting binder
`unit_cost` til å ligge INNI sitt eget band. Hullet er reelt.
**Målt mot fasit-bundelen (`examples/bygg-energi-mikro/`) — begge endringene er byte-nøytrale:**
| Sjekk | Verdi i fasit | Konsekvens |
|---|---|---|
| `claimed_saving_nok` vs. `nominal_feasible` | `30000` vs. `90000.0` | claimed ≤ nominal → en nominal gate endrer ikke `validates` (fortsatt `true`) |
| `unit_cost` vs. eget band | `1.0` i `[0.70, 1.40]` | invarianten er allerede oppfylt → fixture trenger ingen endring |
Kilder: `examples/bygg-energi-mikro/golden.json` (validator-blokken),
`examples/bygg-energi-mikro/validator-input.json` (`affected_items[0]`, `assumptions`).
**Klassifisering:** ekte hull i frossen tekst (begge deler). Gratis mot goldenbytene.
**Operatør-spørsmålet:** skal nominal-grensen gi samme *type* avvisning som p90-blokket
(`:163-166` sier «distinct type … carrying the claimed and feasible figures … and no
percentiles») eller en egen? Teksten har i dag én avvisningsform, og den er definert av p90.
---
## 2. S3.2 / D-A#4 — seedet dom skal nøkles på SINE EGNE features
**Seksjoner:** `method-spec.md` §3 Steg 1, experience fold (`:105-123`).
> **`method-spec.md:108-114`**
> - The retrieval query key is the bundle's candidate features, read from the IR projection
> (§7.1) — available *before* any proposal exists.
> - Seeding: every `type: verdict` file in the bundle becomes a store entry keyed on those
> candidate features, with `decision` from frontmatter (default `approved`) …
`those candidate features` refererer tilbake til forrige kulepunkt — bundelens ENE
IR-projeksjon. Frossen tekst sier altså eksplisitt det punktet vil bort fra: hver seedet dom
arver bundelens projeksjonsnøkkel, ikke sin egen. Hullet er reelt og teksten er entydig.
**Berøringsflate videre:** nøkkelen er det rangeringen (`:115-120`) og id-mintingen
(§4.2 `:254-260`) hviler på. `affected_codes` / `measure_type` / `claimed_saving_nok` er
feltene en «egen-features»-nøkling må komme fra, og §4.2 `:250-252` sier at `description`
bevisst er utenfor både likhet og minting. En amendment her må si hvor en seed-fils egne
features LESES fra (frontmatter? egen projeksjon?) — det er den åpne enden, ikke prinsippet.
**Målt:** fasit-bundelen har én seed (`verdict-led-fro.md`) og én projeksjon, så
`golden.json` kan ikke skille gammel og ny nøkling. Endringen er byte-nøytral her, og
fasiten er derfor ikke et vern mot regresjon på dette punktet.
**Klassifisering:** ekte hull. **Operatør-spørsmålet:** kilden for en seeds egne features.
---
## 3. D-A#3 — ledende `/` : INGEN amendment nødvendig
**Dette punktet er allerede normativt i commons HEAD** (landet `9801d35`, 2026-07-21):
> **`method-spec.md:67-71`** (§3 Steg 1)
> - Navigation starts at `index.md` and follows its intra-bundle markdown cross-links
> (`](target.md)`). A target is resolved **relative to the bundle** and boundary-checked
> fail-closed (below): a leading `/` denotes the **bundle root** (NEVER a filesystem-absolute
> path), any other form is relative to the linking file's own directory — so a target MAY
> address a nested directory (`sub/index.md`, `/a/b.md`).
Og §11 har allerede rød-betingelsen som feiler hvis en implementasjon hopper over den:
> **`method-spec.md:425`** (§11, «Navigation boundary»)
> … an escaping cross-link (`..`, a filesystem-absolute path, or a bundle-root `/` read as
> filesystem-absolute) is followed, a malformed target … is raised instead of skipped, or a
> legitimate nested in-bundle link is skipped
Teksten sier også selv at den ERSTATTET den gamle skip-heuristikken (`:73-74`).
**Klassifisering:** **drift over pull-grensen** — verken spec-hull eller konformitetsavvik.
Ligger et forslag om å «endre» §3 Steg 1 her, endrer det tekst som allerede sier det forslaget
vil oppnå — og risikoen er at ratifiseringen omformulerer en fungerende regel. **Meldt
oppstrøms.**
> **Årsaks-korreksjon (2026-07-26).** Første utgave av dette avsnittet klassifiserte D-A#3 som
> «konformitetsgap i implementasjonen» og skrev at forslaget beskrev implementasjonens
> oppførsel framfor specens. **Det var feil årsak.** `portfolio-optimiser-claude` målte det mot
> eget tre og svarte at deres `shared/method-spec.md` greper 0 for «bundle root» og
> «filesystem-absolute» — fordi teksten landet i `9801d35`, og:
>
> ```
> git merge-base --is-ancestor 9801d35 7aa53fc -> false (reprodusert her)
> ```
>
> Deres split er `7aa53fc`; driften er 15 commits per 2026-07-26. De står i «ikke pullet»
> **bevisst** — avtalen er samme commons-commit i begge repo før noen bygger. D-A#3 var altså
> korrekt formulert mot den frosne teksten de har lov til å se; regelen landet oppstrøms
> etterpå. **Anbefalingen er uendret** (punktet ut av pakken, siden regelen er normativ når
> pakken lander), men den følger av drift, ikke av et avvik hos dem.
>
> Lærdommen generaliserer og er derfor løftet til leseanvisningen øverst: **samme felle venter
> på ethvert punkt målt mot en bevegelig frossen tekst mens konsumentene er pinnet.**
> **Andre korreksjon, samme dag — årsaken er REPO-AVHENGIG, og begge svar er sanne.**
> `portfolio-optimiser` svarte kort etter og klassifiserte D-A#3 som **«et KONFORMITETSGAP i
> implementasjonen vår — ikke et spec-hull»**, med en konkret årsak: *«okf.py hopper over enhver
> lenke med `/`»*. Det er den motsatte klassifiseringen av den `portfolio-optimiser-claude` ga.
>
> **Ingen av dem tar feil.** De beskriver to forskjellige repo:
>
> | Repo | Har `9801d35`? | Årsak der |
> |---|---|---|
> | `portfolio-optimiser-claude` | nei (pinnet `7aa53fc`) | **drift** — regelen finnes ikke i teksten de har |
> | `portfolio-optimiser` | nei (pinnet `7aa53fc`) | **konformitetsgap** — de har målt eget avvik i `okf.py` og har det på operatørkøen som implementasjonssak |
>
> Begge konsumenter står på samme commons-commit (`7aa53fc`, bekreftet av begge uavhengig), så
> pullen er én koordinert handling, ikke en opprydding etter usynk.
>
> **Dette avsnittets egen historie er poenget:** første utgave ga én universell årsak, korreksjonen
> ga en annen universell årsak, og begge var for brede. «Årsaken til D-A#3» er ikke én ting når
> konsumentene er pinnet og har ulik implementasjonstilstand. Anbefalingen har vært uendret hele
> veien — punktet ut av pakken — og den avhenger ikke av hvilken årsak som gjelder hvor.
---
## 4. S4.0 / D-A#2 — kostbaseline-forankring (`cost-baseline.json`)
**Seksjoner:** `method-spec.md` §7 (`:330-333`), §7.1 (`:335-346`), §12 (`:441-464`).
**Frossen tekst har ingen baseline-forankring** — `grep -c 'cost-baseline'` over begge
spec-er: **0 treff**. Det som finnes, og som en ubetinget baseline kolliderer med:
> **`method-spec.md:332-333`** (§7)
> The shared example bundle ships two JSON files that are **the only ground truth** ("fasit")
> for cross-implementation equivalence. Implementations MUST consume them unchanged.
**Målt:** `examples/bygg-energi-mikro/` inneholder nøyaktig to JSON-filer
(`validator-input.json`, `golden.json`) og seks markdown-filer. Ingen baseline. Et ubetinget
krav gjør en tredje fil til ground truth og gjør setningen over usann samtidig — pluss at
fasit-bundelen må utvides, hvilket er en fixture-endring, ikke bare en tekstendring.
`portfolio-optimiser-claude`s egen formulering («åpent om den skal være obligatorisk … et
ubetinget krav endrer golden-bytene») treffer riktig, og §7:332-333 er ankeret som gjør det
konkret.
**Presedens for hvordan en required input formuleres**, hvis den blir obligatorisk:
> **`method-spec.md:345-346`** (§7.1)
> - Loading the IR projection from a bundle is FAIL-FAST: a missing file raises (required
> input — contrast the tolerant inbox, §5).
**Klassifisering:** ekte hull, men det eneste punktet i køen som (hvis ubetinget) **endrer
fasit-bundelen** og ikke bare prosa. **Operatør-spørsmålet:** obligatorisk for alle kjøringer
(→ fixture-endring + §7-setningen må omskrives), eller opsjonell med fail-fast-semantikk kun
når den finnes (→ ren prosa-utvidelse, fasiten uendret)?
---
## 5. S3.5 / D-F — tittel-whitespace
**Seksjoner:** `ingest-spec.md` §4 (`:125`), §5 (`:149-161`), §6 (`:194-197`), §11 (`:278`),
§12 (`:301`).
> **`ingest-spec.md:125`** (§4, extraction-tabellen)
> | `title` | Human-readable title; … Single-line, and MUST NOT contain `[` or `]` … Validated
> fail-fast at manifest load — rendered verbatim thereafter (§5, §6). |
> **`ingest-spec.md:158-161`** (§5, frontmatter-kulepunktet)
> … All values MUST be single-line; `title` is emitted **verbatim** (it is `[`/`]`-free by §4,
> so verbatim rendering is safe — the invariant is met by validation, not repair); the
> materializer MUST collapse whitespace runs (including newlines) in `source_query` to single
> spaces.
Formen på hullet, presist: **collapse er scoped til `source_query` alene**, og `title` er
uttrykkelig `verbatim` med invarianten «met by validation, not repair». En tittel med interne
whitespace-runs er derfor ikke normalisert noe sted — den er bare «single-line», og hva
`single-line`-valideringen dekker (bare `\n`? `\r`? ledende/etterfølgende blanke?) står ikke.
Amendment-punktet ligger i den sømmen, og valget er **validere hardere** vs. **reparere**
teksten har i dag valgt validering for `title` og reparasjon for `source_query`.
**⚠ Anker-avvik oppstrøms (viktig for denne teksten spesielt).** `portfolio-optimiser` ankret
sitatet til `shared/ingest-spec.md:140`. Det linjenummeret er commons ved **`7aa53fc`**, ikke
HEAD:
- ved `7aa53fc`, linje 140: `` `generated`. All values MUST be single-line; the materializer MUST collapse whitespace runs ``
- ved HEAD (`bfa5a9b`): samme setning er splittet over `:158` og `:160-161`, og `title is
emitted verbatim` + «validation, not repair» er **ny tekst** fra `bfa5a9b`.
`bfa5a9b` (+39/9) skrev om nettopp dette kulepunktet OG `title`-raden i §4 (som gikk fra
bare «Single-line.» til dagens `[`/`]`-forbud + fail-fast + verbatim). Deres `shared/`-kopi
ser altså ut til å ligge ett commons-commit bak, fra FØR D1-stempelmodellen landet. Det
betyr at S3.5 kan være formulert mot tekst som ikke lenger finnes i den formen — og det er
samme risiko de selv navnga («pullen må være koordinert, samme commons-commit»). **Meldt
oppstrøms.**
**Klassifisering:** ekte, men smal søm. Ingen fasit-effekt her (våre fixtures har ingen
ingest-manifester; goldenbundlene for ingest bor i implementasjonene, jf. §11 `:259-261`).
---
## 6. D-A#5 — projeksjoner over besparelses-hovedboken (INGEN eksisterende tekst)
**Målt:** `grep -ci 'ledger'` og `grep -ci 'hovedbok'` over `method-spec.md` +
`ingest-spec.md`**0 og 0**. Ingen monetær avrundingsregel finnes heller: alle 13
forekomster av `round` (12 linjer: 9 i method-spec, 3 i ingest-spec) er andre ting
(`round-capped` debatt `:141`/`:386`, `max_rounds` `:378`/`:385`, `shortest round-trip
decimal` `ingest-spec.md:165`, `round-trip` `ingest-spec.md:85`, `around` `:323`).
Nærmeste eksisterende flater, som en ny kontrakt må forholde seg til uten å kollidere:
- **`method-spec.md:367-372`** (§7.2 `learning_surface`) — de monetære feltene som ER frosset
(`modelled_saving_nok`, `expected_actual_saving_nok`, intern konsistens påkrevd).
- **`method-spec.md:199-202`** (§3 Steg 6) — råresultater er output-laget, «plain JSON», og
bruker bevisst IKKE wiki-formatet.
- **`method-spec.md:250-252`** (§4.2) — `claimed_saving_nok` som tall i verdict-kontrakten,
og `description` bevisst utenfor likhet/minting.
- **`method-spec.md:436-464`** (§12) — kryssjekk-tabellen er *fullstendighets-håndhevet* av
spec-integritetstesten (§11 `:434`), så en ny kontrakt med nye felter MÅ inn her, ellers
feiler den testen. Dette er den mekaniske konsekvensen ingen av oppstrøms-meldingene nevner.
**Klassifisering:** ny seksjon, ikke en amendment. Dette er køens største punkt (den eneste
som utvider spec-ens virkeområde) og samtidig den uten story-etikett oppstrøms — mest utsatt
for å falle mellom de to enumerasjonene. **Meldt oppstrøms.**
**Note, videreformidlet ikke verifisert her:** `portfolio-optimiser` melder (16:11Z, pkt. 4)
at forslagets A5-regel 1 («Monetary figures MUST NOT be rounded in the projection») treffer
en persisterings-kant hos dem (NOK→øre-kvantisering) og bør skille projeksjons-aritmetikk fra
enhets-kvantisering. Commons har ikke lest deres kode og fører det som deres måling, ikke som
vårt faktum.
---
## 7. S2.22.4 / D-B — substansen er ikke ankret hos commons
Punktet er kjent bare som etikett. Vi leste det ut av `portfolio-optimiser`s STATE
(GATES-blokk) 2026-07-25 04:05Z og har aldri fått innholdet. `grep -rn 'D-B'` over dette
repoet gir **0 treff** — heller ikke i vår egen STATE, som bare bærer story-etiketten
`S2.2-2.4`. Koblingen `S2.22.4 (D-B)` finnes utelukkende i coord-arkivet
(`20260725T040535Z`, vår egen melding), ikke i noen commons-tekst.
Commons kan derfor ikke si hvilken seksjon det rører. **Ingen antakelse føres.** Dette er den
ene raden i underlaget som er blank av en grunn — og den blir stående blank til substansen
kommer. **Etterspurt oppstrøms.**
### 7.1 Substansen ER LEVERT (2026-07-26) — raden er ikke lenger blank
`portfolio-optimiser` leverte D-B-substansen på direkte forespørsel. Kilde:
`docs/plan/2026-07-10-sesjonsplan-fase2-6.md` **i deres repo, ikke commons** — gjengitt her som
mottatt, ikke verifisert av oss (vi har ikke lesetilgang til premisset, og fører det som
*rapportert*, ikke *målt*).
**D-B er en SCOPE-beslutning, ikke en spec-tekst.** Det er den avklaringen som gjør raden
meningsfull: vi lette etter hvilken seksjon den rører, og svaret er at *den selv* ikke rører
noen — den avgjør om tre andre stories gjør det. Fire delbeslutninger (`:56-62`): (1) amender
ingest-målbildet bevisst vs. nedskopér roadmap-B til mock-herding *(deres anbefaling: nedskopér
nå)*; (2) første live-kilde *(anbefaling: SQL — `read_sql` er mest herdet, read-only by
construction)*; (3) dokument-konnektor-avgrensning *(PDF via `pypdf` nå, DOCX utsatt)*;
(4) MCP-kildefamiliens nettverks-/subprosess-grant-form.
**Konsekvensen for commons — hvilke av de tre gatede storiene som faktisk krever amendment:**
| Story | Krever ingest-spec-amendment? | Hva |
|---|---|---|
| **S2.2** MCP-konnektor | **NEI — UGATED** (se §7.2) | §4s `http`-punkt (HEAD `:113-114` = pin `:101-102`) sier normativt at en MCP-konnektor **er en utvidelse av `http`-familien** med MUST på samme kontrakter. Ingen ny familie, ingen amendment. Bygges mot `http` + §8-grant |
| **S2.3** Dokument-konnektor | **JA** — ny kildefamilie | `{type: "doc"}`. PDF→OKF-konseptfil med provenance, deterministisk mot committede fixtures |
| **S2.4** Konnektor-herding | **NEI — UGATED** (bekreftet av po) | Timeout-parameter, feilkategorisering, beriket §8-logg (kilde/tidspunkt/radantall — aldri innhold). Retry KUN hvis D-B sier ja (default nei, av hensyn til determinisme). Inkrementell re-ingest: **ikke**, med mindre D-B amender §8 |
**Commons' observasjon, ikke et forslag:** §4 har i dag tre kildetyper (`file`, `sql`, `http`),
og §1 (`:27-31`) binder konformans til `file` + `sql` som påkrevde med `http` som eksplisitt
OPTIONAL utvidelsespunkt. To nye familier reiser derfor et spørsmål ingen av meldingene har
stilt: **blir `mcp` og `doc` påkrevde for konformans, eller valgfrie som `http`?** Svaret
avgjør om `:27-31` må skrives om i samme amendment. Vi fører ingen antakelse om hvilket.
**⚠️ Og frossen tekst sier allerede noe om MCP som ingen av meldingene har nevnt.** Ordrett,
`ingest-spec.md:29-31`:
> The `http` source type is an OPTIONAL extension point: implementing it (e.g. against a local
> mock, **or via an MCP-based connector**) does not require any change to this spec, and NOT
> implementing it does not break conformance.
Specen forutser altså eksplisitt at MCP kan være **transporten under `http`**, og sier at den
veien **ikke krever noen spec-endring**. Det gjør S2.2s premiss — «krever ingest-spec-amendment
i commons FØRST» — til noe som må avgjøres, ikke antas:
- Er `mcp` en **fjerde kildefamilie** (nytt `{type: "mcp"}`-skjema, amendment nødvendig), eller
en **transport for den eksisterende `http`-familien** (allerede dekket, ingen amendment)?
- Distinksjonen er ikke akademisk: den avgjør om S2.2 er blokkert på commons i det hele tatt.
Under den andre lesningen er S2.2 **ugated** og kan bygges nå, mot `http` + opt-in-flagget (§8).
### 7.2 Spørsmålet er AVGJORT av frossen tekst — det er ikke to forsvarlige svar (korr. 2026-07-26)
Avsnittet over stilte (a)/(b) som et åpent valg. **Det var feil, og `portfolio-optimiser` fant
hvorfor: det finnes et ANDRE anker vi ikke siterte, og det er normativt.**
> **`ingest-spec.md` §4, kildetypelisten, `type: "http"`-punktet** — sitert ORDRETT fordi
> linjenumrene ikke overlever pull-grensen (se rammen under):
> `type: "http"` — a remote endpoint (OPTIONAL extension point, §1). Field `base_url`: the
> endpoint base; it MUST NOT embed credentials. Optional field `credential_ref`: the NAME of
> a runtime-resolved secret reference. **An MCP-based connector is an extension of this family
> and MUST honour the same extraction, materialization, and gate contracts.**
> **⚠️ Ref-binding for sitatet over (korr. 2026-07-27, meldt av `repos`).** Avsnittet siterte
> tidligere «`:112-114`» uten ref. To feil i én: (1) numrene er HEAD-relative, og konsumentene
> står på `7aa53fc`; (2) selv mot HEAD var de av med én linje. Målt:
>
> | Ref | MCP-setningen | Hele `http`-punktet |
> |---|---|---|
> | commons HEAD | `:113-114` | `:111-114` |
> | `7aa53fc` (konsumentenes pin, verifisert identisk i BEGGE arbeidstrær) | `:101-102` | `:99-102` |
>
> **Failure-moden er grunnen til at dette er verdt en korreksjon:** en konsument som slår opp
> `:112-114` i SIN fil finner ikke ingenting — den finner felt-tabellen for `extractions`
> (`id`/`title`/`query`), troverdig og relatert spec-tekst uten et ord om MCP. Den mest
> sannsynlige konklusjonen er da at ankeret ikke finnes og at kjennelsen hviler på løs grunn.
> Et åpenbart tomt treff hadde vært tryggere. **Regel, samme klasse som `git log -S`-regelen
> under: sitér SEKSJON + ORDRETT TEKST når mottakeren står på en annen ref — eller skriv
> hvilken ref numrene gjelder.**
`:29-31` sier at MCP-veien ikke krever spec-endring. `http`-punktet sier **normativt hvor den
hører hjemme** — som en utvidelse av `http`-familien, med **MUST** på de samme kontraktene.
Frossen tekst har altså allerede valgt (b). En fjerde `{type: "mcp"}`-familie ville **motsagt**
MCP-setningen, ikke utfylt den.
**Konsekvens: S2.2 er UGATED.** Premisset «krever ingest-spec-amendment i commons FØRST» er
avkreftet av vår egen frosne tekst. S2.2 kan bygges mot `http`-familien + §8s opt-in-grant uten
å vente på noe herfra.
**Og §1-spørsmålet i 7.1 faller bort for MCP:** MCP arver `http`s status, og `http` er eksplisitt
OPTIONAL (`:27-31`). `:27-31` trenger derfor **ingen** omskriving for MCP. Spørsmålet gjenstår
kun for **S2.3 (`doc`)**, som fortsatt er en genuint ny familie. `portfolio-optimiser`s
anbefaling der: valgfri som `http` — en konform implementasjon bør ikke tvinges til en
PDF-parser. Det er deres anbefaling til ratifisering, ikke en beslutning.
**(a)-argumentet lever videre, men som implementasjonssak, ikke spec-tekst.** At
`base_url`/`credential_ref` passer dårlig på en kommando, og at env-var-med-kommando er en
subprosess-grant, er ekte friksjon — men MCP-setningen sier MUST på *kontraktene*, ikke på
*feltnavnene*, og §8 dekker «any other non-local transport». Friksjonen lever i hvordan en
kommando uttrykkes innenfor `http`-familien. Støter implementasjonen faktisk på noe MCP-setningen
forbyr, er det et målt funn og kommer tilbake hit.
**Vår egen feil, ført åpent fordi den er tredje instans samme dag:** vi skrev at `:29-31` var
«frossen siden `bfa5a9b`». Målt med `git log -S`: **begge** MCP-ankrene landet i **`7aa53fc`** —
nøyaktig commit-en konsumentene står på. `bfa5a9b` rørte bare D1-stempelmodellen. Vi tok repoets
*siste* ingest-spec-commit og antok at filen daterte derfra. Og vi fant ikke `:113` fordi vårt
`grep -n 'connection_ref' | head -3` stoppet på `:109` uten å lese omgivelsene — setningen i §1
er dessuten linjebrutt (`:30-31`), så et grep på hele frasen ville også bommet.
**Sikt grepet mot seksjonen, ikke mot ett token — og bekreft opphav med `git log -S`, aldri med
«siste commit som rørte filen».**
Merk også at S2.4s «beriket ingest-logg» ligger mot §8, som allerede sier *«Source calls are
logged (which source, when, row count)»* — en berikelse innenfor de tre feltene er neppe en
tekstendring; en berikelse *utover* dem er det. Grensen går ved «aldri innhold», som deres egen
formulering allerede respekterer.
---
## 8. B1 — nav-golden-klassen (utenfor pakken, commons-eid)
Ankret, etter å ha vært et etikett-punkt i tre uker. `llm-ingestion-okf` svarte
`portfolio-optimiser` 2026-07-25 04:19Z at «B1 bundle class» ikke finnes hos dem, og at
beskrivelsen matcher **D4 fra OKF-runden, ratifisert i trinn F 2026-07-21**: commons eier
nav-golden-bundleklassen + forventet utfall og leverer den inn; catalog eier
korpus-containeren, de adversarielle aksene og runner/gate.
**Commons-halvdelen er levert** (`b641741`, 2026-07-21):
| Case | Innhold |
|---|---|
| `examples/nav-golden-escape/` | `bundle/`, `expected-read-context.md`, `README.md`, `SHOULD-NOT-BE-READ.md` |
| `examples/nav-golden-hierarchy/` | `bundle/` (nestet `a/b/`, `c/orphan.md`), `expected-read-context.md`, `README.md` |
**Det åpne spørsmålet er ett, og det er vårt:** `grep -c 'nav-golden'` i `method-spec.md`,
`ingest-spec.md`, `CONCEPT.md`, `README.md` og `skills/expert-reviewer/SKILL.md` → **0 i alle
fem**. Klassen er levert som fixture, men ingen normativ seksjon peker på den — i motsetning til
`validator-input.json` / `golden.json` (navngitt i §7 `:330-346`) og
`examples/ingest-golden-{source type}/` (navngitt som konvensjon i `ingest-spec.md:259-261`).
§11-raden «Navigation boundary» (`:425`) beskriver rød-betingelsen, men nevner ikke fixturene
som beviser den.
**Operatør-spørsmålet:** skal nav-golden-klassen få en normativ referanse (§7 ground truth
og/eller §11-raden), eller forbli en informativ fixture? Dette er commons' eget punkt, ingen
venter på oss, og det hører IKKE inn i oppstrøms-pakken.
**Utskrevet i sin helhet:** `docs/plan/2026-07-25-b1-nav-golden-normative-status.md` — fire
opsjoner med målt kostnad. Spørsmålet viste seg ikke å være binært: specen har **tre**
referanseformer i bruk (artefaktnavn som fasit, katalogkonvensjon, informativ lenke), og
method-spec navngir aldri en repo-sti (`grep -c 'examples/' method-spec.md` → 0).
---
## 9. Sammendrag
| # | Punkt | Fil + seksjoner | Klassifisering | Fasit-effekt |
|---|---|---|---|---|
| 1 | S2.7 / D-A#1 nominal gate + IR-band | method §3.4 `:157-166`, §7.1 `:339-346`, §7.2 `:352-358` | ekte hull | ingen (målt) |
| 2 | S3.2 / D-A#4 seed-nøkkel | method §3.1 `:108-114` | ekte hull | ingen (fasiten skiller ikke) |
| 3 | D-A#3 ledende `/` | method §3.1 `:67-71`, §11 `:425` | **allerede normativt i HEAD — drift, ikke avvik** | — |
| 4 | S4.0 / D-A#2 kostbaseline | method §7 `:332-333`, §7.1 `:345-346` | ekte hull | **endrer fasit hvis ubetinget** |
| 5 | S3.5 / D-F tittel-whitespace | ingest §4 `:125`, §5 `:158-161`, §6 `:194-197`, §11 `:278` | ekte, smal søm | ingen |
| 6 | D-A#5 hovedbok-projeksjoner | ingen tekst; naboer method §7.2 `:367-372`, §12 `:436-464` | **ny seksjon** | ingen direkte; §12 må utvides |
| 7 | S2.22.4 / D-B | **ANKRET** (§7.17.2): kun **S2.3** (`doc`) krever amendment. **S2.2 + S2.4 er UGATED** — S2.2 av §4s `http`-punkt, S2.4 innenfor §8s tre felt | **scope-beslutning, ikke spec-tekst** | ingen |
| 8 | B1 / D4 nav-golden | levert `b641741`; 0 spec-referanser | commons-eget, utenfor pakken | — |
Commons' rolle er uendret: vi forbereder underlaget, operatøren ratifiserer, og frossen tekst
endres ikke uten den ratifiseringen.
---
## Verifiseringslogg
| Påstand | Sjekk | Resultat |
|---|---|---|
| Spec-tekst uendret siden 2026-07-21 | `git log -- method-spec.md ingest-spec.md` | `9801d35` / `bfa5a9b`, begge 07-21 |
| Bare p90 blokkerer i dag | lest `method-spec.md:150-166` i sin helhet | punkt 2 «capped», punkt 4 eneste blokk |
| Ingen `low ≤ unit_cost ≤ high`-invariant | lest §7.1 `:339-346` | én invariant, om claimed vs. total |
| Nominal gate er byte-nøytral | `golden.json`: claimed `30000` ≤ nominal `90000.0` | `validates` uendret `true` |
| IR-band-invarianten er alt oppfylt i fasit | `validator-input.json`: `1.0``[0.70, 1.40]` | ingen fixture-endring |
| Seeding nøkles på bundelens projeksjon | lest `:108-114` | «keyed on those candidate features» |
| Ledende `/` alt normativt | `git log -S'denotes the **bundle root**'` | `9801d35`, 2026-07-21 |
| §11 har alt rød-betingelsen | `method-spec.md:425` | «bundle-root `/` read as filesystem-absolute» |
| Ingen hovedbok-/baseline-tekst | `grep -ci ledger\|hovedbok\|cost-baseline` | 0 / 0 / 0 |
| Ingen monetær avrundingsregel | `grep -n round` begge spec-er, alle 18 treff lest | alle urelaterte |
| Fasit-bundelen har to JSON-filer | `ls examples/bygg-energi-mikro/` | `validator-input.json`, `golden.json` |
| Oppstrøms-anker `:140` er stale | `git show 7aa53fc:ingest-spec.md \| grep -n` | treff på `:140` ved `7aa53fc`, `:158/:160` ved HEAD |
| `bfa5a9b` rørte nettopp den teksten | `git show bfa5a9b -- ingest-spec.md` | +39/9; §5-kulepunkt + §4 `title`-rad omskrevet |
| Multi-manifest er extension point | `ingest-spec.md:173-174` | «Version 1 assumes ONE manifest per bundle» |
| B1 = D4, ikke okf-eid | `~/.claude/coord/portfolio-optimiser/archive/20260725T041948Z-*` | okf: «never owned here; it is D4» |
| nav-golden levert | `git log -- examples/nav-golden-*` | `b641741`, 2026-07-21 |
| nav-golden ikke normativt referert | `grep -c 'nav-golden'` i de fem normative filene | 0 i alle fem |
| D-B ikke ankret hos commons (per 07-25) | `grep -rn 'D-B'` | 0 treff utenfor STATE |
| D-B-substansen levert 07-26 | coord fra `portfolio-optimiser` | rapportert fra deres `sesjonsplan-fase2-6.md:56-62`, ikke målt av oss |
| §1 gjør `http` OPTIONAL, `file`+`sql` påkrevd | `ingest-spec.md:27-31` | ordrett sitert i §7.1 |
| …og nevner MCP som `http`-transport | `ingest-spec.md:29-31` | «or via an MCP-based connector … does not require any change to this spec» |
| **ANDRE anker: MCP hører NORMATIVT til `http`** | `ingest-spec.md` §4, `http`-punktet (HEAD `:113-114` = pin `:101-102`) | «An MCP-based connector **is an extension of this family** and **MUST** honour the same … contracts» |
| Begge MCP-ankere landet i `7aa53fc`, ikke `bfa5a9b` | `git log -S` på hver frase | `7aa53fc` for begge — altså i konsumentenes egen kopi |
| `bfa5a9b` rørte kun stempelmodellen | `git show --stat bfa5a9b` | 39 innsettinger, D1-stempel |
| §8 logger tre felter | `ingest-spec.md:230` | «which source, when, row count» |
| `connection_ref` er env-var-NAVN | `ingest-spec.md:109`, `:117` | «the NAME of a runtime-resolved …», secret resolved at run time |
| Begge konsumenter står på `7aa53fc` | coord fra begge, uavhengig | po: `git log --grep=git-subtree-split``ef1a2c5`; po-claude: egen måling |