mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
docs: handover + next-agent prompt post S0380.131..137
Captures seven slices: heating-oil price flip (S0380.131),
MissingMainFuelType strict-raise (S0380.132), Elmhurst EES → fuel
dispatch (S0380.133), PE pin block-mismatch fix (S0380.134), Table 4a
R-dispatch solid fuel (S0380.135), dual-fuel cost-cascade fix
(S0380.136), Table 4a R-dispatch electric (S0380.137).
Suite: 880 pass / 0 fail at HEAD 3542186f.
Next slice candidate: the +5..+9 SAP cluster across all 7 cascade-OK
electric corpus variants — uniform −£135..−£222 cost under-count
suggests one shared Table 12a tariff-handling gap.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
2907b40ed9
commit
b20751451d
2 changed files with 528 additions and 0 deletions
347
domain/sap10_calculator/docs/HANDOVER_POST_S0380_137.md
Normal file
347
domain/sap10_calculator/docs/HANDOVER_POST_S0380_137.md
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
# Handover — post Slices S0380.131..137
|
||||
|
||||
Branch: `feature/per-cert-mapper-validation`. **HEAD `3542186f`**.
|
||||
Predecessor: [`HANDOVER_POST_S0380_130.md`](HANDOVER_POST_S0380_130.md).
|
||||
|
||||
## TL;DR
|
||||
|
||||
Seven slices landed on top of `c8486077`. The work spanned a fuel-price
|
||||
correction, a strict-raise on missing fuel that surfaced 26 corpus
|
||||
variants relying on a silent mains-gas default, a measurement-bug fix
|
||||
in the corpus's PE pin, and three slices closing per-cluster cascade
|
||||
gaps via SAP 10.2 Table 4a R-dispatch + a canonical electric-fuel
|
||||
classifier.
|
||||
|
||||
| Slice | Commit | Scope |
|
||||
|---|---|---|
|
||||
| **S0380.131** | `14eee259` | Heating-oil price 7.64 → 5.44 (empirical, Elmhurst worksheet + cert 0240 back-solve) |
|
||||
| **S0380.132** | `0aa40b63` | `MissingMainFuelType` strict-raise on empty `main_fuel_type` (26 corpus variants moved to `_BLOCKED_BY_MISSING_MAIN_FUEL_TYPE`) |
|
||||
| **S0380.133** | `0d2d41ab` | Elmhurst §14.0 EES Code → Table 32 fuel code (BAF/BAI/RAM=anthracite, BCC=coal, BDI=dual, BKI=smokeless, BQI=wood chips, RPS=pellets bags, RUN=bulk, RWN=wood logs) — 10 solid-fuel variants unblocked |
|
||||
| **S0380.134** | `7530ed3f` | Corpus PE pin compared against `cert_to_demand_inputs` (EPC block) instead of rating mode (rating block has no Total PE row) |
|
||||
| **S0380.135** | `829a3318` | Table 4a R-dispatch in `_responsiveness` keyed on `sap_main_heating_code` (solid-fuel codes 151-161, 631-636) |
|
||||
| **S0380.136** | `4d004790` | `_is_electric_main` / `_is_electric_water` route via canonical T32-first normaliser (`table_32.is_electric_fuel_code`) — closes solid fuel 6 dual-fuel SAP −11.37 → +1.95 |
|
||||
| **S0380.137** | `3542186f` | Table 4a R-dispatch extended to electric storage / UFH / Electricaire / direct-acting / ceiling (codes 401-409, 421-425, 515, 691, 694, 701) |
|
||||
|
||||
Extended handover suite at HEAD: **880 pass, 0 fail**.
|
||||
|
||||
## What changed
|
||||
|
||||
### Spec compliance (Table 4a + Table 32 + spec line 15271)
|
||||
|
||||
S0380.135 + S0380.137 implement SAP 10.2 spec line 15271:
|
||||
|
||||
> "R = responsiveness of main heating system (Table 4a or Table 4d)"
|
||||
|
||||
Pre-slices the cascade only consulted Table 4d (emitter-based) — Table
|
||||
4a's per-heating-system R (typically lower than 1.0 for non-modulating
|
||||
systems) was silently ignored. The new
|
||||
`_RESPONSIVENESS_BY_SAP_CODE` dispatch in
|
||||
[`cert_to_inputs.py`](../rdsap/cert_to_inputs.py) overrides the
|
||||
Table 4d fallback when the SAP code is in the dict (31 entries
|
||||
covering all solid-fuel + electric storage / UFH / direct-acting /
|
||||
ceiling codes from Table 4a p.169-170).
|
||||
|
||||
S0380.131 corrected `tables/table_32.py` heating oil 7.64 → 5.44
|
||||
(empirical, no spec citation possible — RdSAP 10 spec PDF p.95 is
|
||||
outlier vs Elmhurst worksheet + gov.uk register back-solve).
|
||||
|
||||
### Strict-raise + canonical normalisation pattern
|
||||
|
||||
S0380.132 added `MissingMainFuelType(ValueError)` in
|
||||
[`exceptions.py`](../exceptions.py). `_main_fuel_code` raises when
|
||||
the mapper leaves `main_fuel_type` empty / non-int. This surfaced 26
|
||||
of 41 corpus variants relying on the silent mains-gas default.
|
||||
|
||||
S0380.136 promoted `table_32._is_electric_code` to public
|
||||
`is_electric_fuel_code` and routed `_is_electric_main` /
|
||||
`_is_electric_water` through it. Closed an API/Table-32 code-10
|
||||
collision (API 10 = electricity, T32 10 = dual fuel) that re-routed
|
||||
solid fuel 6's cost through off-peak electric tariff.
|
||||
|
||||
### Mapper extraction extensions
|
||||
|
||||
S0380.133 added `main_heating_ees: str` field to
|
||||
[`elmhurst_site_notes.py:MainHeating`](../../../datatypes/epc/surveys/elmhurst_site_notes.py)
|
||||
and extraction in
|
||||
[`elmhurst_extractor.py`](../../../backend/documents_parser/elmhurst_extractor.py),
|
||||
plus `_ELMHURST_MAIN_HEATING_EES_TO_FUEL_CODE` dict in
|
||||
[`mapper.py`](../../../datatypes/epc/domain/mapper.py) (10 entries
|
||||
keyed on 3-letter EES code).
|
||||
|
||||
### Corpus test structure
|
||||
|
||||
[`test_heating_systems_corpus.py`](../../../backend/documents_parser/tests/test_heating_systems_corpus.py)
|
||||
now has three tiers:
|
||||
|
||||
1. `_EXPECTATIONS` (25 variants) — full residual-pin grid:
|
||||
SAP / cost / CO2 from `cert_to_inputs` (rating block), PE from
|
||||
`cert_to_demand_inputs` (EPC block).
|
||||
2. `_BLOCKED_BY_MISSING_MAIN_FUEL_TYPE` (16 variants) — assert-on-raise
|
||||
tier driving
|
||||
`test_heating_systems_corpus_blocked_variant_raises_missing_main_fuel_type`.
|
||||
3. Each variant covered exactly once across the two tiers (41 total).
|
||||
|
||||
## Current residual cluster at HEAD `3542186f`
|
||||
|
||||
### Solid fuel — 10/10 unblocked, tight cluster
|
||||
|
||||
| variant | SAP code | R | ΔSAP | ΔPE |
|
||||
|---|---:|---:|---:|---:|
|
||||
| solid fuel 2 | 158 | 0.50 | +2.64 | -1211 |
|
||||
| solid fuel 3 | 160 | 0.50 | +1.32 | -935 |
|
||||
| solid fuel 4 | 633 | 0.50 | +1.59 | +151 |
|
||||
| solid fuel 5 | 153 | 0.75 | +1.70 | +160 |
|
||||
| solid fuel 6 | 160 | 0.50 | +1.95 | +87 |
|
||||
| solid fuel 7 | 160 | 0.50 | +2.04 | +44 |
|
||||
| solid fuel 8 | 160 | 0.50 | +1.81 | +88 |
|
||||
| solid fuel 9 | 636 | 0.75 | +1.71 | +155 |
|
||||
| solid fuel 10 | 634 | 0.50 | +1.75 | +120 |
|
||||
| solid fuel 11 | 634 | 0.50 | +1.62 | +171 |
|
||||
|
||||
7/10 PE residuals within ±220 kWh. SAP cluster all +1.32 to +2.64.
|
||||
solid fuel 2 (-1211 PE) + solid fuel 3 (-935 PE) are the remaining
|
||||
outliers — likely Table 4a efficiency variant or kWh-totals issue.
|
||||
|
||||
### Electric direct-acting — 6/7 unblocked, +5..+9 SAP cluster open
|
||||
|
||||
| variant | SAP code | R | ΔSAP | Δcost | ΔPE |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| electric 1 | 191 | 1.00 | +9.64 | −£222 | +165 |
|
||||
| electric 2 | 524 | 1.00 | +5.85 | −£135 | +971 |
|
||||
| electric 3 | 401 | 0.00 | +9.43 | −£217 | -1059 |
|
||||
| electric 5 | 402 | 0.20 | +6.76 | −£156 | -96 |
|
||||
| electric 6 | 404 | 0.40 | +7.82 | −£180 | -494 |
|
||||
| electric 7 | 408 | 0.60 | +7.58 | −£175 | -428 |
|
||||
| electric 8 | 409 | 0.80 | +5.84 | −£135 | +200 |
|
||||
| electric 9 | 421 | 0.00 | +6.77 | −£156 | +154 |
|
||||
|
||||
**Shared pattern across all 7:** SAP +5.8..+9.6 with cost −£135..−£222.
|
||||
Consistent cost under-count strongly suggests a single Table 12a
|
||||
high/low-rate fraction handling bug OR a pumps/fans electric cascade
|
||||
gap. Same "one fix many variants" leverage pattern as previous slices.
|
||||
|
||||
### Other cascade-OK variants
|
||||
|
||||
| variant | ΔSAP | ΔPE | notes |
|
||||
|---|---:|---:|---|
|
||||
| ashp | +5.67 | -12 | ✓ PE closed |
|
||||
| gshp | +5.16 | -455 | |
|
||||
| oil 1 | +2.66 | -1050 | |
|
||||
| oil pcdb 1/2 | +0.42 | -84 | ✓ basically closed |
|
||||
| oil pcdb 3 | +1.16 | -271 | |
|
||||
| pcdb 1 | +6.95 | -3135 | largest open PE |
|
||||
|
||||
### Blocked tier (16 variants in `_BLOCKED_BY_MISSING_MAIN_FUEL_TYPE`)
|
||||
|
||||
| Category | Variants | SAP code(s) | EES code(s) | Likely fix |
|
||||
|---|---|---|---|---|
|
||||
| Community heating | 1, 2, 3, 4, 6 | 301-304 | COM (all share) | Derive fuel from §14.1 Community Heating block |
|
||||
| Electric storage | 11, 12, 13, 14 | 515, 691, 701 | WEA, REA, OEA | Extend `_ELMHURST_MAIN_HEATING_EES_TO_FUEL_CODE` to electric EES codes |
|
||||
| No system | (1) | 699 | NON | Spec assumed electric heaters |
|
||||
| Liquid-fuel non-oil | oil 2-6 | Table 4b 126-141 | BFD, BXE, BXF, BZC, B3C | Extend §15.0 fallback / mapper dict for HVO / FAME / B30K / bioethanol |
|
||||
| PCDB Bulk LPG | pcdb 3 | (PCDB) | (absent) | Add `"Bulk LPG"` → 2 to `_ELMHURST_MAIN_FUEL_TO_SAP10` |
|
||||
|
||||
## Test baseline at HEAD `3542186f`
|
||||
|
||||
```bash
|
||||
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: **880 pass, 0 fail**.
|
||||
|
||||
## Memories to load (in order)
|
||||
|
||||
```
|
||||
project-heating-systems-corpus # full state at HEAD 3542186f
|
||||
feedback-sap-10-2-only-never-10-3 # CRITICAL — never reference SAP 10.3
|
||||
feedback-worksheet-not-api-reference
|
||||
feedback-spec-citation-in-commits
|
||||
feedback-verify-handover-claims
|
||||
feedback-zero-error-strict
|
||||
feedback-commit-per-slice
|
||||
feedback-aaa-test-convention
|
||||
feedback-e2e-validation-philosophy
|
||||
feedback-abs-diff-over-pytest-approx
|
||||
feedback-spec-floor-skepticism
|
||||
feedback-golden-residuals-near-zero
|
||||
feedback-one-e-minus-4-across-the-board
|
||||
reference-unmapped-sap-code # updated S0380.135 + S0380.137
|
||||
reference-unmapped-api-code
|
||||
project-oil-price-spec-divergence # S0380.131 detail
|
||||
```
|
||||
|
||||
## Next-slice candidates (in priority order)
|
||||
|
||||
### 1. Electric +5..+9 SAP cluster — highest leverage
|
||||
|
||||
7 electric corpus variants share +5.8..+9.6 SAP and −£135..−£222 cost
|
||||
under-count. Pattern strongly suggests one shared cascade gap. Likely
|
||||
candidates:
|
||||
|
||||
- **Table 12a high/low-rate fraction** for electric main heating —
|
||||
the cascade applies tariff splits per `space_heating_high_rate_fraction`,
|
||||
but the worksheet may use a different fraction or skip the split.
|
||||
- **Pumps/fans kWh / cost** — cascade reports 130 kWh/yr; worksheet
|
||||
reports 41 kWh/yr. Cascade over-counts by 89 kWh × electric ~13 p/kWh
|
||||
= ~£12 — small, not the dominant cost gap.
|
||||
- **Cost factor cascading** — for electric main on 18-hour tariff, the
|
||||
cascade uses 5.50 p/kWh (off-peak low rate). The worksheet uses... need
|
||||
to probe.
|
||||
|
||||
Probing one variant (electric 3, the worst at +9.43 SAP / -£217 cost)
|
||||
would identify the shared cause. If a single Table 12a / tariff fix
|
||||
closes most of the 7, that's a high-value slice.
|
||||
|
||||
### 2. Unblock community heating cluster
|
||||
|
||||
5 community heating variants all share `EES Code: COM` (no fuel info in
|
||||
the EES code). The fuel must be derived from the §14.1 Community
|
||||
Heating/Heat Network block which lodges the heat source type (gas
|
||||
boiler / CHP / heat pump / etc.). Each maps to a Table 32 heat-network
|
||||
code (51-58, 41-49).
|
||||
|
||||
Implementation pattern: extend the extractor to capture §14.1 community
|
||||
heat source, add a SAP-code-301-304 → community-heating-fuel dispatch
|
||||
in the mapper.
|
||||
|
||||
### 3. Unblock electric storage variants (11, 12, 13, 14)
|
||||
|
||||
4 electric corpus variants blocked because mapper has no fuel. SAP
|
||||
codes 515 (Electricaire), 691 (Panel heaters), 701 (Electric ceiling)
|
||||
imply electric. Extend `_ELMHURST_MAIN_HEATING_EES_TO_FUEL_CODE`:
|
||||
|
||||
| EES | Variant | Fuel |
|
||||
|---|---|---|
|
||||
| WEA | electric 11 (SAP 515) | 30 (standard electric) |
|
||||
| REA | electric 12 (SAP 691) | 30 |
|
||||
| OEA | electric 13/14 (SAP 701) | 30 |
|
||||
|
||||
Or alternative: gate on `sap_main_heating_code in {191, 401-409, 421-425, 515, 691, 694, 701}` and infer electric — broader pattern.
|
||||
|
||||
### 4. solid fuel 2 / 3 PE residuals (-935 to -1211)
|
||||
|
||||
After R-dispatch closed 7/10 solid-fuel PE residuals, 2 remain at
|
||||
~-1000 PE. Both are anthracite (codes 158, 160). Same fuel and same R
|
||||
as other variants that closed. Possible:
|
||||
|
||||
- Table 4a efficiency variant (winter/summer split)
|
||||
- Secondary heating fraction (Table 11) not applying
|
||||
|
||||
### 5. pcdb 1 PE residual −3135
|
||||
|
||||
Oil PCDB-listed boiler cert (no SAP code, PCDB index drives lookup).
|
||||
Largest open PE residual. Separate cause from R-dispatch.
|
||||
|
||||
### 6. Tariff-dependent R promotion
|
||||
|
||||
Codes 402/403/405 have R=0.20/0.40 off-peak vs R=0.40/0.60 24-hour
|
||||
tariff per Table 4a. Current dict uses off-peak default (corpus is all
|
||||
off-peak). If a 24-hour cert ever surfaces, promote
|
||||
`_RESPONSIVENESS_BY_SAP_CODE` from `dict[int, float]` to
|
||||
`dict[(int, Tariff), float]` lookup.
|
||||
|
||||
### 7. Latent strict-raise opportunity
|
||||
|
||||
`table_32.is_electric_fuel_code` / `_is_gas_code` silently return False
|
||||
for unmapped fuel codes. User raised this in S0380.136 discussion as a
|
||||
follow-up forcing-function pattern (same shape as
|
||||
`MissingMainFuelType`). Broad blast radius — defer until after the
|
||||
visible-residual closures.
|
||||
|
||||
## 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`
|
||||
- **Spec line 15271** (R = responsiveness ... Table 4a or Table 4d)
|
||||
- **Table 4a** (p.163-170) — heating systems with R column
|
||||
- **Table 4b** (p.170-171) — gas / liquid fuel boilers
|
||||
- **Table 4d** (p.170) — heat emitter R
|
||||
- **Table 4e** (p.171-174) — control codes
|
||||
- **Table 9 / 9a / 9b** — heating duration + MIT formulas (where R
|
||||
enters the MIT adjustment)
|
||||
- **Table 12** (p.191) — SAP rating fuel prices (regulated tariff)
|
||||
- **Table 12a** — high/low-rate fraction by system × tariff
|
||||
- **RdSAP 10 spec**: `RdSAP 10 Specification 10-06-2025.pdf`
|
||||
- **§19 Table 32** (p.95) — RdSAP10 fuel prices / CO2 / PE
|
||||
- Heating oil price 7.64 in spec but 5.44 empirically (per S0380.131)
|
||||
- **BRE technical papers** at `sap10 technical papers/` — no Table 32
|
||||
errata
|
||||
- **SAP 10.3** at `sap-10-3-full-specification-2026-01-13.pdf`:
|
||||
**DO NOT reference** (per [[feedback-sap-10-2-only-never-10-3]])
|
||||
|
||||
## Workflow per slice
|
||||
|
||||
1. Read spec page + identify rule
|
||||
2. Probe cascade vs worksheet line-by-line for one variant in the
|
||||
cluster; verify the diagnosis closes the residual via monkey-patch
|
||||
3. Write failing AAA test (literal `# Arrange / # Act / # Assert`)
|
||||
4. Implement helper / dispatch entry / mapper extension
|
||||
5. Verify test passes
|
||||
6. Probe full cluster impact + re-pin affected variants
|
||||
7. Run extended handover suite (command above)
|
||||
8. Pyright net-zero check on touched files (`git stash` → pyright →
|
||||
`git stash pop` → pyright)
|
||||
9. Commit with spec citation +
|
||||
`Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>`
|
||||
10. Update `project-heating-systems-corpus` + `MEMORY.md` index
|
||||
|
||||
## What NOT to do
|
||||
|
||||
- **Don't reference SAP 10.3** — track 10.2 deliberately
|
||||
- **Don't widen pin tolerances** to make pins pass — re-pin smaller or
|
||||
find the spec gap
|
||||
- **Don't re-investigate closed work** (Slices .91..137 all settled)
|
||||
- **Don't add new helpers to `domain/sap10_ml/`** — on the deprecation
|
||||
path
|
||||
- **Don't conflate the R-dispatch with the cost cluster** — R closes PE
|
||||
(via demand), the +5..+9 SAP residual on electrics is the *cost-side*
|
||||
gap, a separate issue
|
||||
- **Don't accept "spec-precision floor" framing** without spec-citation
|
||||
work — verify against worksheet PDF + cross-cert empirical evidence
|
||||
|
||||
## User direction at end of session
|
||||
|
||||
The conversation flowed:
|
||||
1. Started on solid fuel 8 +0.87 ΔSAP — discovered it was a compensating-
|
||||
errors illusion (real CO2 Δ +3525)
|
||||
2. User: "could we add an exception in the calculator that an empty
|
||||
fuel type can't be given?" → S0380.132 strict-raise
|
||||
3. User: "I'm okay with breaking the tests if that means not debugging
|
||||
silent, incorrect fallbacks"
|
||||
4. Suggested SAP-code → fuel derivation → S0380.133 solid-fuel EES
|
||||
dispatch
|
||||
5. User asked for audit of remaining patterns → found PE measurement
|
||||
bug + per-cluster issues → S0380.134 (PE pin fix) → S0380.135 (R
|
||||
dispatch solid fuel)
|
||||
6. User: "is this another opportunity to raise an exception?" during
|
||||
S0380.136 — answered: this is a *different bug class*
|
||||
(type ambiguity, not missing data); broader raise opportunity exists
|
||||
for `is_electric_fuel_code` / `_is_gas_code` silent-False on
|
||||
unmapped (catalogued as #7 above)
|
||||
7. S0380.137 extended R-dispatch to electric
|
||||
|
||||
The "find ONE fix that closes MULTIPLE variants" framing is the user's
|
||||
preferred approach. Each slice closed 6-10 variants via a single
|
||||
table-dispatch or convention-routing change.
|
||||
|
||||
Good luck.
|
||||
181
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_137.md
Normal file
181
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_137.md
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# Next-agent prompt — post S0380.131..137
|
||||
|
||||
You are picking up on branch `feature/per-cert-mapper-validation` at
|
||||
**HEAD `3542186f`**. The previous session closed seven slices:
|
||||
|
||||
| Slice | What it did |
|
||||
|---|---|
|
||||
| S0380.131 | Heating-oil price 7.64 → 5.44 (empirical, Elmhurst worksheet) |
|
||||
| S0380.132 | `MissingMainFuelType` strict-raise; 26 corpus variants moved to blocked tier |
|
||||
| S0380.133 | Elmhurst §14.0 EES Code → fuel dispatch (unblocked 10 solid-fuel variants) |
|
||||
| S0380.134 | Corpus PE pin compared against `cert_to_demand_inputs` (EPC block) |
|
||||
| S0380.135 | SAP 10.2 Table 4a R-dispatch keyed on `sap_main_heating_code` (solid fuel) |
|
||||
| S0380.136 | `_is_electric_main` routed via canonical T32-first normaliser (closed solid fuel 6) |
|
||||
| S0380.137 | Table 4a R-dispatch extended to electric storage / UFH / Electricaire / ceiling |
|
||||
|
||||
Extended handover suite: **880 pass, 0 fail**.
|
||||
|
||||
## Read these first
|
||||
|
||||
In order, before any tool call:
|
||||
|
||||
1. [`HANDOVER_POST_S0380_137.md`](HANDOVER_POST_S0380_137.md) — full
|
||||
state at HEAD `3542186f`, all 25 unblocked + 16 blocked variants,
|
||||
per-cluster residuals, ranked next-slice candidates.
|
||||
2. [`HANDOVER_POST_S0380_130.md`](HANDOVER_POST_S0380_130.md) — prior
|
||||
state at HEAD `c8486077` (for context on the corpus + S0380.131
|
||||
plan that landed this session).
|
||||
|
||||
## Load these memories before starting
|
||||
|
||||
```
|
||||
project-heating-systems-corpus # corpus state at HEAD 3542186f
|
||||
feedback-sap-10-2-only-never-10-3 # CRITICAL — never reference SAP 10.3
|
||||
feedback-worksheet-not-api-reference
|
||||
feedback-spec-citation-in-commits
|
||||
feedback-verify-handover-claims
|
||||
feedback-zero-error-strict
|
||||
feedback-commit-per-slice
|
||||
feedback-aaa-test-convention
|
||||
feedback-e2e-validation-philosophy
|
||||
feedback-abs-diff-over-pytest-approx
|
||||
feedback-spec-floor-skepticism
|
||||
feedback-golden-residuals-near-zero
|
||||
feedback-one-e-minus-4-across-the-board
|
||||
reference-unmapped-sap-code # updated this session
|
||||
reference-unmapped-api-code
|
||||
project-oil-price-spec-divergence # S0380.131 detail
|
||||
```
|
||||
|
||||
## Verify baseline first
|
||||
|
||||
```bash
|
||||
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: **880 pass, 0 fail**.
|
||||
|
||||
## Recommended next slice — electric +5..+9 SAP cluster
|
||||
|
||||
**The signal:** all 7 cascade-OK electric corpus variants share a
|
||||
remarkably consistent pattern:
|
||||
|
||||
| variant | SAP | Δcost | ΔPE |
|
||||
|---|---:|---:|---:|
|
||||
| electric 1 (191) | +9.64 | −£222 | +165 |
|
||||
| electric 2 (524) | +5.85 | −£135 | +971 |
|
||||
| electric 3 (401) | +9.43 | −£217 | -1059 |
|
||||
| electric 5 (402) | +6.76 | −£156 | -96 |
|
||||
| electric 6 (404) | +7.82 | −£180 | -494 |
|
||||
| electric 7 (408) | +7.58 | −£175 | -428 |
|
||||
| electric 8 (409) | +5.84 | −£135 | +200 |
|
||||
| electric 9 (421) | +6.77 | −£156 | +154 |
|
||||
|
||||
All 7 carry SAP +5.8..+9.6 with cost under-count −£135..−£222 (cascade
|
||||
under-counts cost → over-counts SAP). The cost under-count is too
|
||||
uniform to be 7 separate causes — strongly suggests one shared cascade
|
||||
gap in electric main heating cost computation.
|
||||
|
||||
**Most likely candidates** (in order):
|
||||
|
||||
1. **Table 12a high/low-rate fraction** for electric main heating on
|
||||
18-hour tariff (all corpus variants lodge `meter_type: 18 Hour`).
|
||||
Cascade applies the tariff split per
|
||||
`space_heating_high_rate_fraction(system, tariff)` — worksheet may
|
||||
use a different split or skip the split.
|
||||
2. **Pumps/fans cascade** — cascade reports 130 kWh/yr, worksheet
|
||||
reports 41 kWh/yr (+89 kWh × ~13 p/kWh = ~£12). Small, won't
|
||||
close £150-£220 cost gap alone.
|
||||
3. **Cost factor selection** — cascade picks 5.50 p/kWh (18-hour low
|
||||
rate) for electric main on off-peak; worksheet may apply a different
|
||||
blended rate.
|
||||
|
||||
**Slice plan:**
|
||||
|
||||
1. Probe `electric 3` (worst at +9.43 SAP / -£217 cost / -1059 PE):
|
||||
dump `inputs.space_heating_fuel_cost_gbp_per_kwh`, cascade
|
||||
`fuel_cost.main_1_*` fields, worksheet block 11a (255) breakdown.
|
||||
2. Compare cascade cost components vs worksheet line refs (240/245/
|
||||
246/249/250/251/255) to localise the gap.
|
||||
3. Identify the spec rule (Table 12a section + page).
|
||||
4. Write failing AAA test for the specific cost-component fix.
|
||||
5. Implement; verify cluster closure across all 7 electric variants
|
||||
(electric 1/2/3/5/6/7/8/9).
|
||||
6. Re-pin affected variants; run extended handover suite + pyright
|
||||
net-zero; commit.
|
||||
|
||||
## Alternative next-slice candidates
|
||||
|
||||
If the electric cost cluster diagnosis turns out heterogeneous (not
|
||||
one shared cause), pivot to:
|
||||
|
||||
| # | Candidate | Variants closed | Notes |
|
||||
|---|---|---|---|
|
||||
| 2 | Community heating unblocking | 5 | Derive fuel from §14.1 Community Heating block (heat-network codes 41-58) |
|
||||
| 3 | Electric storage unblocking (WEA/REA/OEA) | 4 | Extend EES dict (electric 11/12/13/14 currently RAISE) |
|
||||
| 4 | solid fuel 2/3 PE residuals -935/-1211 | 2 | Both anthracite SAP 158/160; same R + fuel as variants that closed |
|
||||
| 5 | pcdb 1 PE -3135 | 1 | Oil PCDB-listed cert, largest open PE |
|
||||
| 6 | Tariff-dependent R promotion (402/403/405) | 0 | No 24-hour cert in corpus; defer until one surfaces |
|
||||
| 7 | `is_electric_fuel_code` / `_is_gas_code` strict-raise on unmapped | latent | User flagged in S0380.136 discussion |
|
||||
|
||||
See `HANDOVER_POST_S0380_137.md` for full detail on each.
|
||||
|
||||
## Standard slice workflow
|
||||
|
||||
1. Read spec page + identify rule
|
||||
2. Probe cascade vs worksheet for one cluster variant; monkey-patch
|
||||
to verify the fix closes
|
||||
3. Write failing AAA test (literal `# Arrange / # Act / # Assert`)
|
||||
4. Implement helper / dispatch entry / mapper extension
|
||||
5. Probe full cluster + re-pin affected variants
|
||||
6. Run extended handover suite + pyright net-zero
|
||||
(`git stash` → pyright → `git stash pop` → pyright)
|
||||
7. Commit with spec citation +
|
||||
`Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>`
|
||||
8. Update `project-heating-systems-corpus` + `MEMORY.md` index
|
||||
|
||||
## What NOT to do
|
||||
|
||||
- **Don't reference SAP 10.3** ([[feedback-sap-10-2-only-never-10-3]])
|
||||
- **Don't widen pin tolerances** to make pins pass — re-pin smaller or
|
||||
find the spec gap
|
||||
- **Don't re-investigate closed work** — Slices .91..137 all settled
|
||||
- **Don't add new helpers to `domain/sap10_ml/`** — on deprecation path
|
||||
- **Don't conflate R-dispatch (PE-side) with the +5..+9 SAP cluster
|
||||
(cost-side)** — R closes PE via demand calc; the cost-side cluster
|
||||
is a separate Table 12a / tariff issue
|
||||
- **Don't accept "spec-precision floor" framing** without spec-citation
|
||||
verification
|
||||
|
||||
## User context
|
||||
|
||||
The user's framing all session: **"find ONE fix that closes MULTIPLE
|
||||
variants at the same time, rather than per-variant chasing."** Each
|
||||
of the seven slices closed 6-10 variants via a single table-dispatch
|
||||
or convention-routing change. The electric +5..+9 cluster is the next
|
||||
high-leverage opportunity matching this pattern.
|
||||
|
||||
The user is also explicitly OK with breaking tests if it surfaces
|
||||
silent fallbacks. Don't patch around silent defaults — make them
|
||||
loud.
|
||||
|
||||
Good luck.
|
||||
Loading…
Add table
Reference in a new issue