mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.8: extension 'As Main Wall' inheritance copies insulation_thickness_mm
Regression fix surfaced by the first-attempt cert 0350 prediction test. `_extract_extensions` in `backend/documents_parser/elmhurst_ extractor.py` builds a synthetic `WallDetails` for any extension that lodges "As Main Wall: Yes" (copying the Main bp's wall fields so the cascade gets the same wall config for the extension). Slice S0380.4 added a new `insulation_thickness_mm` field to `WallDetails` but did NOT update the inheritance code at line 559-567 — so any multi-bp cert with an "As Main Wall" extension was losing the lodged wall insulation thickness on its extension bps, regardless of cert. Cert 0350-2968-2650-2796-5255 is the first multi-bp ASHP cohort cert through the Summary path (Main + 1st Extension, both "CA Cavity / FE Filled Cavity + External / 100 mm"). The dr87 worksheet line ref (29a) lodges: Main: 19.4575 W/K (77.83 m² × 0.25 W/m²K) Ext1: 1.3025 W/K ( 5.21 m² × 0.25 W/m²K) total: 20.7600 W/K Pre-fix Summary cascade produced walls_w_per_k 22.2188 (over by +1.46 W/K) because Ext1's missing thickness defaulted to a higher U-value path. Post-fix walls_w_per_k = **20.7600 — exact match against worksheet (29a) sum**. One-line fix at `elmhurst_extractor.py:567`: + insulation_thickness_mm=main_walls.insulation_thickness_mm, Forcing function: cert 0350 first-attempt SAP moves from Δ -4.7365 to Δ -4.5829 — small +0.1536 SAP gain from walls alone. The remaining ~-4.58 SAP residual on cert 0350 has other contributors to investigate in subsequent slices (HW kWh 1206 vs predicted target, HTC 173.42 vs worksheet (39) avg — likely floor / ventilation / PV gaps not yet covered by Summary mapper). Added focused unit test `test_summary_0350_ext1_inherits_main_wall_insulation_thickness` that pins the inheritance contract directly on the mapper boundary (bp[0].wall_insulation_thickness == bp[1].wall_insulation_thickness == "100mm"). Will fail if a future field-addition to WallDetails again forgets to update the synthetic-WallDetails inheritance block. Pyright net-zero across both edited files. Regression suite: 676 pass + 10 fail (= handover baseline 669 + 10 + 7 new GREEN unit tests across Slices S0380.2..S0380.8). Spec / cohort context: - Affects ALL multi-bp Elmhurst Summary certs with "As Main Wall: Yes" extensions, not just cert 0350. None of the previously- closed cohort certs (001479, 0330) exercised this path — both single-bp dwellings. - SAP 10.2 §3.7 / Table S5 — composite filled-cavity-plus-external U-value calc, keyed on lodged insulation thickness. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
360bf03fe6
commit
2f92edb050
2 changed files with 31 additions and 0 deletions
|
|
@ -563,6 +563,7 @@ class ElmhurstSiteNotesExtractor:
|
|||
u_value_known=main_walls.u_value_known,
|
||||
party_wall_type=main_walls.party_wall_type,
|
||||
thickness_mm=main_walls.thickness_mm,
|
||||
insulation_thickness_mm=main_walls.insulation_thickness_mm,
|
||||
alternative_walls=self._alternative_walls_from_lines(wall_lines),
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ _SUMMARY_001479_PDF = _FIXTURES / "Summary_001479.pdf"
|
|||
_SUMMARY_000897_PDF = _FIXTURES / "Summary_000897.pdf"
|
||||
_SUMMARY_000784_PDF = _FIXTURES / "Summary_000784.pdf"
|
||||
_SUMMARY_000899_PDF = _FIXTURES / "Summary_000899.pdf"
|
||||
_SUMMARY_000903_PDF = _FIXTURES / "Summary_000903.pdf"
|
||||
|
||||
# GOV.UK EPB API JSON for cert 001479 — the API-path counterpart of the
|
||||
# Summary_001479.pdf fixture. Together they drive the API ≡ Summary
|
||||
|
|
@ -620,6 +621,35 @@ def test_summary_0380_cylinder_block_surfaces_full_15_1_lodging() -> None:
|
|||
assert epc.sap_heating.cylinder_thermostat == "Y"
|
||||
|
||||
|
||||
def test_summary_0350_ext1_inherits_main_wall_insulation_thickness() -> None:
|
||||
# Arrange — cert 0350-2968-2650-2796-5255 is a multi-bp dwelling
|
||||
# (Main + 1st Extension). Its Summary §7 Walls block lodges
|
||||
# "1st Extension / As Main Wall / Yes" — the extension's walls
|
||||
# inherit Main's lodgings (CA Cavity, FE Filled Cavity + External,
|
||||
# 100 mm). The `_extract_extensions` "As Main Wall" inheritance
|
||||
# at `elmhurst_extractor.py:559-567` builds a new WallDetails by
|
||||
# copying Main's fields, but the field set it copies was frozen
|
||||
# before Slice S0380.4 added `insulation_thickness_mm` — so the
|
||||
# extension's `WallDetails.insulation_thickness_mm` falls through
|
||||
# to its dataclass default (None), and the mapper surfaces
|
||||
# `wall_insulation_thickness=None` on bp[1]. The cascade then
|
||||
# routes Ext1's composite walls off the lodged-thickness path,
|
||||
# over-stating Ext1 `external_walls_w_per_k` against worksheet
|
||||
# line ref (29a) "External walls Ext1 5.21 0.25 1.3025".
|
||||
pages = _summary_pdf_to_textract_style_pages(_SUMMARY_000903_PDF)
|
||||
site_notes = ElmhurstSiteNotesExtractor(pages).extract()
|
||||
|
||||
# Act
|
||||
epc = EpcPropertyDataMapper.from_elmhurst_site_notes(site_notes)
|
||||
|
||||
# Assert — Ext1 inherits Main's 100 mm thickness and the EPC
|
||||
# surfaces "100mm" on bp[1] (matching bp[0]).
|
||||
assert len(epc.sap_building_parts) == 2
|
||||
main_bp, ext1_bp = epc.sap_building_parts
|
||||
assert main_bp.wall_insulation_thickness == "100mm"
|
||||
assert ext1_bp.wall_insulation_thickness == "100mm"
|
||||
|
||||
|
||||
def test_summary_0380_full_chain_sap_within_spec_floor_of_worksheet() -> None:
|
||||
# Arrange — cert 0380-2471-3250-2596-8761 (Summary_000899.pdf /
|
||||
# dr87-0001-000899.pdf) is the first heat-pump cert under per-cert
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue