mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
docs: handover + next-agent prompt post S0380.96..103 (RIR Unknown + §9 floor + MEV PCDB arc + HP-on-E7 cost split)
8 slices shipped this session: S0380.96 RIR Unknown insulation (RdSAP 10 §3.10.1) S0380.97 Floor §9 insulation thickness (RdSAP 10 §5.13 Table 20) S0380.98 PCDB Table 322 ETL+parser (PCDF Spec §A.19) S0380.99 PCDB Table 329 ETL+parser (PCDF Spec §A.20) S0380.100 MEV SFPav + (230a) helpers (SAP 10.2 §2.6.4) S0380.101 HP SAP code → cat=4 mapper (SAP 10.2 Table 4a) S0380.102 Wire MEV into pumps_fans (SAP 10.2 Table 4f 230a) S0380.103 MEV-fan cost split (SAP 10.2 Table 12a Grid 2) Cert 000565 at HEAD `e3abe9b2`: sap_score (int) ✓ EXACT pumps_fans_kwh_per_yr ✓ EXACT (was +2.48 over) hot_water_kwh_per_yr ✓ 0 EXACT sap_score_continuous Δ +0.0182 (SH cascade-driven) 7 expected fails (was 9) Next slice candidate: S0380.104 investigate §3-§8 space-heating cascade -27 kWh under-count (cert-000565-specific; cohort certs pass at 1e-4). Alternative: S0380.105 CO2 MEV split (mirror of .103 for Table 12d monthly factors). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
860025dbdc
commit
ad953d49c7
2 changed files with 540 additions and 0 deletions
303
domain/sap10_calculator/docs/HANDOVER_POST_S0380_103.md
Normal file
303
domain/sap10_calculator/docs/HANDOVER_POST_S0380_103.md
Normal file
|
|
@ -0,0 +1,303 @@
|
||||||
|
# Handover — post S0380.96..103 (RIR Unknown + §9 floor extractor + MEV PCDB arc + HP-on-E7 cost split)
|
||||||
|
|
||||||
|
Branch: `feature/per-cert-mapper-validation`. **HEAD `e3abe9b2`**.
|
||||||
|
Predecessor: [`HANDOVER_POST_S0380_95.md`](HANDOVER_POST_S0380_95.md).
|
||||||
|
|
||||||
|
## Slices committed this session (S0380.96..103)
|
||||||
|
|
||||||
|
Eight spec-cited slices. The first two closed remaining cert 000565
|
||||||
|
extractor/mapper gaps (RIR "Unknown" insulation + floor §9
|
||||||
|
"Insulation Thickness"). Slices .98..102 built the MEV PCDB
|
||||||
|
decentralised cascade arc end-to-end (Tables 322 + 329 + SFPav
|
||||||
|
formula + HP-category mapper + wiring). The final slice .103 closed
|
||||||
|
the Table 12a Grid 2 MEV-fan cost split, completing the HP-on-E7
|
||||||
|
cost cascade.
|
||||||
|
|
||||||
|
| Slice | Commit | Spec | Cert 000565 outcome |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **S0380.96** | `32a4cf20` | RdSAP 10 §3.10.1 (PDF p.24) — "Unknown" insulation → Table 18 col 4 age-band default | BP[4] FC1 cascade U: 2.30 → **0.15 ✓ EXACT**. roof_w_per_k Δ +12.34 → +1.59 (closed -10.75). Continuous SAP Δ -0.44 → -0.20. |
|
||||||
|
| **S0380.97** | `7121a86b` | RdSAP 10 §5.13 Table 20 (PDF p.47) — exposed/semi-exposed floor U by age × thickness | BP[2] Ext2 floor U: 0.51 → **0.22 ✓ EXACT**. floor_w_per_k **✓ EXACT**. **sap_score 28 → 29 ✓ EXACT**. Continuous SAP Δ -0.0001 (within 1e-4). |
|
||||||
|
| **S0380.98** | `b3330821` | PCDF Spec Rev 6b §A.19 — PCDB Table 322 Format 427/428 | Foundation only. Typed parser + ETL + `decentralised_mev_record(pcdb_id)` lookup. 48 records ingested. No cascade integration. |
|
||||||
|
| **S0380.99** | `433f4a49` | PCDF Spec Rev 6b §A.20 — PCDB Table 329 Format 430/432 | Foundation only. Typed parser + ETL + `mv_in_use_factors_record(system_type)`. 5 records ingested. No cascade integration. |
|
||||||
|
| **S0380.100** | `44fb8c07` | SAP 10.2 §2.6.4 equation (1) + Table 4f line (230a) | New module `worksheet/mev.py` — `mev_sfp_av` + `mev_decentralised_kwh_per_yr` pure helpers. AAA tests pin cert 000565 worksheet values. No cascade integration. |
|
||||||
|
| **S0380.101** | `1b183f9c` | SAP 10.2 Table 4a (PDF p.165) — Heat-pump category 4 | HP SAP codes 211-227 / 521-527 → `main_heating_category=4` in `_elmhurst_main_heating_category` (Elmhurst path). Cert 000565 Main 1 (SAP 224) flipped None→4. Transient regression: pumps_fans 255 → 125 (offset bug exposed). |
|
||||||
|
| **S0380.102** | `a0413155` | SAP 10.2 §2.6.4 + Table 4f (230a) — Wire MEV cascade into `_table_4f_additive_components` | **pumps_fans_kwh_per_yr 255 → 252.5159 ✓ EXACT**. Schema + extractor + mapper for MV PCDF index / wet rooms / duct type. Elmhurst fan-count convention reverse-engineered from cert 000565 (TODO: validate on a 2nd MEV cert). |
|
||||||
|
| **S0380.103** | `e3abe9b2` | SAP 10.2 Table 12a Grid 2 (PDF p.191) — `FANS_FOR_MECH_VENT` blended rate on off-peak | MEV-fan cost weighting: 127.5 kWh at 11.6644 p/kWh + 125 kWh at 13.2440 p/kWh → effective 12.4467 p/kWh. cost Δ +£0.39 → -£1.62 (sign flipped; SH cascade residual exposed). |
|
||||||
|
|
||||||
|
**Test baseline at HEAD `e3abe9b2`:** 597 pass + 7 expected `000565`
|
||||||
|
fails (was 585 + 9 at start of session, with .96+.97 closing the
|
||||||
|
sap_score integer fail and .102 closing the pumps_fans fail). The
|
||||||
|
ETL test count grew by ~25 with the new PCDB tables.
|
||||||
|
|
||||||
|
Pyright net-zero per touched file across every slice.
|
||||||
|
|
||||||
|
## Cert 000565 state (HEAD `e3abe9b2`)
|
||||||
|
|
||||||
|
### Fabric subtotals
|
||||||
|
|
||||||
|
| Component | Cascade W/K | Worksheet W/K | Δ | Status |
|
||||||
|
|---|---:|---:|---:|---|
|
||||||
|
| walls | 601.22 | 604.07 | -2.85 | sub-spec |
|
||||||
|
| **party_walls** | **65.13** | 65.13 | ✓ EXACT | S0380.91 |
|
||||||
|
| **floor** | **61.67** | 61.67 | ✓ EXACT | S0380.97 |
|
||||||
|
| roof | 52.97 | 51.38 | +1.59 | residual +1.29 BP[1] formula |
|
||||||
|
| windows | 9.60 | 11.48 | -1.88 | sub-spec |
|
||||||
|
| roof_windows | 5.02 | 3.58 | +1.44 | sub-spec |
|
||||||
|
| **doors** | **11.10** | 11.10 | ✓ EXACT | full pipeline plumbing |
|
||||||
|
| **thermal_bridging** | **129.35** | 128.65 | +0.70 | S0380.95 |
|
||||||
|
| **total external area** | **862.34** | 857.64 | +4.70 | S0380.95 |
|
||||||
|
|
||||||
|
### SapResult pins (HEAD `e3abe9b2`)
|
||||||
|
|
||||||
|
| Pin | Cascade | Worksheet | Δ | Status |
|
||||||
|
|---|---:|---:|---:|---|
|
||||||
|
| **sap_score (int)** | **29** | 29 | **✓ EXACT** | S0380.97 |
|
||||||
|
| sap_score_continuous | 28.5269 | 28.5087 | +0.0182 | SH cascade-driven |
|
||||||
|
| ecf | 5.3850 | 5.3866 | -0.0016 | SH cascade-driven |
|
||||||
|
| total_fuel_cost_gbp | 4678.6372 | 4680.2593 | -1.6221 | SH cascade-driven |
|
||||||
|
| co2_kg_per_yr | 6445.8198 | 6447.6263 | -1.8065 | mix: CO2 MEV split + SH |
|
||||||
|
| space_heating_kwh_per_yr | 58980.8225 | 59008.3499 | -27.5274 | §3-§8 cascade gap |
|
||||||
|
| main_heating_fuel_kwh_per_yr | 34694.6015 | 34710.7941 | -16.1926 | downstream of SH |
|
||||||
|
| **hot_water_kwh_per_yr** | 3755.0288 | 3755.0288 | ✓ 0 EXACT | unchanged |
|
||||||
|
| lighting_kwh_per_yr | 1387.0237 | 1384.8353 | +2.1884 | sub-spec |
|
||||||
|
| **pumps_fans_kwh_per_yr** | **252.5159** | 252.5159 | **✓ 0 EXACT** | S0380.102 |
|
||||||
|
|
||||||
|
### Continuous SAP journey across this session
|
||||||
|
|
||||||
|
| Slice | sap_score (int) | sap_score_continuous | Δ vs ws |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| Pre-S0380.96 | 28 | 28.07 | -0.44 |
|
||||||
|
| S0380.96 | 28 | 28.31 | -0.20 |
|
||||||
|
| **S0380.97** | **29** | **28.5086** | **-0.0001** (within 1e-4!) |
|
||||||
|
| S0380.98..100 | 29 | 28.5086 | -0.0001 (no cascade change) |
|
||||||
|
| S0380.101 | 29 | 28.6942 | +0.1855 (transient — HP cat=4 only, MEV not yet wired) |
|
||||||
|
| S0380.102 | 29 | 28.5043 | -0.0044 (MEV wired, restored balance) |
|
||||||
|
| **S0380.103** | 29 | **28.5269** | **+0.0182** (MEV cost split exposed pre-existing SH residual) |
|
||||||
|
|
||||||
|
Per user direction [[feedback-spec-floor-skepticism]] +
|
||||||
|
[[feedback-spec-floor-skepticism]]: each slice closed a true spec-
|
||||||
|
correct intermediate-value bug. The continuous-SAP residual is now
|
||||||
|
driven by a §3-§8 SH cascade under-count (main_heating_fuel -16 kWh)
|
||||||
|
that was previously masked by the +£2.01 pumps_fans cost over-count.
|
||||||
|
|
||||||
|
## Open work — prioritised next slices
|
||||||
|
|
||||||
|
### S0380.104 — Investigate §3-§8 space-heating cascade -27 kWh
|
||||||
|
|
||||||
|
**The current biggest residual driver.** main_heating_fuel_kwh is
|
||||||
|
-16.19 kWh under ws (34694.60 vs ws 34710.79) → SH cost £1.58 under
|
||||||
|
ws → continuous-SAP +0.0182 OVER ws.
|
||||||
|
|
||||||
|
Possible causes:
|
||||||
|
1. **Heat transmission HLC residual** — fabric subtotals net to net
|
||||||
|
~+29 W/K (post-S0380.95 fabric snapshot). Walls -2.85, roof
|
||||||
|
+1.59, thermal_bridging +0.70, total_external_area +4.70.
|
||||||
|
Roof BP[1] residual formula gap (+1.29 W/K, deferred from
|
||||||
|
S0380.95) is the largest single localised item.
|
||||||
|
2. **Internal gains** — pumps_fans gains contribution changes with
|
||||||
|
HP cat=4 path; verify against ws line (70) by month.
|
||||||
|
3. **Solar gains / utilization factor** — sub-spec window U-values
|
||||||
|
leak into solar gains too.
|
||||||
|
4. **Mean internal temperature / per-month solve** — possible
|
||||||
|
convergence-loop tolerance issue on this multi-BP cert.
|
||||||
|
|
||||||
|
**Approach:** probe per-month `space_heat_requirement_kwh` vs ws
|
||||||
|
line (98c)m to localise. The cohort certs (000474..000516) hit SH
|
||||||
|
at 1e-4 so the §8 orchestrator IS correct on simpler dwellings —
|
||||||
|
something cert-000565-specific (Detailed-RR + multi-BP + HP + MEV
|
||||||
|
+ FGHRS + solar HW + draught lobby) is the differentiator.
|
||||||
|
|
||||||
|
Expected closure: continuous SAP +0.0182 → within 1e-4.
|
||||||
|
|
||||||
|
### S0380.105 — CO2 cascade MEV split (Table 12d monthly factors)
|
||||||
|
|
||||||
|
Mirror of S0380.103 for CO2. Cert 000565 worksheet line (267):
|
||||||
|
|
||||||
|
Pumps, fans and electric keep-hot 252.5159 × 0.1412 = 35.3349
|
||||||
|
|
||||||
|
Cascade `pumps_fans_co2_factor_kg_per_kwh = 0.14116` (kWh-weighted
|
||||||
|
Table 12d monthly factor for code 30) → 35.6453 kg → +0.31 over ws.
|
||||||
|
|
||||||
|
Cause: cascade uses a single Table 12d profile across all pumps_fans
|
||||||
|
kWh. MEV fans have a different MONTHLY DISTRIBUTION than central-
|
||||||
|
heating pumps + flue fans (MEV runs year-round at 0.5 ach; pumps
|
||||||
|
run heating season only). The worksheet integrates separately.
|
||||||
|
|
||||||
|
**Slice scope:** add `MevFanEntry`-style CO2 helper + new
|
||||||
|
`pumps_fans_co2_factor_kg_per_kwh` resolution that weights the two
|
||||||
|
streams.
|
||||||
|
|
||||||
|
Impact: -0.31 kg/yr → continuous SAP downstream.
|
||||||
|
|
||||||
|
### S0380.106 — PE cascade MEV split (Table 12e monthly factors)
|
||||||
|
|
||||||
|
Mirror of S0380.105 for primary energy. Analogous structure.
|
||||||
|
|
||||||
|
### S0380.107 — BP[1] residual formula refinement (roof)
|
||||||
|
|
||||||
|
BP[1] Ext1 currently has residual +3.68 m² over worksheet (cascade
|
||||||
|
21.93 vs ws 18.25). The Simplified A_RR formula `12.5 × √(34/1.5)`
|
||||||
|
gives 59.51 — minus 37.58 lodged walls = 21.93. Worksheet uses 18.25.
|
||||||
|
|
||||||
|
Hypothesis: Ext1's RR height = 3.0 m (not 2.45 m assumed by formula).
|
||||||
|
A height-aware formula like `A_RR = perimeter × actual_RR_height`
|
||||||
|
might match. Need investigation against multiple Detailed-mode certs
|
||||||
|
with non-2.45 RR heights.
|
||||||
|
|
||||||
|
Impact if closed: roof -1.29 W/K (residual drops by 3.68 × 0.35).
|
||||||
|
|
||||||
|
### S0380.108 — Lighting +2.19 kWh trace residual
|
||||||
|
|
||||||
|
Cascade 1387.02 vs ws 1384.84. Sub-spec but breaks 1e-4 strict pin.
|
||||||
|
|
||||||
|
§5 Appendix L lighting cascade. Likely a per-cert-lodging gap
|
||||||
|
(bulb count, fixed/non-fixed lighting fraction).
|
||||||
|
|
||||||
|
### Deferred (unchanged from earlier handovers)
|
||||||
|
|
||||||
|
- 12 gas-combi PV certs at +0.5..+1.6 PE (no worksheets)
|
||||||
|
- 5 SAP-residual API-only certs (no worksheets)
|
||||||
|
|
||||||
|
## MEV PCDB arc — architecture summary
|
||||||
|
|
||||||
|
The S0380.98..103 arc landed the entire MEV decentralised cascade
|
||||||
|
end-to-end. Architecture (in dependency order):
|
||||||
|
|
||||||
|
```
|
||||||
|
PCDB pcdb10.dat
|
||||||
|
↓ ETL (etl.py, parser.py)
|
||||||
|
Table 322 (per-fan SFP) ←→ Table 329 (per-ducting IUF)
|
||||||
|
↓ runtime lookups (__init__.py)
|
||||||
|
decentralised_mev_record(pcdb_id) + mv_in_use_factors_record(system_type)
|
||||||
|
↓
|
||||||
|
worksheet/mev.py — pure helpers
|
||||||
|
mev_sfp_av(fan_entries) → §2.6.4 equation (1) avg SFP
|
||||||
|
mev_decentralised_kwh_per_yr(sfp_av, V) → Table 4f line (230a) kWh
|
||||||
|
↓
|
||||||
|
cert_to_inputs.py
|
||||||
|
_mev_decentralised_kwh_per_yr_from_cert(epc) — composer
|
||||||
|
reads epc.mechanical_ventilation_index_number, .wet_rooms_count,
|
||||||
|
.mechanical_vent_duct_type
|
||||||
|
builds Elmhurst per-fan count distribution
|
||||||
|
invokes mev.py helpers
|
||||||
|
↓
|
||||||
|
_table_4f_additive_components(epc) adds the MEV contribution
|
||||||
|
↓
|
||||||
|
pumps_fans_kwh_per_yr final cascade output
|
||||||
|
|
||||||
|
For COST (S0380.103):
|
||||||
|
_pumps_fans_fuel_cost_gbp_per_kwh(tariff, mev_kwh, total_pumps_fans_kwh)
|
||||||
|
→ kWh-weighted blended rate (FANS_FOR_MECH_VENT vs ALL_OTHER_USES)
|
||||||
|
CalculatorInputs.pumps_fans_fuel_cost_gbp_per_kwh: Optional[float]
|
||||||
|
Calculator legacy path uses it via `or other_fuel_cost_gbp_per_kwh`.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Open question for the next agent:** the Elmhurst per-fan-count
|
||||||
|
convention in `_mev_decentralised_kwh_per_yr_from_cert` was reverse-
|
||||||
|
engineered from cert 000565 alone:
|
||||||
|
- Each PCDB-defined config (1..6) gets baseline count = 1
|
||||||
|
- Through-wall kitchen (5): wet_rooms_count fans total
|
||||||
|
- Through-wall other wet (6): wet_rooms_count + 1 fans total
|
||||||
|
|
||||||
|
When a 2nd MEV cert lands, validate this. May need to consult
|
||||||
|
Elmhurst's documentation or the BRE-published SAP 10.2
|
||||||
|
implementation guide.
|
||||||
|
|
||||||
|
## How to run the baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PYTHONPATH=/workspaces/model python -m pytest \
|
||||||
|
backend/documents_parser/tests/test_summary_pdf_mapper_chain.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_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 \
|
||||||
|
--no-cov -q
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: **597 pass + 7 expected `test_sap_result_pin[000565-*]` fails**.
|
||||||
|
|
||||||
|
The 7 expected fails (verbatim):
|
||||||
|
```
|
||||||
|
sap_score_continuous
|
||||||
|
ecf
|
||||||
|
total_fuel_cost_gbp
|
||||||
|
co2_kg_per_yr
|
||||||
|
space_heating_kwh_per_yr
|
||||||
|
main_heating_fuel_kwh_per_yr
|
||||||
|
lighting_kwh_per_yr
|
||||||
|
```
|
||||||
|
|
||||||
|
All driven by the §3-§8 SH cascade residual + lighting trace + CO2
|
||||||
|
MEV-split gap.
|
||||||
|
|
||||||
|
## Files touched this session
|
||||||
|
|
||||||
|
| File | Slices | Change |
|
||||||
|
|---|---|---|
|
||||||
|
| `backend/documents_parser/elmhurst_extractor.py` | .96, .97, .102 | "Unknown" insulation token; §9 "Insulation Thickness" cell; §12.1 MV PCDF/Wet-Rooms/Duct-Type fields |
|
||||||
|
| `backend/documents_parser/tests/test_summary_pdf_mapper_chain.py` | .96, .97, .101, .103 | AAA tests for cert 000565 closures |
|
||||||
|
| `datatypes/epc/domain/mapper.py` | .96, .97, .101, .102 | `_elmhurst_rir_insulation_thickness_mm` → `Optional[int]`; floor `insulation_thickness_mm` plumbing; HP SAP-code → category 4; MV duct-type mapper + PCDF plumbing |
|
||||||
|
| `datatypes/epc/surveys/elmhurst_site_notes.py` | .97, .102 | `FloorDetails.insulation_thickness_mm`; `VentilationAndCooling.mechanical_ventilation_pcdf_reference` + `.wet_rooms_count` + `.duct_type` + `.approved_installation` |
|
||||||
|
| `domain/sap10_calculator/tables/pcdb/__init__.py` | .98, .99 | `decentralised_mev_record` + `mv_in_use_factors_record` lookups |
|
||||||
|
| `domain/sap10_calculator/tables/pcdb/etl.py` | .98, .99 | Table 322 + 329 typed ETL |
|
||||||
|
| `domain/sap10_calculator/tables/pcdb/parser.py` | .98, .99 | `DecentralisedMevRecord` + `MvInUseFactorsRecord` + parsers |
|
||||||
|
| `domain/sap10_calculator/tables/pcdb/data/pcdb_table_322_decentralised_mev.jsonl` | .98 | New file — 48 records |
|
||||||
|
| `domain/sap10_calculator/tables/pcdb/data/pcdb_table_329_mv_in_use_factors.jsonl` | .99 | New file — 5 records |
|
||||||
|
| `domain/sap10_calculator/worksheet/mev.py` | .100 | New module — `mev_sfp_av` + `mev_decentralised_kwh_per_yr` helpers |
|
||||||
|
| `domain/sap10_calculator/worksheet/tests/test_mev.py` | .100 | AAA tests pinning cert 000565 SFPav |
|
||||||
|
| `domain/sap10_calculator/rdsap/cert_to_inputs.py` | .102, .103 | `_mev_decentralised_kwh_per_yr_from_cert` composer; `_pumps_fans_fuel_cost_gbp_per_kwh` helper |
|
||||||
|
| `domain/sap10_calculator/calculator.py` | .103 | `CalculatorInputs.pumps_fans_fuel_cost_gbp_per_kwh` field + legacy cost path |
|
||||||
|
| `domain/sap10_calculator/tests/test_pcdb_etl.py` | .98, .99 | Added Tables 322, 329 to file list |
|
||||||
|
| `domain/sap10_calculator/tests/test_pcdb_table_322_lookup.py` | .98 | New file — 3 tests |
|
||||||
|
| `domain/sap10_calculator/tests/test_pcdb_table_329_lookup.py` | .99 | New file — 4 tests |
|
||||||
|
|
||||||
|
## Spec source quick-reference
|
||||||
|
|
||||||
|
- **SAP 10.2 full specification**: `domain/sap10_calculator/docs/specs/sap-10-2-full-specification-2025-03-14.pdf`
|
||||||
|
- §2.6.4 (p.16) — Decentralised MEV SFPav equation (1) — S0380.100
|
||||||
|
- §5 Table 4a (p.165) — Heat-pump category 4 — S0380.101
|
||||||
|
- §5 Table 4f (p.174) — Annual electricity for fans / pumps — S0380.100, .102
|
||||||
|
- §5 Table 4g (p.176) — Default SFP for MV systems — S0380.99
|
||||||
|
- §10a Table 12a (p.191) — High-rate fractions on off-peak tariffs — S0380.103
|
||||||
|
- **RdSAP 10 specification**: `domain/sap10_calculator/docs/specs/RdSAP 10 Specification 10-06-2025.pdf`
|
||||||
|
- §3.10.1 (p.24) — Unknown insulation → Table 18 default — S0380.96
|
||||||
|
- §5.13 + Table 20 (p.47) — Exposed/semi-exposed floor U-values — S0380.97
|
||||||
|
- **PCDF Spec Rev 6b**: `domain/sap10_calculator/docs/specs/PCDF_Spec_Rev-06b_12_May_2021.pdf`
|
||||||
|
- §A.19 Format 427 (Decentralised MEV) — S0380.98
|
||||||
|
- §A.20 Format 430 (MV In-Use Factors) — S0380.99
|
||||||
|
- **SAP 10.3 at** `sap-10-3-full-specification-2026-01-13.pdf`: **DO NOT reference** ([[feedback-sap-10-2-only-never-10-3]])
|
||||||
|
|
||||||
|
## Memory updated this session
|
||||||
|
|
||||||
|
- `project_cert_000565_recovery_state` — slice-by-slice closure
|
||||||
|
table for .96..103 + open-work analysis
|
||||||
|
- `MEMORY.md` — index entry refreshed at HEAD `e3abe9b2`
|
||||||
|
|
||||||
|
## What NOT to do
|
||||||
|
|
||||||
|
- **Don't reference SAP 10.3** ([[feedback-sap-10-2-only-never-10-3]]).
|
||||||
|
- **Don't widen pin tolerances or xfail residual gaps**
|
||||||
|
([[feedback-zero-error-strict]]). The 7 cert 000565 fails are the
|
||||||
|
work queue.
|
||||||
|
- **Don't re-investigate any closed work** (.91..103). All settled.
|
||||||
|
- **Don't add new helpers to `domain/sap10_ml/`** — deprecation path
|
||||||
|
per [[project-sap10_ml-deprecation]]. New cascade helpers belong
|
||||||
|
under `domain/sap10_calculator/`.
|
||||||
|
- **Don't avoid spec-correct closures because continuous SAP drifts
|
||||||
|
away** — user explicitly OK'd transient drift. Zero error
|
||||||
|
achievable only when every component is spec-correct.
|
||||||
|
|
||||||
|
## Memory hygiene
|
||||||
|
|
||||||
|
After the next slice, update:
|
||||||
|
- `project_cert_000565_recovery_state` — append slice closure +
|
||||||
|
refresh the open work-items table
|
||||||
|
- `MEMORY.md` — refresh HEAD + one-line summary
|
||||||
|
|
||||||
|
Good luck.
|
||||||
237
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_103.md
Normal file
237
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_103.md
Normal file
|
|
@ -0,0 +1,237 @@
|
||||||
|
# Next-agent prompt — post S0380.96..103
|
||||||
|
|
||||||
|
Branch: `feature/per-cert-mapper-validation`.
|
||||||
|
HEAD: `e3abe9b2`.
|
||||||
|
|
||||||
|
Read these in order before any tool call:
|
||||||
|
|
||||||
|
1. [`HANDOVER_POST_S0380_103.md`](HANDOVER_POST_S0380_103.md) — full state
|
||||||
|
2. [`HANDOVER_POST_S0380_95.md`](HANDOVER_POST_S0380_95.md) — predecessor (background)
|
||||||
|
|
||||||
|
Also load these memories before starting:
|
||||||
|
|
||||||
|
- `project_cert_000565_recovery_state` — slice history + per-pin state
|
||||||
|
- `reference_unmapped_sap_code` — calculator strict-raise pattern
|
||||||
|
- `project_sap10_ml_deprecation` — `domain/sap10_ml/` is on the
|
||||||
|
deprecation path; new cascade helpers should land under
|
||||||
|
`domain/sap10_calculator/`
|
||||||
|
- `feedback_sap_10_2_only_never_10_3` — **CRITICAL** — never reference
|
||||||
|
SAP 10.3 spec
|
||||||
|
- `feedback_spec_citation_in_commits` — quote spec text + page in
|
||||||
|
commit messages
|
||||||
|
- `feedback_verify_handover_claims` — verify spec citations + numeric
|
||||||
|
claims before implementing the prescribed fix
|
||||||
|
- `feedback_zero_error_strict` — pyright net-zero per touched file
|
||||||
|
- `feedback_commit_per_slice` — one slice = one commit
|
||||||
|
- `feedback_aaa_test_convention` — every new test uses literal
|
||||||
|
`# Arrange / # Act / # Assert` headers
|
||||||
|
- `feedback_e2e_validation_philosophy` — component pins at <1e-3;
|
||||||
|
SAP integer delta=0; no adaptive ceilings
|
||||||
|
- `feedback_abs_diff_over_pytest_approx` — use `abs(x - y) <= tol`
|
||||||
|
instead of `pytest.approx` to keep pyright net-zero
|
||||||
|
- `feedback_spec_floor_skepticism` — skeptical of "spec-precision
|
||||||
|
floor" claims; verify the spec citation against the PDF first
|
||||||
|
|
||||||
|
## Critical user direction
|
||||||
|
|
||||||
|
The user's **primary metric is `sap_score_continuous`** (not just
|
||||||
|
integer `sap_score`). However the user has explicitly stated:
|
||||||
|
|
||||||
|
> "It's okay if we temp drift away from continuous SAP, as long as we
|
||||||
|
> are actually fixing true problems with the intermediate values.
|
||||||
|
> Eventually, I expect the error of continuous SAP to be zero but
|
||||||
|
> that is only possible if we fix all of the sub components and
|
||||||
|
> remain true to spec."
|
||||||
|
|
||||||
|
**Implication:** ship spec-correct slices even when they cause
|
||||||
|
transient continuous-SAP drift. Closing real intermediate-value bugs
|
||||||
|
is the path to zero error.
|
||||||
|
|
||||||
|
## State summary
|
||||||
|
|
||||||
|
This session shipped **S0380.96..103** — eight spec-cited slices.
|
||||||
|
The first two (.96, .97) closed remaining cert 000565 extractor /
|
||||||
|
mapper gaps; .98..102 built the entire MEV PCDB decentralised
|
||||||
|
cascade arc; .103 closed the Table 12a Grid 2 MEV-fan cost split.
|
||||||
|
|
||||||
|
1. **S0380.96** (`32a4cf20`) — RIR "Unknown" insulation → Table 18
|
||||||
|
col 4 default (RdSAP 10 §3.10.1). BP[4] FC1 U: 2.30→**0.15 ✓**.
|
||||||
|
2. **S0380.97** (`7121a86b`) — Floor §9 "Insulation Thickness"
|
||||||
|
extractor (RdSAP 10 §5.13 Table 20). BP[2] floor U:
|
||||||
|
0.51→**0.22 ✓ EXACT**. **sap_score 28→29 ✓ EXACT**. Continuous
|
||||||
|
SAP Δ -0.0001 (within 1e-4 strict floor).
|
||||||
|
3. **S0380.98** (`b3330821`) — PCDB Table 322 (Decentralised MEV)
|
||||||
|
ETL + parser + lookup foundation (PCDF Spec §A.19).
|
||||||
|
4. **S0380.99** (`433f4a49`) — PCDB Table 329 (MV In-Use Factors)
|
||||||
|
ETL + parser + lookup foundation (PCDF Spec §A.20).
|
||||||
|
5. **S0380.100** (`44fb8c07`) — SFPav + Table 4f (230a) cascade
|
||||||
|
helpers in `worksheet/mev.py` (SAP 10.2 §2.6.4).
|
||||||
|
6. **S0380.101** (`1b183f9c`) — HP SAP code 211-227 / 521-527 →
|
||||||
|
`main_heating_category=4` (SAP 10.2 Table 4a).
|
||||||
|
7. **S0380.102** (`a0413155`) — Wire MEV cascade into
|
||||||
|
`_table_4f_additive_components`. **pumps_fans_kwh_per_yr ✓
|
||||||
|
EXACT** (was +2.48 over). Schema + extractor + mapper for MV
|
||||||
|
PCDF index / wet rooms / duct type.
|
||||||
|
8. **S0380.103** (`e3abe9b2`) — MEV-fan cost split via Table 12a
|
||||||
|
Grid 2 `FANS_FOR_MECH_VENT` rate. cost residual Δ +£0.39 →
|
||||||
|
-£1.62 (sign flipped; SH cascade residual now exposed).
|
||||||
|
|
||||||
|
**Cert 000565 state at HEAD `e3abe9b2`:**
|
||||||
|
|
||||||
|
| Pin | Cascade | Worksheet | Δ |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| **sap_score (int)** | **29** | 29 | **✓ EXACT** |
|
||||||
|
| sap_score_continuous | 28.5269 | 28.5087 | +0.0182 |
|
||||||
|
| ecf | 5.3850 | 5.3866 | -0.0016 |
|
||||||
|
| total_fuel_cost_gbp | 4678.6372 | 4680.2593 | -1.6221 |
|
||||||
|
| co2_kg_per_yr | 6445.8198 | 6447.6263 | -1.8065 |
|
||||||
|
| space_heating_kwh_per_yr | 58980.8225 | 59008.3499 | -27.5274 |
|
||||||
|
| main_heating_fuel_kwh_per_yr | 34694.6015 | 34710.7941 | -16.1926 |
|
||||||
|
| **pumps_fans_kwh_per_yr** | **252.5159** | 252.5159 | **✓ 0 EXACT** |
|
||||||
|
| **hot_water_kwh_per_yr** | 3755.0288 | 3755.0288 | **✓ 0 EXACT** |
|
||||||
|
| lighting_kwh_per_yr | 1387.0237 | 1384.8353 | +2.1884 |
|
||||||
|
|
||||||
|
## Recommended next slice — S0380.104 § Investigate §3-§8 SH cascade -27 kWh
|
||||||
|
|
||||||
|
**The current biggest residual driver.** Cert 000565 cascade
|
||||||
|
space_heating_kwh = 58980.82 vs ws 59008.35 → Δ -27.53 kWh under.
|
||||||
|
This propagates downstream to main_heating_fuel (-16.19 kWh under)
|
||||||
|
and total_fuel_cost (-£1.62 under). It is the dominant cause of
|
||||||
|
continuous-SAP residual +0.0182 OVER ws.
|
||||||
|
|
||||||
|
### Why it's now exposed
|
||||||
|
|
||||||
|
S0380.103 closed the +£2.01 MEV-cost over-count (Table 12a Grid 2
|
||||||
|
split). Pre-slice that over-count nearly cancelled the SH under-
|
||||||
|
count → cost looked +£0.39 over. Post-slice the SH under-count
|
||||||
|
shows through to cost / co2 / continuous SAP.
|
||||||
|
|
||||||
|
The SH cascade IS correct on the cohort fixtures (000474..000516 at
|
||||||
|
1e-4) so this is **cert-000565-specific**. The differentiators are:
|
||||||
|
- 5 building parts (Main + 4 extensions)
|
||||||
|
- Heat pump + gas combi WHC 914
|
||||||
|
- Detailed-RR with residual area (S0380.95 closure)
|
||||||
|
- MEV decentralised
|
||||||
|
- FGHRS, solar HW, draught lobby, basement walls (Ext3/Ext4),
|
||||||
|
Curtain Wall Post-2023 (Ext2), CF + CU party walls
|
||||||
|
|
||||||
|
### Investigation approach
|
||||||
|
|
||||||
|
1. **Probe per-month `space_heat_requirement_kwh`** vs ws line
|
||||||
|
(98c)m to identify which month(s) carry the residual:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from domain.sap10_calculator.worksheet.tests._elmhurst_worksheet_000565 import build_epc
|
||||||
|
from domain.sap10_calculator.rdsap.cert_to_inputs import cert_to_inputs
|
||||||
|
epc = build_epc()
|
||||||
|
inputs = cert_to_inputs(epc)
|
||||||
|
print("monthly SH:", inputs.space_heating_monthly_kwh)
|
||||||
|
# Compare to ws (98c)m line refs from U985-0001-000565.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check the fabric subtotals** — net cascade HTC is +29.45 W/K
|
||||||
|
over ws. Closing roof BP[1] residual (+1.29 W/K, deferred) +
|
||||||
|
thermal_bridging (+0.70) brings it to +27.5. Walls are -2.85
|
||||||
|
under and windows/roof_windows offset.
|
||||||
|
|
||||||
|
Big +29 W/K HTC should DRIVE space_heating UP, but cascade SH is
|
||||||
|
-27 kWh UNDER. That means the cascade is OVER-counting heat
|
||||||
|
GAINS somewhere, or UNDER-counting demand by an offsetting factor.
|
||||||
|
|
||||||
|
3. **Check internal gains** — pumps_fans gains (line 70) changed
|
||||||
|
between cohort certs and cert 000565 (HP cat=4 → 0W heating-
|
||||||
|
season pump). Verify against ws line (70)m by month.
|
||||||
|
|
||||||
|
4. **Check solar gains** (line 74-83) — sub-spec window U could
|
||||||
|
propagate to gain magnitude.
|
||||||
|
|
||||||
|
5. **Check utilisation factor / mean-internal-temp solve** — multi-
|
||||||
|
BP cert with mixed age bands might hit a corner case.
|
||||||
|
|
||||||
|
Expected closure: continuous SAP +0.0182 → within 1e-4.
|
||||||
|
|
||||||
|
## Alternative next slice — S0380.105 § CO2 cascade MEV split
|
||||||
|
|
||||||
|
Mirror of S0380.103 for CO2. Cert 000565 worksheet line (267):
|
||||||
|
|
||||||
|
```
|
||||||
|
Pumps, fans and electric keep-hot 252.5159 × 0.1412 = 35.3349
|
||||||
|
```
|
||||||
|
|
||||||
|
Cascade `pumps_fans_co2_factor_kg_per_kwh = 0.14116` (kWh-weighted
|
||||||
|
Table 12d monthly factor for code 30) → 35.6453 kg → +0.31 over ws.
|
||||||
|
|
||||||
|
The cascade applies a single Table 12d profile across all
|
||||||
|
pumps_fans. The worksheet integrates MEV (year-round) separately
|
||||||
|
from heating-season pumps + flue fans.
|
||||||
|
|
||||||
|
**Slice scope:** add an MEV-weighted CO2 factor analogous to
|
||||||
|
`_pumps_fans_fuel_cost_gbp_per_kwh`. Add field
|
||||||
|
`CalculatorInputs.pumps_fans_co2_factor_kg_per_kwh` resolution that
|
||||||
|
weights two streams.
|
||||||
|
|
||||||
|
Impact: -0.31 kg/yr → continuous SAP downstream marginal change.
|
||||||
|
|
||||||
|
This is the **lower-leverage** of the two open options. S0380.104
|
||||||
|
SH investigation is higher leverage.
|
||||||
|
|
||||||
|
## Standard workflow per slice
|
||||||
|
|
||||||
|
1. Read SAP 10.2 / RdSAP 10 spec page for the change — quote it in commit
|
||||||
|
2. Probe current cascade output; identify exact spec-vs-cascade gap
|
||||||
|
3. Write failing test FIRST (AAA structure)
|
||||||
|
4. Implement helper / change
|
||||||
|
5. Verify test passes
|
||||||
|
6. Run full handover suite (command below)
|
||||||
|
7. Check pyright on touched files — net-zero from baseline
|
||||||
|
(use `git stash` + re-run pyright to compute baseline)
|
||||||
|
8. Commit with spec citation + verbatim quote
|
||||||
|
9. Update relevant memory if state changed
|
||||||
|
|
||||||
|
## How to run the baseline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PYTHONPATH=/workspaces/model python -m pytest \
|
||||||
|
backend/documents_parser/tests/test_summary_pdf_mapper_chain.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_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 \
|
||||||
|
--no-cov -q
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: **597 pass + 7 expected `test_sap_result_pin[000565-*]` fails**.
|
||||||
|
|
||||||
|
After S0380.104 lands the expected fail count should drop by 5-7
|
||||||
|
(sap_score_continuous, ecf, total_fuel_cost_gbp, co2_kg_per_yr,
|
||||||
|
space_heating_kwh_per_yr, main_heating_fuel_kwh_per_yr) if the SH
|
||||||
|
cascade closes. Lighting (+2.19 kWh) is unrelated and survives as
|
||||||
|
its own slice.
|
||||||
|
|
||||||
|
## What NOT to do
|
||||||
|
|
||||||
|
- **Don't reference SAP 10.3** ([[feedback-sap-10-2-only-never-10-3]]).
|
||||||
|
- **Don't widen pin tolerances or xfail residual gaps**
|
||||||
|
([[feedback-zero-error-strict]]). The 7 cert 000565 fails are the
|
||||||
|
work queue.
|
||||||
|
- **Don't re-investigate any closed work** (.91..103). All settled.
|
||||||
|
- **Don't add new helpers to `domain/sap10_ml/`** — deprecation path
|
||||||
|
per [[project-sap10_ml-deprecation]]. New cascade helpers belong
|
||||||
|
under `domain/sap10_calculator/`.
|
||||||
|
- **Don't avoid spec-correct closures because continuous SAP drifts
|
||||||
|
away** — user explicitly OK'd transient drift. Zero error
|
||||||
|
achievable only when every component is spec-correct.
|
||||||
|
|
||||||
|
## Memory hygiene
|
||||||
|
|
||||||
|
After the next slice, update:
|
||||||
|
- `project_cert_000565_recovery_state` — append closure + open work-
|
||||||
|
items refresh
|
||||||
|
- `MEMORY.md` index — refresh HEAD + one-line summary
|
||||||
|
|
||||||
|
Good luck.
|
||||||
Loading…
Add table
Reference in a new issue