Model/domain
Khalim Conn-Kowlessar 6a7bf3e074 Slice S0380.138: route every off-peak callsite through the per-tariff Table 32 low-rate (electric +5..+9 SAP cluster + spillover)
Pre-slice every off-peak callsite in `cert_to_inputs.py` —
`_space_heating_fuel_cost_gbp_per_kwh`, `_hot_water_fuel_cost_gbp_per_kwh`,
`_secondary_fuel_cost_gbp_per_kwh`, `_pv_dwelling_import_price_gbp_per_kwh` —
hardcoded `prices.e7_low_rate_p_per_kwh = 5.50` p/kWh (Table 32 code 31,
the 7-hour low rate) regardless of the cert's actual tariff. Every
18-hour cert was thereby under-charged 1.91 p/kWh × off-peak kWh on
its space-heating, hot-water, and secondary-heating cost rows.

Per RdSAP 10 §19 Table 32 (p.95):

> "Electricity ... 7-hour tariff (low rate / off-peak) — code 31 5.50 p/kWh
>  ... 10-hour tariff (low rate) — code 33 7.50 p/kWh
>  ... 18-hour tariff (low rate) — code 40 7.41 p/kWh
>  ... 24-hour tariff — code 35 6.61 p/kWh"

The fix routes through a new `_off_peak_low_rate_gbp_per_kwh(tariff)`
helper that reads the existing per-tariff Table 32 lookup
(`_TARIFF_HIGH_LOW_RATES_P_PER_KWH`). A companion
`_off_peak_low_rate_gbp_per_kwh_via_meter_heuristic(meter_type)` covers
the secondary / PV paths that detect off-peak via the
`_is_off_peak_meter` heuristic (RdSAP meter code 3 = Unknown is treated
as off-peak for electric end-uses), falling back to the SEVEN_HOUR rate
when the meter resolves to STANDARD — codifying the heuristic that the
literal 5.50 constant used to embed.

Per [[feedback-zero-error-strict]] the now-dead
`PriceTable.e7_low_rate_p_per_kwh` field is deleted (no fallback can
silently re-introduce the 5.50 hardcode); the field's docstring +
RDSAP_10_TABLE_32_PRICES instantiation update to point at the new
helpers.

Corpus closure (all 18-hour cohort):

- 8 electric variants — SAP +5.85..+9.64 → -0.10..-2.76; cost
  -£135..-£222 → +£2..+£64
- ashp +5.67 → +0.24 SAP (-£131 → -£5.57)
- gshp +5.16 → +1.15 SAP (-£119 → -£26)
- solid fuel 4..11 — SAP +1.59..+2.04 → ±0.45 (cost ±£10)

Golden 0240 PV path also closes (was raising UnmappedSapCode on
Unknown-meter probe — surfaced an unreachable PV literal that the
meter-heuristic helper now resolves).

Tests:
- new AAA test `test_space_heating_off_peak_fallback_uses_actual_tariff_low_rate_not_e7`
  exercising the EIGHTEEN_HOUR fallback at the helper level
- 19 corpus pins re-tightened (8 electric + ashp + gshp + 8 solid-fuel
  + golden 0240's implicit pin)

Extended handover suite: 881 pass (was 880; +1 new test), 0 fail.
Pyright net-zero on touched files (43 → 43 errors, all pre-existing).

Per [[feedback-spec-citation-in-commits]] +
[[feedback-worksheet-not-api-reference]] +
[[reference-unmapped-sap-code]].

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 16:28:48 +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.138: route every off-peak callsite through the per-tariff Table 32 low-rate (electric +5..+9 SAP cluster + spillover) 2026-06-01 16:28:48 +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