From e09bed31bc210349e851c9ca05cc2da6fe315061 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 5 Jun 2026 19:08:32 +0000 Subject: [PATCH] =?UTF-8?q?fix(mapper):=20drop=20the=20"wall=20location=20?= =?UTF-8?q?=E2=86=92=20vertical"=20guard=20that=20broke=20cert=20000516?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slice f68cea27 (re-homed here as 97f44b53) added a guard to _is_elmhurst_roof_window — "a window lodged on a wall is vertical by definition" — to keep 001431's two "Double pre 2002" External-wall units in the vertical sap_windows list for the Modelling draught-proofing count. But that guard fires on the §11 `location` string, which is an unreliable lodging artifact: every one of cert 000516's six §11 rows reads "External wall", and only the U-value separates the five vertical panes (U 2.8) from the one genuine rooflight (U 3.1, area 1.18, lifted to 3.40 by the Table 24 lookup). Elmhurst's own worksheet routes that U 3.1 "External wall" unit through (27a) Roof Windows — so location is NOT a vertical signal and the U > 3.0 backstop (RdSAP 10 §3.7.1) is what matches the worksheet. Removing the guard restores both 000516 pins (test_summary_000516_full_chain_sap_matches_worksheet_pdf_exactly, test_from_elmhurst_site_notes_matches_hand_built_000516) with no other regression (2879 pass; the lone test_total_floor_area failure is pre-existing on the branch base, unrelated to window classification). The extractor half of 97f44b53 (capturing the standalone "BFRC data" §11 row) is retained — it is independent of this classifier and harmless here. The 001431 Modelling draught-proofing count must instead include roof windows (the draught_proofed-on-SapRoofWindow approach noted in the glazing handover), which is feature/bill-derivation's front, not this branch. Co-Authored-By: Claude Opus 4.8 --- datatypes/epc/domain/mapper.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index b992254a..cce444ab 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -4116,14 +4116,14 @@ def _is_elmhurst_roof_window( _ELMHURST_BP_ROOF_TYPES_WITH_ROOFLIGHTS ): return True - # A window lodged on a wall is vertical by definition. The U-value - # backstop below only catches skylights whose location/BP gives no - # roof signal; without this guard a high-U *wall* window (e.g. an old - # "Double pre 2002" unit at U 3.1 / 3.4) is mis-routed to the roof- - # window list on U-value alone — cert 001431 §11 lodges two such - # External-wall windows that must remain vertical `sap_windows`. - if "wall" in (w.location or "").lower(): - return False + # U > 3.0 backstop — Elmhurst routes high-U "Double pre 2002" units + # through the worksheet's (27a) Roof Windows line regardless of the + # lodged "External wall" location, which is a §11 lodging artifact + # (cert 000516's W6 is lodged "External wall" yet scored via (27a)). + # The location string is therefore NOT a reliable vertical signal: + # all six of 000516's §11 rows read "External wall", and only U + # separates the five vertical (2.8) panes from the one rooflight + # (3.1). Matching the worksheet means trusting U here, not location. return w.u_value > _ELMHURST_ROOF_WINDOW_U_THRESHOLD