Commit graph

7536 commits

Author SHA1 Message Date
Khalim Conn-Kowlessar
325c0ea257 Merge remote-tracking branch 'origin/main' into fix/full-sap-export-capable-mapping 2026-07-03 12:11:25 +00:00
Khalim Conn-Kowlessar
c5b55197b4 Full-SAP certs carry their lodged PV export-capability flag 🟩
`from_sap_schema_17_1` hardcoded is_dwelling_export_capable=False, so
SAP 10.2 Appendix M1 zeroed the PV export credit on every export-capable
full-SAP cert. Cert 0380-3044-6070-2305-5925 (property 741840, PRD #1435
WS3) now reproduces its lodged 92 exactly (was 89); the existing
19.1.0 pin 10096028301 closes its documented -1 residual (84 -> 85 =
lodged). The full-SAP top-level pv_connection is deliberately NOT
carried: its enum disagrees with the RdSAP one the calculator gates on.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:09:04 +00:00
Khalim Conn-Kowlessar
6656d8dec2 A full-SAP export-capable PV cert reproduces its lodged SAP 10.2 score 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:05:04 +00:00
Jun-te Kim
5c510e1b15
Merge pull request #1439 from Hestia-Homes/feat/sap-corpus-campaign
test(accuracy): corpus-1000 — 74.2% → 77.7% within-0.5, MAE 0.721 → 0.637 (8 fixes; mapper+calc validated vs Elmhurst)
2026-07-03 12:52:57 +01:00
Daniel Roth
7abf466b56
Merge pull request #1445 from Hestia-Homes/feature/abri-api-integration
Abri deal abandonment check
2026-07-03 11:48:37 +01:00
Daniel Roth
1a5368571f add typehint 2026-07-03 10:46:24 +00:00
Daniel Roth
f4f915cfb7 Abri deal abandonment names its attempt threshold 🟪
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:19:06 +00:00
Jun-te Kim
645789456e docs(corpus): find the third driver — mixer-shower default, 91% of gap now traced
Walked the water-heating worksheet section: assumed occupancy (42) matched
exactly (2.4234 both sides), but (43) average daily hot water use was
117.41 L/day (Elmhurst) vs 110.73 L/day (ours) — same occupancy, different
shower/bath demand. Root cause: the cert's shower_outlets field is
genuinely unlodged, which the mapper correctly maps to 0 mixer showers
per its documented, already-validated "no entry = no shower" convention.
Elmhurst's build shows a "Non-electric shower" fixture anyway — its UI
silently defaults one when the build script doesn't explicitly configure
"0 showers" to match the cert.

Verified: a single 7 L/min vented mixer reproduces Elmhurst's (42a)
monthly series exactly (4 d.p., all 12 months) and closes hot water to
2616.04 vs Elmhurst's 2616.03. Corpus-wide check across 170 certs sharing
this "bath present, no shower data" pattern shows no systematic bias
(mean dSAP +0.12, median -0.04) — confirms the mapper convention is
correct on average; this is a build-entry artifact on this one cert, not
a mapper bug (no code change warranted).

Combining all three found causes (window orientation, Table 11, shower
default): SAP 72.4567 vs Elmhurst's precise 72.0681 — residual 0.39,
~91% of the original 4.26-point gap now precisely explained.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:19:05 +00:00
Daniel Roth
18989252f4 Deal differ detects number of attempts changes for db update 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:17:51 +00:00
Daniel Roth
c00ae894ee Deal differ detects number of attempts changes for db update 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:14:22 +00:00
Daniel Roth
58ce855e0b Abri deal abandonment fires only when the deal newly becomes abandoned 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:13:58 +00:00
KhalimCK
f822f8a15d
Merge pull request #1443 from Hestia-Homes/fix/electric-room-heater-overlay-companions
Electric room heaters override forces its category + control (fix silent storage-companion inheritance)
2026-07-03 11:13:35 +01:00
Daniel Roth
9559f23741 Abri deal abandonment fires only when the deal newly becomes abandoned 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:12:59 +00:00
Daniel Roth
6de0da869e Abri deal abandonment requires a negative outcome 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:11:14 +00:00
Daniel Roth
41d62ce2b2 Abri deal abandonment requires a negative outcome 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:10:26 +00:00
Daniel Roth
88093eb7cd Abri deal abandonment requires at least three parseable attempts 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:10:03 +00:00
Daniel Roth
af85e0ed2b Abri deal abandonment requires at least three parseable attempts 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:07:38 +00:00
Daniel Roth
79423f594c Abri deal abandonment ignores deals that are not Abri condition deals 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:06:53 +00:00
Daniel Roth
33848a76fe Abri deal abandonment ignores deals that are not Abri condition deals 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:04:45 +00:00
Daniel Roth
262f22764a Abri deal abandonment triggers after three attempts with a negative outcome 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:03:57 +00:00
Daniel Roth
aca507cc47 Abri deal abandonment triggers after three attempts with a negative outcome 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 10:03:42 +00:00
Jun-te Kim
d15ea8b7d4 docs(corpus): find the second driver of 100061275133's residual gap
Walked the worksheet section-by-section (dimensions, ventilation, fabric,
internal/solar gains, MIT, space-heating requirement, fuel cost) against
the calculator's matching intermediates. Internal gains and heat loss
matched closely, but solar gains (worksheet line 83) was 2.2x off in
January (56.9 W vs our 123.4 W) — traced to the Elmhurst BUILD entering
all 12 real windows (3 orientations: NW 7.05 m2, NE 1.21 m2, SE 7.06 m2)
as a single synthetic 15.32 m2 "North" group, understating solar gain.

Verified by reproducing both build artifacts in the calculator: real
windows + real Table-11 gating = 76.33 (our answer, matches lodged 76
exactly); collapsing to a synthetic single-North window + forcing Table
11 on = 72.62, reproducing Elmhurst's 72 almost exactly. Confirms neither
residual is a mapping or calculator bug — one is a deliberate,
regression-tested spec choice (Table 11) and the other is an artifact of
how this specific Elmhurst reconciliation build was entered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:52:22 +00:00
Jun-te Kim
f69d345493 docs(corpus): correct 100061275133 pin comment — real driver is Table 11
The prior comment blamed a stale build-side combi artifact (already fixed
this session) and my earlier conversational claim that Elmhurst's overall
SAP used regional weather was wrong too — verified the worksheet's (5)
dwelling volume and wind table match our UK-average rating cascade exactly.

The actual, now-quantified driver: Elmhurst's worksheet (201)/(202)/(215)
show it unconditionally applies SAP 10.2 Table 11's 10% secondary/portable-
electric-heater fraction based on main heating category alone, with no
secondary lodged on the cert. Our `_secondary_fraction` deliberately gates
this on an actual lodged/forced secondary (see the adjacent S-B30 note:
applying it unconditionally regressed the full 1000-cert corpus MAE by
+0.16). Forcing Table 11 on for just this cert moves 76.33 -> 73.62 (~62%
of the 76.33-vs-72 gap) — confirms this, not a mapping error, drives the
residual. Documented so the next reader doesn't re-litigate it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:41:09 +00:00
Daniel Roth
701a6aa5cd Merge branch 'main' into feature/abri-api-integration 2026-07-03 09:40:18 +00:00
Daniel Roth
71a309ad0a
Merge pull request #1442 from Hestia-Homes/feature/abri-api-integration
Abri API Integration: check for tenant data fetch trigger
2026-07-03 10:33:44 +01:00
Jun-te Kim
5abc87ea18 chore(corpus): reconciliation pass over the 1-2 SAP band, no new bug found
Per the PR #1439 handoff: swept every cert now sitting at |Δ| in [1.0, 2.0)
(58 certs) using the cost-vs-demand signature bucketer (why_diverge.py's
logic) plus field_bias.py's full-corpus subgroup scan (re-run clean after
the two engine fixes above — no |meanΔ|>=0.5 systematic subgroup with
coherent median).

Breakdown: 17 room-in-roof (already spec-mandated/worksheet-validated per
PRs #1440/#1441), 7 electric cost/tariff variants (spec-faithful vs lodged,
consistent with the diagnosed electric cluster), 4 non-electric cost
residuals (spec-faithful), ~26 non-electric fabric/demand certs. Manually
inspected geometry (floor areas/perimeters/heights, wall/roof codes,
window/door counts) for the 4 largest fabric/demand outliers in the band
(100031768368, 100070450818, 100110097281, 100051051866) — no data-entry
anomaly comparable to the earlier 12109191 decimal-floor-area bug. This
confirms the handoff's "our calc faithful, lodged differs" pattern holds
across the band; no engine bug survived the pass. Notes appended per-cert
in worklist.md (`<-`, preserved by build_worklist.py reruns).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:26:05 +00:00
Khalim Conn-Kowlessar
dd30903ace Merge remote-tracking branch 'origin/main' into fix/electric-room-heater-overlay-companions 2026-07-03 09:25:11 +00:00
Khalim Conn-Kowlessar
244c5b65ed Document heating-companion coherence: category/control forced, fuel/meter deferred (ADR-0048)
ADR-0048 records why a system-replacing heating override must emit a
complete companion set — category and control archetype-forced for
coherence, fuel and meter deferred where multiple values are valid, and
an unmapped companion logged rather than silently inherited. Adds the
Heating Companion Set glossary term to CONTEXT.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:21:47 +00:00
Jun-te Kim
6c1828e8bf chore(hyde): fix 100061275133 Elmhurst build — 0 fans + PCDB exact boiler
ventilation(): the cert lodges no extract-fan count and RdSAP 10 Table 5's
age-band B default is 0, but the build entered 1 — inflating Elmhurst's own
(8)/(21) infiltration lines relative to both the cert and our engine.

space_heating(): switched from the generic "Combi condens" SAP-Table dialog
code (84% efficiency, no PCDB record) to elmhurst_lib.set_pcdb_boiler(18908)
via clear_main_heating_code — resolves the exact lodged product (Worcester
Greenstar 4000, 88.70%) and its correct keep-hot classification (None),
matching the SAP engine's own PCDB lookup and removing the "Standard Combi"
keep-hot artifact the reused generic code carried.

Also corrected the file's stale docstring (described a different property
entirely — mid-terrace/250mm/DUAL meter/11 windows/lodged 63 — left over
from a copy-paste).

Verified against the refreshed worksheet: (21) shelter-adjusted ACH 0.6938
now EXACT vs our engine's ventilation_from_cert; (61) combi loss monthly
kWh matches ours to ~0.01 kWh (was carrying a ~360 kWh/yr keep-hot artifact).
Both open items from the PR #1439 handoff are resolved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:20:12 +00:00
Khalim Conn-Kowlessar
962a443ed2 A complete room-heater overlay does not log a companion gap 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:17:06 +00:00
Khalim Conn-Kowlessar
390e3e89d7 The overlay logs an error when it cannot complete a heating companion set 🟩
A system-replacing override whose category or control is not yet mapped
now logs an error naming the archetype and code, so the incomplete
companion set (which otherwise silently inherits the replaced system's
value) is visible for review — log-and-continue, matching flag_fuel_mismatch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:16:25 +00:00
Khalim Conn-Kowlessar
ea113b58fb The overlay logs an error when it cannot complete a heating companion set 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:15:31 +00:00
Khalim Conn-Kowlessar
ffd21689fd An electric room heaters override sets the room-heater charge control 🟩
Control 2601 (SAP Table 4e Group 6 room-heater, +0.3 C conservative
default) now overlaid for electric room heaters, matching the gas/oil/
solid siblings, so a replaced storage heater's manual charge control
2401 (+0.7 C) no longer survives and over-warms the modelled dwelling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:13:32 +00:00
Khalim Conn-Kowlessar
cfd9799500 An electric room heaters override sets the room-heater charge control 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:13:03 +00:00
Jun-te Kim
dee72bbdfa fix(rdsap): §5 (12) floor infiltration falls back to floors[].description
_has_suspended_timber_floor_per_spec only read the Main bp's per-part
floor_construction_type lodgement; the gov-API mapper frequently leaves
that None even when the global epc.floors[].description carries an
explicit "Suspended, ..." observation. _main_floor_u_value already fell
back to this joined description for the U-value calc — the infiltration
rule did not, so a genuinely suspended-timber floor silently entered
(12)=0 instead of 0.2 unsealed. Extracted the shared
_effective_floor_description helper and added a tri-state resolver
(explicit lodgement -> description, excluding "not timber" -> Table 19
footnote-1 age-A/B default) so both paths agree.

Cert 100061275133 (Elmhurst-validated build, PR #1439 handoff): engine
77.24 -> 76.33, now an exact match to lodged (76). Corpus gauge 77.7% ->
77.8% within-0.5, MAE 0.637 -> 0.636; floors ratcheted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:12:19 +00:00
Khalim Conn-Kowlessar
bf032d17d0 An electric room heaters override sets the room-heater heating category 🟩
Category 10 (SAP Table 4a Room heaters) now overlaid for electric room
heaters (691-701), so a replaced storage heater's category 7 no longer
survives onto the effective cert and mis-bills via the Table 12a resolver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:12:19 +00:00
Khalim Conn-Kowlessar
5e7e51d8b2 An electric room heaters override sets the room-heater heating category 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 09:11:38 +00:00
Daniel Roth
05ca0bb280 move static method below non-statics 2026-07-03 08:33:10 +00:00
Daniel Roth
a36fe00132 Abri tenant data fetch resolves abri deals by associated project id 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:28:25 +00:00
Daniel Roth
5df1237b90 Abri tenant data fetch requires a parseable new commencement date 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:27:42 +00:00
Daniel Roth
47842da7b9 Abri tenant data fetch requires a parseable new commencement date 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:27:22 +00:00
Daniel Roth
b4d2d9cd37 Abri tenant data fetch ignores already-set commencement dates 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:26:20 +00:00
Daniel Roth
c18f4feb3e Abri tenant data fetch ignores already-set commencement dates 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:26:02 +00:00
Daniel Roth
426aa9a15e Abri tenant data fetch does not trigger for non-abri deals 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:25:26 +00:00
Daniel Roth
0b8f0f17a9 Abri tenant data fetch does not trigger for non-abri deals 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:25:07 +00:00
Daniel Roth
2f1dfaa5a6 Abri tenant data fetch triggers when commencement date is first set 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:24:36 +00:00
Daniel Roth
da0ef3e5e0 Abri tenant data fetch triggers when commencement date is first set 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:24:11 +00:00
Daniel Roth
050bb78313 Merge branch 'main' into feature/abri-api-integration 2026-07-03 08:20:08 +00:00
Jun-te Kim
3fd7c5708d feat(hyde): PCDB exact-boiler entry (set_pcdb_boiler + clear_main_heating_code)
Cracks the 'PCDB disabled' blocker. The PCDF boiler reference resolves the exact
lodged boiler (e.g. 18908 -> Worcester Greenstar 4000, 88.70%) when: (1) the main
heating CODE is empty server-side (else the field + magnifying glass are
aspNetDisabled), and (2) the index is entered via REAL keyboard + Tab (a JS-set
.value doesn't survive the AutoPostBack). Now Elmhurst uses the same boiler
efficiency as the SAP engine, so worksheet vs calculator compare like-for-like.

Verified on 100061275133: Elmhurst now shows 'Efficiency of main space heating
system 1 = 88.70%' (was generic 84%). Includes updated worksheet evidence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 07:49:23 +00:00
Jun-te Kim
b9d36f72cb chore(hyde): refresh 100061275133 Elmhurst PDFs after draught-proofing rebuild
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:45:58 +00:00