Model/datatypes/epc
Khalim Conn-Kowlessar aff331ff34 Slice 87: implement RdSAP 10 §5 (12) spec rule for suspended timber floor
Replace the empirical `_elmhurst_has_suspended_timber_floor` heuristic
(which keyed on Room-in-Roof < Main ground area) with the mechanical
RdSAP 10 Specification §5 rule (page 29):

  - Age band A-E: U-value < 0.5 → sealed (0.1); retro insulation + no
    U → sealed (0.1); otherwise unsealed (0.2)
  - Age band F-M: sealed (0.1)
  - Park home: unsealed (0.2)
  - Only applies when Main bp's lowest floor is a "Ground floor" with
    "Suspended timber" construction

The spec rule is derived in `_has_suspended_timber_floor_per_spec`
(cert_to_inputs.py) and applied in `ventilation_from_cert` whenever
the lodged `epc.sap_ventilation.has_suspended_timber_floor` is None.
Explicit lodged values (cohort hand-built fixtures) take precedence.

Impact on cert 001479 (the load-bearing API↔Elmhurst parity-test
fixture; previously the RR-based heuristic returned False for this
no-RR semi-detached, dropping (12) entirely):

  Mapper → cascade → SAP delta vs worksheet 69.0094:
    BEFORE: +1.1903 (mapper extracted False; cascade applied (12)=0)
    AFTER : +0.2290 (mapper extracts None; spec derives True/unsealed;
                     cascade applies (12)=0.2 → matches worksheet)

  Cohort cascade pins remain GREEN (66 of 66) — cohort hand-built
  fixtures retain their explicit `has_suspended_timber_floor` values
  which override the spec derivation.

Expected cohort regressions to triage in the next slice:
  - 4 cohort chain tests RED (000474, 000480, 000487, 000490) — their
    Elmhurst worksheets enter non-spec (12) values (0.0 or 0.2 when
    spec predicts the opposite) so the mapper-path cascade now
    diverges from the worksheet PDF at 1e-4.
  - 6 cohort diff tests RED — mapper now produces
    has_suspended_timber_floor=None while the cohort hand-builts
    retain explicit True/False overrides, producing a 1-field
    divergence per cohort cert.

Pyright net-zero (mapper 35→35; cert_to_inputs 35→35) — dead
`_elmhurst_has_suspended_timber_floor` removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 20:29:54 +00:00
..
domain Slice 87: implement RdSAP 10 §5 (12) spec rule for suspended timber floor 2026-05-25 20:29:54 +00:00
loaders demo generated for use in address2uprn 2026-05-08 14:48:15 +00:00
schema Slice 44: flat_roof_insulation_thickness mapper fix — surface lodged value on SapBuildingPart 2026-05-24 15:28:10 +00:00
search bolstering testing 2026-04-28 13:46:09 +00:00
surveys Slice 53: Summary_000487 chain pins SAP at 1e-4 — last cohort cert closed 2026-05-24 21:42:42 +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