From 55af4ee2d7dba4064959fc3c024a5e267f2193b1 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 3 Jun 2026 22:59:35 +0000 Subject: [PATCH] docs: Thread 1 (roof) CLOSED by S0380.211; Thread 2 needs code-301 gas ws MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record the roof closure (vaulted NI → Table 18 col 1 0.16, cohort-arbitrated not the guessed 0.25), the AGENT_GUIDE suite-command gap (sap10_ml/tests/ not run) + pre-existing stone failures, cases 11/12/13 now available, and the fuel-20 = community-gas (Table 12 code 51) note. Thread 2 still needs a code-301 community-boiler + mains-gas worksheet (case 13 is code-302 CHP). Co-Authored-By: Claude Opus 4.8 --- .../docs/HANDOVER_MAPPER_BUGS.md | 90 +++++++++++-------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/domain/sap10_calculator/docs/HANDOVER_MAPPER_BUGS.md b/domain/sap10_calculator/docs/HANDOVER_MAPPER_BUGS.md index 5087fb1f..f735dfc1 100644 --- a/domain/sap10_calculator/docs/HANDOVER_MAPPER_BUGS.md +++ b/domain/sap10_calculator/docs/HANDOVER_MAPPER_BUGS.md @@ -6,11 +6,13 @@ state after closing the 0240 investigation and fixing the first of several API-mapper/cascade bugs the audit surfaced. - **Branch:** `feature/per-cert-mapper-validation` -- **HEAD:** `c75ef641` (S0380.210). Confirm with `git rev-parse HEAD`. +- **HEAD:** `90f6720c` (S0380.211). Confirm with `git rev-parse HEAD`. - **Baseline:** `2384 passed, 1 skipped, 0 failed` (AGENT_GUIDE §4 suite command). -- **Next slice number:** **S0380.211**. -- **Open:** Thread 1 (roof, needs case 11) + Thread 2 (community 9390, needs 9390 ws). - Thread 3 (0390) **CLOSED** below. + ALSO run `domain/sap10_ml/tests/` when touching `rdsap_uvalues.py` — 2 PRE-EXISTING + stone-formula failures there, see Thread 1. +- **Next slice number:** **S0380.212**. +- **Open:** Thread 2 (community 9390) — needs a **code-301 boiler + mains-gas** worksheet + (case 13 is code-302 CHP-gas, close but not 9390's scheme). Threads 1 + 3 **CLOSED**. --- @@ -21,6 +23,7 @@ API-mapper/cascade bugs the audit surfaced. | **S0380.208** | Promoted **simulated case 7** (combi swap of case 6) to an e2e fixture. PROVED the condensing-oil-combi (SAP code 130, no cylinder, combi instantaneous DHW, Eq D1, Table 3a keep-hot) path is **exact at 1e-4** with zero calculator changes → exonerated the heating as the source of 0240's residual. | | **S0380.209** | Fixed the **API-path wall U** "as built, insulated (assumed)" bug — routes to the as-built age-band row, not the 50 mm retrofit bucket. New `_described_as_retrofit_insulated` in `heat_transmission.py`. Worksheet-validated by case 9 (sandstone J → 0.35) + case 10 (solid brick J → 0.35). Re-pinned 0240 PE +1.8687 → +5.5044, CO2 +0.0907 → +0.2757 (SAP integer 72 unchanged). | | **S0380.210** | **CLOSED cert 0390** (Thread 3). Cavity wall "as built, **partial** insulation (assumed)" (type 4) was mis-routed to the Table 6 "Filled cavity" row (band F 0.40) → should be "Cavity as built" (band F 1.0). New `_cavity_described_as_filled` in `rdsap_uvalues.py` excludes "partial insulation" from the filled trigger (keeps "insulated (assumed)" → filled). SAP +7 → +0, PE −27.97 → +0.53, CO2 −2.71 → −0.12. Mirrors S0380.209 on the cavity path. | +| **S0380.211** | **CLOSED Thread 1 (roof).** 0240 Ext1 vaulted (code 5) NI roof returned 0.68 (§5.11.4 50 mm) → should be Table 18 col (1) age-band (band J 0.16), matching 33 cohort-2 `ND` vaulted roofs. New `u_roof(is_sloping_ceiling=...)` flag threaded from heat_transmission (codes 5/8). 0240 PE +5.50 → +1.52, CO2 +0.28 → +0.07 (SAP 72). Also corrected the S0380.210 cavity unit test in `domain/sap10_ml/tests/` (suite-command gap — see Thread 1). | Both also carry a memory: [[project_case7_combi_exonerated]], [[project_as_built_insulated_assumed_bug]]. @@ -58,39 +61,42 @@ Elmhurst worksheets readily (cases 7–10 done) — ask for one. --- -## OPEN THREAD 1 — Roof fix (S0380.210), needs **case 11** +## THREAD 1 — Roof fix — **CLOSED (S0380.211)** -Same root cause as the wall (`project_as_built_insulated_assumed_bug`): the API mapper -populates `epc.roofs` with "Pitched, insulated (assumed)"; `u_roof` -([`rdsap_uvalues.py:708`](../../sap10_ml/rdsap_uvalues.py)) routes -`insulation_thickness_mm==0 and _described_as_insulated(description)` → **0.68** -(retrofit 50 mm). 0240's Ext1 is `roof_construction=5` "vaulted ceiling", `NI` thickness, -band J → cascade **0.68**, should be a Table 18 sloping-ceiling value. +0240's Ext1 (BP2) lodges `roof_construction=5` (vaulted), `NI` thickness, "Pitched, +insulated (assumed)", band J → the cascade hit `u_roof`'s +`insulation_thickness_mm==0 and _described_as_insulated` override → **0.68** (the +§5.11.4 retrofit-50 mm joist row). A vaulted/sloping ceiling has no joist void, so per +RdSAP 10 §5.11 Table 18 (p.45) it takes the **column (1) age-band default (band J = +0.16)**, NOT 0.68. -**Why it's harder than the wall:** -- Just swapping to `_described_as_retrofit_insulated` makes thickness-0 fall to the - Table 16 ladder → **2.30** (uninsulated). `NI`/unknown must route to the age-band - default, not 0 mm. -- `u_roof` receives the **joined all-roofs description** (can't tell which call is the - vaulted Ext1) and **no construction type** — needs the per-BP sloping/vaulted signal - threaded through (heat_transmission already computes `is_flat_roof`; add an - `is_sloping_ceiling`/vaulted flag similarly). -- **Code-5 "vaulted" is not recognised as a sloping ceiling** — only code-8 - "sloping ceiling" is (`_api_resolve_sloping_ceiling_thickness` gates on `==8`; - `heat_transmission` keys the cos(30°) area factor on the "sloping ceiling" substring). -- **Value ambiguity (needs case 11):** Table 18 (RdSAP 10 p.45) band J gives - col (1) joists/unknown **0.16**, col (2) **at rafters 0.20**, col (3) flat / - "sloping ceiling + unheated space above" (footnote b) **0.25**. Case 9 (code-8 - sloping, Unknown) → Elmhurst **0.25**, but that may not equal code-5 vaulted (could - be 0.20). All three give 0240 integer 72 — it's a PE-pin precision question. +**The arbiter was the cohort, not case 11 — a methodology trap avoided.** The handover +above guessed the value was col-3 **0.25** (→ cont 72.31), citing case 9. That was +WRONG. The decisive evidence: **33 cohort-2 certs lodge `ND` (thickness None) vaulted +roofs** (`roof_construction=5`, band D) that already pin to their dr87 worksheets at +**0.40 = Table 18 col (1)**. 0240's only difference is the `NI` sentinel (insulation +present, unknown thickness), which uniquely hit the 0.68 override. So the spec-correct +value is **col (1) 0.16**, and 0240 lands at **cont 72.4617**, integer 72 — NOT 72.31. +A first broad attempt (route sloping → col-3 `_FLAT_ROOF_BY_AGE`) broke all 33 cohort +certs (band D col-3 = 2.30 vs worksheet 0.40) — that failure is what revealed the +col-1 answer. Lesson: when a U-value change moves worksheet-pinned cohort certs off +their pins, the change is wrong; the cohort worksheets are ground truth. -**Generate case 11:** a **vaulted Ext1 roof (`roof_construction` vaulted), insulation -Unknown/NI, band J**; report worksheet **`(30)` U** (0.20 or 0.25?). Then implement the -roof fix to match, re-pin 0240 (both bugs fixed → cont ≈ 72.31, integer 72). +**Implementation:** new `u_roof(is_sloping_ceiling=...)` flag, threaded from +`heat_transmission` for `roof_construction_type` containing "sloping ceiling" (code 8) +or "vaulted" (code 5). Fires only on the `NI` case (thickness 0 + "insulated +(assumed)") → col (1); the `ND`/None path is untouched (already col 1) and a normal +pitched-with-loft roof still takes the §5.11.4 50 mm row (flag defaults False). 0240 +PE +5.5044 → +1.5181, CO2 +0.2757 → +0.0728 (SAP 72 unchanged). Re-pinned in +`test_golden_fixtures.py`. -Simulated worksheet `(30)` decompositions seen so far: case 9 Ext1 sloping-Unknown = -0.25; case 7/8/10 roofs are all 400 mm loft (col 1, 0.11) so they do NOT exercise the -sloping path. +**⚠ Suite-command gap discovered:** the AGENT_GUIDE §4 suite command does NOT run +`domain/sap10_ml/tests/`, where `u_roof`/`u_wall` unit tests live. S0380.210 shipped a +broken `test_u_wall_cavity_..._filled_cavity_row` there unnoticed; S0380.211 corrected +it (→ `..._as_built_row`). **When touching `rdsap_uvalues.py`, also run +`domain/sap10_ml/tests/`.** Two PRE-EXISTING failures live there (stone §5.6 thin-wall +formula 3.7408 vs Table-6 1.7 cap, granite + sandstone band A) — they fail at HEAD +`58ff7d88` too, unrelated to this branch. --- @@ -169,8 +175,8 @@ that test. | cert | SAP resid | diagnosis | |---|---|---| | 0390-2954-3640 | ~~+7~~ **+0** | **CLOSED S0380.210** — cavity partial-insulation → as-built row | -| 9390-2722-3520 | +4 | community fuel-code collision → CO2 6× low (Thread 2) | -| 0240-0200-5706 | −1 | NOT a bug — unpreserved 2013+ pump; true SAP 72 | +| 9390-2722-3520 | +4 | community fuel-code collision → CO2 6× low (Thread 2, OPEN) | +| 0240-0200-5706 | −1 | NOT a bug — unpreserved 2013+ pump; true SAP 72. Roof PE-pin tightened by **S0380.211** (PE +5.50 → +1.52) | | 2130-1033-4050 | +1 | minor fabric precision (multi-part solid-brick wall); low value | | 7536-3827-0600 | +1 | minor fabric precision (multi-bp D/L/F cavity); low value | @@ -182,10 +188,16 @@ All others pin at residual 0. - **Available** (user-generated, `sap worksheets/golden fixture debugging/simulated case N/`): case 7 (combi), case 8 (unknown pump), case 9 (sandstone wall + sloping roof), - case 10 (solid-brick wall). Case 7's Summary is the only one mirrored into tracked - fixtures (`backend/.../Summary_001431_case7.pdf`, used by the e2e pin). -- **Needed:** **case 11** (vaulted Ext1 roof, NI, band J — Thread 1) and a **9390** - worksheet (community PE/CO2/cost — Thread 2). + case 10 (solid-brick wall), **case 11** (001431 sloping-ceiling Unknown roof — used to + scope Thread 1; the cohort `ND` certs were the real arbiter), **case 12** (community + CHP **coal**, code 302), **case 13** (community CHP **mains gas**, code 302). Case 7's + Summary is the only one mirrored into tracked fixtures + (`backend/.../Summary_001431_case7.pdf`, used by the e2e pin). +- **Still needed (Thread 2):** a **code-301** (community boilers, NOT CHP) + **mains gas** + worksheet to pin 9390's exact PE/CO2/cost. case 13 is code-302 CHP-gas: it confirms the + community-gas direction (heat-network `(386)` CO2 0.2456) but the CHP heat-power split + differs from 9390's boiler scheme. **API `main_fuel_type=20` = community/district + heating from mains gas → SAP Table 12 code 51** (CO2 0.210, PEF 1.130). ## Pointers - Golden pins + slice history: `tests/domain/sap10_calculator/rdsap/test_golden_fixtures.py`.