diff --git a/domain/sap10_calculator/docs/HANDOVER_GOLDEN_COVERAGE.md b/domain/sap10_calculator/docs/HANDOVER_GOLDEN_COVERAGE.md index 7dc0290a..f461c375 100644 --- a/domain/sap10_calculator/docs/HANDOVER_GOLDEN_COVERAGE.md +++ b/domain/sap10_calculator/docs/HANDOVER_GOLDEN_COVERAGE.md @@ -150,6 +150,102 @@ When grabbing certs from the data dump, filter by `main_heating[0].description` - `Electric storage heaters` / `Direct-acting electric heaters` - `Community scheme` +## ★★ Elmhurst-only path (calculator gap closure WITHOUT API JSON) + +**User insight from end of session:** the mapper is a thin pass-through; +when residuals remain after closing mapper gaps (cohort-2 → golden), +the gap is in the **calculator cascade**, not the mapper. For +calculator gaps, the API JSON is not load-bearing — only the Elmhurst +Summary PDF (input) and the worksheet PDF (ground-truth line refs) are +needed. + +This is a different fixture shape from the cohort-2 + ASHP path. It +mirrors the **6 original Elmhurst U985 fixtures** (000474, 000477, +000480, 000487, 000490, 000516) — the historical worksheet-pinned test +vectors at `domain/sap10_calculator/worksheet/tests/_elmhurst_worksheet_NNNNNN.py` ++ `test_e2e_elmhurst_sap_score.py`. No API JSON in the loop. + +### Concrete next-target: the extended test case at `sap worksheets/extended test case/` + +``` +sap worksheets/extended test case/ + Summary_000565.pdf ← input lodgement (Elmhurst RdSAP10 PDF) + U985-0001-000565.pdf ← worksheet output (line refs ground-truth) +``` + +Cert 000565 is a **wacky stress-test cert** (user-supplied) that exercises +many cascade paths absent from the cohort-2 + ASHP corpus: + +- **5 building parts**: Main + 4 extensions (vs cohort max 2 extensions) +- **Age mix**: Main A (pre-1900), Ext1 E (1967-75), Ext2 H (1991-95), + Ext3 I (1996-2002), Ext4 J (2003-06) — spans 100+ years of construction +- **Room-in-roof on every part** at different ages (H, I, J, I, M) +- **Conservatory** thermally separated WITH fixed heaters (zero coverage + elsewhere) +- **Wall variety**: + - Main: Solid Brick + 75mm External insulation + Alt Wall Stone granite (23 m² with 120mm As Built + dry-lining) + - Ext1: Stone granite, U Unknown, **Cavity filled** party wall + - Ext2: **Curtain Wall Post 2023** (zero coverage) + - … +- **Party walls**: CU Cavity unfilled (Main), CF Cavity filled (Ext1), U Unable to determine (Ext2) +- **Multi-storey extensions** with floor 0/1 having varying room heights + (1.0 m to 4.0 m) and party_wall_length (0 to 23 m) + +Every uncommon cascade path the cohort-2 + ASHP fixtures don't exercise +will light up against this cert. + +### Implementation outline (mirror the existing pattern) + +1. **Hand-build a `_elmhurst_worksheet_000565.py` module** under + `domain/sap10_calculator/worksheet/tests/`. Pattern is exactly the + shape of `_elmhurst_worksheet_000474.py`: + - `build_epc() -> EpcPropertyData` — hand-construct the EpcPropertyData + from the Summary_000565.pdf §1-19 lodgings. Use the existing + `make_minimal_sap10_epc`, `SapBuildingPart`, `SapFloorDimension` + etc. constructors. + - Module-level `LINE_NN_FOO: type = value` constants for every U985 + line ref the test pins. Extract values from U985-0001-000565.pdf. + +2. **Register the fixture in `test_e2e_elmhurst_sap_score.py`**: + - Add `from . import _elmhurst_worksheet_000565 as _w000565` import. + - Add `"000565": FixtureCascadePins(sap_score=..., sap_score_continuous=..., ...)` entry to `_FIXTURE_PINS`. + - Add `"000565": _w000565` entry to `_FIXTURE_MODULES`. + - The parametrized `test_sap_result_pin[000565-FIELD]` test cases fire automatically. + +3. **Per [[feedback-e2e-validation-philosophy]] + [[feedback-zero-error-strict]]**: + - Tolerances are `abs=1e-4` on every field. No widening, no xfail. + - Failing pins are **named calculator bugs to fix**, not tolerances + to relax. Each failing pin is its own slice. + +### Why this path is more powerful than API-route closure for calculator gaps + +| API-route closure | Elmhurst-only path | +|---|---| +| Cert needs both API JSON AND worksheet | Cert needs only Summary + worksheet PDFs | +| Tests run via `from_api_response → cert_to_inputs → calculator` — failure could be mapper OR calculator | Tests run via `build_epc() → cert_to_inputs → calculator` — failure is **definitionally** a calculator bug | +| Cohort acquisition: gov.uk EPB JSON + assessor's worksheet ZIP | Cohort acquisition: assessor's tool export only (Elmhurst SAP) | +| Cross-mapper parity is a 2nd-order check on top of cascade correctness | Direct cascade correctness check | + +For diverse fuel-type / property-type calculator coverage, the user can +generate test certs in Elmhurst SAP without needing to lodge them at +gov.uk first. **Targets to generate** for closure on currently-zero- +coverage paths: + +| Fuel / config | Why critical | Cascade paths exercised | +|---|---|---| +| Oil boiler PCDB-listed (Firebird etc.) | Closes cert 0240 + 0390 oil residuals; no current oil worksheet | Table 105 oil + oil-tariff fuel cost + oil CO2/PE factors | +| Solid fuel (anthracite, wood pellets, biomass) | Zero coverage | Table 32 solid-fuel branch + solid-fuel CO2/PE factors | +| LPG | Zero coverage | Table 32 LPG branch + LPG-specific tariff lookup | +| Electric direct-acting / storage heaters | Zero coverage; off-peak meter path raises in cert_to_inputs | `_RDSAP_DEFINITELY_OFF_PEAK` dispatch (codes 1/4/5) + Table 12a high/low-rate split | +| Multi-main-heating (main 1 + main 2) | Currently un-exercised — `main_2_fuel_kwh_per_yr` cascade is dormant | Per-main efficiency + per-main fuel cost + summed PE | +| Basement | Minimal coverage | `u_basement_wall` + `u_basement_floor` Table 23 dispatch | +| Conservatory with fixed heaters | Zero coverage | Conservatory exclusion / inclusion rule + heated-conservatory fuel routing | + +The wacky 000565 cert exercises 3-4 of these in one shot (multi- +extension + multi-age + conservatory + curtain wall). After it lands, +the user can generate single-feature certs (one oil cert, one LPG cert, +etc.) to isolate single-cause calculator gaps. + ## Strict-raise pattern (S0380.51) — extension queue The `UnmappedApiCode` strict-raise pattern is established in