Model/tests
Khalim Conn-Kowlessar da993b5359 Treat a lodged party ceiling as U=0 instead of a pitched roof 🟩
RdSAP 10 item 2-3(h) "another dwelling above" is U=0 (spec p.45: "There is no
heat loss through the roof of a building part that has the same dwelling above
or another dwelling above"). gov-API `roof_construction = 3` is that code, but
the mapper labelled it "Pitched (slates/tiles), no access to loft" (which is
code 5), so the per-part party override at heat_transmission.py:1172 never
matched and the part fell through to the dwelling_type-label-only
has_exposed_roof heuristic.

190 of the 200 corpus code-3 parts sit at index 0 and are already suppressed by
`_cert_lodges_exposed_roof` off the roof_insulation_location == "ND" signal. The
unmitigated set is the 10 parts at index > 0, where extensions default to
exposed and were billed a phantom pitched roof. Also removes a latent PV defect:
the bogus "Pitched" prefix satisfied `is_pitched` and divided PV array area by
cos(35 deg), inflating kWp.

Shipped with the stairwell fix so the corpus pin moves once: within-0.5
78.8% -> 79.6%, SAP MAE 0.626 -> 0.611, PE MAE 2.9 -> 2.7.

The roof change alone trades 4 certs out of the +-0.5 band for 2 in (one moving
4.4 SAP closer). Those 4 were investigated and are NOT a masked bug: the corpus
error distribution is symmetric (mean +0.076, median +0.03, sigma 1.606; 112
certs above +0.5 vs 102 below), ground-floor flats show 7 positive / 8 negative
with no excess over the null, and closing them needs HLC changes of 2.3-5.6% —
below the ~8.8% noise floor of the RHI anchor, calibrated on the 76 certs whose
SAP is exact (space-heating ratio 1.062 +/- 0.088).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 22:23:52 +00:00
..
abri Surface both canceljob failure shapes as verbatim rejections 🟥 2026-07-07 15:33:16 +00:00
applications Model the newer stored survey when refetching EPCs 🟩 2026-07-15 09:40:15 +00:00
backend Hand-pick selection by landlord_property_id, not property.id 2026-07-08 12:04:35 +00:00
datatypes Treat a lodged party ceiling as U=0 instead of a pitched roof 🟩 2026-07-21 22:23:52 +00:00
domain Bill a sheltered wall to a stairwell at Ru 2.1, not the corridor 0.5 🟩 2026-07-21 22:02:31 +00:00
e2e Prove prediction resolves landlord overrides to a real cohort match end-to-end 🟩 2026-06-16 15:20:49 +00:00
fixtures Expired-pairs integration gate: frozen single-file corpus + ratcheting floors 🟩 2026-07-06 13:05:18 +00:00
harness The multi-measure trigger fixture is a cert the sized ASHP alone cannot clear 🟩 2026-07-03 12:25:03 +00:00
infrastructure Treat a lodged party ceiling as U=0 instead of a pitched roof 🟩 2026-07-21 22:23:52 +00:00
lambdas new application to trigger e2e for a single property and scenario 2026-06-22 12:54:53 +00:00
magic_plan Mapper reads new 'Total Trickle Vent Effective Area' label 🟥 2026-06-30 12:56:54 +00:00
orchestration Fetch a property's lodged EPC by UPRN, not property_id 2026-07-14 10:35:51 +00:00
repositories Break lodged-UPRN duplicates by latest inspection_date, then id 2026-07-14 10:46:01 +00:00
scripts The historic roof description conditions the cohort by form family 🟩 2026-07-06 12:05:56 +00:00
utilities abri_api not abri 2026-07-07 14:40:33 +00:00
utils SharePoint 404s raise ResourceNotFoundError without error-level logging 🟩 2026-07-03 12:26:33 +00:00
__init__.py added postcode splitter rewrite to ddd 2026-05-19 16:35:09 +00:00
conftest.py Audit generator populates XLSX, uploads to S3, and records UploadedFile row 🟪 2026-06-09 12:05:55 +00:00
test_lambda_packaging.py better smoke tests to check what is failign 2026-06-17 11:53:33 +00:00