mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
docs: handover + next-agent prompt for S0380.64..69
New `HANDOVER_POST_S0380_69.md` covers the 6 slices shipped this session — cert 000565 closure to sap_score=29 EXACT + main_heating_ co2_factor=0.1533 EXACT, Appendix H pure math module + orchestrator (magnitude calibration deferred on SAP 10.2 spec ambiguity), and the cohort-2 (38 cert) PE/CO2 golden-coverage addition. Includes residuals table, open work breakdown with reasons (Appendix H spec ambiguity, RR fold-in geometry, MEV PCDB external blocker, House coal secondary cascade), spec-source quick-reference, and key-file map. Predecessor `HANDOVER_CERT_000565_COST_CASCADE.md` (S0380.52..63) gets a "superseded by" note at the top so the chain is navigable. `NEXT_AGENT_PROMPT_POST_S0380_69.md` is a self-contained prompt for a new agent picking this up cold — references the memories to load, ranks 5 well-scoped next-slice options (cert 2102 House coal / Appendix H magnitude calibration / RR fold-in / PE cluster / MEV coupled set), and includes the standard probe commands. Reinforces `feedback_sap_10_2_only_never_10_3` as a critical-load constraint. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9ba194db18
commit
bcad2c281c
3 changed files with 632 additions and 0 deletions
|
|
@ -0,0 +1,286 @@
|
|||
# Handover — Cert 000565 cost cascade + remaining residuals
|
||||
|
||||
> **Superseded by** [`HANDOVER_POST_S0380_69.md`](HANDOVER_POST_S0380_69.md) at HEAD `c4b27829` (S0380.64..69 closed sap_score to 29 EXACT + CO2 factor to EXACT, plus 38 cohort-2 certs added to golden coverage). The doc below covers S0380.52..63 — kept for slice-history reference.
|
||||
|
||||
Branch `feature/per-cert-mapper-validation`. **HEAD `a21195ff`** (Slice
|
||||
S0380.63 — Table 4f additive Main 2 flue + solar HW pump).
|
||||
**Test baseline: 427 pass + 10 expected `000565` cascade-gap fails.**
|
||||
Pyright net-zero on every touched file.
|
||||
|
||||
## Scope
|
||||
|
||||
This handover documents 12 slices (S0380.52..63 plus one docs flag)
|
||||
closing the Elmhurst-only fixture cert 000565 from 11 mapper-raises to
|
||||
1 fully-green pin (`secondary_heating_fuel_kwh_per_yr = 0`) + 10
|
||||
small-magnitude cascade-gap residuals. The cascade work spans the
|
||||
extractor, mapper, RdSAP-10-spec tariff dispatch, SAP-10.2 Table 12a
|
||||
high-rate fractions, Table 32 standing charges, and SAP-10.2 Table 4f
|
||||
pumps_fans line items.
|
||||
|
||||
## What "cert 000565" is
|
||||
|
||||
The first **mapper-driven Elmhurst-only** fixture in the test suite
|
||||
(see [[reference-elmhurst-only-test-pattern]]). All prior worksheet
|
||||
fixtures hand-built the EpcPropertyData; 000565 routes
|
||||
`Summary_000565.pdf → ElmhurstSiteNotesExtractor → EpcPropertyDataMapper
|
||||
.from_elmhurst_site_notes → cert_to_inputs → calculate_sap_from_inputs`,
|
||||
making every failing pin localise to extractor / mapper / calculator.
|
||||
|
||||
It is a deliberately wacky 5-bp stress test: Main + 4 extensions, age
|
||||
mix A → J, Room-in-Roof on every bp, conservatory with fixed heaters,
|
||||
curtain-wall Ext2, basement walls on Ext3+Ext4. The heating side is
|
||||
also exotic — Main 1 = ASHP (SAP code 224, no PCDB ref), Main 2 = gas
|
||||
combi (PCDB 15100 Vaillant Ecotec plus 415) servicing DHW via Water
|
||||
Heating SapCode 914, plus solar HW + FGHRS + decentralised MEV.
|
||||
|
||||
The Summary PDF lives at `backend/documents_parser/tests/fixtures/
|
||||
Summary_000565.pdf`; the U985 worksheet (ground-truth line refs)
|
||||
lives at `sap worksheets/extended test case/U985-0001-000565.pdf`.
|
||||
|
||||
## Slices committed in this session
|
||||
|
||||
| Slice | Commit | Domain |
|
||||
|---|---|---|
|
||||
| **S0380.52** | `e51fcb74` | Fixture + 3 §11 glazing labels (`"Triple between 2002 and 2021"`/9, `"Single glazing"`/1, `"Double glazing, known data"`/3) |
|
||||
| **S0380.53** | `bb9097e1` | §14.0 `Main Heating SAP Code` extractor + Main 1 SAP code passthrough + `UnmappedElmhurstLabel("main_heating", ...)` strict-raise when Main 1 has neither PCDB ref nor SAP code |
|
||||
| **S0380.54** | `35330316` | New `MainHeating2` dataclass + extractor for §14.1 Main Heating2 block + mapper builds 2nd `MainHeatingDetail` (strict-raise mirror for Main 2) |
|
||||
| **S0380.55** | `1eff5cf4` | New `_water_heating_main(epc)` helper + cascade routes water-heating efficiency to Main 2 when `water_heating_code == 914` |
|
||||
| **S0380.56** | `e0bca4c3` | New `_water_heating_fuel_code(epc)` helper + 5 cascade sites updated (CO2 / PE / cost) to read from the WHC-914-routed main |
|
||||
| **S0380.57** | `3b61ca8c` | `_ELECTRIC_SAP_MAIN_HEATING_CODES` covering Table 4a HP rows 191-196, 211-217, 221-227, 401-409, 421-425, 521-527; mapper infers `main_fuel_type=30` (electricity) when fuel_type string is empty + SAP code matches |
|
||||
| **S0380.58** | `3e058810` | Per-extension Room(s) in Roof extraction — `ExtensionPart.room_in_roof` field + `_room_in_roof_from_bodies` helper + mapper sums each extension's RR floor area into TFA (cert 000565: 246.91 m² → **319.91 m² ✓**) |
|
||||
| **S0380.59** | `98384999` | Final WHC-914-routing site: `_hot_water_fuel_cost_gbp_per_kwh` argument fix |
|
||||
| **docs** | `1ce1a697` | TODO docstrings flagging deferred HP-on-E7 + Table 4f cascade gap |
|
||||
| **S0380.60** | `488492a9` | **RdSAP 10 §12 page 62** dispatch — Rules 1-4 for Dual meter + heating SAP code → SEVEN_HOUR / TEN_HOUR / etc. New `rdsap_tariff_for_cert(meter_type, main_1_sap_code=..., main_2_sap_code=..., main_1_is_heat_pump_database=..., main_2_is_heat_pump_database=...)` in `table_12a.py` |
|
||||
| **S0380.61** | `b732ceac` | Wire §12 dispatch into the three scalar cost helpers (`_space_heating_fuel_cost_gbp_per_kwh`, `_hot_water_fuel_cost_gbp_per_kwh`, `_other_fuel_cost_gbp_per_kwh`). New `_rdsap_tariff(epc)`, `_TARIFF_HIGH_LOW_RATES_P_PER_KWH`, `_table_12a_system_for_main(main)` helpers. Off-peak HP carriers now blend SH cost via Table 12a Grid 1 ASHP_OTHER row; other-uses blend via Grid 2 ALL_OTHER_USES row |
|
||||
| **S0380.62** | `e19145ac` | New `CalculatorInputs.standing_charges_gbp: float = 0.0` field plumbed into the off-peak cost fallback. `cert_to_inputs` populates via existing `additional_standing_charges_gbp(...)`. Cert 000565: £143 exact (gas £120 + 10-hour high £23) |
|
||||
| **S0380.63** | `a21195ff` | New `_table_4f_additive_components(epc)` summing (230e) Main 2 gas flue fan (45 kWh) + (230g) solar HW pump (80 kWh = `[25 + 5×H1]×2` with H1=3 m² default). MEV (230a) and HP-category derivation deferred together — see "Open work" below |
|
||||
|
||||
## Current 000565 residuals (HEAD `a21195ff`)
|
||||
|
||||
| Pin | Actual | Expected | Δ | Status |
|
||||
|---|---:|---:|---:|---|
|
||||
| sap_score (int) | 30 | 29 | **+1** | Within 1 SAP point |
|
||||
| sap_score_continuous | 30.2312 | 28.5087 | **+1.7225** | Compounds from cost residual |
|
||||
| ecf | 5.2123 | 5.3866 | −0.1743 | Same |
|
||||
| total_fuel_cost_gbp | 4,529.33 | 4,680.26 | **−150.93** | 86% closed vs −1,081 at S0380.59 |
|
||||
| co2_kg_per_yr | 5,713.91 | 6,447.63 | −733.72 | Independent cascade gap (Table 12d monthly electric CO2 factor for HP) |
|
||||
| main_heating_fuel_kwh_per_yr | 34,064.03 | 34,710.79 | −646.77 | Downstream of `space_heating × 1/COP` (COP 1.70 exact) |
|
||||
| space_heating_kwh_per_yr | 57,908.85 | 59,008.35 | **−1,099.50** | Fabric / solar gains fine-grained — likely RR construction U-values on Ext1-4 |
|
||||
| hot_water_kwh_per_yr | 4,026.87 | 3,755.03 | **+271.84** | Likely FGHRS / Table 3a no-keep-hot fine-grained |
|
||||
| lighting_kwh_per_yr | 1,387.02 | 1,384.84 | +2.19 | Essentially closed (TFA-proportional) |
|
||||
| pumps_fans_kwh_per_yr | 255.00 | 252.52 | +2.48 | Surplus is the 130 default base × ~MEV miss — see "Open work" |
|
||||
| secondary_heating_fuel_kwh_per_yr | 0.00 | 0.00 | **0.0** ✓ | Green |
|
||||
|
||||
## Open work — prioritised next slices
|
||||
|
||||
### 1. MEV cascade (230a) — closes pumps_fans pin exactly
|
||||
|
||||
Cert 000565 worksheet (line 230a) shows `MEV = 127.5159 kWh`. The
|
||||
spec formula (Table 4f page 174) is:
|
||||
|
||||
```
|
||||
MEV = IUF × SFP × 1.22 × V
|
||||
```
|
||||
|
||||
For cert 000565, worksheet values:
|
||||
- PCDF 500755 SFP = 0.1274 W/(L/s) (from PCDB MEV record)
|
||||
- V = 641.59 m³ (= `dim.volume_m3`)
|
||||
- IUF ≈ 1.278 (derived empirically: `127.5159 / (0.1274 × 1.22 × 641.59) = 1.278`)
|
||||
|
||||
The PCDB MEV / MVHR record table is **not yet in the codebase** —
|
||||
no JSONL file under `domain/sap10_calculator/tables/pcdb/data/`
|
||||
for ventilation systems. Acquiring + parsing it is the gating
|
||||
step. The Table 4g defaults (centralised/decentralised MEV SFP =
|
||||
0.8, IUF unspecified) would give a wildly wrong value here.
|
||||
|
||||
After MEV is wired AND `_PUMPS_FANS_KWH_BY_MAIN_CATEGORY[4] = 0` is
|
||||
applied to Main 1 HP (next item), pumps_fans closes from 255 → 252.5
|
||||
matching the pin exactly.
|
||||
|
||||
### 2. HP SAP code → main_heating_category=4 in mapper
|
||||
|
||||
The mapper's `_elmhurst_main_heating_category` only sets category=4
|
||||
when a PCDB Table 362 record is lodged. Cert 000565 Main 1 has
|
||||
sap_main_heating_code=224 (ASHP) but no PCDB ref → category=None.
|
||||
The category=None routes pumps_fans to the 130 kWh default base
|
||||
instead of the 0 base for HP (Table 4f "circulation pump in COP").
|
||||
|
||||
The TODO is already written into the mapper docstring at
|
||||
`datatypes/epc/domain/mapper.py:_elmhurst_main_heating_category`.
|
||||
|
||||
**Coupling**: applying this fix alone would worsen pumps_fans
|
||||
(255 → 125) because MEV is still missing. Land it AFTER the MEV
|
||||
slice so the residual closes cleanly.
|
||||
|
||||
`_HEAT_PUMP_SAP_MAIN_HEATING_CODES` should cover Table 4a HP rows
|
||||
211-217, 221-227, 521-524 (verified verbatim from RdSAP 10 §12
|
||||
page 62 — same set used in the tariff dispatch).
|
||||
|
||||
### 3. HW kWh +272 fine-grained — FGHRS / Table 3a no-keep-hot
|
||||
|
||||
Cert 000565 hot_water_kwh_per_yr = 4,026.87 vs worksheet pin
|
||||
3,755.03. The +272 surplus likely tracks one of:
|
||||
|
||||
- **FGHRS** — cert lodges Zenex SuperFlow (PCDF index 60063). The
|
||||
cascade has FGHRS support but the specific PCDF record may be
|
||||
unlodged.
|
||||
- **Table 3a** — gas combi DHW path. For a non-keep-hot combi
|
||||
Table 3a row 4 gives a specific monthly losses tuple. Verify the
|
||||
cascade is using the right row.
|
||||
- **Table 3b/c** — combi DHW with two-profile efficiency override
|
||||
(the `separate_dhw_tests=2` PCDB records that blocked 4/6 cohort
|
||||
fixtures per [[project_section_4_hw_next_ticket]]). For 000565
|
||||
Main 2 PCDB 15100 Vaillant Ecotec plus 415 — check whether it's
|
||||
a separate-DHW-test record.
|
||||
|
||||
Recommend a diagnostic probe first: dump per-month HW kWh from the
|
||||
cascade vs the worksheet's `Fuel for water heating, kWh/month` row
|
||||
(line 219m).
|
||||
|
||||
### 4. space_heating −1,099 kWh fine-grained — fabric / solar gains
|
||||
|
||||
Largest *energy* residual. Drivers:
|
||||
|
||||
- **RR construction U-values** on extensions (Ext1-4 RR added in
|
||||
S0380.58). The mapper currently routes their surfaces through
|
||||
the same cascade as Main RR — but Ext2 RR has detailed
|
||||
construction (`Stud 1 4×6 125mm Mineral, Stud 2 2×2 400+mm PUR`)
|
||||
while Ext3 RR is `Simplified` assessment with only a gable wall
|
||||
(9×7 Exposed). Check the U×A heat-loss per RR surface against
|
||||
the worksheet's §3 line refs.
|
||||
- **Solar gains on §11 windows** — 6 windows added in S0380.52
|
||||
via mapped glazing labels. Cascade reads `g_⊥` from
|
||||
`_G_PERPENDICULAR_BY_GLAZING_TYPE` by code. Verify each window's
|
||||
derived `g_⊥` against the lodged manufacturer values (cert
|
||||
lodges g=0.72 / 0.85 across the 6 windows).
|
||||
- **Internal gains** — TFA-proportional. TFA is now exact (319.91
|
||||
✓), so this is unlikely to be the driver.
|
||||
|
||||
main_heating_fuel residual (−647) is *exactly* `space_heating / COP`
|
||||
(COP 1.70 verified), so closing space_heating closes main_heating
|
||||
automatically. Δ = -647 ≈ -1099 × (1/1.70).
|
||||
|
||||
### 5. CO2 −734 kg/yr cascade gap
|
||||
|
||||
Independent of cost. Likely the Table 12d **monthly electric CO2
|
||||
factor** cascade isn't kicking in for the HP path. For 000565 Main 1
|
||||
HP carrier the cascade should use a monthly cascade per
|
||||
`_effective_monthly_co2_factor`, but the residual suggests it's
|
||||
defaulting to the annual factor.
|
||||
|
||||
Verify by probing `inputs.main_heating_co2_factor_kg_per_kwh` and
|
||||
comparing against worksheet line 273-282 monthly factors.
|
||||
|
||||
### 6. Mains gas tariff divergence (£0.0364 vs £0.0348) — code-wide
|
||||
|
||||
`SAP_10_2_SPEC_PRICES.unit_price_p_per_kwh` (table_12.py) returns
|
||||
3.64 p/kWh for mains gas; RdSAP 10 Table 32 has 3.48 p/kWh. Cert
|
||||
000565 worksheet uses 3.48. The £0.16 p/kWh delta on 3,755 HW kWh
|
||||
adds £6 to the HW cost residual. Fix is a code-wide PriceTable
|
||||
calibration question (ADR-0010 amendment territory), NOT a single-
|
||||
cert fix. Cohort fixtures were calibrated against Table 12 prices
|
||||
so swapping would regress them — needs a coordinated cohort
|
||||
re-pin.
|
||||
|
||||
## Conventions reinforced this session
|
||||
|
||||
- **Verify spec before implementing** ([[feedback-verify-handover-
|
||||
claims]]) — ChatGPT supplied the §12 dispatch which was verified
|
||||
verbatim against RdSAP 10 page 62 before writing code. Slice
|
||||
S0380.60 docstring cites the spec verbatim.
|
||||
- **Bigger slices for uniform work** ([[feedback-bigger-slices-for-
|
||||
uniform-work]]) — Main 2 plumbing (S0380.54) bundled schema +
|
||||
extractor + mapper. Glazing labels (S0380.52) bundled 3 labels.
|
||||
- **Strict-raise on unmapped data** ([[reference-unmapped-api-
|
||||
code]] / `UnmappedElmhurstLabel`) — applied to Main 1 + Main 2
|
||||
identifier checks in S0380.53 + S0380.54.
|
||||
- **One slice = one commit, spec-citation in commit messages**
|
||||
([[feedback-commit-per-slice]] + [[feedback-spec-citation-in-
|
||||
commits]]).
|
||||
- **Pyright net-zero per touched file** ([[feedback-zero-error-
|
||||
strict]]) — verified every slice.
|
||||
- **Coupling-aware reverts** — Slice attempted before S0380.60 to
|
||||
apply HP category derivation alone was reverted because it
|
||||
worsened pumps_fans without MEV in place. Architectural
|
||||
correctness must land AS A SET, not piecewise, when components
|
||||
are spec-coupled.
|
||||
|
||||
## How to run the cert 000565 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/rdsap/tests/test_cert_to_inputs.py \
|
||||
domain/sap10_calculator/rdsap/tests/test_golden_fixtures.py \
|
||||
--no-cov -q
|
||||
```
|
||||
|
||||
Expected: **427 pass + 10 expected 000565 fails** (the 10 pins
|
||||
above with non-zero Δ).
|
||||
|
||||
## How to probe 000565 residuals
|
||||
|
||||
```python
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
from domain.sap10_calculator.worksheet.tests._elmhurst_worksheet_000565 import build_epc
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import cert_to_inputs, SAP_10_2_SPEC_PRICES
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
epc = build_epc()
|
||||
inputs = cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
r = calculate_sap_from_inputs(inputs)
|
||||
# ... per-field comparison vs worksheet pin
|
||||
"
|
||||
```
|
||||
|
||||
The U985 worksheet (`sap worksheets/extended test case/U985-0001-
|
||||
000565.pdf`) contains the ground-truth line refs. Key lines:
|
||||
|
||||
- §3 lines 1-44 — fabric heat loss components per bp
|
||||
- §4 lines 45-65 — water heating
|
||||
- §5 lines 66-89 — internal + solar gains
|
||||
- §6/§7/§8 lines 90-200 — MIT + space heating
|
||||
- §9a lines 201-238 — fuel kWh totals (211 main, 219 HW, 230a-h
|
||||
pumps/fans components, 231 pumps/fans total, 232 lighting)
|
||||
- §10a lines 240-255 — fuel cost cascade (Table 12a + Table 32)
|
||||
- §11a lines 256-258 — SAP rating
|
||||
- §12a lines 259-272 — CO2 emissions
|
||||
|
||||
## Spec source quick-reference
|
||||
|
||||
- **SAP 10.2 full specification**: `domain/sap10_calculator/docs/
|
||||
specs/sap-10-2-full-specification-2025-03-14.pdf`
|
||||
- **RdSAP 10 specification**: `domain/sap10_calculator/docs/specs/
|
||||
RdSAP 10 Specification 10-06-2025.pdf` (§12 page 62, Table 32
|
||||
page 95)
|
||||
- **BRE technical papers**: `domain/sap10_calculator/docs/specs/
|
||||
sap10 technical papers/` (STP09-B04 + S10TP-{02..13})
|
||||
|
||||
## Key file map
|
||||
|
||||
| Path | Role |
|
||||
|---|---|
|
||||
| `domain/sap10_calculator/tables/table_12a.py` | Tariff enum + §12 dispatch + Grid 1/Grid 2 fraction lookups |
|
||||
| `domain/sap10_calculator/tables/table_32.py` | Unit prices + standing charges + electric/gas code sets |
|
||||
| `domain/sap10_calculator/rdsap/cert_to_inputs.py` | All three cost scalar helpers + `_rdsap_tariff` + `_table_12a_system_for_main` + `_table_4f_additive_components` + `_water_heating_main` + `_water_heating_fuel_code` |
|
||||
| `domain/sap10_calculator/calculator.py` | `CalculatorInputs.standing_charges_gbp` field + off-peak fallback total_cost summation |
|
||||
| `datatypes/epc/surveys/elmhurst_site_notes.py` | `MainHeating` + `MainHeating2` + `ExtensionPart.room_in_roof` |
|
||||
| `backend/documents_parser/elmhurst_extractor.py` | §14.0 SAP code + §14.1 Main Heating2 + per-extension RR parsing |
|
||||
| `datatypes/epc/domain/mapper.py` | Elmhurst → SAP mapping; electric fuel inference; strict-raises |
|
||||
| `domain/sap10_calculator/worksheet/tests/_elmhurst_worksheet_000565.py` | The fixture itself (`build_epc()`) |
|
||||
| `domain/sap10_calculator/worksheet/tests/test_e2e_elmhurst_sap_score.py` | Pin assertions per field |
|
||||
| `backend/documents_parser/tests/fixtures/Summary_000565.pdf` | The cert input PDF (mirrored from `sap worksheets/extended test case/`) |
|
||||
| `sap worksheets/extended test case/U985-0001-000565.pdf` | Ground-truth worksheet (line refs source of truth) |
|
||||
|
||||
## When this handover becomes stale
|
||||
|
||||
- After MEV PCDB table lands and pumps_fans pin closes — update
|
||||
this doc's residual table.
|
||||
- After HP category derivation lands — flag the deferred-coupling
|
||||
TODO docstring on `_elmhurst_main_heating_category` as resolved.
|
||||
- After space_heating fabric / solar gain residual closes — update
|
||||
the main_heating_fuel residual (which follows via COP).
|
||||
- After the gas tariff calibration question is decided (ADR
|
||||
amendment vs cert-specific override) — note the resolution here.
|
||||
184
domain/sap10_calculator/docs/HANDOVER_POST_S0380_69.md
Normal file
184
domain/sap10_calculator/docs/HANDOVER_POST_S0380_69.md
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
# Handover — post S0380.69 (cert 000565 + cohort-2 golden coverage)
|
||||
|
||||
Branch `feature/per-cert-mapper-validation`. **HEAD `c4b27829`** (Slice
|
||||
S0380.69 — cohort-2 added to test_golden_fixtures.py).
|
||||
Predecessor: [`HANDOVER_CERT_000565_COST_CASCADE.md`](HANDOVER_CERT_000565_COST_CASCADE.md)
|
||||
covers S0380.52..63. This doc covers S0380.64..69.
|
||||
|
||||
**Test baseline: 317 pass (was 279) + 9 expected `000565` cascade-gap fails.**
|
||||
Pyright net-zero on every touched file.
|
||||
|
||||
## Slices committed this session (S0380.64..69)
|
||||
|
||||
| Slice | Commit | Domain | Headline closure |
|
||||
|---|---|---|---|
|
||||
| **S0380.64** | `6b02bad0` | Elmhurst per-extension `wall_construction` mappings (`SG → 1` stone-granite, `B → 6` basement, `CF → 4` cavity-filled party) + strict-raise on unknown gable codes via `UnmappedElmhurstLabel`. RdSAP 10 §5.17 / Table 23 basement-wall routing. | **sap_score 30 → 29 EXACT**; space_heating Δ −1,099 → +266; HTC 1281 → 1321 W/K |
|
||||
| **S0380.65** | `7855a715` | SAP 10.2 Table 12d + Table 12a Grid 1 dual-rate main-heating CO2 factor. New `_TARIFF_HIGH_LOW_FUEL_CODES_TABLE_12` dict + `_main_heating_co2_factor_kg_per_kwh(main, tariff, monthly_kwh)` helper mirroring the cost-side dual-rate split from S0380.61. | **CO2 Δ −624 → −20 kg/yr**; main_heating_co2_factor 0.136 → 0.1533 EXACT vs worksheet line 261 |
|
||||
| **S0380.66** | `db4f1b31` | New `domain/sap10_calculator/worksheet/appendix_h_solar.py` — SAP 10.2 Appendix H pure math module (HW path). Line refs (H10), (H11), (H14)..(H16), (H17)..(H24) + 18 unit tests pinning to worksheet lines 407 / 410 / 411 / 412. | Pure math; no cascade integration yet |
|
||||
| **S0380.67** | `2795e256` | Added `monthly_solar_energy_available_h9_w` helper + fixed (H23) unit handling: W·h → kWh integration via explicit `hours_in_month` parameter (S0380.66 elided this by absorbing time integration into the parameter name). | Unit consistency |
|
||||
| **S0380.68** | `f0ab7446` | Added (H7)m flux helper (`monthly_collector_solar_flux_w_per_m2`) reusing existing `surface_solar_flux_w_per_m2` + top-level orchestrator `solar_water_heating_input_monthly_kwh`. Shape test pins winter-zero / summer-peak. | Orchestrator landed; magnitude calibration DEFERRED (see §"Open / deferred — Appendix H magnitude" below) |
|
||||
| **S0380.69** | `c4b27829` | Added 38 cohort-2 certs to `test_golden_fixtures.py` with SAP / PE / CO2 baseline pins. | Cert 2102's +20.36 PE / −0.79 CO2 outlier now visible to any cascade refactor (was invisible to all prior tests) |
|
||||
|
||||
## Current cert 000565 residuals (HEAD `c4b27829`)
|
||||
|
||||
| Pin | Cascade | Worksheet | Δ | Status |
|
||||
|---|---:|---:|---:|---|
|
||||
| **sap_score** | **29** | **29** | **0** ✓ | **EXACT** since S0380.64 |
|
||||
| sap_score_continuous | 29.1421 | 28.5087 | +0.6334 | Closed from +1.7225 (S0380.64) |
|
||||
| ecf | 5.3223 | 5.3866 | −0.0643 | Closed from −0.1735 |
|
||||
| total_fuel_cost_gbp | 4,624.18 | 4,680.26 | −56.08 | Closed from −150.93 |
|
||||
| **co2_kg_per_yr** | **6,427.86** | **6,447.63** | **−19.77** | **EXACT** at sub-spec level since S0380.65 (was −624) |
|
||||
| main_heating_fuel | 34,867.33 | 34,710.79 | +156.54 | Follows `space_heating / 1.70` exactly |
|
||||
| **space_heating** | **59,274.46** | **59,008.35** | **+266.11** | **Largest remaining energy residual**. Now slightly OVER-counting (was −1,099 pre-S0380.64). Basement walls add ~+170 vs worksheet's lower U formula |
|
||||
| **hot_water** | **4,026.87** | **3,755.03** | **+271.84** | Second-largest. Blocked on Appendix H magnitude calibration |
|
||||
| lighting | 1,387.02 | 1,384.84 | +2.19 | Essentially closed (sub-spec) |
|
||||
| pumps_fans | 255.00 | 252.52 | +2.48 | MEV gap (blocked on external PCDB data) |
|
||||
| secondary_heating_fuel | 0.00 | 0.00 | 0 ✓ | Green |
|
||||
| **main_heating_co2_factor** | **0.1533** | **0.1533** | **0** ✓ | **EXACT** since S0380.65 |
|
||||
|
||||
Cert 000565 now has TWO exact pins (sap_score + CO2 factor) and 9 small-magnitude residuals.
|
||||
|
||||
## Open / deferred work
|
||||
|
||||
### A. Appendix H magnitude calibration — BLOCKED on external reference
|
||||
|
||||
S0380.66-68 delivered the Appendix H pure math module + top-level orchestrator. Cert 000565 worksheet pins all helpers individually (H11, H14, H15, H16 — exact). But the end-to-end orchestrator produces **~510 kWh annual H24 vs worksheet 281.35** (1.8×).
|
||||
|
||||
Root cause is a **SAP 10.2 spec ambiguity** between two formulations of Y:
|
||||
|
||||
| Source | Spec page | Formula | Δ vs other |
|
||||
|---|---|---|---|
|
||||
| Top-level Eqn H1 commentary | p.75 line 4517 | `Y = Px × Aap × IAM × η0 × ηloop × Im × Hm / (1000 × Dm)` | **excludes H8** |
|
||||
| Line-ref (H23) formula | p.76 line 4620 | `Y = [(H18) × (H6) × (H5) × (H9) × ((41) × 24)] / [1000 × (H17)]` where `(H9) = (H1) × (H2) × (H7) × (H8)` | **includes H8** |
|
||||
|
||||
The two formulations differ by factor H8 (0.8 for cert 000565). Both formulations were also tried (removing H8 / keeping H8 / adding H5/H6 to H9 / dividing by H8 in X / etc.) — **none close the 1.8× gap**. The 1.8× factor isn't H8 alone.
|
||||
|
||||
**Resolving this needs an external reference NOT in this repo:**
|
||||
1. BRE's own worksheet trace of (H22)/(H23) intermediates for any cert (only annual H24 is shown in the U985 worksheet)
|
||||
2. The underlying **EN 15316-4-3:2017** standard text (this is what Appendix H implements per SAP 10.2 p.74)
|
||||
3. An open-source SAP calculator's Appendix H implementation source
|
||||
|
||||
**Important constraint per [[feedback-sap-10-2-only-never-10-3]]**: do NOT reference SAP 10.3 (the spec ambiguity is identical in 10.3 anyway).
|
||||
|
||||
The orchestrator is **wired but NOT integrated** into `water_heating_from_cert.solar_monthly_kwh` (still hardcoded to zero12 at `domain/sap10_calculator/worksheet/water_heating.py:943`). Integrating with the current 1.8× over-estimate would WORSEN cert 000565's HW residual (4027 − 510 × eff ≈ 3624 vs worksheet 3755 → Δ −131 instead of today's +272).
|
||||
|
||||
### B. RR fold-in for `space_heating +266` — DEFERRED, multi-component piece
|
||||
|
||||
`walls_w_per_k = 322 vs worksheet 604` (Δ −282 W/K). Most of the gap is RR Common Walls + Gable Walls not folded into the `(29a)` external-walls channel.
|
||||
|
||||
Attempted in this session (S0380.69 candidate, reverted): routing `gable_type='Exposed'` to `gable_wall_external` would close the classification gap, BUT the cascade's gable AREA (raw `L × H` from Summary PDF) is 4× the worksheet's RR-portion-only area (e.g. Ext1 Gable 2: cascade 72 m² vs worksheet 16.08 m²). Classification fix without area fix overshoots: sap_score regresses 29 → 25, space_heating overshoots +6029 kWh.
|
||||
|
||||
**RR fold-in requires three coordinated changes:**
|
||||
1. Extractor / mapper area computation per RdSAP §3.10 detailed-RR geometry — the worksheet computes some kind of triangulated / truncated area, not raw L×H
|
||||
2. Classification fix (Exposed / Connected gable_type values surfaced)
|
||||
3. Common Wall extraction (currently filtered at `_map_elmhurst_rir_surface` line 3260)
|
||||
|
||||
Each in isolation regresses sap_score. Reverse-engineering the area formula from cert 000565 alone wasn't tractable in this session — the cascade has a Simplified-RR formula at `heat_transmission.py:389` that doesn't match worksheet's 16.08 for any plausible H_common_wall value.
|
||||
|
||||
**Recommendation:** wait for another cohort cert with cleaner RR geometry lodgement, OR get a clear read of RdSAP 10 §3.10 detailed-RR area formula, before re-attempting.
|
||||
|
||||
### C. MEV cascade (line 230a) — BLOCKED on external BRE data
|
||||
|
||||
Cert 000565 worksheet line 230a: `MEV = IUF × SFP × 1.22 × V = 127.5159 kWh`. PCDF 500755 record carries SFP=0.1274 and a derived IUF≈1.278. **The PCDB MEV / MVHR record table is NOT in the codebase** (only Tables 105, 122, 143, 313, 353, 362, 391, 506 are present under `domain/sap10_calculator/tables/pcdb/data/`). Acquiring the PCDB MEV table from BRE is the gating step.
|
||||
|
||||
Couples with HP-category-derivation fix (item D) — landing alone would worsen `pumps_fans` from 255 → 125 W/K.
|
||||
|
||||
### D. HP SAP code → `main_heating_category=4` in mapper
|
||||
|
||||
`_elmhurst_main_heating_category` only sets category=4 when a PCDB Table 362 record is present. Cert 000565 Main 1 SAP code 224 (ASHP) with no PCDB ref → category=None → cascade routes pumps_fans to 130 default base instead of HP's 0 base. Couples with MEV (item C); see [project_cert_000565_recovery_state.md] memory.
|
||||
|
||||
### E. Cert 2102 +20.36 PE / −0.79 CO2 — newly visible via S0380.69
|
||||
|
||||
Cohort-2 cert lodges House coal as secondary heating. S0380.43 closed SAP via spec-fuel routing but didn't address the PE/CO2 paths. This is now the **largest cohort-2 PE residual** and the cleanest next investigation target.
|
||||
|
||||
## Conventions reinforced this session
|
||||
|
||||
- **Verify spec before implementing** ([[feedback-verify-handover-claims]]) — S0380.64 + S0380.65 cited Table 23 / Table 12d directly; S0380.66 quoted SAP 10.2 spec page numbers verbatim.
|
||||
- **SAP 10.2 only, never 10.3** ([[feedback-sap-10-2-only-never-10-3]]) — added this session after I reached for 10.3 to resolve the Appendix H ambiguity. The project tracks SAP 10.2 deliberately; 10.3 has the same ambiguity anyway.
|
||||
- **Bigger slices for uniform work** ([[feedback-bigger-slices-for-uniform-work]]) — S0380.64 bundled three mapper entries + two strict-raise calls; S0380.69 bundled 38 parametrised cohort-2 pins.
|
||||
- **Coupling-aware sequencing** — attempted RR classification fix was reverted because area-fix wasn't ready; HP-category fix is held back because MEV isn't ready. Components must land as a SET.
|
||||
- **Strict-raise on unmapped data** ([[reference-unmapped-api-code]] / `UnmappedElmhurstLabel`) — extended to gable wall codes in S0380.64.
|
||||
- **One slice = one commit, spec-citation in commit messages** ([[feedback-commit-per-slice]] + [[feedback-spec-citation-in-commits]]).
|
||||
- **Pyright net-zero per touched file** ([[feedback-zero-error-strict]]).
|
||||
|
||||
## 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/rdsap/tests/test_cert_to_inputs.py \
|
||||
domain/sap10_calculator/rdsap/tests/test_golden_fixtures.py \
|
||||
--no-cov -q
|
||||
```
|
||||
|
||||
Expected: **317 pass + 9 expected `test_sap_result_pin[000565-*]` fails** (the 9 non-exact cascade-gap pins in the residuals table above).
|
||||
|
||||
## How to probe cert 000565 residuals
|
||||
|
||||
```python
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
from domain.sap10_calculator.worksheet.tests._elmhurst_worksheet_000565 import build_epc
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import cert_to_inputs, SAP_10_2_SPEC_PRICES
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
epc = build_epc()
|
||||
inputs = cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
r = calculate_sap_from_inputs(inputs)
|
||||
# inspect fields per the residuals table above
|
||||
"
|
||||
```
|
||||
|
||||
## How to probe cohort-2 golden residuals (cert 2102 is the next target)
|
||||
|
||||
```python
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
SAP_10_2_SPEC_PRICES, cert_to_demand_inputs, cert_to_inputs,
|
||||
)
|
||||
fixtures = Path('/workspaces/model/domain/sap10_calculator/rdsap/tests/fixtures/golden')
|
||||
doc = json.loads((fixtures / '2102-3018-0205-7886-5204.json').read_text())
|
||||
epc = EpcPropertyDataMapper.from_api_response(doc)
|
||||
rating = calculate_sap_from_inputs(cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
demand = calculate_sap_from_inputs(cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
# Pinned residuals: PE +20.36, CO2 −0.79 (see test_golden_fixtures.py)
|
||||
"
|
||||
```
|
||||
|
||||
## Spec source quick-reference
|
||||
|
||||
- **SAP 10.2 full specification**: `domain/sap10_calculator/docs/specs/sap-10-2-full-specification-2025-03-14.pdf`
|
||||
- Table 12d (monthly electric CO2 factors): p.194
|
||||
- Table 12a (Grid 1 SH + Grid 2 other uses fractions): p.191
|
||||
- Appendix H (Solar thermal systems): p.74-78 + Tables H1-H4 p.78
|
||||
- Appendix U §U3.2 (horizontal solar flux + tilt polynomial): p.127
|
||||
- **RdSAP 10 specification**: `domain/sap10_calculator/docs/specs/RdSAP 10 Specification 10-06-2025.pdf`
|
||||
- §12 page 62 (dual-meter tariff dispatch)
|
||||
- Table 32 page 95 (unit prices + standing charges)
|
||||
- **BRE technical papers**: `domain/sap10_calculator/docs/specs/sap10 technical papers/` (STP09-B04 + S10TP-{02..13})
|
||||
- **SAP 10.3** at `domain/sap10_calculator/docs/specs/sap-10-3-full-specification-2026-01-13.pdf`: **DO NOT reference** ([[feedback-sap-10-2-only-never-10-3]]).
|
||||
|
||||
## Key file map (added / touched this session)
|
||||
|
||||
| Path | Role | Touched in |
|
||||
|---|---|---|
|
||||
| `datatypes/epc/domain/mapper.py` | `_ELMHURST_WALL_CODE_TO_SAP10` + `_ELMHURST_PARTY_WALL_CODE_TO_SAP10` dicts + strict-raise helpers | S0380.64 |
|
||||
| `domain/sap10_calculator/rdsap/cert_to_inputs.py` | `_TARIFF_HIGH_LOW_FUEL_CODES_TABLE_12` + `_main_heating_co2_factor_kg_per_kwh` helper | S0380.65 |
|
||||
| `domain/sap10_calculator/worksheet/appendix_h_solar.py` | **NEW** SAP 10.2 Appendix H pure math + orchestrator | S0380.66-68 |
|
||||
| `domain/sap10_calculator/worksheet/tests/test_appendix_h_solar.py` | **NEW** 22 unit tests pinning Appendix H math | S0380.66-68 |
|
||||
| `domain/sap10_calculator/rdsap/tests/test_golden_fixtures.py` | Cohort-2 38 _GoldenExpectation entries | S0380.69 |
|
||||
| `backend/documents_parser/tests/test_summary_pdf_mapper_chain.py` | 5 new tests for cert 000565 gable-code coverage + strict-raise | S0380.64 |
|
||||
| `domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py` | 2 new tests for dual-rate CO2 factor | S0380.65 |
|
||||
|
||||
## When this handover becomes stale
|
||||
|
||||
- After Appendix H magnitude calibration resolves (EN 15316-4-3 sourced, or BRE worksheet intermediates trace, or empirical multi-cert calibration) — wire `solar_water_heating_input_monthly_kwh` into `water_heating_from_cert.solar_monthly_kwh`, expect cert 000565 HW residual to close from +272 to ~0.
|
||||
- After MEV PCDB data lands + HP-category-derivation fix lands as a SET — pumps_fans pin closes 255 → 252.5.
|
||||
- After RR fold-in lands (3-slice coordinated piece) — cert 000565 walls_w_per_k closes 322 → 604; space_heating closes +266 → ~0.
|
||||
- After cert 2102 House-coal secondary PE/CO2 cascade closes — cohort-2 largest residual drops from +20.36 / −0.79.
|
||||
162
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_69.md
Normal file
162
domain/sap10_calculator/docs/NEXT_AGENT_PROMPT_POST_S0380_69.md
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
# Next-agent prompt — post S0380.69
|
||||
|
||||
Branch: `feature/per-cert-mapper-validation`. HEAD: `c4b27829` (S0380.69 — cohort-2 added to test_golden_fixtures.py).
|
||||
|
||||
Read [`HANDOVER_POST_S0380_69.md`](HANDOVER_POST_S0380_69.md) end-to-end before any tool call. It has the full state, the 6 slices shipped (S0380.64..69), the residual table for cert 000565, the open / deferred work items with reasons, and spec references.
|
||||
|
||||
Also load these memories before starting:
|
||||
- `project_cert_000565_recovery_state` — cert 000565 slice history and residuals
|
||||
- `project_golden_coverage_state` — golden coverage state with cohort-2 added
|
||||
- `feedback_sap_10_2_only_never_10_3` — **CRITICAL** — never reference SAP 10.3 spec
|
||||
- `feedback_verify_handover_claims` — verify spec citations + handover claims before implementing
|
||||
- `feedback_zero_error_strict` — pyright net-zero per touched file
|
||||
- `feedback_commit_per_slice` — one slice = one commit
|
||||
- `feedback_spec_citation_in_commits` — quote spec text + page in commit messages
|
||||
- `feedback_aaa_test_convention` — every new test uses `# Arrange / # Act / # Assert`
|
||||
- `reference_unmapped_api_code` — strict-raise pattern for unmapped enums
|
||||
|
||||
## State summary
|
||||
|
||||
**Cert 000565** is the active fixture. After S0380.64..68 it sits at:
|
||||
- `sap_score = 29 EXACT` ✓ (was Δ +1)
|
||||
- `main_heating_co2_factor_kg_per_kwh = 0.1533 EXACT` ✓ (was 0.136 / Δ -624 kg/yr CO2)
|
||||
- 9 small-magnitude residuals (HW +272, space_heating +266, CO2 −20, others smaller)
|
||||
|
||||
**Cohort-2** (38 certs) added to golden coverage in S0380.69. Cert 2102 (`+20.36 PE / −0.79 CO2`) is the largest residual, now visible to all future cascade refactors.
|
||||
|
||||
## Recommended next slices (ranked)
|
||||
|
||||
The choice is yours — each is well-scoped and independently valuable.
|
||||
|
||||
### Option 1 — Cert 2102 House-coal secondary PE/CO2 closure
|
||||
|
||||
**Why:** Largest visible PE residual on the cohort-2 set. Concrete, single-cert investigation. Likely sits in `secondary_heating_co2_factor_kg_per_kwh` / `secondary_heating_pe_factor` cascade for House coal (fuel code 1 in Table 12). S0380.43 closed the SAP path (spec-fuel routing); PE/CO2 paths were not addressed.
|
||||
|
||||
**Probe first:**
|
||||
```python
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
SAP_10_2_SPEC_PRICES, cert_to_demand_inputs,
|
||||
)
|
||||
fixtures = Path('/workspaces/model/domain/sap10_calculator/rdsap/tests/fixtures/golden')
|
||||
doc = json.loads((fixtures / '2102-3018-0205-7886-5204.json').read_text())
|
||||
epc = EpcPropertyDataMapper.from_api_response(doc)
|
||||
inputs = cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
r = calculate_sap_from_inputs(inputs)
|
||||
print('lodged PE:', doc['energy_consumption_current'])
|
||||
print('cascade PE:', r.primary_energy_kwh_per_m2)
|
||||
print('lodged CO2:', doc['co2_emissions_current'])
|
||||
print('cascade CO2:', r.co2_kg_per_yr / 1000)
|
||||
print('secondary kwh:', r.secondary_heating_fuel_kwh_per_yr)
|
||||
print('secondary co2:', r.intermediate.get('secondary_heating_co2_kg_per_yr', 'N/A'))
|
||||
"
|
||||
```
|
||||
|
||||
Expected scope: 1-2 slices. Closes cert 2102 + likely unblocks any other House-coal-secondary cohort cert.
|
||||
|
||||
### Option 2 — Appendix H magnitude calibration (unblocks cert 000565 HW +272)
|
||||
|
||||
The pure math module + orchestrator are landed (S0380.66-68). The blocker is a SAP 10.2 spec ambiguity in the (H23) Y formula — top-level commentary (p.75 line 4517) excludes H8, line-ref (H23) formula (p.76 line 4620) includes H8 via H9. Both formulations have been tried; neither closes the 1.8× over-estimate.
|
||||
|
||||
**Resolution paths (any one of these unblocks):**
|
||||
1. Source the EN 15316-4-3:2017 standard (Appendix H is an implementation of this) — find the canonical Y formula
|
||||
2. Find a BRE worked-example trace of (H22)/(H23) intermediates for ANY cert — Elmhurst worksheets only show H1-H10 inputs + H24 totals
|
||||
3. Multi-cert empirical calibration: if S0380.66-68 orchestrator output is consistently 1.8× worksheet for ≥2 different certs, the multiplier might be a coverable empirical factor
|
||||
|
||||
Once calibrated, wire `solar_water_heating_input_monthly_kwh` into `domain/sap10_calculator/worksheet/water_heating.py:943` (currently `solar_monthly_kwh=zero12` hardcoded) — cert 000565 HW residual closes from +272 to ~0.
|
||||
|
||||
**Important:** do NOT reference SAP 10.3 ([[feedback-sap-10-2-only-never-10-3]]). 10.3 has the same ambiguity.
|
||||
|
||||
### Option 3 — RR fold-in for cert 000565 space_heating +266
|
||||
|
||||
3-slice coordinated piece. Need to land all three together — each in isolation regresses sap_score:
|
||||
1. Extractor / mapper area computation per RdSAP §3.10 detailed-RR geometry (raw L×H from Summary PDF doesn't match worksheet)
|
||||
2. Classification fix — route `gable_type='Exposed'` to `gable_wall_external` with lodged U
|
||||
3. Common Wall extraction — currently filtered at `_map_elmhurst_rir_surface` line 3260
|
||||
|
||||
Blocker: reverse-engineering the RR-area formula from cert 000565 alone wasn't tractable in S0380.69-attempt — Ext1 Gable 2 cascade=72 m² vs worksheet=16.08 m². Cascade has a Simplified-RR formula at `heat_transmission.py:389` that doesn't match. RdSAP 10 §3.10 spec text needs careful re-read.
|
||||
|
||||
### Option 4 — Cohort PE/CO2 cluster investigation
|
||||
|
||||
S0380.69 surfaced 14 cohort-2 certs at PE ≈ −2.7 to −4.2 kWh/m² (gas combi PCDB + boiler PE under-count pattern). Cohort-1 cert 2130 + ASHP cohort share the same residual range. A single cascade fix here would close many residuals at once. Likely sits in:
|
||||
- Gas combi PE Table 12e monthly factor (similar to S0380.65's CO2 dual-rate fix, but for PE)
|
||||
- OR PCDB winter efficiency lookup that's lifting PE under-count
|
||||
|
||||
Lower-risk than RR fold-in or Appendix H magnitude.
|
||||
|
||||
### Option 5 — MEV + HP-category coupled slice (cert 000565 pumps_fans)
|
||||
|
||||
Blocked on external BRE data (PCDB MEV / MVHR record table not in repo). Acquiring the table is the gating step. After that AND HP-category fix landing as a SET, pumps_fans pin closes 255 → 252.5.
|
||||
|
||||
## Standard workflow per slice
|
||||
|
||||
1. Read SAP 10.2 spec page for the change you're making — quote it in the commit message
|
||||
2. Probe current cascade output, identify exact spec-vs-cascade gap
|
||||
3. Write failing test FIRST (AAA structure with `# Arrange / # Act / # Assert`)
|
||||
4. Implement helper / change
|
||||
5. Verify test passes
|
||||
6. Run full handover suite (command in handover doc §"How to run the baseline")
|
||||
7. Check pyright on touched files — must be net-zero from baseline
|
||||
8. Commit with spec citation (Table N page P, §section)
|
||||
9. Update relevant memory if the slice changes load-bearing state
|
||||
|
||||
## Carryforward conventions
|
||||
|
||||
- **Spec-floor skepticism** ([[feedback-spec-floor-skepticism]]) — "spec-precision floor" framing usually masks a real spec-citation bug. Verify before accepting.
|
||||
- **Bigger slices for uniform work** ([[feedback-bigger-slices-for-uniform-work]]) — bundle related entries (e.g. S0380.69 bundled 38 cohort-2 pins; S0380.64 bundled 3 wall codes + strict-raise).
|
||||
- **Worksheet, not API, is the target** ([[feedback-worksheet-not-api-reference]]) — pin against U985 / dr87 worksheet PDFs, not API EPC values.
|
||||
- **Prefer abs(diff) over pytest.approx** ([[feedback-abs-diff-over-pytest-approx]]) — keeps pyright net-zero on strict repos.
|
||||
|
||||
## Files / commands you'll touch most often
|
||||
|
||||
```bash
|
||||
# Baseline test suite (8s runtime, expect 317 pass + 9 expected 000565 fails)
|
||||
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/rdsap/tests/test_cert_to_inputs.py \
|
||||
domain/sap10_calculator/rdsap/tests/test_golden_fixtures.py \
|
||||
--no-cov -q
|
||||
|
||||
# Cert 000565 residual probe
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
from domain.sap10_calculator.worksheet.tests._elmhurst_worksheet_000565 import build_epc
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import cert_to_inputs, SAP_10_2_SPEC_PRICES
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
epc = build_epc()
|
||||
inputs = cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES)
|
||||
r = calculate_sap_from_inputs(inputs)
|
||||
# ...
|
||||
"
|
||||
|
||||
# Cohort-2 cert probe (replace cert number)
|
||||
PYTHONPATH=/workspaces/model python -c "
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
SAP_10_2_SPEC_PRICES, cert_to_demand_inputs, cert_to_inputs,
|
||||
)
|
||||
doc = json.loads(Path('domain/sap10_calculator/rdsap/tests/fixtures/golden/<CERT>.json').read_text())
|
||||
epc = EpcPropertyDataMapper.from_api_response(doc)
|
||||
rating = calculate_sap_from_inputs(cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
demand = calculate_sap_from_inputs(cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES))
|
||||
# ...
|
||||
"
|
||||
```
|
||||
|
||||
## When to stop and report
|
||||
|
||||
Per [[feedback-spec-floor-skepticism]] — don't accept "precision floor" framing without verifying the spec.
|
||||
|
||||
But also be honest about blockers. Spec ambiguities (like the Appendix H Y formula) or external data gaps (like the PCDB MEV table) are legitimate blockers — report and ask for direction rather than guessing. Three of this session's six slices (S0380.66-68) deliberately deferred end-to-end closure because the magnitude calibration was blocked; the pure math was still landed cleanly.
|
||||
|
||||
Good luck.
|
||||
Loading…
Add table
Reference in a new issue