From 6707ab084fd1c38371a052e38b5bae1da39abb7c Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 3 Jul 2026 14:22:40 +0000 Subject: [PATCH] =?UTF-8?q?An=20incomplete=20heating=20companion=20set=20r?= =?UTF-8?q?aises=20instead=20of=20logging=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../main_heating_system_overlay.py | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py index b8c945393..6d25d979c 100644 --- a/domain/epc/property_overlays/main_heating_system_overlay.py +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -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(