Model/domain/modelling
Khalim Conn-Kowlessar ae7e6a0c42 feat(modelling): composite per-dwelling boiler + tune-up costing (ADR-0027)
Replace the flat placeholder scalars (boiler £3000; tune-up £500/£900) with a
per-dwelling composite cost, mirroring the ASHP architecture (ADR-0025): a
`HeatingRates` table (data, `heating_rates.json`), typed `BoilerCostInputs` /
`TuneUpCostInputs`, pure `Products.boiler_bundle_cost` / `tune_up_cost`, and
modelling-layer interpreters that read the dwelling into those inputs.

The cost mirrors the Simulation Overlay component-for-component, sharing the
controls + cylinder pricing across both options:

- tune-up (standard) = standard controls + cylinder fixes
- tune-up (zone)     = zone controls + cylinder fixes
- boiler upgrade     = £3200 all-in + standard controls (only when the upgrade
  fired a controls change) + cylinder fixes

Standard controls are priced INCREMENTALLY — only the parts missing to reach
SAP 2106 (programmer £120 / room thermostat £150 / TRV £35×radiators), read
from a Table 4e Group-1 feature map so a dwelling that already has a room
thermostat + TRVs is only charged the programmer. Zone controls are a full
smart kit (hub £205 + smart TRV £50×radiators) — the smart TRV is itself the
room sensor, so there is no separate per-room sensor line. Cylinder fixes:
jacket £50 (when under-insulated) + thermostat £150 (when absent). The boiler
is a like-for-like wet swap (no radiators/flue/pipework — eligibility already
requires an existing wet boiler), so those dead-code extras are not modelled.

Figures are research-validated 2025/26 UK installed costs (legacy Costs.py
lineage); fully-loaded totals with one contingency on top (Model B, not the
legacy VAT/preliminaries engine). Contingency: boiler 0.26; tune-ups 0.10
(was a 0.15 placeholder). ADR-0027 records the design; CONTEXT.md's Heating
Eligibility entry updated to cover the partial boiler/tune-up family + composed
cost. Products cost pins (delta<=1e-9) + interpreter tests + generator
composite-cost assertions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 19:41:06 +00:00
..
generators feat(modelling): composite per-dwelling boiler + tune-up costing (ADR-0027) 2026-06-10 19:41:06 +00:00
optimisation refactor(modelling): type measure_type fields as MeasureType 2026-06-08 20:13:31 +00:00
scoring feat(modelling): solid-fuel(coal)->gas boiler upgrade + boiler_flue_type end-state 2026-06-10 08:27:07 +00:00
__init__.py feat(modelling): Overlay Applicator folds EpcSimulation onto EpcPropertyData 2026-06-02 22:13:51 +00:00
ashp_rates.json refactor(modelling): load ASHP rates from a committed costs file 2026-06-06 23:19:53 +00:00
considered_measures.py feat(modelling): considered_measures allowlist on the orchestrator 2026-06-08 20:32:11 +00:00
contingencies.py feat(modelling): composite per-dwelling boiler + tune-up costing (ADR-0027) 2026-06-10 19:41:06 +00:00
heating_rates.json feat(modelling): composite per-dwelling boiler + tune-up costing (ADR-0027) 2026-06-10 19:41:06 +00:00
measure_type.py feat(modelling): system tune-up options (standard + zone controls) 2026-06-10 10:20:46 +00:00
plan.py refactor(modelling): type measure_type fields as MeasureType 2026-06-08 20:13:31 +00:00
portfolio_goal.py refactor(modelling): move PortfolioGoal to domain/modelling/ 2026-06-03 22:44:48 +00:00
product.py feat(modelling): persist recommendation.material_id from the catalogue 2026-06-04 08:26:58 +00:00
products.py feat(modelling): composite per-dwelling boiler + tune-up costing (ADR-0027) 2026-06-10 19:41:06 +00:00
recommendation.py refactor(modelling): type measure_type fields as MeasureType 2026-06-08 20:13:31 +00:00
scenario.py feat(modelling): domain Scenario + ScenarioPostgresRepository (#1157) 2026-06-03 11:19:52 +00:00
simulation.py feat(modelling): solid-fuel(coal)->gas boiler upgrade + boiler_flue_type end-state 2026-06-10 08:27:07 +00:00
solar_potential.py feat(modelling): typed SolarPotential projection over Google buildingInsights 2026-06-08 09:55:55 +00:00
solar_rates.json feat(modelling): Products.solar_bundle_cost + committed solar rate sheet 2026-06-08 12:10:27 +00:00
valuation.py feat(modelling): ValuationUplift domain class (percentage-primary) 2026-06-04 08:33:19 +00:00