An incomplete heating companion set raises instead of logging 🟩

ADR-0048's intended end-state (#1444 Part C): every mapped archetype now
resolves confident companions, so an incomplete set can only mean a new
archetype landed without choosing them — fail loudly at overlay time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-03 14:22:40 +00:00
parent 1925cdd65d
commit 6707ab084f

View file

@ -28,7 +28,6 @@ are left UNKNOWN until modelled. Unresolvable values produce no overlay.
from __future__ import annotations
import logging
from typing import Optional
from domain.modelling.simulation import EpcSimulation, HeatingOverlay
@ -36,8 +35,6 @@ from domain.sap10_calculator.tables.table_12a import (
OFF_PEAK_IMPLYING_HEATING_CODES,
)
logger = logging.getLogger(__name__)
# Off-peak (Economy 7) meter. Electric storage / CPSU systems charge overnight at
# the low rate and cannot run economically on a single-rate meter; "Dual" lets
# the §12 dispatch resolve the specific tariff (storage 7-hour, CPSU 10-hour).
@ -418,21 +415,19 @@ def main_heating_overlay_for(
category = _category_for(code)
control = _control_for(code)
if category is None or control is None:
# A system-replacing override should stamp a complete, coherent companion
# A system-replacing override must stamp a complete, coherent companion
# set; an unmapped category or control leaves the field unset, so the
# effective cert inherits the REPLACED system's value (a silent mis-rating
# — e.g. a room heater keeping a storage heater's category/control). We do
# not yet have confident defaults for every archetype, so log-and-continue
# (matching `flag_fuel_mismatch`) to make the gap visible for review
# rather than raise mid-run.
logger.error(
"Landlord main_heating_system %r (SAP code %d) overlaid with an "
"incomplete companion set (category=%s, control=%s); the effective "
"cert may inherit the replaced system's value — known gap, review",
main_heating_value,
code,
category,
control,
# effective cert inherits the REPLACED system's value — the silent
# mis-rating class ADR-0048 exists to stop. Every mapped archetype now
# carries confident defaults (ADR-0050/0052/0053), so an incomplete set
# can only mean a new archetype landed without choosing its companions:
# fail loudly at overlay time rather than ship an incoherent cert
# (ADR-0048's intended end-state, #1444 Part C).
raise ValueError(
f"Landlord main_heating_system {main_heating_value!r} (SAP code "
f"{code}) resolves an incomplete companion set (category="
f"{category}, control={control}); add the archetype's SAP Table 4a "
f"category and conservative Table 4e control before mapping it"
)
return EpcSimulation(
heating=HeatingOverlay(