Model/domain/modelling/contingencies.py
Khalim Conn-Kowlessar 7648032d73 feat(modelling): wire solid-wall insulation into the candidate pool
Slice 2e. recommend_solid_wall joins the orchestrator's fabric generator pool
(restrictions default unrestricted until slice 3 sources them); the harness
catalogue + contingencies (26%) gain external_wall_insulation /
internal_wall_insulation. run_modelling on an uninsulated solid-brick dwelling
(baseline SAP 36.6) now selects internal wall insulation into the optimised
package; the catalogue-completeness guard covers both new measure types.
Golden cohort 57/57 still error-free; IWI now fires on a real cohort cert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 16:15:56 +00:00

27 lines
959 B
Python

"""Per-Measure-Type contingency rates.
The one cost component carried separately from a Product's fully-loaded total
(CONTEXT.md). Mirrors the legacy `recommendations/Costs.py::Costs.CONTINGENCIES`;
extended as each measure type lands.
"""
_CONTINGENCY_RATES: dict[str, float] = {
"cavity_wall_insulation": 0.10,
"loft_insulation": 0.10,
"suspended_floor_insulation": 0.20,
"solid_floor_insulation": 0.26,
"mechanical_ventilation": 0.26,
"external_wall_insulation": 0.26,
"internal_wall_insulation": 0.26,
}
def contingency_rate(measure_type: str) -> float:
"""Return the contingency rate for a Measure Type, raising if unknown
(strict — do not silently default, per the repo's strict-raise convention)."""
try:
return _CONTINGENCY_RATES[measure_type]
except KeyError as exc:
raise ValueError(
f"no contingency rate configured for measure type {measure_type!r}"
) from exc