Model/datatypes/epc
Khalim Conn-Kowlessar af6fcfb190 Cohort residual slice 2: cert→ventilation cascade closes useful kWh on all 6 fixtures
Surfaces four cert lodgements that the §2 ventilation cascade was
missing on the cert→inputs path. Without them, `cert_to_inputs` was
defaulting:
  - extract_fans_count    → 0  (PDF: 1-2 fans per fixture)
  - percent_draughtproofed → 0  (PDF: 75-100% per fixture)
  - sheltered_sides        → 2  (PDF: 1-3 per fixture — hardcoded TODO)
  - has_suspended_timber_floor → False (PDF: True on 000477/000487)

Net effect on (25)m monthly effective ACH ranged from -19% (000477)
to +5% (000490) → propagated 1:1 through HLC × ΔT → useful space heat
→ main + secondary fuel kWh → cost / SAP integer.

Schema:
- `SapVentilation` gains 4 new optional fields: `sheltered_sides`,
  `has_suspended_timber_floor`, `suspended_timber_floor_sealed`,
  `has_draught_lobby`. RdSAP cert lodges these but the type didn't
  surface them.
- `cert_to_inputs.cert_to_inputs` reads them when set; falls back to
  the SAP10.2 §2 worst-case defaults (sheltered=2, no timber floor,
  no draught lobby) when the cert hasn't lodged. Removes the long-
  standing `sheltered_sides=2` hardcode + 4 TODOs.
- `make_minimal_sap10_epc` accepts a `sap_ventilation` kwarg.

Per-fixture build_epc() updates lodge the U985 PDF values verbatim.

E2E pin: new parametrized test
`test_elmhurst_cert_to_inputs_monthly_infiltration_ach_matches_u985_
worksheet` asserts `inputs.monthly_infiltration_ach[m] == LINE_25_
EFFECTIVE_ACH[m]` at abs=1e-3 across all 6 fixtures + 12 months
(72 assertions). All pass.

Useful space heating drift:
  000474: useful 10821.69 → 10765.85 (Δ -55.8 kWh vs PDF 10612.86 → +1.4% over, was +2.0%)
  000490: useful 11262.05 → 11184.06 (Δ -78.0 kWh vs PDF 11183.28 → +0.007% — essentially exact)

SAP integer status:
  000474: 62 = PDF 62 (delta 0) ✓
  000490: 58 vs PDF 57 (delta 1; continuous 57.77 vs 57.40)
          — remaining residual is pumps_fans hardcoded at 130 kWh
          vs PDF 160 (Table 4f cascade not yet implemented → -£4 cost
          + 0.3 continuous SAP). Next slice.

Tightens `result.secondary_heating_fuel_kwh_per_yr` pin abs=10 → abs=0.1
(was loose to absorb the +0.7% useful overshoot which has now closed).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:15:31 +00:00
..
domain Cohort residual slice 2: cert→ventilation cascade closes useful kWh on all 6 fixtures 2026-05-22 11:15:31 +00:00
loaders demo generated for use in address2uprn 2026-05-08 14:48:15 +00:00
schema slice 15d: +50 features (gap fill + secondary building part); drop 2 derived 2026-05-17 10:13:03 +00:00
search bolstering testing 2026-04-28 13:46:09 +00:00
surveys Handle wall thickness "Unmeasurable" 🟩 2026-04-30 16:41:16 +00:00
__init__.py testing out rebaselining 2026-02-12 22:25:03 +00:00
construction_age_band.py testing out rebaselining 2026-02-12 22:25:03 +00:00
efficiency.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
floor.py preparing partiy class 2026-02-05 08:54:27 +00:00
fuel.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
heating_controls.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
hotwater.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
main_heating.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
property_type_built_form.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
roof.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
walls.py beginning to assembly the parity class 2026-02-04 18:34:59 +00:00
windows.py testing out rebaselining 2026-02-12 22:25:03 +00:00