Commit graph

7281 commits

Author SHA1 Message Date
Khalim Conn-Kowlessar
390df5a6bd Default a solid-fuel room heater's natural fuel to house coal 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:54:07 +00:00
Khalim Conn-Kowlessar
d5927c68a9 docs: ADR-0041 amendment — natural-fuel coherence
Record the natural-fuel drag-along rule the overlay now implements: drag a fuel
only where the archetype is unambiguous (electric/gas), leave ambiguous
solid/oil room heaters to the main_fuel override, let a present main_fuel
override win by last-wins composition, and LOG (not raise) a landlord fuel that
contradicts the archetype's natural fuel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:46:56 +00:00
Khalim Conn-Kowlessar
d8acc9baa5 Drag electricity as an electric room heater's natural fuel 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:46:18 +00:00
Khalim Conn-Kowlessar
5a29238480 Drag electricity as an electric room heater's natural fuel 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:45:20 +00:00
Khalim Conn-Kowlessar
0cd30a13e6 Drag a solid-fuel room heater's coherent room-heater companions 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:44:04 +00:00
Khalim Conn-Kowlessar
d5280e9d96 Drag a solid-fuel room heater's coherent room-heater companions 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 16:42:48 +00:00
Daniel Roth
afe1801273 implausible-lodged-score check fires for bad upstream EPC data (lodged < 13, gap >= 15) 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 15:27:19 +00:00
Daniel Roth
e70df63ee6 implausible-lodged-score check fires for bad upstream EPC data (lodged < 13, gap >= 15) 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 15:26:29 +00:00
Daniel Roth
fe1d04983b effective-lodged-divergence is silent for implausible lodged scores (< 13) 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 15:25:02 +00:00
Daniel Roth
cf097afc00 effective-lodged-divergence is silent for implausible lodged scores (< 13) 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 15:24:22 +00:00
Khalim Conn-Kowlessar
f097561160 Recognise a solid-fuel room heater as its own heating archetype 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 14:44:30 +00:00
Khalim Conn-Kowlessar
d51154fe73 Recognise a solid-fuel room heater as its own heating archetype 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 14:43:24 +00:00
Khalim Conn-Kowlessar
72e1e67c6d docs: ADR-0041 — landlord-heating classification targets a complete taxonomy
grill-with-docs output for PRD #1361 Class A. The band-G baselines are not a
fabric/rebaseline bug (walls are correct — landlord asserted as-built); they are
a target-vocabulary gap in the landlord-description heating classifier. The LLM
maps unbounded free-text onto a closed internal taxonomy, but that taxonomy had
9 archetypes vs ~13 RdSAP families, so it overflowed into "Gas CPSU"/storage
(the "convector" collision sent direct-acting room heaters to off-peak storage
403 → SAP ~10).

- ADR-0041: fix the taxonomy not the mapper; unmapped input -> None (keep lodged
  EPC, surface to user), never a forced archetype; heat pumps modellable via a
  default Table 4a code (no PCDB id); community heating via codes 301/302/304
  with a documented DLF-1.50 / boiler-source default.
- CONTEXT.md: sharpen Landlord-Description Classification and the four distinct
  vocabularies (landlord / recognised-internal / lodged / SAP code).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 14:33:54 +00:00
Daniel Roth
851f8150b6 Merge branch 'main' into feature/ventilation-audit-changes 2026-06-30 14:08:16 +00:00
Daniel Roth
a7ecb0eaec add local handler and orchestrator 2026-06-30 13:58:41 +00:00
Daniel Roth
78673e96f7 Mapper reads 'Individual Trickle Vent' label variant 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 13:44:38 +00:00
Daniel Roth
33061ba347 Mapper reads 'Individual Trickle Vent' label variant 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 13:43:48 +00:00
Daniel Roth
3461b54498 Mapper falls back to legacy trickle vent label for pre-existing API responses 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 13:34:57 +00:00
Daniel Roth
093563b0c9 Mapper falls back to legacy trickle vent label for pre-existing API responses 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 13:34:06 +00:00
Khalim Conn-Kowlessar
4a110d13cd Guard the portfolio audit against the 26m-row recommendation seq-scan
The `recommendation` table (~26m rows) has no index on `plan_id`, so any query
reaching it via `plan_id` — including the audit's own rollup — seq-scans the
whole table and saturates the shared DB (it blocked the DB during the
portfolio-796 audit). Make the audit safe-by-default:

- statement_timeout (120s) on the audit connection — a hard ceiling so a bad
  plan aborts instead of hammering the DB.
- The recommendation rollup (the two solar checks) is now opt-in via
  --with-recommendations, and EXPLAIN-gated: it refuses to run (raising
  RecommendationScanError) when the plan contains a Seq Scan on recommendation,
  which it does on any large portfolio until idx_recommendation_plan_id exists.
- SKILL.md documents the plan_id-no-index trap, the reach-via-property_id /
  EXPLAIN-first / confirm-with-user rules, and the index as the real fix.

Verified on 796/1268: default run is bounded and completes (2,952 anomalies over
31,919 properties); --with-recommendations aborts pre-scan portfolio-wide but is
allowed for a single property.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 13:23:26 +00:00
Daniel Roth
7fcb64bd8c Door columns shift to Q/R/S/T after column P deletion 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 12:58:46 +00:00
Daniel Roth
372586bb29 Door columns shift to Q/R/S/T after column P deletion 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 12:58:00 +00:00
Daniel Roth
6cb9800608 Mapper reads new 'Total Trickle Vent Effective Area' label 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 12:57:26 +00:00
Daniel Roth
54f045f4c6 Mapper reads new 'Total Trickle Vent Effective Area' label 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 12:56:54 +00:00
Daniel Roth
52749d4931 delete redundant column from spreadsheet 2026-06-30 12:53:29 +00:00
Daniel Roth
550b2ae5e6 revert changes 2026-06-30 11:34:16 +00:00
KhalimCK
ee9a1c4d90
Merge pull request #1364 from Hestia-Homes/audit/schema-mapping-gaps
Audit other schema mappers for the meter/PV drop class — fix full-SAP 18-hour tariff
2026-06-30 11:08:23 +01:00
Daniel Roth
d623a29c2d Merge branch 'main' into audit/schema-mapping-gaps 2026-06-30 10:00:33 +00:00
Daniel Roth
1f0fffe8af Write total trickle vent area to column O; shift door columns to Q/R/S/T 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 09:59:37 +00:00
Daniel Roth
367fd3664b Write total trickle vent area to column O; shift door columns to Q/R/S/T 🟥
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 09:37:55 +00:00
Daniel Roth
fad7bd6e96
Merge pull request #1363 from Hestia-Homes/fix/hyde-portfolio-audit
fix(full-sap): seven mapper/overlay fixes from the portfolio-796 modelling audit
2026-06-30 10:26:17 +01:00
Khalim Conn-Kowlessar
2c851e9e5e Re-baseline pins for full-SAP PV + tariff mapper fixes 🟩
The PV-array (ea7f4f43) and electricity-tariff (6ec09892) mapper fixes shifted
the observed output of five frozen gates that weren't updated alongside:

- has_pv component-accuracy floor 0.9798 -> 0.9697: carrying full-SAP lodged PV
  now reads the true has_pv=True for full-SAP PV dwellings, so the leave-one-out
  scorer's actual changes (ground-truth-method shift, ADR-0037 pattern).
- uprn_10093116528 80->... pin 82 -> 83: tariff=1 (standard) was wrongly read as
  dual/Economy 7; translating to "single" re-prices the gas semi's electricity.
- uprn_10096028301 82 -> 84, uprn_10023444324 80 -> 82 (== lodged 82),
  uprn_10023444320 81 -> 83: now credit the lodged sap_energy_source.pv_arrays
  the schema previously dropped. Comments document the per-cert PV/Elmhurst
  relationship (incl. the mid-floor sibling landing +2 over its lodged integer).

Pre-existing, unrelated failures untouched: the missing
sap_16_0_full_no_floor_dims.json fixture and the RdSAP-21 floor-area test (both
reproduce on origin/main).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 09:18:39 +00:00
Daniel Roth
398016505d
Merge pull request #1362 from Hestia-Homes/audit/portfolio-796-scenario-1268
docs(audit): record stale-default-plan expectation + default-plan-only rule
2026-06-30 08:36:29 +01:00
Khalim Conn-Kowlessar
450ecfb9b4 Lock full-SAP 16.x tariff translation via the assessment_type gate 🟩
Confirming regression test for the prime-lead suspicion (SAP-16.x meter
over-rating). A full-SAP-shaped 16.x cert lodges the SAP energy_tariff code
space; the assessment_type=SAP gate routes it to the full-SAP mapper, which
translates the code (1=standard → STANDARD) rather than raw-passing it to the
RdSAP normaliser (where 1="dual" → SEVEN_HOUR, the over-rating bug). No fix
needed — the gate already prevents the drop; this pins that behaviour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 22:58:35 +00:00
Khalim Conn-Kowlessar
7866b4a34c Translate full-SAP 18-hour off-peak tariff (code 5) to EIGHTEEN_HOUR 🟩
Add code 5 → "off-peak 18 hour" to _SAP_TARIFF_TO_RDSAP_METER_TYPE so the
full-SAP meter translation covers the whole energy_tariff code space, not
just 1-4. Table 12a resolves the word alias to Tariff.EIGHTEEN_HOUR.

Real SAP-19.1.0/19.2.0 sample certs lodge tariff 5 and now resolve to the
18-hour off-peak split instead of defaulting to STANDARD (under/over-rated).
The same fix covers 17.0/17.1/18.0.0/19.0.0 — all route through the full-SAP
mapper via the assessment_type=SAP gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 22:55:40 +00:00
Khalim Conn-Kowlessar
c6c07c2c51 Full-SAP 18-hour off-peak tariff (code 5) must resolve to EIGHTEEN_HOUR 🟥
The full-SAP energy_tariff code space includes 5=off-peak-18-hour, but
_sap_17_1_meter_type only maps 1-4, dropping code 5 to "" → STANDARD.
Real SAP-19.1.0/19.2.0 certs lodge tariff 5, so the 18-hour off-peak
split is silently lost.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 22:50:34 +00:00
Khalim Conn-Kowlessar
0b8765481d Engine now matches lodged 82 on a PV cert (was under-rating to 80) 🟩
Crediting the full-SAP lodged PV closes the 2-point under-rating on uprn
10023444324 — the engine now reproduces the accredited lodged value exactly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 22:01:33 +00:00
Khalim Conn-Kowlessar
ea7f4f4329 Carry full-SAP lodged PV arrays through to the domain 🟩
Full-SAP certs lodge measured PV under sap_energy_source.pv_arrays, but the
SAP-Schema-17.1 SapEnergySource modelled only wind, so from_dict dropped it at
parse and the mapper hardcoded no PV. A new SapPvArray schema field + the
_sap_17_1_pv_arrays mapper helper carry it to the domain photovoltaic_arrays the
Appendix-M generation credit reads — without it an all-electric dwelling the
array lifts to A/B is mis-modelled down a band or more.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 21:59:21 +00:00
Khalim Conn-Kowlessar
4393812638 Carry full-SAP lodged PV arrays through to the domain 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 21:51:09 +00:00
Khalim Conn-Kowlessar
e02e6a76e1 Preserve an existing more-off-peak cert meter under a heating overlay 🟩
A landlord heating override DESCRIBES the dwelling, so its assumed off-peak meter
(Dual/E7) is a coherent default — it must not downgrade a cert that already
lodges a more-off-peak meter (e.g. property 709874's 24-hour all-low tariff). The
overlay opts in via keep_existing_off_peak_meter; _fold_heating then keeps the
cert's meter when both it and the desired meter are off-peak. Heating MEASURES
build HeatingOverlay directly and leave the flag False, so they still re-meter
for real (Elmhurst re-lodges 18-hour -> Dual on a storage install) — the cascade
pins stay green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 20:32:31 +00:00
Khalim Conn-Kowlessar
e3c023e0f6 Preserve an existing more-off-peak cert meter under a heating overlay 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 20:00:41 +00:00
Khalim Conn-Kowlessar
6279924773 Stop a System-built landlord override being mis-read as a basement 🟩
System-built is RdSAP code 6, colliding with the gov-EPC code-6 basement
sentinel that main_wall_is_basement falls back to. The wall overlay now pins
wall_is_basement=False for system-built, mirroring the gov-API mapper's
_clear_basement_flag_when_system_built, so the override no longer adds a phantom
basement (which inflated both wall and ground-floor heat loss).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:37:11 +00:00
Khalim Conn-Kowlessar
da17ddce8f Stop a System-built landlord override being mis-read as a basement 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:30:25 +00:00
Khalim Conn-Kowlessar
6ec0989283 Translate full-SAP electricity tariff into the RdSAP meter type 🟩
Full-SAP energy_tariff (1=standard/2=7hr/3=10hr/4=24hr) and RdSAP meter_type
(1=dual/2=single/3=unknown/4=24hr) are different code spaces; the mapper passed
the code through untranslated, reading standard-tariff full-SAP certs as Economy 7
(over-rated) and Economy-7 certs as single (under-rated). Map onto the RdSAP word
aliases so the resolved Table 12a tariff is correct; absent/ND -> unknown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 18:54:51 +00:00
Khalim Conn-Kowlessar
a764b5fa9c Translate full-SAP electricity tariff into the RdSAP meter type 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 18:45:27 +00:00
Khalim Conn-Kowlessar
4e96ea91a5 Assume a dual Economy-7 meter for all-electric room-heater dwellings 🟩
Electric room heaters (691) get a Dual meter from the overlay (not single-rate):
an all-electric room-heater dwelling realistically bills on Economy 7, and the
§12 dispatch then applies a high/low split rather than a single-rate over-penalty.
Overlay owns its assumed-meter policy via _ASSUMED_DUAL_METER_CODES (the §12
off-peak systems + room heaters), keeping OFF_PEAK_IMPLYING_HEATING_CODES pure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:18:13 +00:00
Khalim Conn-Kowlessar
13f1981776 Assume a dual Economy-7 meter for all-electric room-heater dwellings 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:15:48 +00:00
Khalim Conn-Kowlessar
54acc0388b docs(audit): record stale-default-plan expectation + default-plan-only rule 🟪
Portfolio-796/scenario-1268 audit found the bulk of MEDIUM/HIGH anomalies
(already-meets-goal-with-works, zero-works-post-differs, plan-score-below-
baseline, and the non-fuel-switch slice of negative-bill-savings) trace to one
root cause: the persisted default plan is stale relative to the live model, so
it resolves on re-model rather than a code change. Confirmed via
run_modelling_e2e on three samples (stored vs live plans differ wholesale).

No new check added — the staleness is already surfaced by the existing checks
and addressed by the override-aware-rebaseline / persistence-fidelity work, so
a new check would only re-flag known divergence. Instead record the expectation
and the "audit the default plan only" rule in the skill Notes so the next
reviewer starts ahead. References kept to durable docs/adr (no PR numbers).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:08:17 +00:00
Khalim Conn-Kowlessar
4b2f406b6c Add Electric room heaters as a canonical landlord heating archetype 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:01:07 +00:00
Khalim Conn-Kowlessar
2b0b7eff91 Add Electric room heaters as a canonical landlord heating archetype 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 16:00:36 +00:00