Model/domain
Khalim Conn-Kowlessar ab614d7756 Slice S0380.120: distinguish NI from explicit int(0) roof_insulation_thickness per RdSAP 10 §5.11.4
RdSAP 10 §5.11.4 (PDF p.44):

  "If retrofit insulation present of unknown thickness use 50 mm."

The cascade encoded "unknown thickness" via the cert's "NI" (Not-
Indicated) sentinel which `_parse_thickness_mm` collapses to int(0).
But that conflates two structurally different signals:

  (a) explicit int(0) — `_api_resolve_sloping_ceiling_thickness`
      returns this for cert 001479 Ext2 PS sloping ceiling age C, a
      per-BP "uninsulated" override of the dwelling-level description
      ("Pitched, insulated" from another BP).
  (b) string "NI" — the cert lodgement marker for "thickness not
      indicated; defer to description"; §5.11.4 should fire when the
      description carries an "insulated" signal.

Pre-slice the heat_transmission cascade dropped `roof_description`
whenever `roof_thickness == 0`, killing the §5.11.4 path in `u_roof`
(line 711) for the (b) case. 346 corpus certs lodge the NI +
"insulated (assumed)" pattern per the §5.11.4 test's arrange comment.

Fix: inspect the raw `part.roof_insulation_thickness` value (pre-
parse) — drop the description only when the lodgement is the literal
int(0), keep it for the "NI" string sentinel so `u_roof`'s §5.11.4
branch fires (`_described_as_insulated` + thickness=0 → return 0.68).

Test movement:
  test_roof_insulated_assumed_with_ni_thickness_uses_50mm_per_section_5_11_4 → PASS
  test_summary_001479_full_chain_sap_matches_worksheet_pdf_exactly → PASS (cohort safe)
  cert 000565 e2e — 11/11 PASS (unaffected — explicit per-BP thicknesses)

Golden corpus impact: cert 0240 had this exact pattern (BP[1] NI + global
description includes "Pitched, insulated (assumed)"). The fix drops its
roof U from 2.30 → 0.68 for that BP, closing massive mapper-gap residuals:

  expected_sap_resid:                 -14    → -10     (Δ +4 SAP)
  expected_pe_resid_kwh_per_m2:    +12.49   → +0.054   (Δ −12.43 kWh/m²)
  expected_co2_resid_tonnes_per_yr:  +0.696 → +0.063   (Δ −0.633 t/yr)

Re-pinned per [[feedback-golden-residuals-near-zero]]: "Re-pin to the
new (smaller) value when a gap closes". The remaining 0240 residuals
(SAP -10 / PE +0.05 / CO2 +0.06) are tiny — the bulk of 0240's mapper
gap is now closed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 16:28:47 +00:00
..
addresses standardist Address 2026-05-22 10:13:32 +00:00
data_transformation moved classifier data transformation to an easy one 2026-06-01 14:53:34 +00:00
epc pr review, move domain and orhcestration 2026-06-01 14:00:31 +00:00
sap10_calculator Slice S0380.120: distinguish NI from explicit int(0) roof_insulation_thickness per RdSAP 10 §5.11.4 2026-06-01 16:28:47 +00:00
sap10_ml Slice S0380.109: Solid brick + insulation via §5.7 Table 13 + §5.8 Table 14 (RdSAP 10) 2026-06-01 16:28:47 +00:00
tasks added postcode splitter rewrite to ddd 2026-05-19 16:35:09 +00:00
postcode.py get rid of comments 2026-05-20 13:21:11 +00:00