docs(shared): bygg-energi mikro-eksempel — OKF-bundle + golden + load-bearing test
Persistent dev-fixture for energieffektivisering (energiledelse/M&V), valgt for sin lærings-overflate: gapet mellom modellert besparelse (validatoren regner) og faktisk realisert besparelse i drift (eksperten kjenner) — det ExpeL skal lære. Ett kontorbygg, ett LED-retrofit-tiltak. OKF-bundle (index/project/hypothesis/ methodology/reference/verdict) bærer kontekst-laget; verdict-led-fro.md koder realiseringsgraden (RR ≈ 0,82, forankret i National Grid SBS 2010) som ExpeL-frø. Energi mappet inn i den EKSISTERENDE kost-IR-en uendret (affected = byggets totale energikostnad, claimed = modellert besparelse ~10 % < 30 %-cap), så validatoren kjører som-den-er — src/ urørt. golden.json fryser de seeded percentilene; testen beviser at fixturen er konsumerbar (validerer, ikke Rejection), ikke bare til stede. Domenetall verifisert mot primærkilder (EVO/IPMVP, DOE/NREL UMP, CPUC, fire evalueringsstudier); norsk energipris mot SSB Q1 2026. README + shared/README oppdatert (eksempel finnes, ikke lenger "planned"). Suite 121/4, ruff+mypy rene. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
This commit is contained in:
parent
dd8529e132
commit
cbc7a22c78
11 changed files with 457 additions and 3 deletions
|
|
@ -12,8 +12,10 @@ The result will never fit any single customer 100%. The goal is a **~90% genuine
|
|||
|
||||
## Docs
|
||||
|
||||
- [`docs/plan/2026-06-26-maalbilde-agentic-loop.md`](docs/plan/2026-06-26-maalbilde-agentic-loop.md) — target picture: the agentic cost-saving loop + OKF knowledge architecture (north star).
|
||||
- [`docs/research/2026-06-23-prior-art-platform.md`](docs/research/2026-06-23-prior-art-platform.md) — prior-art & platform research (incl. implementation register §15).
|
||||
- [`docs/plan/2026-06-23-incremental-plan.md`](docs/plan/2026-06-23-incremental-plan.md) — incremental delivery plan.
|
||||
- [`docs/plan/2026-06-23-incremental-plan.md`](docs/plan/2026-06-23-incremental-plan.md) — incremental delivery plan (deterministic backbone).
|
||||
- [`shared/`](shared/) — framework-neutral shared core (concept + example OKF knowledge bundles), reused unchanged by both reference implementations.
|
||||
|
||||
## Stack
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@ so the only thing that differs is the agent framework itself.
|
|||
|
||||
- [`CONCEPT.md`](CONCEPT.md) — the business concept, written for a non-specialist
|
||||
(e.g. a business developer at another company).
|
||||
- *(planned)* the method specification, the example knowledge bundles (OKF / LLM-wiki),
|
||||
the expert-reviewer persona, and the golden-suite of expected validator outcomes.
|
||||
- [`examples/bygg-energi-mikro/`](examples/bygg-energi-mikro/) — the first example knowledge
|
||||
bundle (OKF / LLM-wiki): one office building, one LED-retrofit measure, with a seed expert
|
||||
verdict encoding the realization gap and a golden-suite of expected validator outcomes. A
|
||||
small **dev fixture** for exercising the agentic loop; a realistic full-scale example comes later.
|
||||
- *(planned)* the method specification and the expert-reviewer persona.
|
||||
|
||||
## Rules
|
||||
|
||||
|
|
|
|||
40
shared/examples/bygg-energi-mikro/bygg-kontor-nord.md
Normal file
40
shared/examples/bygg-energi-mikro/bygg-kontor-nord.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
type: project
|
||||
title: "Kontorbygg Nord"
|
||||
description: "Fiktivt næringsbygg (kontor) brukt som mikro-eksempel. Energibaseline og rammer for ett effektiviseringstiltak."
|
||||
resource: BYGG-KONTOR-NORD
|
||||
tags: [kontorbygg, energibaseline, naeringsbygg]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# Kontorbygg Nord (BYGG-KONTOR-NORD)
|
||||
|
||||
Fiktivt kontorbygg. Tallene er **illustrative men forankret i typiske norske verdier** —
|
||||
ikke et ekte bygg. En produksjons-deployer erstatter denne med en ekte kunnskapsbase.
|
||||
|
||||
## Energibaseline
|
||||
|
||||
| Størrelse | Verdi | Merknad |
|
||||
|---|---|---|
|
||||
| Oppvarmet bruksareal (BRA) | ~2 500 m² | [I] illustrativt |
|
||||
| Totalt elforbruk | **300 000 kWh/år** | [I]; ~120 kWh/m²/år — typisk norsk kontor |
|
||||
| Herav belysning | ~54 000 kWh/år (~18 %) | 200 armaturer × 90 W × 3 000 t/år |
|
||||
| Variabel energikostnad | **1,00 NOK/kWh** ekskl. mva | [V-forankret] kraftpris + nettleie-energiledd + elavgift |
|
||||
|
||||
**Energiprisen** (1,00 NOK/kWh) er den marginale variable kostnaden et spart kWh faktisk
|
||||
unngår, ekskl. mva (næring trekker fra mva). Sammensetning, forankret i SSB Q1 2026:
|
||||
kraftpris tjenesteytende næringer ~0,80–1,12 NOK/kWh + nettleie energiledd ~0,10–0,13 +
|
||||
elavgift 0,0713. Den varierer kraftig med prisområde (NO4 ~0,13 vs NO2 ~0,96 i kraftpris
|
||||
alene) og sesong — derfor er den **konfigurerbar**, og usikkerheten håndteres i Monte
|
||||
Carlo-steget (band 0,70–1,40 NOK/kWh). Se [kilder-realiseringsgap.md](kilder-realiseringsgap.md).
|
||||
|
||||
## Rammer (constraints)
|
||||
|
||||
- Tiltak vurderes **inne i** dette prosjektet (ikke på tvers av en portefølje).
|
||||
- Budsjett og tekniske rammer eies av deployer; her holdes de minimale.
|
||||
- Bygget driftes i normal kontortid; belysning styres delvis på timeplan (relevant for
|
||||
realiseringsgapet — se [verdict-led-fro.md](verdict-led-fro.md)).
|
||||
|
||||
## Kandidat-tiltak
|
||||
|
||||
- [tiltak-led-retrofit.md](tiltak-led-retrofit.md) — LED-retrofit av belysning.
|
||||
21
shared/examples/bygg-energi-mikro/golden.json
Normal file
21
shared/examples/bygg-energi-mikro/golden.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"_note": "Golden-suite (forventet utfall) for bygg-energi-mikro. To deler: (1) 'validator' fryser den deterministiske (seeded, _MC_SEED=20260624) outputen av validate_proposal pa validator-input.json — en regresjon som fanger utilsiktede endringer i validator/MC. Den MENINGSFULLE assertionen er validates=true (claimed < P90). (2) 'learning_surface' koder realiseringsgapet validatoren IKKE kan regne — ExpeL-froet fra verdict-led-fro.md. expected_actual = realization_rate * modelled.",
|
||||
"validator": {
|
||||
"outcome": "ValidatedProposal",
|
||||
"validates": true,
|
||||
"claimed_saving_nok": 30000,
|
||||
"nominal_feasible": 90000.0,
|
||||
"p10": 68543.08886748762,
|
||||
"p50": 95443.98966314227,
|
||||
"p90": 121057.08845805985,
|
||||
"_percentile_meaning": "OVRE FEASIBLE GRENSE (30% av samplet energikostnad), IKKE LED-besparelsens fysiske band. Se tiltak-led-retrofit.md, 'Mapping til validatoren'."
|
||||
},
|
||||
"learning_surface": {
|
||||
"modelled_saving_nok": 30000,
|
||||
"realization_rate": 0.82,
|
||||
"expected_actual_saving_nok": 24600,
|
||||
"gap_source": "hours-of-use-overestimation",
|
||||
"context_key": "kontorbygg; HOU-kilde=timeplan-stipulert",
|
||||
"_meaning": "Det validatoren IKKE kan regne fra parameterne. ExpeL-frøet loopens steg 1 skal hente og anvende. Se verdict-led-fro.md."
|
||||
}
|
||||
}
|
||||
41
shared/examples/bygg-energi-mikro/index.md
Normal file
41
shared/examples/bygg-energi-mikro/index.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
type: index
|
||||
title: "Bygg-energi mikro-eksempel — kontorbygg, LED-retrofit"
|
||||
description: "Minimal OKF-bundle for ett kontorbygg med ett energieffektiviseringstiltak (LED-belysningsretrofit). Utviklings-fixture for den agentiske loopen: kontekst → hypotese → deterministisk validering → ekspert-dom → læring."
|
||||
tags: [energieffektivisering, M&V, IPMVP, mikro-eksempel, fixture]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# Bygg-energi mikro-eksempel
|
||||
|
||||
En **mikro OKF-bundle** (Open Knowledge Format): ett kontorbygg, ett kandidat-tiltak.
|
||||
Den er liten med vilje — formålet er **rask småskala-testing og validering** av den
|
||||
agentiske loopen gjennom hele utviklingsløpet. Et **realistisk fullskala-eksempel**
|
||||
bygges senere (målbilde §8); dette er forløperen.
|
||||
|
||||
> Dette er en framework-nøytral artefakt (null kode-avhengighet). Den deles uendret
|
||||
> mellom MAF- og Claude-SDK-implementasjonene. Se [shared/README.md](../../README.md).
|
||||
|
||||
## Hvorfor energieffektivisering
|
||||
|
||||
Domenet ble valgt for sin **lærings-overflate**: et reelt, dokumentert gap mellom det
|
||||
en deterministisk validator kan *regne* (modellert besparelse fra parametere) og det en
|
||||
fagekspert *kjenner* (faktisk realisert besparelse i drift). Det gapet — realiseringsgraden
|
||||
— er det lærings-sløyfa (ExpeL) skal lære. Se [verdict-led-fro.md](verdict-led-fro.md).
|
||||
|
||||
## Innhold (progressiv disclosure)
|
||||
|
||||
- [bygg-kontor-nord.md](bygg-kontor-nord.md) — `type: project` — bygget og energibaseline.
|
||||
- [tiltak-led-retrofit.md](tiltak-led-retrofit.md) — `type: hypothesis` — kandidat-tiltaket
|
||||
(LED-retrofit) med alle parametere for den modellerte besparelsen.
|
||||
- [metode-ipmvp-a.md](metode-ipmvp-a.md) — `type: methodology` — M&V-metoden (IPMVP Option A).
|
||||
- [kilder-realiseringsgap.md](kilder-realiseringsgap.md) — `type: reference` — verifisert
|
||||
litteratur om realiseringsgrad og dets årsaker.
|
||||
- [verdict-led-fro.md](verdict-led-fro.md) — `type: verdict` — frøsatt ekspert-dom som koder
|
||||
realiseringsgapet. **ExpeL-frøet** loopens steg 1 henter fra.
|
||||
|
||||
## Hvordan den kjøres i dag
|
||||
|
||||
`validator-input.json` er IR-projeksjonen den **eksisterende deterministiske validatoren**
|
||||
konsumerer uendret (energitiltaket mappet inn i kost-IR-en); `golden.json` fryser det
|
||||
forventede utfallet. Se [tiltak-led-retrofit.md](tiltak-led-retrofit.md) §«Mapping til validatoren».
|
||||
46
shared/examples/bygg-energi-mikro/kilder-realiseringsgap.md
Normal file
46
shared/examples/bygg-energi-mikro/kilder-realiseringsgap.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
type: reference
|
||||
title: "Realiseringsgrad og energy performance gap — verifisert litteratur"
|
||||
description: "Kildebelagte tall for gapet mellom modellert og faktisk realisert besparelse, og dets systematiske årsaker. Grunnlaget for verdict-frøets realiseringsgrad."
|
||||
tags: [realization-rate, performance-gap, M&V, evaluering, kilder]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# Realiseringsgrad (realization rate) — verifisert litteratur
|
||||
|
||||
**Realiseringsgrad (RR)** = faktisk evaluert besparelse (ex-post) ÷ modellert/påstått
|
||||
besparelse (ex-ante). RR < 1 betyr at drift leverte mindre enn modellen lovte. Avviket
|
||||
kalles *energy performance gap*. Alle tall under er verifisert mot primærkilde [V].
|
||||
|
||||
| Nivå | Funn | Kilde |
|
||||
|---|---|---|
|
||||
| Program (regulatorisk default) | Default gross RR **0,90** for kWh/kW/therm; ex-ante «generally over-estimated» | CPUC Resolution E-4952 |
|
||||
| Program (lys, drift lavere) | Operational adjustment ned til **81,1 %** (metrede driftstimer 15 % lavere); coincidence factor **0,566** vs antatt 1,0 | National Grid SBS 2010 (DNV KEMA) |
|
||||
| Program (lys, drift høyere) | Hours-of-Use RR **106,5 %**; coincidence 72,2 % — gapet går **begge veier** | Massachusetts Impact Evaluation 2010 |
|
||||
| Parameter (driftstimer) | Metret **3 053 t/år** vs antatt **3 772 t/år** (≈19 % lavere); CV ≈ 0,5 | Efficiency Maine 2021 |
|
||||
| Portefølje | Commercial lighting **98 %** vs residential **61 %** vs total **93 %** | LADWP Retrospective FY15/16–19/20 |
|
||||
| Bygg (grønne næringsbygg) | Predikert besparelse **1,5–3×** realisert; ~⅓ av LEED-bygg bruker mer energi | "Mind the energy performance gap", ScienceDirect |
|
||||
| Måleterskel | Besparelse bør overstige **~10 % av baseline** for å skilles pålitelig fra støy | FEMP/RDH M&V-veiledning |
|
||||
|
||||
## Systematiske årsaker (hvorfor faktisk < modellert) [V]
|
||||
|
||||
1. **Driftstimer / Hours-of-Use** — dominerende. Timeplan-baserte estimat (det Option A
|
||||
stipulerer) treffer sjelden metret brenntid (3 053 vs 3 772).
|
||||
2. **Baseline- og værjustering** — over-predikert baseline blåser opp absolutt besparelse.
|
||||
3. **Coincidence / diversity factor** — for effekt(kW): andel last under nett-topp ~0,57–0,72, ikke 1,0.
|
||||
4. **HVAC interactive effects** — mindre spillvarme → endret kjøle-/varmebehov; «too small to measure», stipuleres.
|
||||
5. **In-service rate, drift & persistens** — ikke alt installeres/forblir; styringer overstyres; degradering.
|
||||
6. **Måleusikkerhet** — under ~10 %-terskelen drukner signalet i støy.
|
||||
7. **Rebound / atferd** — mer lys på, lengre, fordi det «koster mindre».
|
||||
|
||||
## Kilder (URL)
|
||||
|
||||
- EVO IPMVP Generally Accepted M&V Principles (okt. 2018): https://evo-world.org/images/corporate_documents/IPMVP-Generally-Accepted-Principles_Final_26OCT2018.pdf
|
||||
- DOE/NREL Uniform Methods Project, Ch. 2 Commercial & Industrial Lighting (NREL 68558): https://docs.nrel.gov/docs/fy17osti/68558.pdf
|
||||
- Massachusetts Impact Evaluation of 2010 Prescriptive Lighting: https://ma-eeac.org/wp-content/uploads/Impact-Evaluation-of-2010-Prescriptive-Lighting-Installations-Final-Report-6-21-13.pdf
|
||||
- National Grid SBS 2010 Prescriptive Lighting (DNV KEMA): https://www.nationalgridus.com/media/pdfs/our-company/eereports/2014-ngrid-sbs-impact-eval-final-prot.pdf
|
||||
- Efficiency Maine Retail & Distributor Lighting 2021: https://www.efficiencymaine.com/docs/Retail-and-Distributor-Lighting-Final-Impact-Evaluation-Report-2021.pdf
|
||||
- LADWP Retrospective Impact Evaluation FY15/16–19/20: https://www.ladwp.com/sites/default/files/2024-01/LADWP%20Retrospective%20Report%20FINAL%20V4.pdf
|
||||
- CPUC Resolution E-4952: https://docs.cpuc.ca.gov/publisheddocs/published/g000/m232/k459/232459122.pdf
|
||||
- "Mind the energy performance gap" (ScienceDirect): https://www.sciencedirect.com/science/article/abs/pii/S0921344918303860
|
||||
- SSB Elektrisitetspriser (kraftpris tjenesteytende næringer, Q1 2026): https://www.ssb.no/energi-og-industri/energi/statistikk/elektrisitetspriser
|
||||
40
shared/examples/bygg-energi-mikro/metode-ipmvp-a.md
Normal file
40
shared/examples/bygg-energi-mikro/metode-ipmvp-a.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
type: methodology
|
||||
title: "IPMVP Option A — Retrofit Isolation, Key Parameter Measurement"
|
||||
description: "M&V-metoden for å verifisere besparelsen fra ett isolert tiltak ved å måle nøkkelparameteren (effekt) og estimere resten (driftstimer)."
|
||||
methodology: IPMVP
|
||||
option: A
|
||||
tags: [IPMVP, M&V, EVO, retrofit-isolation]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# M&V-metode: IPMVP Option A
|
||||
|
||||
**IPMVP** (International Performance Measurement and Verification Protocol) er
|
||||
konsensus-rammeverket for å måle og verifisere energibesparelser, eid og vedlikeholdt av
|
||||
**EVO** (Efficiency Valuation Organization). Kjerneinnsikten som begrunner hele
|
||||
lærings-sløyfa står eksplisitt i protokollen [V]:
|
||||
|
||||
> *"Savings cannot be directly measured, because savings represent the absence of energy use."*
|
||||
|
||||
Besparelse er en **kontrafaktisk** størrelse — det finnes ingen måler for «det som ikke ble
|
||||
brukt». Den *beregnes*: `Baseline-energi − Rapporterings-energi ± justeringer` (IPMVP Eq. 1).
|
||||
|
||||
## De fire opsjonene (EVO, offisielle navn) [V]
|
||||
|
||||
- **Option A — Retrofit Isolation: Key Parameter Measurement.** Måler nøkkelparameteren
|
||||
(typisk effekt) på det berørte utstyret; øvrige parametere (typisk driftstimer) *estimeres*.
|
||||
- **Option B — Retrofit Isolation: All Parameter Measurement.** Måler alle relevante parametere.
|
||||
- **Option C — Whole Facility.** Besparelse fra byggets hovedmåler, med rutinejustering (vær/produksjon).
|
||||
- **Option D — Calibrated Simulation.** Besparelse via simuleringsmodell kalibrert mot måledata.
|
||||
|
||||
## Hvorfor Option A for dette tiltaket [V]
|
||||
|
||||
EVOs egen tabell bruker nettopp et **lysarmatur-retrofit** som den kanoniske Option A-saken:
|
||||
effekt før/etter måles (billig, presist), mens **driftstimer stipuleres** fra byggets
|
||||
timeplan. Det gjør Option A enklest og billigst for ett isolert tiltak.
|
||||
|
||||
**Kritisk for lærings-overflaten:** parameteren Option A tillater å *estimere* — driftstimer
|
||||
— er nøyaktig der realiseringsgapet oppstår. Den stipulerte timeplanen treffer sjelden den
|
||||
faktiske, metrede brenntiden. Se [verdict-led-fro.md](verdict-led-fro.md) og
|
||||
[kilder-realiseringsgap.md](kilder-realiseringsgap.md).
|
||||
66
shared/examples/bygg-energi-mikro/tiltak-led-retrofit.md
Normal file
66
shared/examples/bygg-energi-mikro/tiltak-led-retrofit.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
type: hypothesis
|
||||
title: "LED-retrofit av kontorbelysning"
|
||||
description: "Bytte 200 lysrørarmaturer (3-rørs T8 troffer, ~90 W) til LED-paneler (~40 W). Kandidat-tiltak med modellert besparelse og usikkerhet."
|
||||
resource: BYGG-KONTOR-NORD
|
||||
measure_id: LED-RETROFIT-01
|
||||
tags: [LED, belysning, retrofit, ECM]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# Tiltak: LED-retrofit av kontorbelysning
|
||||
|
||||
Bytte av 200 lysrørarmaturer (2×4 fluorescerende troffer) til LED-paneler. Dette er det
|
||||
vanligste enkelt-ECM-et (Energy Conservation Measure) og IPMVPs egen kanoniske
|
||||
Option A-illustrasjon — se [metode-ipmvp-a.md](metode-ipmvp-a.md).
|
||||
|
||||
## Parametere
|
||||
|
||||
| Parameter | Verdi | Status | Kilde/forankring |
|
||||
|---|---|---|---|
|
||||
| Antall armaturer | 200 | [I] | mikro-skala valgt |
|
||||
| Effekt før (T8 troffer m/ ballast) | 90 W | [V] | 3×32 W ≈ 90–96 W m/ ballastfaktor |
|
||||
| Effekt etter (LED-panel) | 40 W | [V] | kommersielt 2×4 LED-panel ~40 W |
|
||||
| Reduksjon per armatur (ΔW) | 50 W | beregnet | 90 − 40 |
|
||||
| Driftstimer (HOU) | 3 000 t/år | [I] | forankret i metret 3 053 t (Efficiency Maine) |
|
||||
| Variabel energipris | 1,00 NOK/kWh | [V-forankret] | se [bygg-kontor-nord.md](bygg-kontor-nord.md) |
|
||||
|
||||
## Modellert besparelse (ex-ante)
|
||||
|
||||
Lysligning (DOE/NREL Uniform Methods Project, Eq. 3):
|
||||
`kWh = Σ (W_før − W_etter) × antall × HOU / 1000`
|
||||
|
||||
> ΔW = 90 − 40 = **50 W/armatur**
|
||||
> kWh/år = 50 × 200 × 3 000 / 1 000 = **30 000 kWh/år**
|
||||
> kr/år = 30 000 × 1,00 = **30 000 NOK/år**
|
||||
|
||||
HVAC-interaktiv effekt (effektivt lys → mindre spillvarme → endret kjøle-/varmebehov,
|
||||
UMP Eq. 6) er ~+5 % i elektrisk kjølte bygg, men **utelatt fra kjernetallet** her
|
||||
(konservativt; den lille interaktive justeringen er en ex-post-vurdering eksperten kan
|
||||
legge til). Modellert kjernebesparelse: **30 000 kWh/år ≈ 30 000 NOK/år**.
|
||||
|
||||
## Usikkerhet (for Monte Carlo P10/P50/P90)
|
||||
|
||||
Den dominerende usikkerheten i en *energibesparelse* ligger i driftstimer (HOU), ikke
|
||||
prisen — men den eksisterende validatorens Monte Carlo varierer enhetspris. I denne
|
||||
mikro-mappingen brukes derfor **prisbandet 0,70–1,40 NOK/kWh** som usikkerhetsakse
|
||||
(region/sesong, jf. [bygg-kontor-nord.md](bygg-kontor-nord.md)). Den fysiske HOU-usikkerheten
|
||||
og — viktigere — den *systematiske* HOU-skjevheten håndteres i verdict-laget, ikke her.
|
||||
|
||||
## Mapping til validatoren (hvorfor `validator-input.json` ser ut som den gjør)
|
||||
|
||||
Den eksisterende deterministiske validatoren er en *feasibility-gate* (`claimed ≤ 30 % av
|
||||
affected total`, Monte Carlo over enhetspris) bygd for kostnadskutt. Energitiltaket mappes
|
||||
inn **uendret**:
|
||||
|
||||
- `affected_items = [{code: "ENERGI-TOTAL-EL", quantity: 300000 kWh/år, unit_cost: 1.00 NOK/kWh}]`
|
||||
→ byggets **totale** årlige energikostnad (300 000 NOK). LED-besparelsen er ~10 % av den,
|
||||
godt innenfor 30 %-cap-en.
|
||||
- `claimed_saving_nok = 30000` → den modellerte LED-besparelsen.
|
||||
- `assumptions = {"ENERGI-TOTAL-EL": [0.70, 1.40]}` → prisbandet for Monte Carlo.
|
||||
|
||||
**Ærlig begrensning:** validatorens P10/P50/P90 betyr her «øvre feasible grense» (30 % av
|
||||
samplet energikostnad), *ikke* «LED-besparelsens fysiske band». Det er bevisst — den
|
||||
domenetro besparelses-modelleringen og realiseringsgapet hører hjemme i verdict-laget
|
||||
([verdict-led-fro.md](verdict-led-fro.md)), som er nettopp det lærings-sløyfa skal lære.
|
||||
En energi-bevisst validator (ΔW × antall × HOU) er senere fase-arbeid, ikke dette fixturet.
|
||||
16
shared/examples/bygg-energi-mikro/validator-input.json
Normal file
16
shared/examples/bygg-energi-mikro/validator-input.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"_note": "IR-projeksjon (ir.SavingsProposal) for det eksisterende deterministiske validatoren. Energitiltaket er mappet inn i kost-IR-en UENDRET: affected_items = byggets totale arlige energikostnad; claimed_saving_nok = modellert LED-besparelse (~10% av total, innenfor 30%-cap); assumptions = energipris-band (NOK/kWh) for Monte Carlo. Se tiltak-led-retrofit.md, seksjon 'Mapping til validatoren'.",
|
||||
"project_id": "BYGG-KONTOR-NORD",
|
||||
"measure": "LED-retrofit av 200 lysrorarmaturer (90 W -> 40 W) i kontorlokaler",
|
||||
"affected_items": [
|
||||
{
|
||||
"code": "ENERGI-TOTAL-EL",
|
||||
"quantity": 300000,
|
||||
"unit_cost": 1.0
|
||||
}
|
||||
],
|
||||
"claimed_saving_nok": 30000,
|
||||
"assumptions": {
|
||||
"ENERGI-TOTAL-EL": [0.70, 1.40]
|
||||
}
|
||||
}
|
||||
56
shared/examples/bygg-energi-mikro/verdict-led-fro.md
Normal file
56
shared/examples/bygg-energi-mikro/verdict-led-fro.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
type: verdict
|
||||
title: "Ekspert-dom (frø): LED-retrofit — godkjent med realiseringskorreksjon"
|
||||
description: "Frøsatt ekspert-dom som koder realiseringsgapet for LED-tiltaket. ExpeL-frøet loopens steg 1 henter fra: modellert besparelse korrigeres ned med realiseringsgraden eksperten kjenner fra drift."
|
||||
resource: BYGG-KONTOR-NORD
|
||||
measure_id: LED-RETROFIT-01
|
||||
decision: approved_with_adjustment
|
||||
realization_rate: 0.82
|
||||
modelled_saving_nok: 30000
|
||||
expected_actual_saving_nok: 24600
|
||||
gap_source: hours-of-use-overestimation
|
||||
context_key: "kontorbygg; HOU-kilde=timeplan-stipulert"
|
||||
provenance: "frø — AI-forfattet, forankret i National Grid SBS 2010 (RR 0,81); erstattes av ekte HITL i produksjon"
|
||||
tags: [verdict, realization-rate, ExpeL-seed, HITL]
|
||||
timestamp: 2026-06-29
|
||||
---
|
||||
|
||||
# Ekspert-dom (frø): LED-retrofit
|
||||
|
||||
> **Dette er et frø**, ikke en ekte dom. I simulering gir en ekspert-persona slike dommer;
|
||||
> i produksjon gir et menneske dem via samme mappe-grensesnitt. Frøet er forankret i
|
||||
> verifisert litteratur ([kilder-realiseringsgap.md](kilder-realiseringsgap.md)), ikke
|
||||
> oppdiktet. Det er **provenance-merket** og promoteres til wikien kun fordi en (simulert)
|
||||
> ekspert har godkjent det (målbilde, steg 8 gated).
|
||||
|
||||
## Dommen
|
||||
|
||||
**Beslutning:** godkjent — med realiseringskorreksjon.
|
||||
|
||||
Den modellerte besparelsen (**30 000 NOK/år**) er teknisk korrekt fra parameterne, og
|
||||
validatoren bekrefter at den er innenfor feasibelt område. Men i drift realiseres erfaringsvis
|
||||
**~82 %** av en timeplan-stipulert LED-besparelse i kontorbygg → forventet faktisk
|
||||
besparelse **≈ 24 600 NOK/år**.
|
||||
|
||||
## Begrunnelse (det validatoren ikke kan regne)
|
||||
|
||||
Realiseringsgapet her er **ikke** spredning i parameterne — det er en *systematisk skjevhet*
|
||||
mellom de stipulerte parameterne og driftsvirkeligheten:
|
||||
|
||||
- **Driftstimer overvurdert (dominerende):** den antatte timeplanen (3 000 t) ligger over
|
||||
faktisk metret brenntid — naturlig dagslys, tomme rom, sensorstyring. Jf. National Grid
|
||||
(RR-bidrag 0,81 fra 15 % lavere metrede timer) og Efficiency Maine (3 053 vs 3 772 t).
|
||||
- **In-service rate < 1:** ikke alle 200 armaturer er nødvendigvis montert/i drift ved
|
||||
evaluering.
|
||||
- **Atferd/persistens:** rebound (mer lys på fordi det «er gratis») og overstyrte styringer.
|
||||
|
||||
Du kan **ikke** regne deg til RR = 0,82 fra `{200, 90 W, 40 W, 3 000 t, 1,00 NOK/kWh}`.
|
||||
Skjevheten er epistemikk parameterne ikke bærer — den finnes bare i akkumulert drifts-erfaring.
|
||||
|
||||
## Lærings-signalet (ExpeL)
|
||||
|
||||
Korreksjonen er **kontekstbetinget**: `context_key = "kontorbygg; HOU-kilde=timeplan-stipulert"`.
|
||||
Neste kjøring, gitt en lignende hypotese i samme kontekst, skal hente denne dommen og
|
||||
justere den modellerte ex-ante-besparelsen mot forventet ex-post (≈ 0,82×) — uten å vente
|
||||
på 12 måneders måling. **Det er denne dataflyten — verdict inn i neste hypotese — loopens
|
||||
steg 1 må wire (målbilde §5, §7). Dette frøet er testankeret.**
|
||||
123
tests/test_bygg_energi_mikro.py
Normal file
123
tests/test_bygg_energi_mikro.py
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
"""Bygg-energi mikro-eksempel — fixture-konsumerbarhet (shared/examples/bygg-energi-mikro).
|
||||
|
||||
The energi micro-fixture is a *dev fixture* exercised through the whole build. These tests
|
||||
prove it is actually consumable, not merely present:
|
||||
|
||||
1. the IR projection (``validator-input.json``) drives the EXISTING deterministic validator to
|
||||
a ``ValidatedProposal`` (not a ``Rejection``) — energi mapped into the cost-IR unchanged;
|
||||
2. that validator output is frozen against ``golden.json`` (seeded ``_MC_SEED=20260624``);
|
||||
3. the OKF bundle is well-formed (every file declares ``type``; index cross-links resolve);
|
||||
4. the seed verdict encodes a realization gap (RR < 1) consistent with the golden — the anchor
|
||||
the later step-1 ExpeL wiring becomes load-bearing against.
|
||||
|
||||
No ``yaml`` dependency: frontmatter is parsed with a minimal key:value reader.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from portfolio_optimiser.ir import AffectedItem, SavingsProposal
|
||||
from portfolio_optimiser.validator import Rejection, ValidatedProposal, validate_proposal
|
||||
|
||||
BUNDLE_DIR = Path(__file__).resolve().parents[1] / "shared" / "examples" / "bygg-energi-mikro"
|
||||
|
||||
_EXPECTED_TYPES = {
|
||||
"index.md": "index",
|
||||
"bygg-kontor-nord.md": "project",
|
||||
"tiltak-led-retrofit.md": "hypothesis",
|
||||
"metode-ipmvp-a.md": "methodology",
|
||||
"kilder-realiseringsgap.md": "reference",
|
||||
"verdict-led-fro.md": "verdict",
|
||||
}
|
||||
|
||||
|
||||
def _parse_frontmatter(path: Path) -> dict[str, str]:
|
||||
"""Minimal YAML-frontmatter reader: the ``---``-delimited leading block as key:value
|
||||
strings. Enough for ``type`` and the verdict's scalar fields; list values (``tags: [...]``)
|
||||
are kept verbatim and unused."""
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
if not lines or lines[0].strip() != "---":
|
||||
return {}
|
||||
fm: dict[str, str] = {}
|
||||
for line in lines[1:]:
|
||||
if line.strip() == "---":
|
||||
break
|
||||
key, sep, val = line.partition(":")
|
||||
if sep:
|
||||
fm[key.strip()] = val.strip()
|
||||
return fm
|
||||
|
||||
|
||||
def _proposal_from_input() -> SavingsProposal:
|
||||
raw = json.loads((BUNDLE_DIR / "validator-input.json").read_text(encoding="utf-8"))
|
||||
return SavingsProposal(
|
||||
project_id=raw["project_id"],
|
||||
measure=raw["measure"],
|
||||
affected_items=[AffectedItem(**a) for a in raw["affected_items"]],
|
||||
claimed_saving_nok=raw["claimed_saving_nok"],
|
||||
assumptions={k: tuple(v) for k, v in raw["assumptions"].items()},
|
||||
)
|
||||
|
||||
|
||||
def _golden() -> dict:
|
||||
return json.loads((BUNDLE_DIR / "golden.json").read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def test_validator_input_validates() -> None:
|
||||
"""The core: the energi tiltak, mapped into the cost-IR, passes the blocking validator —
|
||||
a ``ValidatedProposal``, never a ``Rejection`` (claimed 30k < P90 feasible)."""
|
||||
result = validate_proposal(_proposal_from_input())
|
||||
assert isinstance(result, ValidatedProposal)
|
||||
assert not isinstance(result, Rejection)
|
||||
assert result.proposal.claimed_saving_nok < result.p90
|
||||
assert result.p10 <= result.p50 <= result.p90
|
||||
|
||||
|
||||
def test_validator_output_matches_golden() -> None:
|
||||
"""Regression: the deterministic (seeded) percentiles match the frozen golden."""
|
||||
result = validate_proposal(_proposal_from_input())
|
||||
assert isinstance(result, ValidatedProposal)
|
||||
g = _golden()["validator"]
|
||||
assert g["validates"] is True
|
||||
assert result.nominal_feasible == pytest.approx(g["nominal_feasible"])
|
||||
assert result.p10 == pytest.approx(g["p10"])
|
||||
assert result.p50 == pytest.approx(g["p50"])
|
||||
assert result.p90 == pytest.approx(g["p90"])
|
||||
|
||||
|
||||
def test_bundle_files_declare_type() -> None:
|
||||
"""Every OKF bundle file carries the one required field (``type``) with the expected value."""
|
||||
for name, expected_type in _EXPECTED_TYPES.items():
|
||||
fm = _parse_frontmatter(BUNDLE_DIR / name)
|
||||
assert fm.get("type") == expected_type, f"{name}: type={fm.get('type')!r}"
|
||||
|
||||
|
||||
def test_index_crosslinks_resolve() -> None:
|
||||
"""Intra-bundle cross-links in ``index.md`` resolve to existing files (our own example
|
||||
must have no broken links, even though OKF consumers must tolerate them)."""
|
||||
index = (BUNDLE_DIR / "index.md").read_text(encoding="utf-8")
|
||||
targets = re.findall(r"\]\(([^)]+\.md)\)", index)
|
||||
internal = [t for t in targets if "/" not in t]
|
||||
assert internal, "expected intra-bundle .md links in index.md"
|
||||
for target in internal:
|
||||
assert (BUNDLE_DIR / target).exists(), f"index links to missing {target}"
|
||||
|
||||
|
||||
def test_verdict_seed_encodes_realization_gap() -> None:
|
||||
"""The seed verdict encodes a realization gap (RR < 1), and the golden learning-surface is
|
||||
internally consistent (expected_actual = RR x modelled). This is the anchor the later
|
||||
step-1 ExpeL wiring is made load-bearing against."""
|
||||
fm = _parse_frontmatter(BUNDLE_DIR / "verdict-led-fro.md")
|
||||
rr = float(fm["realization_rate"])
|
||||
assert 0.0 < rr < 1.0, "a realization gap means RR strictly below 1"
|
||||
|
||||
ls = _golden()["learning_surface"]
|
||||
assert ls["realization_rate"] == pytest.approx(rr)
|
||||
assert ls["expected_actual_saving_nok"] == pytest.approx(
|
||||
ls["realization_rate"] * ls["modelled_saving_nok"]
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue