mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Outcome of the /grill-with-docs session scoping #1157. - CONTEXT.md: add **Plan Measure** (the persisted selected Option + role-3 attribution + cost); Recommendation stays the candidate. Remove Scenario Phase / Plan Phase / Rolled-over Options — multi-phase is deferred. Reshape Scenario + Plan to single-phase; fix relationships, dialogue, and the "phase" ambiguity note. - ADR-0005: rewritten to Deferred (multi-phase was speculative prospective-client work; single-phase now; future plan_phase back-fill path preserved). Stray phase refs cleaned in ADR-0016 / ADR-0009. - ADR-0017 (new): Plan persistence — reuse the live plan/recommendation tables via SQLModel mirrors + a PlanRepository on the UoW; add recommendation.plan_id, retire the plan_recommendations m2m; flat post-retrofit on plan; idempotent replace; CO2 in tonnes. Unselected alternatives + bills noted as deferred directions. - docs/migrations/recommendation-plan-id.md: the FE-owned Drizzle change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
31 lines
3.7 KiB
Markdown
31 lines
3.7 KiB
Markdown
# Multi-phase scenarios — deferred (speculative)
|
||
|
||
**Status: Deferred / Out of scope.** Superseded by the single-phase decision taken in a `/grill-with-docs` session (2026-06-03) while scoping the #1157 Plan persistence schema. This ADR previously proposed an *Accepted* multi-phase Scenario aggregate with per-phase recompute against rolling state; that design is **not** being built now. The original proposal is preserved below under "Deferred design" for the day the requirement returns.
|
||
|
||
## Why deferred
|
||
|
||
Multi-phase sequencing — letting a user split a Scenario into ordered phases ("fabric this year, heat pump next, solar after"), each with its own measure allowlist / budget / target, and producing Plans shaped to match — came from a **prospective (not current) client**. It is entirely speculative: we may never build it. Baking it into the core domain as an accepted decision made the model "too strong" — it forced a first-class **Scenario Phase** / **Plan Phase** / **Rolled-over Options** vocabulary and a `plan_phase` table into a live product that has no consumer for any of it.
|
||
|
||
The current goal is to **replicate and improve the existing pipeline**, which is single-phase. So:
|
||
|
||
- A **Scenario** carries one set of permitted measure types (no ordered phases).
|
||
- A **Plan** holds one **Optimised Package** of **Plan Measures** plus the Property's flat post-retrofit figures (the legacy `plan` columns). There is no `plan_phase` table and no `phase` column.
|
||
- The terms **Scenario Phase**, **Plan Phase**, and **Rolled-over Options** are removed from `CONTEXT.md`.
|
||
|
||
This is cheap to reverse: re-introducing phases is additive, and the [ADR-0016](0016-package-rescore-over-warm-start-optimisation.md) scoring split (per-Option signal → whole-package re-score → marginal-cascade attribution) already works against a single package and generalises to per-phase rolling state unchanged.
|
||
|
||
## Future migration path (when/if the requirement returns)
|
||
|
||
Scope it properly as a feature in its own right — do **not** retrofit it implicitly. The migration shape we expect:
|
||
|
||
1. Add a `plan_phase` table; give each existing live **Plan** exactly one Plan Phase and back-fill its current Optimised Package + post-retrofit figures into that single phase.
|
||
2. Add ordered phases to the **Scenario** aggregate (allowlist / budget / target per phase).
|
||
3. Generalise the Optimiser to run per phase against the **rolling** Effective EPC (phase 1 = baseline; phase 2 = post-phase-1 state; …), so phase ordering becomes load-bearing in the optimisation rather than decorative.
|
||
|
||
This back-fill keeps every live single-phase Plan valid as a degenerate one-phase case.
|
||
|
||
## Deferred design (original proposal, for reference)
|
||
|
||
The Scenario aggregate becomes ordered phases: each phase has a measure-type allowlist, an optional budget, and an optional goal. The pipeline walks the phases in order; for each phase it (1) generates candidate recommendations restricted to the phase's measure types, (2) re-runs scoring 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.
|
||
|
||
The rationale was 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. The cost is ML/calculator calls scaling with `N_phases × N_scenarios × N_candidate_measures` per property. A single-phase Scenario was modelled as `phases: [<one ScenarioPhase>]` with all measure types allowed — i.e. exactly the single-phase product we are now building directly, without the phase machinery.
|