Model/docs/adr/0005-multi-phase-scenarios-per-phase-recompute.md
2026-05-16 14:15:56 +00:00

2.3 KiB
Raw Blame History

Multi-phase scenarios with per-phase recompute against rolling state

The Scenario aggregate becomes ordered phases: each phase has a measure-type allowlist, an optional budget, and an optional goal. The ModellingPipeline walks the phases in order; for each phase it (1) generates candidate recommendations restricted to the phase's measure types, (2) re-runs ImpactPredictionService against the rolling Effective EPC state (baseline for phase 1; post-phase-1 for phase 2; etc.), (3) optimises within the phase's budget/goal, (4) applies the selected package and rolls the state forward. We considered scoring all measures once against the baseline and slicing the scored list by phase, and rejected that.

Per-phase recompute makes phase ordering load-bearing in the optimisation, not decorative. Installing fabric measures before a heat pump materially changes the heat pump's SAP impact; a single-pass-against-baseline pipeline forces that fact into the optimiser as a hard rule rather than a derived effect, and any cross-measure interaction we don't know to encode becomes silent error. The cost is ML calls scaling with N_phases × N_scenarios × N_candidate_measures per property — multi-phase scenarios pay their own ML bill, single-phase scenarios cost the same as today (the loop body runs once).

A single-phase Scenario is phases: [<one ScenarioPhase>] with all measure types allowed and the full budget on it. There is no special-case path for single-phase — the pipeline always loops. This avoids two code paths and lets the FE evolve from single-phase to multi-phase without rewiring the backend.

Consequences

  • Plan carries phases: list[PlanPhase] rather than a flat OptimisedPackage. Every consumer of plan output (FE, exports, downstream reports) reads phases.
  • The optimiser must accept rolling-state input rather than only baseline state — a generalisation of today's single-shot pass.
  • ML cost can be controlled at the scenario layer: keeping a scenario single-phase is the lever for "score once, optimise once" if cost becomes a problem.
  • Open future change: SAP impact of a measure is not strictly additive even within a phase. The current per-measure scoring + linear optimisation approximates this. A future iteration may pre-define candidate packages and ML-score whole packages, accepting combinatorial cost for accuracy. Track in PRD §15.