From a756114aedd2eba09b1f63b416c78ece5d02f6e8 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Sun, 24 May 2026 21:43:40 +0000 Subject: [PATCH] =?UTF-8?q?Handover:=20all=206=20Elmhurst=20Summary?= =?UTF-8?q?=E2=86=92SAP=20chains=20closed=20at=201e-4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Final state across Slices 47-53: 000474 0.0000 ✓ Slice 47 000477 0.0000 ✓ Slice 52 000480 0.0000 ✓ Slice 50 000487 0.0000 ✓ Slice 53 000490 0.0000 ✓ Slice 49 000516 0.0000 ✓ Slice 51 758 tests pass; pyright net-zero (35 baseline). Updates the handover doc with a summary of each slice's contribution and a pointer to likely next workstreams. Co-Authored-By: Claude Opus 4.7 --- docs/sap-spec/NEXT_AGENT_PROMPT.md | 174 +++++++++++------------------ 1 file changed, 64 insertions(+), 110 deletions(-) diff --git a/docs/sap-spec/NEXT_AGENT_PROMPT.md b/docs/sap-spec/NEXT_AGENT_PROMPT.md index eadfaf07..66f1b97e 100644 --- a/docs/sap-spec/NEXT_AGENT_PROMPT.md +++ b/docs/sap-spec/NEXT_AGENT_PROMPT.md @@ -1,145 +1,99 @@ -# Handover — close the remaining 4 Elmhurst Summary→SAP chains to 1e-4 +# Handover — Elmhurst Summary→SAP cohort all closed at 1e-4 -You are picking up branch `ara-backend-design-prd` mid-stream. Two -of six fixtures are now closed at 1e-4 (000474 + 000490). The other -four still have substantive diffs that each need their own mapper -or extractor extension to close. +You are picking up branch `ara-backend-design-prd` after the 6-fixture +Elmhurst Summary→SAP validation chain landed end-to-end. -## The 30-second picture +## State + +All 6 cohort fixtures pass at the **1e-4** unrounded-SAP tolerance. ``` -Cert Mapped SAP Target SAP Δ State -000474 62.2584 62.2584 0.0000 ✓ Slice 47 -000477 67.6612 65.0057 +2.6555 Room-in-Roof support (15.06 m² 3rd storey) -000480 65.4941 61.2986 +4.1955 diagnosis pending -000487 66.0984 61.6431 +4.4553 extractor drops most §11 windows -000490 57.3979 57.3979 0.0000 ✓ Slice 49 -000516 64.3099 62.7937 +1.5162 roof-window separation +Cert Mapped SAP Target SAP Δ State +000474 62.2584 62.2584 0.0000 ✓ Slice 47 +000477 65.0057 65.0057 0.0000 ✓ Slice 52 +000480 61.2986 61.2986 0.0000 ✓ Slice 50 +000487 61.6431 61.6431 0.0000 ✓ Slice 53 +000490 57.3979 57.3979 0.0000 ✓ Slice 49 +000516 62.7937 62.7937 0.0000 ✓ Slice 51 ``` -All Δ are positive — mapper computes SAP too HIGH. Forcing functions -in `backend/documents_parser/tests/test_summary_pdf_mapper_chain.py`: -2 chain tests green (000474, 000490), 2 structural tests green (BPs, -windows for 000474). 4 mirror tests to add as each closes. +Forcing functions in +`backend/documents_parser/tests/test_summary_pdf_mapper_chain.py` — +8 tests (6 chain pins + 2 structural pins) all green. Wider regression: +**758 tests pass**, pyright net-zero (35 errors baseline, no change). -## What landed already +## What landed (Slices 47–53) | Slice | Commit | What | |---|---|---| -| 47 | `29ab80b0` | `main_heating_category=2` in mapper → pumps_fans 130→160; window-gap partitioned on glazing-type-start marker → fixes W4/W5 orientation. Closed 000474. | -| 48 | `00a27efd` | Extractor handles `Wood 0.70` combined frame-line; data anchor allows trailing glazing-type (`1.22 1.76 2.15 Double pre 2002`); partition falls back to second-orient-token when no glazing marker in gap. 5 fixture PDFs copied to `backend/documents_parser/tests/fixtures/`. | -| 49 | `7f17de84` | Elmhurst `MainHeating.secondary_heating_sap_code` extracted from §14.1 Main Heating2 sub-section; mapper threads through to `SapHeating.secondary_heating_type`. RdSAP §S5 sheltered-sides defaults derived from built_form. Closed 000490. | +| 47 | `29ab80b0` | `main_heating_category=2` → pumps_fans 130→160; window-gap partition on glazing-type marker (W4/W5 orient). **Closed 000474.** | +| 48 | `00a27efd` | Extractor: combined `Wood 0.70` frame line; data anchor with trailing glazing-type; partition fallback on second orient-token. 5 fixture PDFs copied to `backend/documents_parser/tests/fixtures/`. | +| 49 | `7f17de84` | `MainHeating.secondary_heating_sap_code` extracted from §14.1 sub-section; RdSAP §S5 sheltered-sides from built_form. **Closed 000490.** | +| 50 | `598f0408` | `ElmhurstSiteNotes.RoomInRoof` + `RoomInRoofSurface` with §3.10 detailed-surface support; `_map_elmhurst_room_in_roof` builds `SapRoomInRoof.detailed_surfaces`. Party-wall construction code mapping. Roof "N None" → 0mm. `number_baths` lodgement. **Closed 000480.** | +| 51 | `cb4e31a1` | Roof-window separation by U-value threshold (>3.0); Table 24 lookup for raw U (Double pre 2002 → 3.40). `SapWindow.window_width × window_height = lodged Area` convention. **Closed 000516.** | +| 52 | `4ccf9c97` | RR detailed-surface area rounded half-up via Decimal (6.585 → 6.59); suspended-timber-floor heuristic (RIR < storey area → True); electric-vs-mixer shower from outlet_type. **Closed 000477.** | +| 53 | `58088c10` | `WallDetails.alternative_walls` extraction + `SapAlternativeWall` mapper plumbing; "TI Timber Frame" code mapping; `Thickness Unknown: Yes` → cascade thickness=None (TF age B uninsulated → U=1.9 default). **Closed 000487.** | -## Per-cert diff diagnoses (already done — don't re-discover) +## Architecture summary -### 000477 — Δ +2.66 — Room-in-Roof support needed -Summary PDF §4.0 lodges `Room(s) in Roof: 15.06` (m²). Mapper drops -this entirely — `total_floor_area_m2=62.52` vs handbuilt 77.58 -(exactly +15.06 m²); `storey_count=2` vs 3; `roof_w_per_k=4.38` vs -35.97. Look at: +**Two-path validation**: +- Path A — hand-built `_elmhurst_worksheet_NNNNNN.py` fixtures build + `EpcPropertyData` directly. Pins the cascade against the + worksheet PDF's line refs (1a..486). +- Path B — `Summary_NNNNNN.pdf → ElmhurstSiteNotes → + EpcPropertyData → cascade → SAP`. Pins the mapper + extractor + against the worksheet PDF's unrounded SAP rating (line 257). -- `ElmhurstSiteNotes.BuildingPartDimensions` — needs a - `room_in_roof_area_m2` field (and probably room-in-roof construction - + insulation details too). -- `ElmhurstSiteNotesExtractor._extract_dimensions` (or wherever §4 is - handled) — parse the "Room(s) in Roof" line. -- `from_elmhurst_site_notes` — build a `SapRoomInRoof` and attach to - the building part. See existing API paths like - `datatypes/epc/domain/mapper.py:749-760` for the API-side analog. -- Handbuilt: see `_elmhurst_worksheet_000477.py` `sap_room_in_roof=...`. +Both paths run the same `calculate_sap_from_inputs` cascade and now +both close to 1e-4 across the 6 cohort fixtures. -Once Room-in-Roof lands, the other diffs (party_walls, infiltration, -lighting kWh) may shrink as the dwelling shape becomes correct. +## Conventions you must honour (project memory) -### 000487 — Δ +4.46 — only 1 of many windows extracted -Despite Slice 48's frame-line + data-anchor improvements, the §11 -table layout of this cert still drops most windows. Run -`python /tmp/dump_section.py 000487` to inspect — this PDF has yet -another layout pattern (see lines 14-50 in the section dump). Look -at the actual fields: `'1st'` ordinal in prefix WITHOUT a preceding -glazing-type line, etc. +- AAA test convention: every new test uses literal `# Arrange / # Act + / # Assert` headers. +- `abs(diff) <= tol` not `pytest.approx` (strict pyright). +- One slice = one commit; stage by name. +- 1e-4 tolerance, no widening, no xfail. +- Strict pyright net-zero on every commit (35-error baseline on these files). -### 000516 — Δ +1.52 — roof-window contamination -6 vertical windows extracted (correct: 5 vertical + 1 roof). The 6th -is a roof window (`1.05×1.12=1.18 m² U=3.10` lodged → U=2.99 in -worksheet line 27a, but handbuilt uses `u_value_raw=3.40` — needs -investigation of how Elmhurst computes the in-situ value). Handbuilt: - -```python -sap_roof_windows=[SapRoofWindow( - area_m2=1.18, u_value_raw=3.40, orientation=2 NE, - pitch_deg=45.0, g_perpendicular=0.76, frame_factor=0.70, -)] -``` - -The Summary PDF doesn't have an explicit "roof window" type marker — -the discrimination is by **U-value range** (>3.0 W/m²K characteristic -of roof window) or by some other heuristic. Investigate which signal -Elmhurst uses; may also need a `Roof Windows` subsection if a later -fixture has one. - -### 000480 — Δ +4.20 — diagnosis pending -Run `python /tmp/diff_objects.py 000480` to start. Already has 2 BPs -+ 7 windows correctly extracted post-Slice 48. - -## Probe scripts (in `/tmp`) +## Probe scripts (in `/tmp`, regenerated as needed) ```bash -# Probe all 6 fixtures' SAP delta +# Cohort SAP delta — verify nothing has regressed python /tmp/probe_all.py -# Dump raw extracted windows for a cert -python /tmp/dump_one.py 000516 - -# Dump the §11 Windows section layout (debug extractor) -python /tmp/dump_section.py 000487 - -# Field-by-field input diff mapped vs handbuilt (scalars + objects) -python /tmp/diff_objects.py 000477 - -# Verify secondary heating + sheltered-sides plumbing -python /tmp/check_secondary.py +# Field-level cascade-input diff for a single cert +python /tmp/diff_objects.py 000487 ``` -If `/tmp` got wiped, the contents are documented in commit `7f17de84`'s -diff (the prior handover writeup). Re-create them by following the -patterns there. +## What's NEXT for future work -## Suggested next slices +The Elmhurst Summary→SAP chain is closed. Likely future directions: -| Slice | Cert | Effort | Why next | -|---|---|---|---| -| 50 | 000516 | Medium | Roof-window separation by U-value threshold; smallest remaining Δ | -| 51 | 000477 | High | Room-in-Roof schema + extractor + mapper plumbing; biggest unlock | -| 52 | 000487 | Medium-High | Extractor §11 layout — third PDF variant; may share work with 000477's room-in-roof if §11 layout matches | -| 53 | 000480 | Unknown | Diagnose then close after others reveal patterns | - -## Definition of done (unchanged) - -- All 6 `test_summary_pdf_mapper_chain.py` chain tests pin at 1e-4. -- Wider regression stays green (currently 755 pass). -- Pyright net-zero on every commit (strict mode; baseline 35 errors). -- One slice = one commit. -- No widening, no xfail (project memory `feedback_zero_error_strict`). - -## Reference materials - -- `docs/sap-spec/HANDOVER_NEXT.md` — original cascade-conventions handover. -- `docs/sap-spec/SAP_CALCULATOR.md` — public API + two-cascade architecture. -- Hand-built worksheet fixtures: `packages/domain/src/domain/sap/worksheet/tests/_elmhurst_worksheet_*.py`. -- Untracked source PDFs: `sap worksheets/` (`Summary_NNNNNN.pdf` + `U985-0001-NNNNNN.pdf` worksheets). +- **Pin against more Elmhurst worksheets** beyond the 6-cohort. Each + new cert may surface a §11 layout variant, a new wall_construction + code, or a new gable-type lodgement that the cohort didn't exercise. +- **Apply the same chain to other surveyor tools** (e.g. Pashub site + notes). The cascade is reusable; the mapper-per-surveyor pattern + established here generalises. +- **The API-cert residual cohort** still uses 0.5 tolerance (the API + publishes rounded SAP integers). Tighten that as a separate + workstream — different forcing function, different conventions. ## Branch state at handover ``` -$ git log --oneline -7 +$ git log --oneline -10 +58088c10 Slice 53: Summary_000487 chain pins SAP at 1e-4 — last cohort cert closed +4ccf9c97 Slice 52: Summary_000477 chain pins SAP at 1e-4; electric shower + decimal RIR rounding +cb4e31a1 Slice 51: Summary_000516 chain pins SAP at 1e-4; roof-window separation +598f0408 Slice 50: Summary_000480 chain pins SAP at 1e-4; Room-in-Roof + baths + party-wall + roof-none 7f17de84 Slice 49: Summary_000490 chain pins SAP at 1e-4; secondary heating + RdSAP sheltered-sides 00a27efd Slice 48: Elmhurst extractor handles 3 new layout quirks; 5 fixture PDFs added 29ab80b0 Slice 47: Summary_000474 chain pins SAP at 1e-4 vs worksheet PDF +ec4916b5 Handover: 2/6 Elmhurst chains closed at 1e-4; per-cert diagnoses for remaining 4 b6544e1c Handover: tighten Summary→SAP chain pin to 1e-4 + brief next agent 256a5afe Slice 46c: Elmhurst mapper produces calculator-equivalent EpcPropertyData — Summary_000474 SAP within 0.5 of worksheet PDF -066dce19 Slice 46b: Elmhurst extractor parses windows from layout-style Summary PDFs -36f2c7bb Slice 46a: Elmhurst mapper handles multi-bp Summary PDFs — Summary_000474 chain test flips green ``` -Good luck. +Good luck on whatever comes next.