feat(portfolio): K2 — sequential multi-project run (parity row 4)
New portfolio.py: run_portfolio drives N projects sequentially from a schema-validated reference config, composing each project's §5 context (merge inbox -> seed -> fold) and running the loop core UNCHANGED per project, collecting one typed result per project IN CONFIG ORDER. This is the run path MAF got in its Fase 1 and D7 never had — the prior entrances (run.py, run_s10.py) drive a single bundle. PortfolioResult holds per-project results tagged with the config project_id. Re-entrancy (§3 Step 3): each project composes its OWN context inside the loop, never a hoisted shared one, so nothing survives one project into the next except the explicitly shared mutable state — the §8 budget meter, a portfolio-wide cap. Failure policy is a STACK-LOCAL choice until D-D: the default RAISES (today everything is thrown); K18 flips it to collect-and-continue when the D-D wave model lands. New config contract in contracts.py: ReferenceProjectContract (project_id + required non-empty bundle_dir + optional inbox_dir) + ReferenceProjectsContract, loaded fail-fast by load_reference_projects (§10) — a project without a bundle path is refused before any run. New data/reference_projects.json example (shape-validated, never executed by the suite). New repo-local mini-bundle fixture under tests/data/ (a distinct second project, VFD-retrofit — ALDRI in shared/). Two detach proofs delivered: drop the bundle_dir Field requirement -> a run starts on the invalid config and only crashes mid-run -> the fail-fast test goes red; hoist the per-project composition out of the loop -> project 2 runs on project 1's context and the VFD marker never reaches its prompt -> the re-entrancy test goes red. 11 new tests (test_portfolio.py 5 + test_contracts.py TestReferenceProjects 6). 426 -> 437 tests, golden byte-exact, full gate clean (ruff + format + mypy strict). README synced (test count + a Run layer module block). [skip-docs] — README documents the new module; CLAUDE.md holds invariants (rules/commands) only, and K2 adds no new invariant, command, or convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiTwaKLesgcwXx2mDviqpt
This commit is contained in:
parent
a7e8ffecb8
commit
f2c64da9ee
10 changed files with 406 additions and 3 deletions
21
tests/data/mini-bundle/index.md
Normal file
21
tests/data/mini-bundle/index.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
type: index
|
||||
title: "Mini-bundle (K2-fixture) — pumpe-VFD, ett tiltak"
|
||||
description: "Repo-lokal mini OKF-bundle for portefølje-testing (K2): ett bygg, ett VFD-retrofit-tiltak. ALDRI i shared/ — dette er en test-fixture, ikke en delt fasit."
|
||||
tags: [fixture, portefølje, K2]
|
||||
timestamp: 2026-07-16
|
||||
---
|
||||
|
||||
# Mini-bundle (K2-fixture) — K2-VFD-CONTEXT-MARKER
|
||||
|
||||
En repo-lokal **mini OKF-bundle** brukt KUN av porteføljetesten (`test_portfolio.py`): ett
|
||||
bygg, ett kandidat-tiltak (VFD-retrofit på sirkulasjonspumper). Den ligger under `tests/data/`
|
||||
med vilje — den er en test-fixture og deles ALDRI som fasit i `shared/`.
|
||||
|
||||
Formålet er et andre, distinkt prosjekt ved siden av `shared/examples/bygg-energi-mikro`, så
|
||||
`run_portfolio` kan kjøre N prosjekter sekvensielt med per-prosjekt kontekst.
|
||||
|
||||
## Innhold
|
||||
|
||||
- [tiltak-vfd.md](tiltak-vfd.md) — `type: hypothesis` — VFD-retrofit-kandidaten.
|
||||
- [verdict-vfd-fro.md](verdict-vfd-fro.md) — `type: verdict` — frøsatt ekspert-dom (ExpeL-frø).
|
||||
21
tests/data/mini-bundle/tiltak-vfd.md
Normal file
21
tests/data/mini-bundle/tiltak-vfd.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
type: hypothesis
|
||||
title: "VFD-retrofit av sirkulasjonspumper"
|
||||
description: "Turtallsregulering (variable frequency drive) på 12 sirkulasjonspumper som i dag går på konstant hastighet."
|
||||
measure_id: VFD-RETROFIT-01
|
||||
resource: PUMPE-SOR
|
||||
tags: [pumper, VFD, energieffektivisering]
|
||||
timestamp: 2026-07-16
|
||||
---
|
||||
|
||||
# VFD-retrofit av sirkulasjonspumper
|
||||
|
||||
Kandidat-tiltaket: montere frekvensomformere (VFD) på 12 sirkulasjonspumper i et
|
||||
sørvendt næringsbygg. Pumpene går i dag på konstant turtall; med turtallsregulering
|
||||
følger de faktisk lastbehov, og pumpeeffekten faller tilnærmet kubisk med turtallet.
|
||||
|
||||
## Mapping til validatoren
|
||||
|
||||
`validator-input.json` projiserer tiltaket inn i kost-IR-en: `affected_items` er byggets
|
||||
årlige pumpe-energikostnad (`ENERGI-PUMPE-EL`), `claimed_saving_nok` er den modellerte
|
||||
VFD-besparelsen, og `assumptions` bærer energipris-båndet for Monte Carlo-en.
|
||||
16
tests/data/mini-bundle/validator-input.json
Normal file
16
tests/data/mini-bundle/validator-input.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"_note": "IR-projeksjon (ir.SavingsProposal) for K2-fixturen. Distinkt fra bygg-energi-mikro: annet prosjekt, annet tiltak, annen kost-kode. claimed_saving_nok ligger godt under feasibel-grensen (0.30 x 120000 = 36000) slik at validate_proposal deterministisk gir ValidatedProposal uansett MC-band.",
|
||||
"project_id": "PUMPE-SOR",
|
||||
"measure": "VFD-retrofit av 12 sirkulasjonspumper (konstant -> turtallsregulert drift)",
|
||||
"affected_items": [
|
||||
{
|
||||
"code": "ENERGI-PUMPE-EL",
|
||||
"quantity": 120000,
|
||||
"unit_cost": 1.0
|
||||
}
|
||||
],
|
||||
"claimed_saving_nok": 12000,
|
||||
"assumptions": {
|
||||
"ENERGI-PUMPE-EL": [0.70, 1.40]
|
||||
}
|
||||
}
|
||||
26
tests/data/mini-bundle/verdict-vfd-fro.md
Normal file
26
tests/data/mini-bundle/verdict-vfd-fro.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
type: verdict
|
||||
title: "Ekspert-dom (frø): VFD-retrofit — godkjent med realiseringskorreksjon"
|
||||
description: "Frøsatt ekspert-dom for VFD-tiltaket. Koder et realiseringsgap distinkt fra LED-frøet (0.75, ikke 0.82) så porteføljetesten kan skille prosjektenes kontekst."
|
||||
resource: PUMPE-SOR
|
||||
measure_id: VFD-RETROFIT-01
|
||||
decision: approved_with_adjustment
|
||||
realization_rate: 0.75
|
||||
modelled_saving_nok: 12000
|
||||
expected_actual_saving_nok: 9000
|
||||
gap_source: pump-affinity-oversimplification
|
||||
context_key: "naeringsbygg; pumpe-last=stipulert"
|
||||
provenance: "frø — AI-forfattet test-fixture; erstattes av ekte HITL i produksjon"
|
||||
tags: [verdict, realization-rate, ExpeL-seed, fixture]
|
||||
timestamp: 2026-07-16
|
||||
---
|
||||
|
||||
# Ekspert-dom (frø): VFD-retrofit
|
||||
|
||||
> **Dette er et frø**, ikke en ekte dom — en test-fixture for porteføljekjøringen.
|
||||
|
||||
## Dommen
|
||||
|
||||
**Beslutning:** godkjent — med realiseringskorreksjon. Den modellerte besparelsen er
|
||||
teknisk plausibel, men i drift realiseres erfaringsvis ~75 % fordi den antatte
|
||||
affinitets-forenklingen overvurderer hvor mye tid pumpene faktisk kjører på redusert turtall.
|
||||
Loading…
Add table
Add a link
Reference in a new issue