Replaces stale legacy content (cert-mapper-validation workflow, dated to a 9-triple staging slice) with the current handoff: branch state, 3 shipped slices (S0380.44 → S0380.46), and concrete directives for the 3 remaining slices (cost cascade wiring, E_PV magnitude audit, final fixture re-pin). Companion to docs/HANDOVER_PV_BETA_SPLIT.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.6 KiB
Next-agent prompt — PV β-split slices 4-6
Branch: feature/per-cert-mapper-validation. HEAD: beb0db95 (docs commit on top of S0380.46 5b269f23).
Read domain/sap10_calculator/docs/HANDOVER_PV_BETA_SPLIT.md end-to-end before any tool call. It has the full state, the 3 slices shipped (S0380.44 → S0380.46), the residual table showing where each cert sits, and the concrete plans for the 3 remaining slices.
My directives
The PV β-split work is a 6-slice plan; 3/6 are shipped. Continue:
-
Slice 4 (S0380.47) — cost cascade β wiring. fuel_cost.py:182 currently does
pv_credit = -pv_generation × pv_export_credit_gbp_per_kwh— treats ALL PV as exported at 13.19 p/kWh. Per Appendix M1 §6, onsite-consumed PV should bill at the IMPORT price (Table 12a standard tariff ~18 p, or weighted high/low if off-peak meter). The β infrastructure is already in place (pv_dwelling_kwh_per_yr+pv_exported_kwh_per_yron CalculatorInputs from Slice 2). Add a newpv_dwelling_import_price_gbp_per_kwhfield, wire it incert_to_inputsusing the same off-peak meter logic as_space_heating_fuel_cost_gbp_per_kwh, and split the credit in fuel_cost.py.This is the riskiest slice because every PV cert's SAP rating shifts. The cohort-1 + cohort-2 chain-test 1e-4 pins will need re-pinning — expect small Δ (~0.02-0.05 SAP per cert) so the new pins will still be tight against worksheets. Re-pin AS PART OF SLICE 4 so the suite stays green between commits.
-
Slice 5 (S0380.48) — E_PV magnitude audit. The 7-cert ASHP+5kWh-battery cohort (0350/0380/2225/2636/3800/9285/9418) overshoots PE by +2.7..+8.1 because the cascade computes E_PV ≈ 3× the worksheet's value. For cert 0380: cascade thinks 2570 kWh/yr, worksheet uses 831 kWh/yr. Either
peak_power=3in the API JSON is in non-kWp units, the cascade's S lookup is wrong, or ZPV is mis-mapped.Concrete probes (in handover §"Slice 5 plan"):
- Compare cert 0380's API
peak_power=3against the Elmhurst Summary PDF Section 19 for the same cert - Compute cascade S for orientation=South, pitch=45°, overshading=1=None — compare to SAP Appendix U3.3 spec value (expected ~1100 kWh/m²/yr UK avg)
- Verify Table M1 ZPV[1] = 1.0 against spec
- Empirical test: set cert 0380
peak_power = 1.0and check if residuals close
If it's a kWp interpretation bug, surface via the schema or API mapper.
- Compare cert 0380's API
-
Slice 6 (S0380.49) — final fixture re-pin + tolerance tightening. Once Slices 4 + 5 ship, the ASHP cohort residuals should land near zero. Re-pin all affected golden fixtures; if the cluster lands tightly (~0.01 PE / ~0.001 CO2), tighten
_PE_ABS_TOLERANCE_KWH_PER_M2/_CO2_ABS_TOLERANCE_TONNESaccordingly per feedback-golden-residuals-near-zero.
Conventions preserved (carry forward)
- 1e-4 across the board (feedback-one-e-minus-4-across-the-board)
- Worksheet, not API, is the chain-test target (feedback-worksheet-not-api-reference)
- Cross-mapper parity via cascade (feedback-cross-mapper-parity-via-cascade)
- Spec-floor skepticism (feedback-spec-floor-skepticism)
- Bigger slices OK for uniform work (feedback-bigger-slices-for-uniform-work)
- Golden residuals → ~0 (feedback-golden-residuals-near-zero)
- AAA test convention +
abs(diff) <= tol(feedback-aaa-test-convention, feedback-abs-diff-over-pytest-approx) - Spec citation in commit messages (feedback-spec-citation-in-commits)
- One slice = one commit; stage by name; re-pin shifted fixtures IN SAME SLICE so suite stays green (feedback-commit-per-slice)
- Pyright net-zero per touched file
- Strict-enum raises on unmapped labels
First concrete actions
-
Re-run the diagnostic baseline at the bottom of
HANDOVER_PV_BETA_SPLIT.mdto confirm 763 pass + 0 fail at HEAD. -
Start Slice 4 by reading fuel_cost.py:182 and the existing
_space_heating_fuel_cost_gbp_per_kwhin cert_to_inputs.py to understand the off-peak meter price-resolution logic. Mirror that pattern for the dwelling IMPORT price. -
After Slice 4 lands and chain tests are re-pinned: Slice 5's first probe is comparing cert 0380's API
peak_poweragainst the Summary PDF lodgement. The golden-fixture cert 0380 is0380-2471-3250-2596-8761; its Summary PDF + dr87 worksheet live inbackend/documents_parser/tests/fixtures/— Section 19 of the Summary carries the PV array lodgement. -
Slice 6 wraps up — re-pin, verify, document.
Architecture lessons that landed this session (load-bearing)
- β-split shape is uniform across PE / CO2 / Cost. Each cascade had the same bug — credit ALL PV at one rate (IMPORT for PE; missing for CO2; EXPORT for cost). The spec-correct fix is uniformly onsite-at-IMPORT + exported-at-EXPORT.
CalculatorInputs.pv_dwelling_kwh_per_yr+pv_exported_kwh_per_yrare shared cross-cascade state; each cascade adds its own factor-pair fields.Nonefalls back to legacy single-rate for synthetic test constructions. - The EXPORT factor is Table 12 code 60 ("electricity sold to grid, PV") at all three cascades — already in
domain/sap10_calculator/tables/table_12.pyfor PE (0.501) and CO2 (monthly Table 12d). For Slice 4 cost, you'll reference the same code 60 export-price from Table 12a (typically 13.19 p/kWh for the spec price set). - Cert 9501 is the validation pin. It has PV but no battery, and its PE + CO2 residuals both closed to ~0 after Slices 2-3. Any future cascade refactor must keep cert 9501 closed.
Good luck. The β-implementation is spec-correct (cert 9501 proves it). Slices 4-5 surface the remaining bugs as forcing functions; Slice 6 finalises the closure.