diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md
index 3838dbc8e..b34a142da 100644
--- a/.claude/skills/expand-sap-accuracy-corpus/worklist.md
+++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md
@@ -405,7 +405,7 @@ methodology) is still open โ see comment in test_real_cert_sap_accuracy.py.
All 20 pinned as `RealCertExpectation`s to the engine's OWN observed output.
- [x] ๐ง 100010359769 โ SAP-15.0 ยท eng 68 (2011 lodged 68, not a target)
- [x] ๐ง 100010359788 โ SAP-15.0 ยท eng 72 (2011 lodged 73, not a target)
-- [x] ๐ 100010086084 โ SAP-15.0 ยท eng 53, Elmhurst worksheet 51 (2011 lodged 45, not a target) ยท FULL Elmhurst RdSAP10 rebuild REDONE 2026-07-10 โ the prior 46/48 readings were CONTAMINATED (stale open-chimneys=2 and wall-thickness=280mm carried over from a PRIOR cert build in the shared Elmhurst session; the build script never explicitly zeroed `TextBoxOpenChimneys`). Fixed the build script (explicit chimney zeroing + wall thickness set to 220mm, since `CheckBoxWallThicknessUnknown` doesn't persist via Playwright and leaving it blank makes the Walls section invalid) and a real build-script bug (`ref.input_value()` truthiness check treated the string `"0"` as truthy, causing spurious navigation to Home.aspx that broke the SpaceHeating nav). Clean rebuild: eng 53 vs Elmhurst 51 โ only a ~2pt gap now (was ~5-7pt). No mapper.py change was needed/made โ the gov-API mapper's open_chimneys_count=0 was correct all along; the register itself lodges open_fireplaces_count=0. Remaining ~2pt gap not chased further: single-window-orientation approximation (South, max solar gain) plus untriaged minor divergences. See test_real_cert_sap_accuracy.py comment for full detail, incl. a possible Elmhurst-PDF-parser mismatch (cylinder size / boiler flue type) noted but out of scope.
+- [x] ๐ 100010086084 โ SAP-15.0 ยท eng 53, Elmhurst worksheet 51 (2011 lodged 45, not a target) ยท FULL Elmhurst RdSAP10 rebuild REDONE 2026-07-10 โ the prior 46/48 readings were CONTAMINATED (stale open-chimneys=2 and wall-thickness=280mm carried over from a PRIOR cert build in the shared Elmhurst session; the build script never explicitly zeroed `TextBoxOpenChimneys`). Fixed the build script (explicit chimney zeroing + wall thickness set to 220mm, since `CheckBoxWallThicknessUnknown` doesn't persist via Playwright and leaving it blank makes the Walls section invalid) and a real build-script bug (`ref.input_value()` truthiness check treated the string `"0"` as truthy, causing spurious navigation to Home.aspx that broke the SpaceHeating nav). Clean rebuild: eng 53 vs Elmhurst 51 โ only a ~2pt gap now (was ~5-7pt). No mapper.py change was needed/made โ the gov-API mapper's open_chimneys_count=0 was correct all along; the register itself lodges open_fireplaces_count=0. Remaining ~2pt gap not chased further: single-window-orientation approximation (South, max solar gain) plus untriaged minor divergences. FOLLOW-UP (2026-07-10): root-caused + fixed the cylinder_size / boiler_flue_type mismatches, both (a) Elmhurst input errors (same silent-stale-value class as chimneys/wall-thickness) โ build script's cylinder-size select assumed option VALUE==numeric code, but this DOM's option values are the visible litre-band text, so it silently no-opped and left a prior cert's "Medium" selected (fixed: match by text, "Normal"); the boiler-code dialog's combined "Balanced/Open Flue" category doesn't drive the separate FlueType field, which was left at a stale "Balanced" (fixed: explicit select to "Open"). Added mapper dict entries for the litre-suffixed cylinder labels (mapper.py `_ELMHURST_CYLINDER_SIZE_LABEL_TO_SAP10`). boiler_flue_type isn't consumed by the calculator at all (ML/generator-only), so zero SAP-score effect; cylinder fix moved Elmhurst-PDF-inputs SAP 46โ47 only. gov-API SAP (53) and Elmhurst worksheet (51) unchanged. Full suite re-run clean (67 passed/67 skipped/1 xfailed). See test_real_cert_sap_accuracy.py comment for full detail.
- [x] ๐ง 100010090369 โ SAP-15.0 ยท eng 53 (2011 lodged 47, not a target) ยท ditto
- [x] ๐ง 100010074470 โ SAP-15.0 ยท eng 46 (2011 lodged 39, not a target) ยท ditto
- [x] ๐ง 100010100813 โ SAP-15.0 ยท eng 59 (2011 lodged 47, not a target) ยท ditto
diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_summary.pdf
index b67bc1da4..6ce8e8ebb 100644
Binary files a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_summary.pdf and b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_summary.pdf differ
diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_worksheet.pdf
index 887cf0bc0..00c6fb183 100644
Binary files a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_worksheet.pdf and b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-15.0/uprn_100010086084/elmhurst_worksheet.pdf differ
diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py
index da1753453..20ef69613 100644
--- a/datatypes/epc/domain/mapper.py
+++ b/datatypes/epc/domain/mapper.py
@@ -7555,7 +7555,9 @@ _ELMHURST_CYLINDER_SIZE_LABEL_TO_SAP10: Dict[str, int] = {
# The live RdSAP10-Online tool renders the size band WITH its litre range
# suffix (observed on the SAP-Schema-15.0 UPRN 100010086084 build) rather
# than the bare label the cohort fixtures used above.
+ "Normal (Less than 130L)": 2,
"Medium (131-170L)": 3,
+ "Large (Greater than 171L)": 4,
}
diff --git a/scripts/hyde/build_100010086084.py b/scripts/hyde/build_100010086084.py
index fb67bfa65..a700725da 100644
--- a/scripts/hyde/build_100010086084.py
+++ b/scripts/hyde/build_100010086084.py
@@ -5,7 +5,7 @@ UNKNOWN, not a specific mm value), pitched 300mm loft insulation, SOLID
ground floor uninsulated, mains-gas generic (no-PCDB) REGULAR boiler โ SAP
Table 4b code 115 (pre-1998, balanced/open flue, "BGL Pre 98 Wall mount
BF/OF") + programmer/room-thermostat control (2104/CBC) + radiators +
-cylinder (size 2 = "Medium (131-170L)" on the live tool, foam, 25mm), gas
+cylinder (size 2 = "Normal (Less than 130L)" on the live tool, foam, 25mm), gas
room-heater SECONDARY (603, approximated as RGB "Modern fire with open flue
post 1980" -- the cert gives no finer detail), TFA 68, single meter,
2-storey / 2 floor-dims (no extensions). Partial double glazing
@@ -244,6 +244,15 @@ def space_heating(page):
E.set_heating_dialog(page, f"{MH1B}ButtonMainHeatingControls",
"^Boilers", "^Standard", "CBC Programmer and room thermostat")
print("control:", page.locator(f"#{E.MH1}TextBoxMainHeatingControls").input_value())
+ # Explicit flue type (BUG fixed): the "Balanced/Open Flue" boiler-code
+ # CATEGORY picked above is a combined Table 4b group name (BF/OF) that
+ # does NOT set the separate `RadioButtonListFlueType` select on this
+ # page -- that field kept its inherited/default "Balanced" from a
+ # prior cert (silent-stale-value class of bug, see docstring), which
+ # mismatches the lodged gov-API `boiler_flue_type=1` ("Open"). Set it
+ # explicitly to match.
+ E.set_select(page, f"{MH1B}RadioButtonListFlueType", "Open")
+ print("flue type:", page.locator(f"#{E.FP}{MH1B}RadioButtonListFlueType").input_value())
E.save_close(page)
@@ -269,12 +278,18 @@ def water_heating(page):
E.set_heating_dialog(page, f"{WH}ButtonWaterHeatingCode",
"From Space Heating", "From the primary heating system")
print("water code:", page.locator(f"#{E.FP}{WH}TextBoxWaterHeatingCode").input_value())
- # cylinder: size 2 (lodged cylinder_size code -- set_select matches by
- #