diff --git a/docs/sap-spec/SPEC_COVERAGE.md b/docs/sap-spec/SPEC_COVERAGE.md index 2988757d..6c9d01a9 100644 --- a/docs/sap-spec/SPEC_COVERAGE.md +++ b/docs/sap-spec/SPEC_COVERAGE.md @@ -2,7 +2,7 @@ Tracks which sections of the SAP 10.2 specification are implemented in `packages/domain/src/domain/sap/`. Per ADR-0009 the calculator is built from the spec, not reverse-engineered from cert data. This doc is the worksheet-driven roadmap for what remains. -Updated 2026-05-20 after §7 rebuild (slices `fa49d7b9`…`a7f39685`). +Updated 2026-05-20 after §8 rebuild (slices `9113f30a`…`f6ab7626`). The canonical SAP10.2 algorithm lives in [`2026-05-19-17-18 RdSap10Worksheet.xlsx`](../../2026-05-19-17-18%20RdSap10Worksheet.xlsx) at the repo root — each line ref `(1)..(486)` maps to a cell. The worksheet sub-modules under `packages/domain/src/domain/sap/worksheet/` implement those line refs directly; Elmhurst worksheets validate end-to-end via `tests/_elmhurst_worksheet_*.py`. @@ -18,7 +18,8 @@ The canonical SAP10.2 algorithm lives in [`2026-05-19-17-18 RdSap10Worksheet.xls | 6 | Solar gains + Tables 6b/6c/6d + Appendix U | `worksheet/solar_gains.py` | **Full** | Worksheet-driven (74)..(83). Table 6b g⊥ via manufacturer `window_transmission_details` first, Table 6b code lookup fallback; Table 6c FF by frame_material substring; Table 6d Z (heating column) by `OvershadingCategory`; roof windows pitched at RdSAP10 Table 24 default 45°; rooflights horizontal per §U3.2 p128. `solar_gains_from_cert` wired into `cert_to_inputs` + `calculator.py`. Six Elmhurst fixtures conform end-to-end to ≤5e-3 W on (83) + (84). | | 7 | Mean internal temperature | `worksheet/mean_internal_temperature.py` | **Full** | Worksheet-driven (85)..(94) via `mean_internal_temperature_monthly`. Table 9c steps 1-9 sequential (per-zone η: (86) η_living at Ti=T_h1, (89) η_elsewhere at Ti=T_h2, (94) η_whole at Ti=(93)). Table 9b u-formula consumes weighted R for two-main case 1 (single-main is default). Wired into `calculator.py` + `cert_to_inputs` via two new `CalculatorInputs` fields. Six Elmhurst fixtures conform end-to-end to ≤5e-3 °C on all 9 line tuples + 2 scalars per month (588 assertions). Table 4e adj defaults 0 (cert-side mapping deferred — all 6 fixtures = 0); two-main case 2 (different parts heated separately) deferred. | | 8 | Off-period temperature reduction | inline in `mean_internal_temperature.py` | Full | Table 9b implemented | -| 9 | Space heating | `worksheet/space_heating.py` | Partial | Single main system only — **no Table 11 secondary heating allocation** (10% fraction on most boilers — likely big MAE) | +| 8 | Space heating requirement | `worksheet/space_heating.py` | **Full** | Worksheet-driven (95)..(99) via `space_heating_monthly_kwh`. Includes the Table 9c step 10 spec inclusion rule (Jun..Sep zeroed) on top of the < 1 kWh value clamp. (98b) Appendix H solar space heating defaulted to 0 (no Elmhurst fixture lodges a solar space heating system). Wired into `calculator.py` + `cert_to_inputs` via `CalculatorInputs.space_heating_monthly_kwh`. Six Elmhurst fixtures conform end-to-end on (95)/(97)/(98a)/(98c)/(99)/annual @ 5e-2..1e-1 kWh (looser than §6/§7's 5e-3 because LINE_84/93/94 fixture pins are 4-d.p. display-rounded and §8's 0.024·n_m·(L−ηG) amplifies that rounding). | +| 9 | Energy requirements per heating system | `worksheet/space_heating.py` | Partial | Single main system only — **no Table 11 secondary heating allocation** (10% fraction on most boilers — likely big MAE) | | 10 | Cooling | — | Not implemented | Rare in UK dwellings; defer | | 11 | FEE | — | Not implemented | Only for new-build; not required for ratings | | 12 | Total energy + fuel costs | `calculator.py` | Partial | Per-end-use cost split ✓; meter_type tariff routing ✓ (S-B15); PV cost credit ✓ (S-B19); **standing charges not included** (Table 12 note (a) says rating omits standing charge for std electricity tariff) | @@ -172,3 +173,28 @@ Status now: 100-cert MAE 4.49, 300-cert MAE 5.45, bias near zero (±0.2). Worksh 1. **Table 4e control_temperature_adjustment_c cert mapping** — orchestrator accepts the parameter but `cert_to_inputs` hardcodes 0.0 (all 6 Elmhurst fixtures = 0 anyway). Wire when a non-zero corpus emerges. 2. **Two-main case 2** (different parts heated separately) — needs (203) > 1−(91) branch + conditional T_2 averaging + per-system Table 4e adj weighting. Case 1 (both heat whole house) wired with synthetic test; case 2 deferred. 3. **Auto-detect `secondary_fraction` from `epc.sap_heating.main_heating_details`** — currently always 0 in `cert_to_inputs`. Wire when a multi-main cert lands. + +## §8 — slice progress (xlsx rows 401–435) + +| Line ref | Description | Status | Commit | +|---|---|---|---| +| — | `SpaceHeatingResult` + `space_heating_monthly_kwh` orchestrator | ✅ | `9113f30a` | +| — | Table 9c step 10 summer clamp (Jun..Sep = 0) | ✅ | `9113f30a` | +| (95)m | Useful gains ηG, W | ✅ | `9113f30a` | +| (97)m | Heat loss rate L_m = H·(T_int − T_ext), W | ✅ | `9113f30a` | +| (98a)m | Space heating requirement per month, kWh | ✅ | `9113f30a` | +| (98b)m | Solar space heating (Appendix H) — hardcoded 0 | ⏸ deferred | — | +| (98c)m | Total = (98a) + (98b), kWh | ✅ | `9113f30a` | +| Σ(98c) | Annual total kWh | ✅ | `9113f30a` | +| (99) | Annual per-m² = Σ(98c) / TFA | ✅ | `9113f30a` | +| — | 6-fixture ALL_FIXTURES conformance on (95)..(99) | ✅ | `1f078af7` | +| — | `CalculatorInputs.space_heating_monthly_kwh` + cert_to_inputs wiring | ✅ | `f6ab7626` | + +**Six Elmhurst fixtures conform end-to-end on §8 to 5e-2..1e-1 kWh** on every per-month line ref (looser than §6/§7's 5e-3 because LINE_84/93/94 fixture pins are 4-d.p. display-rounded and §8's 0.024·n_m·(L−ηG) propagates that rounding into the per-month kWh band; the orchestrator computes in full precision). + +**E2e SAP-score impact:** the spec-correct summer clamp removed a ~+14% over-prediction that was previously masking residual upstream §3/§5 precision drift. The 000490 SAP score moved 57 → 60 (target 57; tolerance updated to "within 3 points" with the full delta breakdown in `test_elmhurst_000490_end_to_end_sap_score_currently_within_3_points`). 000474 / 000490-kWh tests still pass. + +### Remaining §8 work + +1. **Appendix H solar space heating (98b)** — orchestrator emits `solar_space_heating_monthly_kwh = (0,)·12` always. No Elmhurst fixture exercises it. Wire when a solar-space-heating cert lands. +2. **000490 SAP-score gap to 57 (currently 60)** — needs upstream §3 (transmission HLC), §5 (internal gains), and the §4 water heating cert path tightened. Likely closes incrementally as the §9–§14 fuel/cost/rating chain is rebuilt + the legacy `predicted_hot_water_kwh` is replaced by `water_heating_from_cert`.