Commit graph

7399 commits

Author SHA1 Message Date
Daniel Roth
9b58bebfb8 Rename SapEnergySource.mains_gas to gas_connection_available 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 10:59:21 +00:00
KhalimCK
9968e2b9df
Merge pull request #1379 from Hestia-Homes/fix/1376-flat-roof-insulation-thickness
Score flat roofs by their known insulation depth, not the age-band default (#1376)
2026-07-01 11:58:46 +01:00
Daniel Roth
a174301136 rename mains_gas to gas_connection_available 2026-07-01 10:50:58 +00:00
Daniel Roth
2f93b0b292 Revert "Rename SapEnergySource.mains_gas to gas_connection_available 🟥"
This reverts commit 490499d2a9.
2026-07-01 10:48:48 +00:00
Jun-te Kim
3282cef04e Fix RdSAP-17.0 mapper dropping lodged secondary heating
The `from_rdsap_schema_17_0` path hardcoded `sap_heating.secondary_heating_type`
and `secondary_fuel_type` to None, unlike every other API path (19.0/20.0/…),
which read them from `schema.sap_heating`. The gov EPC API *does* populate a
secondary heating SAP code for a genuine fixed secondary (e.g. 691 "electric
room heaters", 694), so the hardcode silently discarded it.

Because `recommend_secondary_heating_removal` gates purely on
`sap_heating.secondary_heating_type`, any 17.0 cert carrying a fixed secondary
would never get its removal recommendation. Surfaced while auditing portfolio
814's recommendations; 814 has 17.0 certs but none with a fixed secondary, so
the defect was latent there — this restores parity with the other paths so it
cannot bite.

Mirrors the 19.0 path exactly (secondary_fuel_type via `_api_secondary_fuel_type`).
Adds a regression guard that injects a fixed secondary into a real 17.0 cert and
asserts the code survives the mapping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:41:52 +00:00
Daniel Roth
490499d2a9 Rename SapEnergySource.mains_gas to gas_connection_available 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 10:40:23 +00:00
Daniel Roth
9835b7115c On-gas-street electric dwelling (API fuel code 29) is offered HHRSH 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 10:38:30 +00:00
Daniel Roth
5d99956133 On-gas-street electric dwelling (API fuel code 29) is offered HHRSH 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 10:36:52 +00:00
KhalimCK
2d3067c0e6
Merge pull request #1377 from Hestia-Homes/fix/1376-roof-party-ceiling-guard
Guard party-ceiling roof overrides so they never score as external roofs (#1376)
2026-07-01 11:27:53 +01:00
Khalim Conn-Kowlessar
32e296ca3f Re-classify flat-roof overrides with a known depth onto their thickness member 🟩
One-time script (dry-run default, --apply in a transaction, idempotent) mapping a
flat roof's stated depth (flat: Nmm) onto the nearest Table 16 rung member so the
overlay scores it by thickness, not the age-band default. Updates property_overrides
(TEXT) immediately; the roof_type pgEnum cache writes are deferred until the FE adds
the FLAT_*MM members. Dry-run against the audited DB reports 102 rows, deferring
Flat 50/100/150 mm.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:19:09 +00:00
Khalim Conn-Kowlessar
acf05584d6 Add flat-roof insulation-thickness taxonomy members lock-step with the overlay 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:16:35 +00:00
Khalim Conn-Kowlessar
463d4df048 Carry a flat roof's known insulation depth into the overlay 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:14:53 +00:00
Khalim Conn-Kowlessar
736b5877e9 Carry a flat roof's known insulation depth into the overlay 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 10:13:31 +00:00
Daniel Roth
266a276dae revert changes 2026-07-01 09:52:06 +00:00
Daniel Roth
d4f735e096 Broaden mains_gas comment to cover all non-gas heating fuels, not just electric
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 09:48:22 +00:00
Khalim Conn-Kowlessar
9af90aa718 Re-classify party-ceiling roof overrides mis-read as external roofs 🟩
One-time script (dry-run default, --apply in a transaction, idempotent) that maps
every party-ceiling override (another/same dwelling or premises above) currently
stored as an external roof value onto the party-ceiling member, reusing the live
roof_party_ceiling_guard so the backfill and the classifier cannot drift. Updates
property_overrides (TEXT, the modelling read path) and the roof classifier cache;
dry-run against the audited DB reports 106 rows. No FE migration — the party-
ceiling values already exist in the roof pgEnum.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:46:01 +00:00
Daniel Roth
5a537df14b HHRSH offered to solid-biomass dwelling with mains_gas=True despite off-gas heating fuel 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 09:42:32 +00:00
Khalim Conn-Kowlessar
3987ca4667 Guard the roof classifier so party ceilings never classify as external roofs 🟩
Wires GuardedColumnClassifier(roof_party_ceiling_guard, <llm>) into the roof_type
column so a party-ceiling marker (another/same dwelling or premises above), with or
without a trailing depth, deterministically resolves to its party-ceiling member
(no overlay, ~0 heat loss) instead of the LLM occasionally reading it as a pitched
loft (#1376).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:41:45 +00:00
Daniel Roth
0192dd8efd HHRSH not offered to solid-biomass dwelling with mains_gas=True despite off-gas heating fuel 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 09:41:09 +00:00
Khalim Conn-Kowlessar
0a9d835e66 Let a deterministic guard override the fallback classifier per description 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:39:50 +00:00
Khalim Conn-Kowlessar
4396e5fb22 Let a deterministic guard override the fallback classifier per description 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:39:16 +00:00
Khalim Conn-Kowlessar
fe663deef5 Leave a genuine (non-party-ceiling) roof description to the LLM classifier 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:38:03 +00:00
Khalim Conn-Kowlessar
3aa5dfc45f Resolve every party-ceiling marker variant to its member 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:37:41 +00:00
Khalim Conn-Kowlessar
7f00ee69e1 Resolve every party-ceiling marker variant to its member 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:37:21 +00:00
Khalim Conn-Kowlessar
87d0cc41ab Resolve a party-ceiling roof marker to the party-ceiling member 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:36:28 +00:00
Khalim Conn-Kowlessar
6fc10683d2 Resolve a party-ceiling roof marker to the party-ceiling member 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:35:24 +00:00
Khalim Conn-Kowlessar
cba536eba8 Record flat-roof-thickness and glazing-reconcile decisions (ADR 0041/0042)
ADR-0041: flat roofs ARE scored by insulation thickness via RdSAP Table 16
col (1) ('joists at ceiling level and flat roof'); the RoofType taxonomy lacks
flat-thickness members so the depth is discarded — fix needs new FLAT_*MM members
(FE-owned pgEnum). ADR-0042: a landlord glazing override reconciles against the
cert's per-window sap_windows composition rather than flattening every window to
one type; mixed-and-close defers to the cert, mixed-and-far is flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 09:22:13 +00:00
Daniel Roth
a8821c9cdb
Merge pull request #1370 from Hestia-Homes/feature/ventilation-audit-changes
Ventilation audit changes: directly populate Total Effective Area for trickle vents from form data, rather than calculating it
2026-07-01 09:20:54 +01:00
Daniel Roth
db27a6153f
Merge pull request #1374 from Hestia-Homes/audit/bad-lodged-source-data
fix(audit): Class C — silence effective-lodged-divergence for implausible lodged scores (#1361)
2026-07-01 09:15:45 +01:00
Daniel Roth
7f63702295
Merge pull request #1369 from Hestia-Homes/audit/ara-newest-plan-guardrails
Guard the Ara portfolio audit against the 26m-row recommendation seq-scan
2026-07-01 08:52:27 +01:00
Daniel Roth
c73846b448 Merge branch 'main' into audit/bad-lodged-source-data 2026-07-01 07:49:21 +00:00
Daniel Roth
0c701ba3de
Merge pull request #1373 from Hestia-Homes/fix/1361-class-b-predicted-null-lodged
Drop the phantom Lodged Performance on predicted Properties (#1361 Class B)
2026-07-01 08:35:58 +01:00
Daniel Roth
db66b3b273
Merge pull request #1372 from Hestia-Homes/fix/1361-class-a-heating-classification-taxonomy
Fix PRD #1361 Class A: complete the landlord-heating classification taxonomy
2026-07-01 08:16:45 +01:00
Khalim Conn-Kowlessar
09b3bc98ba Document the nullable lodged_* migration for the FE/Drizzle owner
Specifies the ALTER ... DROP NOT NULL on the four lodged_* columns (#1361) and
the ordering constraint: it must land before the backend writes NULL or runs the
backfill, else the predicted-Property INSERT aborts the batch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:19:54 +00:00
Khalim Conn-Kowlessar
7e06aa63c6 Backfill the phantom Lodged Performance on predicted Properties to NULL 🟩
One-time script (dry-run default, --apply in a transaction, idempotent) that
NULLs the four lodged_* columns on every predicted-source baseline row — a
predicted EPC exists and no lodged one does — leaving Effective, the bill block,
and rebaseline_reason intact. Dry-run against the audited DB reports 12,236 rows.
Must run after the FE-owned Drizzle ALTER ... DROP NOT NULL lands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:17:57 +00:00
Khalim Conn-Kowlessar
b9bec18f44 Round-trip a null Lodged Performance through persistence 🟩
The four lodged_* columns are nullable as a unit; from_domain writes them all
NULL when a predicted Property has no Lodged Performance, and to_domain
reconstructs lodged=None (lodged_sap_score is the read discriminator, mirroring
the bill block). The production lodged_* columns are FE-owned (Drizzle) and need
a companion ALTER ... DROP NOT NULL migration before the backend writes NULL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:13:04 +00:00
Khalim Conn-Kowlessar
da805bce21 Persist no Lodged Performance for a predicted Property 🟩
The PropertyBaselineOrchestrator now reads no Lodged Performance off a predicted
Property's neighbour-synthesised EPC: lodged is None when source_path is
'predicted', so no phantom lodged figure is manufactured. The Effective half is
unchanged. Rebaseliner port + PropertyBaselinePerformance.lodged widen to
Optional; the pristine-cert paths assert non-None (lodged is None only for a
predicted Property, which is always physical_state_changed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:10:57 +00:00
Khalim Conn-Kowlessar
5d63118d5a Persist no Lodged Performance for a predicted Property 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:07:27 +00:00
Khalim Conn-Kowlessar
7ecb7eebd1 Record that a predicted Property has no Lodged Performance
Amends ADR-0004's both-halves-always-populated invariant: EPC Prediction
borrows a neighbour's recorded figures, so a predicted Property has no Lodged
Performance — its lodged half is absent (NULL), only the Effective half is
persisted. Sharpens the CONTEXT.md glossary for Lodged / Baseline Performance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 22:07:27 +00:00
Khalim Conn-Kowlessar
585c8b1501 One-time script to re-classify stale heating overrides
Deterministic catalogue remap (no LLM) that re-resolves the stored archetype for
the canonical RdSAP heating descriptions the under-populated taxonomy
mis-classified. Dry-run by default; --apply writes inside a transaction;
idempotent. Updates property_overrides.override_value (TEXT — what the modelling
reads, the actual band-G fix: 3,028 rows incl. 2,210 community boilers + 770
panel/convector room heaters). Cache (the Drizzle-owned main_heating_system
pgEnum) updates are deferred per-value until the FE-repo enum migration adds the
new archetypes — surfaced explicitly by the script.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:30:59 +00:00
Khalim Conn-Kowlessar
478f459e6c Recognise community CHP and boilers as a heat-network system 🟩
Covers the 10 audited "community CHP and boilers" properties (302) alongside the
2,210 "community boilers" (301) — both were mis-bucketed to Gas CPSU.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:16:15 +00:00
Khalim Conn-Kowlessar
2fab2ad82e Recognise community CHP and boilers as a heat-network system 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:15:38 +00:00
Khalim Conn-Kowlessar
ba258d6018 Drag a gas room heater's coherent companions 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 18:08:51 +00:00
Khalim Conn-Kowlessar
c2a842e9b9 Drag a gas room heater's coherent companions 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 18:04:30 +00:00
Khalim Conn-Kowlessar
42e9dafd0b Recognise gas room-heater variants by their SAP codes 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 18:03:57 +00:00
Khalim Conn-Kowlessar
60e27c80a1 Recognise gas room-heater variants by their SAP codes 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 18:03:07 +00:00
Khalim Conn-Kowlessar
1d0633f4a5 Drag an oil room heater's coherent companions 🟩
Generalise the room-heater category-10 + conservative-control drag to cover both
solid and oil families; oil's natural fuel is heating oil (28).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:57:04 +00:00
Khalim Conn-Kowlessar
34302adce5 Drag an oil room heater's coherent companions 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:55:07 +00:00
Khalim Conn-Kowlessar
efa3a588df Recognise a modern oil room heater as its own archetype 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:54:38 +00:00
Khalim Conn-Kowlessar
fe97a7fc1c Recognise a modern oil room heater as its own archetype 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:53:54 +00:00