diff --git a/domain/sap10_calculator/docs/HANDOVER_API_SAMPLE_ACCURACY.md b/domain/sap10_calculator/docs/HANDOVER_API_SAMPLE_ACCURACY.md index b47ff6ed..ffd15274 100644 --- a/domain/sap10_calculator/docs/HANDOVER_API_SAMPLE_ACCURACY.md +++ b/domain/sap10_calculator/docs/HANDOVER_API_SAMPLE_ACCURACY.md @@ -4,11 +4,43 @@ Point-in-time note. Start from [`AGENT_GUIDE.md`](AGENT_GUIDE.md) for methodolog 1e-4 bar, the per-line debugging loop, the section helpers, and the suite command. - **Branch:** `feature/per-cert-mapper-validation` -- **HEAD:** `f326e4eb`. Next SAP slice: **S0380.232**. +- **HEAD:** `9521d524`. Next SAP slice: **S0380.235**. - **Baseline (§4 suite):** `tests/domain/sap10_calculator/ backend/documents_parser/tests/` - → green (2407 passed, 1 skipped). Pre-existing out-of-scope failures unchanged + → green (2412 passed, 1 skipped). Pre-existing out-of-scope failures unchanged (stone-§5.6 in `domain/sap10_ml/tests/`; `test_from_rdsap_schema.py::...test_total_floor_area`). +## Shipped this session (S0380.232-234 — the case-19 PV closure) + +The PV diverter (the prior handover's S0380.232 ask) needed two prerequisite +spec bugs fixed first; all three landed: + +| slice | commit | spec | what | +|---|---|---|---| +| **S0380.232** | `212b0c92` | App M1 §3a (p.93, l.5470-5476) | D_PV excludes the LOW-rate portion of an off-peak electric main: `(211)` is only PV-eligible where its §10a code ∈ {30,32,34,35,38}. Storage heaters on 7-hr charge wholly at low rate → fraction 0.0 → excluded. β_Jan 0.894→0.792 (ws 0.791). New `_main_space_heating_high_rate_fraction`. | +| **S0380.233** | `d4a8c02b` | App M1 §6 (p.94, l.5510-5513) | PV-used-in-dwelling credited at the Table 12a ALL_OTHER_USES **weighted** rate (7-hr 14.311 p/kWh), not the bare low rate (5.50). Was under-crediting onsite PV on every off-peak PV cert. Delegates to `_other_fuel_cost_gbp_per_kwh`; STANDARD unchanged. | +| **S0380.234** | `9521d524` | Appendix G4 (p.72-73) | The PV diverter. 3 layers: extractor `Diverter present` + schema `pv_diverter` → `pv_diverter_present` flag (Elmhurst + API mappers) → `_pv_diverter_monthly_kwh` (SPV = export×0.8×0.9, clamp ≤ (62)+(63a), → (63b)m); `cert_to_inputs` recomputes (219) + PV export, β fixed pre-diverter. | + +**Case 19 now: SAP cont 50.33 → 51.34** (ws 51.2221; both round to lodged **51**), +cost (255) 1847.5→1812.3 (ws 1816.6), CO2 3331→3120 (ws 3126), (233a) dwelling +1280.6 (ws **1280.4** — the β fix pins it). The diverter formula is **exact in +summer** (Jun SPV 186.07 = export×0.72, matches ws (63b)). + +**The remaining +0.11 SAP on case 19 = two separate, still-open causes:** +1. **Winter Appendix-M monthly EPV shape.** Our annual EPV (2684.17) matches the + worksheet exactly and Jun-Sep match per-month exactly, but Jan-May/Oct-Dec our + EPV is ~9-11% LOW (worksheet Jan 68.2 vs ours 62.5). Back-solve: ws EPV_m = + |(233a)_m| + |(63b)_m|/0.72. This under-diverts in winter → export (233b) 280.7 + vs ws 184.2, and (219) 3322 vs ws 3188. **A two-array PV apportionment issue + (case 19 has SE + NW arrays with different overshading) — chase in §M / Appendix U + monthly radiation, NOT the diverter (which is validated).** +2. **Fabric (33) +1.0 W/K** (ours 305.04 vs ws 304.04) — a single element off by + exactly 1.0; floor=25.000 is suspiciously round. Walk the per-element §3 breakdown. + +The **eval headline is flat** (42.9→43.0% <0.5; cat-7 5.25→4.93) — expected: the +diverter is rare and the β/price effects are small on the rounded SAP. The value +was pinning the worksheet-validated case 19 + fixing three real spec bugs that the +curated cohort masked. + ## Headline now (1,000-cert 2026 API sample, HEAD `f326e4eb`) | metric | value | was (handover baseline `9c0a373f`) | @@ -188,6 +220,14 @@ pages → ElmhurstSiteNotesExtractor(...).extract() → from_elmhurst_site_notes 4. **Non-PCDB gas boilers (cat 2, no idx, 91 certs, mean 3.18)** and **Flats (282, mean 2.57)** — the next volume levers once the electric clusters are worksheet-pinned. Flats = geometry / communal; start with the worst (`2100-5421` negative SAP). + - **`2100-5421-0922-1622-3463` diagnosed (S0380.234 session):** NOT a flat — `property_type 0`, + a **352 m² 2-storey uninsulated solid-wall** dwelling (wall_constr 3 / wall_ins 4 as-built; + roof_type 4, no roof insulation). Our space-heating demand is **71,084 kWh/yr** → (37)=995.93 + W/K → SAP −24.8 (lodged 36), cost £14,045. This is the **`as-built insulated-assumed`** + U-value front ([[project_as_built_insulated_assumed_bug]]; S0380.209 fixed walls, "roof next"): + the uninsulated-roof / as-built U over-estimates demand on big old dwellings. API-only (no + worksheet → ±0.5 lodged fallback only); needs a generated worksheet or a roof-U spec audit to + pin. It is one outlier, not a cluster-wide flats bug. ### B. Remaining raises (16 certs — all U-value / heat-loss-sensitive, NOT enum guesses) - **`gable_wall_type` 2 & 3 (14 certs).** RdSAP 10 **Table 4** RR walls: 0=Party (U=0.25),