Model/domain
Khalim Conn-Kowlessar 9dc60c91d3 Slice S0380.77: WHC 914 routes primary-loss gate to DHW main; cert 000565 +1175 kWh
SAP 10.2 §4 line 7700 + Table 3 (PDF p.159) defines primary loss
as the loss between "a heat generator (e.g. boiler) connected to a
hot water storage vessel via insulated or uninsulated pipes (the
primary pipework)". The spec keys eligibility off the heat
generator that feeds the cylinder, NOT the space-heating main.

Verbatim spec (Table 3, p.159):

    Primary circuit loss applies when hot water is heated by a heat
    generator (e.g. boiler) connected to a hot water storage vessel
    via insulated or uninsulated pipes (the primary pipework).
    Primary loss is set to zero for the following:
      - Electric immersion heater
      - Combi boiler (including when it is part of a combined heat
        pump and boiler package and provides all the hot water)
      - CPSU (including electric CPSU)
      - Boiler and thermal store within a single casing
      - Separate boiler and thermal store connected by no more than
        1.5 m of insulated pipework
      - Direct-acting electric boiler
      - Heat pump (not combined heat pump and boiler package with a
        non-combi boiler) from PCDB with hot water vessel integral
        to package

    For other cases (indirect cylinders and thermal stores connected
    by uninsulated pipework or more than 1.5 m of insulated
    pipework) the loss in kWh/month is calculated as follows.

    Primary loss = n_m × 14 × [{0.0091 × p + 0.0245 × (1 − p)} × h
                              + 0.0263]

`_water_heating_section` was routing the gate through
`_first_main_heating` (Main 1). Cert 000565 lodges ASHP Main 1 +
gas combi Main 2 + WHC 914 ("from second main system") + 160 L
combined cylinder + cylinder thermostat "N". The cylinder is
heated by Main 2 via uninsulated primary pipework, so the spec
formula applies; the cascade was zeroing (59)m because Main 1's
HP record (or its absence) drove the gate.

Fix: `_primary_loss_override` resolves its `main` via
`_water_heating_main(epc)` (the WHC-914 routing) so the
eligibility check follows the heat generator that physically
incurs the loss. Call site loses the `main` argument; the gate's
internals are unchanged.

Cert 000565 worksheet line (59)m (U985-0001-000565 Block 1):

    128.3772, 115.9536, 128.3772, 124.2360, 128.3772,  41.9160,
     43.3132,  43.3132,  41.9160, 128.3772, 124.2360, 128.3772

sums to 1174.79 kWh/yr. Cascade now matches every month at < 1e-4
kWh under the spec params (uninsulated p=0 from RdSAP §3 age band
A-J default, h_winter=11 / h_summer=3 from "no cylinder
thermostat" row).

Cert 000565 movements at HEAD:
  - sap_score:                   29 ✓ EXACT (unchanged)
  - sap_score_continuous:        29.2905 → 29.1090 (Δ +0.78 → +0.60)
  - space_heating_kwh:           59274.46 → 58725.77 (Δ +266 → −283)
  - main_heating_fuel:           34867.33 → 34544.57 (Δ +157 → −166)
  - hot_water_kwh:                3668.54 →  5154.02 (Δ −86 → +1399)
  - co2_kg:                       6352.61 →  6616.01 (Δ −95 → +168)
  - total_fuel_cost_gbp:          4611.14 →  4627.10 (Δ −69 → −53)
  - ecf:                           5.3073 →   5.3256 (Δ −0.08 → −0.06)

HW pin over-shoots by +1399 as expected — the +1174.79 spec credit
is amplified by the gas combi's 0.88 water efficiency (≈ +1335
kWh) plus cascade coupling (heat-gain feedback into space heating
drops it −549 kWh). The +1399 will be pulled back by the next two
demand-cascade slices:
  - (45)m energy_content over by ~903 kWh (occupancy + shower mix)
  - (56)/(57)m storage-loss over by ~98 kWh + missing solar
    `(57)m = (56)m × (H13 − H12)/H13` adjustment (~298 kWh)

New test pins the full 12-month (59)m tuple for cert 000565's
heating shape at abs=1e-4. Old `_first_main_heating`-based test
(`test_cert_with_hot_water_cylinder_computes_primary_loss_59m_…`)
unchanged — still passes via the WHC-901 fall-through to Main 1.

Test baseline: 547 → 548 pass (new test added) + 9 expected
`test_sap_result_pin[000565-*]` cascade-gap fails. Pyright
net-zero on both touched files (45 baseline = 45 after).

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.77: WHC 914 routes primary-loss gate to DHW main; cert 000565 +1175 kWh 2026-06-01 16:28:47 +00:00
sap10_ml Slice S0380.26: RdSAP10 §5.8 dry-lining adjustment on alt walls — closes cert 7700 -0.44 → +5e-5 2026-06-01 16:28:46 +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