Model/domain/sap10_calculator/docs/HANDOVER_POST_S0380_155.md
Khalim Conn-Kowlessar 4350c71bdd docs: handover post S0380.153..155
Session landed three spec-clean slices closing four major residuals:

- S0380.153 (Table 3 middle row for solid-fuel boilers): SF3 EXACT all
  4 metrics (+0.30 → -0.0000). Found the rule that solid-fuel boilers
  don't ship with dual programmers per §9.2.4.

- S0380.154 (§12.4.4 back-boiler summer-immersion): SF2 SAP+cost
  EXACT (+1.86 → -0.0000 SAP; -£42.84 → -£0.00 cost). Implemented HW
  fuel kWh split + monthly blend across cost / CO2 / PE / standing.

- S0380.155 (Table 4a HP water-column dispatch): gshp closed ±0.02
  SAP (+0.94 → -0.0178). HW kWh 841 → 1138 matches worksheet exactly.

Σ |ΔSAP_c| 14.5 (session start of S0380.150) → 2.7 = 81% reduction
across 6 slices, two sessions.

Handover doc captures:
- Per-line discipline (walk worksheet before forming hypothesis)
- Elmhurst-vs-spec divergences to defer (lighting-PE +48.66 cluster
  uses Table 12 annual factor; spec Table 12d mandates monthly)
- Ranked open fronts (electric 5 R=0.20 storage MIT, electric 2
  warm-air HP HW, deferred lighting-PE cluster)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 16:01:52 +00:00

15 KiB
Raw Blame History

Handover — post Slices S0380.153..155

Branch: feature/per-cert-mapper-validation. HEAD 152db1ae. Predecessor: HANDOVER_POST_S0380_152.md.

TL;DR

Three slices landed. Each addressed a distinct spec rule the cascade was missing, all surfaced through the same heating-systems corpus (property 001431 × 41 heating-system variants).

Slice Commit Spec rule closed
S0380.153 e4bf4e70 SAP 10.2 Table 3 (p.160) — "not separately timed" middle row for solid-fuel boilers (codes 151-161). DHW timer follows the appliance, not a separate programmer.
S0380.154 5e941b92 SAP 10.2 §12.4.4 (p.36-37) — back-boiler summer-immersion HW split for codes 156, 158. Cascade now blends winter boiler + summer electric immersion across kWh/cost/CO2/PE/standing-charge fields.
S0380.155 152db1ae SAP 10.2 Table 4a (p.163-164) — heat-pump water column distinct from space column for 10 codes (211/213/215/216/217 + 521/523/525/526/527). Cascade was using space efficiency for HW on these codes.

Extended handover suite at HEAD: 899 pass, 0 fail. Pyright net-zero (43 → 43).

Disciplines reinforced this session

  1. Per-line walk before spec hypothesis. S0380.153 found via dumping SF3's worksheet (59)m row — it showed winter h=5 / summer h=3 (= "not separately timed"), not the h=3 year-round the cascade was using. The handover narrative said "SF2 separately-timed-DHW gate" but the per-line walk revealed the rule applies to ALL solid-fuel boilers (codes 151-161), not just back-boiler combos.

  2. Bigger slice OK when one spec rule has multiple wire points. S0380.154 (§12.4.4) touched HW kWh + cost rate + CO2 factor + PE factor + standing charges + primary-loss override — five distinct plumbing points. Doing it as one coherent slice (vs splitting into "fix kWh first, then fix cost") kept the residual pin monotonic.

  3. Spec correctness > pin stability for Elmhurst-vs-spec gaps. The lighting-PE +48.66 cluster (5 variants with identical offset from off-peak HW immersion) was deferred because Elmhurst uses Table 12 ANNUAL factor (1.501 PE / 0.136 CO2) for off-peak HW while spec Table 12d/12e header mandates MONTHLY factors. The cascade follows spec; the cohort residual stays.

Current residual state at HEAD 152db1ae

Cascade-OK tier (25 variants on pin grid)

Sorted by |ΔSAP_c|:

Variant ΔSAP_c Δcost ΔPE Notes
oil 1 -0.0000 -0.00 +0.00 EXACT
oil pcdb 1/2 +0.0000 +0.00 +0.00 EXACT
oil pcdb 3 +0.0000 +0.00 -0.00 EXACT
electric 1 -0.0000 -0.00 +48.66 SAP exact, PE Elmhurst quirk
solid fuel 5 +0.0000 +0.00 +48.66 SAP exact, same quirk
solid fuel 6 +0.0000 +0.00 +48.66 SAP exact, same quirk
solid fuel 7 -0.0000 +0.00 +48.66 SAP exact, same quirk
solid fuel 8 -0.0000 +0.00 +48.66 SAP exact, same quirk
solid fuel 2 -0.0000 -0.00 -1027.51 closed by .154 (SAP+cost EXACT; CO2/PE Elmhurst blend artifact)
solid fuel 3 -0.0000 -0.00 -0.00 closed by .153 (4-metric EXACT)
pcdb 1 -0.0108 +£0.24 +5.70 basically exact
gshp -0.0178 +£0.41 +33.52 closed by .155 (HW kWh 841→1138 matches worksheet)
ashp -0.024 +£0.55 +36.34 basically exact
solid fuel 4 +0.085 -£1.96 -5.78 close
solid fuel 11 +0.0912 -£2.10 -0.74 close
electric 8 +0.0941 -£2.17 +6.58 close
electric 7 +0.1017 -£2.34 +3.10 close
electric 6 +0.1081 -£2.49 +0.16 close
solid fuel 9 +0.1072 -£2.47 -5.07 close
solid fuel 10 +0.1134 -£2.61 -13.91 close
electric 9 +0.1199 -£2.76 -4.51 close
electric 3 +0.1215 -£2.80 -5.99 close
electric 2 -0.4584 +£10.56 +443.13 warm-air HP code 524 — open Cluster C
electric 5 -1.1759 +£27.09 +438.03 storage code 402 R=0.20 — open

Σ |ΔSAP_c| across 25 variants ≈ 2.7 SAP points (was 14.5 at session start, ~6.4 after .150-.152, now ~2.7 = 81% reduction across 6 slices over two sessions).

Blocked tier (16 variants — MissingMainFuelType)

Unchanged. Community heating × 5, electric storage 11-14, no system, oil 2-6, pcdb 3.

Open fronts ranked by leverage

1. electric 5 — SAP -1.18 / cost +£27 / PE +438 (largest open)

Storage heater code 402 (R=0.20, slimline). REGRESSED by S0380.145 + S0380.151 — pre-S0380.145 was net-zero from offsetting bugs.

Per-line probe at session-end:

  • Cascade adjusted MIT[Jan] = 19.10 vs worksheet (93) = 18.61 (cascade +0.49 K higher)
  • Cascade base MIT[Jan] = 18.70 vs worksheet (92) = 18.21 (cascade +0.49 K higher — same diff)
  • Cascade control_temperature_adjustment_c = +0.4 K (Table 4e code 2402 — correct)
  • Per-zone components diverge: cascade T_living = 19.85 vs ws 19.65; T_h2 = 18.59 vs ws 19.12; T_elsewhere = 17.27 vs ws 17.59.

The diverging components suggest §9 Table 9a/9b off-period reduction formula differs in Elmhurst for R=0.20 storage heaters. Cascade's formula:

  T_sc = (1-R)(T_h - 2) + R(T_e + η·G/H)
  if t_off > t_c:  u = (T_h - T_sc)(t_off - 0.5·t_c) / 24

matches spec verbatim. But the per-zone numbers (T_h2 cascade 18.59 vs ws 19.12) suggest a HEAT LOSS PARAMETER or HLP-formula divergence upstream of the off-period reduction.

This needs careful spec analysis of Table 9c steps for low-R systems — may take 1-2 slices. NOT a quick win.

2. electric 2 — SAP -0.46 / cost +£10.56 / PE +443

Warm-air ASHP code 524 (Space = Water = 170, so S0380.155 fix doesn't apply). Cascade HW kWh OVER worksheet by 465 kWh (+19%) — opposite direction from gshp. Distinct spec rule. Probably HW efficiency cascade for warm-air HPs (Appendix N3 has separate treatment from Cat 4 hydronic HPs).

3. Lighting-only PE +48.66 cohort cluster (5 variants)DEFERRED

electric 1, solid fuel 5/6/7/8. All have identical PE +48.66 / CO2 +11.94 offset from off-peak HW immersion. Worksheet uses Table 12 ANNUAL factor (1.501 / 0.136) on the "low-rate cost" line; cascade uses Table 12d/12e MONTHLY cascade per spec header. Cascade is spec-correct. Elmhurst applies an undocumented exception for off-peak HW immersion. Cannot close without violating spec.

4. electric 3 / 6 / 7 / 8 / 9 + solid fuel 9-11 — ΔSAP ±0.09-0.12

Residual cluster — likely a shared shave-the-residual fix. Probably the same Elmhurst-vs-spec PE blend artifact as #3 but for the secondary-heating fraction or similar. Lowest leverage.

5. gshp ΔSAP -0.018 / ΔPE +34 — landed in S0380.155

Sub-tolerance close but not 1e-4. Same Elmhurst-vs-spec PE blend artifact as #3 (HW from HP is on standard tariff, not off-peak, so NOT the same off-peak-immersion path — but same monthly-vs-annual factor pattern). Defer until the cluster fix lands.

Slice history (this session)

Slice HEAD Scope
S0380.153 e4bf4e70 SAP 10.2 Table 3 (PDF p.160) middle row "Cylinder thermostat, water heating NOT separately timed" applies to solid-fuel boiler systems. Per §9.2.4 these are "independent solid fuel boilers, open fires with a back boiler and room heaters with a boiler" — the appliance is the timer. New _TABLE_4A_SOLID_FUEL_BOILER_CODES frozenset + branch in _separately_timed_dhw. SF3 (code 160 + WHC=901): worksheet (59)m winter 64.58 / summer 41.92 matches cascade. ΔSAP +0.30 → -0.0000 EXACT all 4 metrics. SF2 narrows +2.06 → +1.86 (remaining is the §12.4.4 immersion rule).
S0380.154 5e941b92 SAP 10.2 §12.4.4 (PDF p.36-37) back-boiler summer-immersion HW split. For Table 4a codes 156 + 158 (back-boiler combos) + WHC ∈ {901, 902, 914} + cylinder, HW splits: winter (Oct-May) at boiler eff + summer (Jun-Sep) at 100% electric immersion. New _section_12_4_4_summer_immersion_applies(epc, main) predicate + _section_12_4_4_hw_blend(...) returning 5-tuple (annual_hw_fuel_kwh, blended_cost, blended_co2, blended_pe, extra_standing). _primary_loss_override zeros (59)m Jun-Sep. Orchestrator wires 4 fields + standing once. SF2 closures: ΔSAP +1.86 → -0.0000 EXACT, Δcost -£42.84 → -£0.00 EXACT; CO2/PE residuals -93/-1027 are Elmhurst summer CO2/PE blend artifacts vs Table 12d/12e.
S0380.155 152db1ae SAP 10.2 Table 4a (PDF p.163-164) heat-pump rows split efficiency into Space and Water columns. Codes 211/213 (Cat 4 GSHP/WSHP ≤35°C: SH 230 / DHW 170), 215/216/217 (Cat 4 gas-fired HP ≤35°C: SH 120-110 / DHW 84-77), and Cat 5 warm-air equivalents 521/523/525/526/527. New _TABLE_4A_HEAT_PUMP_WATER_EFFICIENCY 10-code dict consulted in _water_efficiency_with_category_inherit before seasonal_efficiency fallback. Codes where Space == Water (214/221/223/224/524) unchanged. gshp (code 211) HW kWh 841 → 1138.45 (matches worksheet 1138.46). ΔSAP +0.94 → -0.0178. No regressions on 40 other variants.

Standard slice workflow (unchanged)

  1. Read spec page + identify rule
  2. Probe one cluster variant; verify diagnosis via monkey-patch / direct walk
  3. Write failing AAA test (literal # Arrange / # Act / # Assert)
  4. Implement helper / dispatch entry / mapper extension
  5. Re-pin affected variants (DO NOT widen tolerance)
  6. Run extended handover suite (command below)
  7. Pyright net-zero check (git stash → pyright → git stash pop → pyright)
  8. Commit with spec citation + Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
  9. Update project-heating-systems-corpus + MEMORY.md index

Test baseline at HEAD 152db1ae

PYTHONPATH=/workspaces/model python -m pytest \
    backend/documents_parser/tests/test_summary_pdf_mapper_chain.py \
    backend/documents_parser/tests/test_heating_systems_corpus.py \
    backend/documents_parser/tests/test_elmhurst_extractor.py \
    backend/documents_parser/tests/test_elmhurst_end_to_end.py \
    domain/sap10_calculator/worksheet/tests/test_e2e_elmhurst_sap_score.py \
    domain/sap10_calculator/worksheet/tests/test_heat_transmission.py \
    domain/sap10_calculator/worksheet/tests/test_internal_gains.py \
    domain/sap10_calculator/worksheet/tests/test_solar_gains.py \
    domain/sap10_calculator/worksheet/tests/test_dimensions.py \
    domain/sap10_calculator/worksheet/tests/test_rating.py \
    domain/sap10_calculator/worksheet/tests/test_ventilation.py \
    domain/sap10_calculator/worksheet/tests/test_appendix_h_solar.py \
    domain/sap10_calculator/worksheet/tests/test_mev.py \
    domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py \
    domain/sap10_calculator/rdsap/tests/test_golden_fixtures.py \
    domain/sap10_calculator/tests/test_pcdb_table_322_lookup.py \
    domain/sap10_calculator/tests/test_pcdb_table_329_lookup.py \
    domain/sap10_calculator/tests/test_table_12a.py \
    --no-cov -q

Expected: 899 pass, 0 fail.

Memories to load (in order)

project-heating-systems-corpus            # HEAD 152db1ae
feedback-sap-10-2-only-never-10-3         # CRITICAL — never reference SAP 10.3
feedback-software-no-special-handling     # CRITICAL — apply spec uniformly
feedback-spec-floor-skepticism            # CUTS BOTH WAYS — skeptical of your OWN audit narrative
feedback-worksheet-not-api-reference
feedback-spec-citation-in-commits
feedback-verify-handover-claims
feedback-zero-error-strict                # TARGET: ΔSAP_c < 1e-4 vs worksheet
feedback-commit-per-slice
feedback-aaa-test-convention
feedback-e2e-validation-philosophy
feedback-abs-diff-over-pytest-approx
feedback-golden-residuals-near-zero
feedback-one-e-minus-4-across-the-board
reference-unmapped-sap-code
reference-unmapped-api-code
project-oil-price-spec-divergence

What NOT to do

  • Don't reference SAP 10.3 — track 10.2 deliberately
  • Don't widen pin tolerances — re-pin smaller or find the spec gap
  • Don't add empirical gates to keep cohort pins stable when a spec rule clearly applies
  • Don't re-investigate Slices .91..155 — all settled
  • Don't add new helpers to domain/sap10_ml/ — on deprecation path; domain/sap10_calculator/tables/ is the canonical home
  • Don't treat ΔSAP=0.07 as "closed" — target is <1e-4 vs worksheet
  • Don't try to close the lighting-PE +48.66 cluster — it's an Elmhurst-vs-spec quirk (Elmhurst uses Table 12 annual factor for off-peak HW immersion while spec Table 12d/12e header mandates monthly factors). Closing it would violate spec.
  • Don't form a spec hypothesis without per-line data — walk the worksheet line-by-line for the failing variant first, then look up the spec rule. Headline residuals tell you a gap exists; only the per-line walk tells you which section of the spec it lives in.

Spec source quick-reference

All under domain/sap10_calculator/docs/specs/:

  • SAP 10.2 full spec: sap-10-2-full-specification-2025-03-14.pdf
    • §4 (p.135-137) — water heating worksheet (45..65)
    • §9.2.4 (p.27) — Solid fuel boiler systems (the appliance is the timer; Table 3 not-separately-timed row applies). Slice .153.
    • §9.4.11 (p.30) — Boiler interlock: -5pp to BOTH SH and DHW
    • §9.4.19 (p.34-35) — Storage heater controls
    • §12 (p.45) — Electricity tariff types
    • §12.4.4 (p.36-37) — Solid fuel systems; back-boiler combos use electric immersion in summer. Slice .154.
    • §A.2.2 (~p.189) — Forced-secondary set
    • Appendix D §D2.1 (2) (p.57) — Eq D1 monthly water eff cascade
    • Appendix F2 (p.63) — 18-hour CPSU: high rate for all other uses
    • Appendix N3 (p.107-109) — Heat pump DHW efficiency cascade
    • Table 3 (p.160) — Primary circuit loss; zero-loss list + middle row "not separately timed" h=5/h=3. Slices .152 / .153.
    • Table 4a (p.163-170) — heating systems incl. separate Space + Water columns for HP rows. Slice .155.
    • Table 4b (p.168) — gas/liquid boilers seasonal efficiency
    • Table 4e (p.171-173) — heating system controls + temperature adjustment column. Group 4 codes 2401/2402/2403 = electric storage controls (+0.7/+0.4/+0.4 K).
    • Table 4f (p.174) — pumps + fans
    • Table 9a/9b (p.183) — utilisation factor + off-period reduction
    • Table 9c (p.184) — MIT cascade (step 8 = Table 4e adj wired)
    • Table 11 (p.188) — secondary heating fraction
    • Table 12 (p.191) — SAP rating fuel prices + standing charges
    • Table 12a (p.191) — high/low-rate fraction by system × tariff
    • Table 12d (p.195) — monthly variation in CO2 factors for electricity (spec mandates use INSTEAD OF Table 12 annual)
    • Table 12e (p.196) — monthly variation in PE factors
    • Table 13 (p.197) — high-rate fraction for electric DHW
  • RdSAP 10 spec: RdSAP 10 Specification 10-06-2025.pdf
    • §4.1 Table 5 (p.28) — Ventilation parameters incl. extract fans age-band default
    • §5 (p.29) — Floor infiltration spec rule
    • §10.11 Table 29 (p.56) — Heating/HW parameters; inaccessible cylinder
    • §19 Table 32 (p.95) — RdSAP10 fuel prices / CO2 / PE

Good luck.