Commit graph

8186 commits

Author SHA1 Message Date
Khalim Conn-Kowlessar
64207ea225 Accrue Table 3 primary-circuit loss for water-only heat-network cylinders 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:30:51 +00:00
Khalim Conn-Kowlessar
f5e4814bf9 Int-code the surveyed cylinder insulation label for the storage-loss cascade 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:25:48 +00:00
Khalim Conn-Kowlessar
87922b622a Int-code the surveyed cylinder insulation label for the storage-loss cascade 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:24:47 +00:00
Khalim Conn-Kowlessar
5a7ff6de1c Lodge the surveyed Wall Dry-Lined answer on the SAP building part 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:22:22 +00:00
Khalim Conn-Kowlessar
073e5ce30c Lodge the surveyed Wall Dry-Lined answer on the SAP building part 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:21:36 +00:00
Khalim Conn-Kowlessar
483b69ff41 Capture the surveyed Wall Dry-Lined answer per building part 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:20:36 +00:00
Khalim Conn-Kowlessar
0b47798403 Capture the surveyed Wall Dry-Lined answer per building part 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:20:09 +00:00
Khalim Conn-Kowlessar
1f1bb8a556 Withhold roof insulation from RIR surfaces the surveyor marked insulation-unknown 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:17:30 +00:00
Khalim Conn-Kowlessar
7f854e7219 Withhold roof insulation from RIR surfaces the surveyor marked insulation-unknown 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:17:30 +00:00
Khalim Conn-Kowlessar
8e58f7e871 Capture the per-surface RIR insulation-known answer from the survey 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:12:08 +00:00
Khalim Conn-Kowlessar
d743f6fb3b Capture the per-surface RIR insulation-known answer from the survey 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:11:09 +00:00
Khalim Conn-Kowlessar
a67473ceae Add extractor-accuracy campaign handover (state, recipe, remaining targets)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:43:24 +00:00
Khalim Conn-Kowlessar
e0b189aa6d Correct two pashub-verified pre_sap values in the accuracy manifest
Manually verified in pashub (Khalim, 2026-07-14): deal 499584755922
(9 Council Houses, CW5 8AP) is F33, not the stale D67 — our computed 34.0
was right within a point; deal 499617935574 (Brightholme, 14 North Road)
is the accredited E43, not the preliminary 53. 58 Hackle Street (D58) and
16 Bingley Close (E52) were confirmed correct, so our +7.8/+5.7 deviations
there are extraction bugs to hunt next. Harness MAE 1.684 -> 1.551; ceiling
ratcheted to 1.56.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:42:03 +00:00
Khalim Conn-Kowlessar
f45651dbc0 Lodge the heat-network SAP code and Table 12 community fuel for PasHub community heating 🟩
The extractor now captures "Heating System (Other):" and the mapper resolves
it to the Table 4a code (301, community boilers) + Table 12 community fuel
(51 via the shared _resolve_community_heating_fuel_code), so
is_heat_network_main routes the DLF / standing-charge / 80%-efficiency
branch instead of pricing the dwelling as an ordinary mains-gas boiler
(fixture 507644414148: +14.3 over-rate closes by ~8.6). Harness MAE
1.726 -> 1.684; ceiling ratcheted to 1.70.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:34:50 +00:00
Khalim Conn-Kowlessar
4d60d79cc9 Extract the PasHub community heat-source label 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:33:08 +00:00
Khalim Conn-Kowlessar
f9d8d33147 Lodge the heat-network SAP code and Table 12 community fuel for PasHub community heating 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:30:28 +00:00
Khalim Conn-Kowlessar
6f1ba4be25 Bill room-in-roof surfaces with the surveyed roof insulation, stud-wall commons 🟩
Two dig-confirmed defects in the fresh RIR mapping (499617935574 overshot
-9): the roof-space-level insulation (Joists/200mm) was never threaded into
the RIR surfaces, so slopes/commons/flat ceilings fell to the Table 18
"unknown" full-uninsulated 2.30 default; and common walls were mislabeled
"common_wall" (a Simplified-Type-2-only concept) instead of the Detailed-mode
stud_wall every worksheet-validated fixture uses. 44.0 -> ~50.3 on the target
fixture; harness MAE 1.748 -> 1.726.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:29:20 +00:00
Khalim Conn-Kowlessar
25c3f0b2a0 Bill room-in-roof surfaces with the surveyed roof insulation, stud-wall commons 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:28:10 +00:00
Khalim Conn-Kowlessar
955b4dc1e8 Extract the PasHub detailed room-in-roof block 🟩
_parse_room_in_roof captures the RdSAP §3.10 block (age range, floor area,
gables with Exposed/Party type, slopes, common walls, flat ceiling as
length x height) on main and extension roof spaces; both part builders now
carry it to sap_room_in_roof (issue #1590 bug 5 — closes the last #1590
subtask). Harness MAE 1.748 (754917 corrects to pashub's own pre-SAP; RIR
surfaces now billed per-surface instead of as insulated loft).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:09:44 +00:00
Khalim Conn-Kowlessar
518c682793 Extract the PasHub detailed room-in-roof block 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:05:31 +00:00
Khalim Conn-Kowlessar
f067f94ec9 Carry room_in_roof on extension roof spaces too (pyright union access) 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:04:33 +00:00
Khalim Conn-Kowlessar
0ca5108584 Carry the surveyed room-in-roof block onto the SAP building part 🟩
_pashub_room_in_roof mirrors _api_build_room_in_roof: every surveyed RIR
surface (gable typed Exposed/Party per Table 4, slopes, common walls, flat
ceiling) becomes a detailed_surfaces entry of length x height, so the
cascade bills exact RIR surfaces instead of treating the shell as
well-insulated loft (issue #1590 bug 5).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:01:30 +00:00
Khalim Conn-Kowlessar
9599fd8239 Carry the surveyed room-in-roof block onto the SAP building part 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:59:41 +00:00
Khalim Conn-Kowlessar
895df42afe Keep a PasHub system-build wall off the basement cascade 🟩
PasHub surveys never lodge a basement wall, but "System Build (i.e Any
Other)" maps to wall code 6 — the gov-API basement sentinel — and with
wall_is_basement left None the dwelling silently routed through the basement
wall/floor U-value cascade (issue #1590 bug 7). Both part builders now pin
the flag False. Harness MAE 1.732 -> 1.727.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:56:27 +00:00
Khalim Conn-Kowlessar
5980b2d6ed Keep a PasHub system-build wall off the basement cascade 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:53:21 +00:00
Khalim Conn-Kowlessar
de15bd1ed7 Resolve the PasHub Cylinder Size label to the SAP10 Table 28 enum 🟩
"Normal (90-130 litres)"->2, "Large (>170 litres)"->4; "No Access" follows
RdSAP 10 Table 28 p.55 (otherwise-branch 110L for a main-fed cylinder;
electric-immersion No Access strict-raises until meter context is plumbed).
The raw band string was int-or-noned by _cylinder_volume_l_from_code, skipping
the Table 28 volume convention (issue #1590 bug 6). Golden block updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:52:32 +00:00
Khalim Conn-Kowlessar
2949460e6a Resolve the PasHub Cylinder Size label to the SAP10 Table 28 enum 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:48:47 +00:00
Khalim Conn-Kowlessar
090e16ddc2 Dispatch PasHub mechanical ventilation into the §2 ACH cascade 🟩
The surveyed "Ventilation type" label never reached
mechanical_ventilation_kind, so ventilation_from_cert silently defaulted every
mechanical system to NATURAL (24d), dropping its ACH heat loss — 76/205
cohort fixtures lodge dMEV/MEV/PIV (issue #1590 bug 4). Mapping mirrors the
gov-API _API_MECHANICAL_VENTILATION_TO_KIND table (PIV-from-loft is
"as natural"). Harness: within-0.5 12.2% -> 18.5%, MAE 2.538 -> 1.730 — the
campaign's largest single move; floors ratcheted to 0.18 / 1.75.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:45:24 +00:00
Khalim Conn-Kowlessar
5220b51961 Dispatch PasHub mechanical ventilation into the §2 ACH cascade 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:43:00 +00:00
Khalim Conn-Kowlessar
56b36ce7f0 Resolve the PasHub PV Connection label to the gov-API credit-gate int 🟩
"Not connected to electricity meter" -> 1 (zero Appendix M credit), "Connected
to dwellings electricity meter" -> 2; the raw string fell through the credit
gate's non-int branch to True, crediting a separately-metered array (issue
#1590 bug 3, fixture 499516101839 -6.9 SAP). Harness MAE 2.571 -> 2.538;
ceiling ratcheted to 2.55.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:41:04 +00:00
Khalim Conn-Kowlessar
f9079eb0ac Resolve the PasHub PV Connection label to the gov-API credit-gate int 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:39:08 +00:00
Khalim Conn-Kowlessar
f92d4f26b8 Extract the PasHub per-system PV block and diverter flag 🟩
"Photovoltaic array kWp Known? Yes" lodges a per-system block (kWp, pitch,
orientation, overshading) instead of the percent-roof estimate; the extractor
only read the estimate, so measured PV never reached the mapper and the
Appendix M credit was silently zero (issue #1590 bug 1). Harness MAE
2.632 -> 2.571 (fixture 507639151843's 13.5-SAP under-rate closes to +0.5);
ceiling ratcheted to 2.58.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:38:07 +00:00
Khalim Conn-Kowlessar
80de9b0c04 Extract the PasHub per-system PV block and diverter flag 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:35:34 +00:00
Khalim Conn-Kowlessar
1282f81a72 Map surveyed PasHub PV arrays into the Appendix M photovoltaic_arrays input 🟩
_pashub_pv_arrays mirrors _elmhurst_pv_arrays, reusing its format-agnostic
pitch/orientation/overshading converters (PasHub lodges "South East"
space-separated; normalise to the octant map's hyphenated keys). Wired into
the SapEnergySource construction so the calculator's Appendix M generation
path sees measured PV instead of silently zero credit (issue #1590 bug 1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:33:18 +00:00
Khalim Conn-Kowlessar
9a1422f6d7 Map surveyed PasHub PV arrays into the Appendix M photovoltaic_arrays input 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:31:08 +00:00
Khalim Conn-Kowlessar
bc58cf4930 Lodge explicit zero roof insulation for a surveyed "Insulation At: None" 🟩
"Insulation At: None" is the assessor recording zero loft insulation, not an
unknown — with thickness left None, u_roof fell through to the age-band
"assumed insulated" default (0.16 W/m²K at band J/K) instead of the Table 16
uninsulated row (2.30), understating roof loss ~14x (issue #1590 bug 2).
Harness MAE 2.701 -> 2.632 (the two ~7-SAP roof over-raters correct exactly);
ceiling ratcheted to 2.64.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:28:25 +00:00
Khalim Conn-Kowlessar
66e0adf619 Lodge explicit zero roof insulation for a surveyed "Insulation At: None" 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:26:42 +00:00
Khalim Conn-Kowlessar
178af2f044 Add local modelling runner + portfolio-838 problem-properties handover
scripts/run_pashub_modelling.py invokes the modelling_e2e handler in-process
over a portfolio using STORED EPCs (refetch_epc=False — the correct source for
PasHub cohorts, issue #1589), parametrised by env (portfolio/scenario/pids/
dry-run/batch). Handover documents the 3 re-extraction stragglers, the
rebaseliner pass-through gotcha (effective_sap_score IS the pashub rating for
unchanged lodged EPCs — never validate the calculator against it), and the 7
root-caused extractor bugs now tracked in #1590.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:24:37 +00:00
Khalim Conn-Kowlessar
999008f9d0 Refresh pashub accuracy manifest pre_sap from the corrected DB rows
Two hubspot_deal_data corrections: 499539910905 D58->B82 (confirmed bad row)
and one C73->C75. Rebuilt via scripts/build_pashub_accuracy_fixtures.py
(no --force; PDFs unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:24:37 +00:00
Khalim Conn-Kowlessar
cab7e3d613 Close the last PasHub mapper gaps: secondary fuel + Group 3 heat-network control 🟩
Secondary fuel 'Mains gas'/'Mains Gas'->26 and 'House Coal'->11 (Table 32);
main-heating control resolution becomes group-aware with a Table 4e Group 3
map ('Charging system linked to use of community heating, room thermostat
only' -> 2306, the code the accredited Elmhurst certs lodge for this cohort;
all four linked-to-use codes are calculation-identical). All 205 Guinness
fixtures now compute (was 201/4 xfails); ratchet re-baselined to the
full-coverage aggregate (12.2% within-0.5 floor, MAE ceiling 2.71) with the
two newly-computable outliers documented for verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:24:36 +00:00
Daniel Roth
533f33d62b
Merge pull request #1581 from Hestia-Homes/feature/pashub-map-main-heating-control-1557
PasHub mapper: resolve main_heating_control label → SAP Table 4e code (#1557)
2026-07-14 19:03:25 +01:00
Daniel Roth
ecb113b52e Re-ratchet PasHub SAP-accuracy floor to the current integrated aggregate (12.4% within-0.5) 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 17:57:34 +00:00
Daniel Roth
328887c4d3 Merge branch 'main' into feature/pashub-map-main-heating-control-1557 2026-07-14 17:53:04 +00:00
KhalimCK
8eb2649b9b
Merge pull request #1587 from Hestia-Homes/worktree-issue-1566-roof-construction-country
Set roof_construction_type and country_code on the PasHub site-notes path
2026-07-14 18:51:10 +01:00
KhalimCK
6be73555c6
Merge pull request #1586 from Hestia-Homes/feat/pashub-heating-efficiency-1563
PAS Hub mapper: boiler PCDB product_id → main_heating_index_number (#1563)
2026-07-14 18:50:37 +01:00
Daniel Roth
df3fce0a3f
Merge branch 'main' into feature/pashub-map-main-heating-control-1557 2026-07-14 18:50:08 +01:00
Daniel Roth
fdcf29a057 Resolve PasHub control labels only for boiler systems, strict-raise otherwise 🟩
Table 4e is organised by heating-system family and the same control label
recurs across groups under different 2xxx codes, so the boiler (Group 1) map is
gated behind a boiler system_type; any other system strict-raises rather than
silently taking a boiler code. Adds a guard that every mapped code exists in the
calculator's _CONTROL_TYPE_BY_CODE inventory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 17:49:18 +00:00
Daniel Roth
6c61055e6c
Merge pull request #1585 from Hestia-Homes/feat/pashub-residual-main-fuel-1558
PAS Hub: code residual main-fuel labels (Bulk LPG + Fuel: Mains Gas) (#1558)
2026-07-14 18:49:17 +01:00
Daniel Roth
bf550fdfdc
Merge branch 'main' into feat/pashub-residual-main-fuel-1558 2026-07-14 18:48:40 +01:00
Daniel Roth
313ae5253a Strict-raise a PasHub control label on a non-boiler system 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 17:46:23 +00:00