Commit graph

133 commits

Author SHA1 Message Date
Jun-te Kim
3f6f17bb85 fix merge conflicts 2026-06-23 16:51:06 +00:00
Jun-te Kim
0401797524 sap fixes 2026-06-23 16:48:04 +00:00
Daniel Roth
a4aaf0e81f Merge branch 'main' into trigger-e2e-locally 2026-06-23 16:38:03 +00:00
Daniel Roth
79a76b10a9 fix db issues 2026-06-23 16:36:59 +00:00
Jun-te Kim
8f0432721c test(accuracy): pin RdSAP-20.0.0 PV semi uprn_22086693 (PV-list fix corpus)
Corpus validation of the modelling_e2e photovoltaic_supply-as-list fix. Cert
6102-6227-8000-0083-2292 (RdSAP-20.0.0 semi, gas combi + 2× 1.14 kW PV arrays)
crashed from_rdsap_schema_20_0_0 on the measured-array list; the fix routes it
through the dict-tolerant _map_schema_21_pv. PV correctly credited: engine 61
(no PV) → 66 (+5). Built in Elmhurst (evidence: epc.json + summary + worksheet,
fabric+heating; the PV "New Technologies" Panel-details grid deferred): worksheet
55 = engine-on-Elmhurst-inputs 55 exactly → calculator faithful. The +6 engine-vs-
Elmhurst base-dwelling residual is the documented RdSAP-default gap (band-C cavity-
uninsulated suspended-floor semi). Pinned engine 66.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:13:34 +00:00
Jun-te Kim
a7d3e00178 32 2026-06-23 15:42:00 +00:00
Jun-te Kim
75341da42d 32 2026-06-23 15:38:38 +00:00
Jun-te Kim
17b1d63f0e test(accuracy): pin SAP-16.0 storage-flat uprn_10070004512 (built_form fix corpus)
Corpus validation of the modelling_e2e built_form fix. Cert 8742-6624-9300-2780-4926
(SAP-Schema-16.0, ground-floor electric-storage-heater flat) omits built_form; the
mapper now derives it from dwelling_type. built_form is ML-only so the fix is
SAP-neutral: engine 66 = lodged 66 exactly. Built in Elmhurst (evidence: epc.json +
summary + worksheet): worksheet 54, engine-on-Elmhurst-inputs 53 ≈ 54 → calculator
faithful. The +12 engine-vs-Elmhurst is a build/input gap (cert size-1 small cylinder
unrepresentable in Elmhurst's Normal/110L-minimum entry → higher HW + reduced-field
16.0 defaults). Pinned engine 66.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 15:35:06 +00:00
Daniel Roth
cbc14f1ca2 better tracking of already processed properties 2026-06-23 14:09:59 +00:00
Daniel Roth
aa92ffaac1 Merge branch 'main' into trigger-e2e-locally 2026-06-23 13:41:29 +00:00
Jun-te Kim
00af7b5a54 data types 2026-06-23 12:42:53 +00:00
Daniel Roth
f20646d774 missing files 2026-06-23 12:25:52 +00:00
Daniel Roth
901b74ae7c udpate 2026-06-23 12:25:43 +00:00
Khalim Conn-Kowlessar
52e5a4d402 Merge remote-tracking branch 'origin/main' into feature/e2e-runs 2026-06-23 11:05:15 +00:00
Khalim Conn-Kowlessar
efaff228ac feat(scripts): add --from-db re-model path + raise EPC API timeout
- run_modelling_e2e --from-db re-models from already-persisted inputs (reads
  each Property's Effective EPC + planning protections + solar from the DB) and
  skips every live fetcher — zero gov-API calls. With --persist it re-writes the
  Plan and, for lodged-EPC Properties, the Baseline. Self-contained loop; the
  live-fetch path is untouched. Makes local re-runs instant and avoids tripping
  the gov API's per-IP rate limit (6000 req / 5 min) during iteration.
- EpcClientService.REQUEST_TIMEOUT 10s -> 30s: a cold per-UPRN search can exceed
  10s and the old timeout turned it into a timeout-then-retry; 30s rides it out.

Note: an open perf question remains — modelling is fast in isolation (<0.5s/
property) but a long-lived --persist run shows ~1 min/property; suspected in the
persist path (plan.save / baseline) or connection handling, NOT the API. Left
mid-diagnosis for handover.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:05:06 +00:00
Daniel Roth
78c358d5e8 tweak script to use provided input. track output in md file 2026-06-23 10:27:39 +00:00
Jun-te Kim
210ca6397f updated sap scaema to take in inputs 2026-06-23 10:22:40 +00:00
Daniel Roth
625edbefa4 trigger workflows 2026-06-23 08:26:19 +00:00
Khalim Conn-Kowlessar
4ce2a71871 feat(scripts): one-pass e2e run — baseline + plans + prediction + recovery
Make run_modelling_e2e the single script that does everything for a portfolio,
so the 291-property run needs one invocation with per-property recovery (no
all-or-nothing chunking):

- On --persist, a lodged-EPC Property now also gets its Baseline Performance
  row written via PropertyBaselineOrchestrator (per Property, so one bad cert
  does not abort the batch). Predicted (EPC-less) Properties have no lodged
  figures, so they get a Plan but no baseline row.
- The run CSV gains api_sap (register) vs baseline_sap (calculator) + sap_delta,
  so calculator-vs-API divergence is reviewable per property.

Fill the off-catalogue overlay for the measures the live material catalogue
cannot price, so they stop crashing the run:

- double_glazing (£550/window) and secondary_glazing (£400/window): priced
  per window (the generator multiplies by single-glazed window count, matching
  the legacy window_glazing). Grounded in 2025/26 UK installed costs; per-window
  is the right unit for windows (fixed per-unit install dominates) — per-m2 fits
  walls/floors, not glazing.
- gas_boiler_upgrade / system_tune_up / system_tune_up_zoned: these are priced
  off the heating rate sheet (Products()), with get() reading the catalogue only
  for an id — so the overlay entry exists to satisfy that lookup (material_id
  stays None, as with ASHP); the rate sheet remains authoritative.

Validated on a 12-property sample (incl. a secondary-glazing case and a
SAP-Schema-16.2 cert): 12/12 baseline rows + plans, 0 errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 08:24:03 +00:00
Khalim Conn-Kowlessar
564a2ee78f Merge remote-tracking branch 'origin/main' into feature/e2e-runs
# Conflicts:
#	scripts/run_modelling_e2e.py
2026-06-23 07:49:22 +00:00
Daniel Roth
f1a2bbc467 list of properties when triggering locally 2026-06-22 16:13:10 +00:00
Daniel Roth
5ecb47d46c Merge branch 'main' into feature/trigger-e2e-lamnda 2026-06-22 14:55:16 +00:00
Jun-te Kim
9c89a0e680 neighbouring properties added 2026-06-22 14:38:00 +00:00
Daniel Roth
d05e5bd1f3 new application to trigger e2e for a single property and scenario 2026-06-22 12:54:53 +00:00
Jun-te Kim
1b53c57a07 re run ddd tests 2026-06-22 08:52:45 +00:00
Jun-te Kim
a3e2566378 landlord override data added 2026-06-20 12:57:54 +00:00
Jun-te Kim
abd4bbc2d0 Merge branch 'feautre/hyde_upload_and_extend_landlord_overrides' into feature/hyde_make_it_more_accurate_with_tests 2026-06-20 07:26:35 +00:00
Jun-te Kim
3044c70202 sap score and elmhirst mapper optimsaiation 2026-06-20 07:25:42 +00:00
Jun-te Kim
6c0545a8ee Add resume prompt to finish portfolio-796 run after Khalim review 📝
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:58:53 +00:00
Jun-te Kim
36b8b7a939 Add Hyde portfolio-796 unknowns review doc for Khalim sign-off 📝
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:57:34 +00:00
Jun-te Kim
c1ab179d51 Add Hyde property_overrides build script + creds-free smoke test 🟩
Two-pass org_ref-matched builder for property_overrides (classify via ChatGPT
into the landlord ledger, validate+apply user edits, write idempotently);
ephemeral-Postgres smoke proves the one-property chain without creds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:02:42 +00:00
Jun-te Kim
e03fd27357 Type-clean the override_component consistency guard 🟪
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:19:07 +00:00
Khalim Conn-Kowlessar
11393e54dc feat(modelling): price secondary-heating-removal from an off-catalogue overlay
The FE-owned `material.type` pgEnum cannot carry `secondary_heating_removal`,
so pricing it through the DB catalogue raises a DataError that poisons the
session — the modelling pipeline crashed on any property with a lodged
secondary heater unless the measure was excluded on the Scenario.

Realise the `ProductRepository` docstring's intent (DB catalogue today, a JSON
file for costs the ETL does not yet supply, behind the same port): add a
`CompositeProductRepository` that resolves an override source first, then the
catalogue. Checking the override first keeps that Measure Type away from the DB
entirely; every other type misses the override and falls through unchanged.

- off_catalogue_costs.json prices it at £270 flat per-dwelling — the legacy
  `Costs.heater_removal` ported to the new flat model (ADR-0028):
  (£25 + £200 baseline) x 1.2 VAT, for the single fixed secondary a cert lodges.
  Contingency (0.25) is joined from config, not the file.
- Wire the composite into PostgresUnitOfWork.product and run_modelling_e2e, so
  the first-run pipeline and the local runner both honour the overlay.
- Integration test: drop the unrealistic seeded secondary_heating_removal DB
  rows (the pgEnum can't hold the type) and assert it is JSON-sourced
  (material_id is None, cost £270) end-to-end through a real Unit of Work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 14:49:51 +00:00
Jun-te Kim
0e85da1507 Resolve a landlord mains-gas override to the primary fuel code 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:15:54 +00:00
Jun-te Kim
37b0a38425 add more test cases 2026-06-19 10:59:51 +00:00
Jun-te Kim
e6a829aaea more examples 2026-06-19 09:51:49 +00:00
Khalim Conn-Kowlessar
a7de8c5c35 Merge remote-tracking branch 'origin/main' into feature/per-cert-mapper-validation 2026-06-18 15:00:32 +00:00
Khalim Conn-Kowlessar
6950deae06 chore(scripts): triage PE/CO2 on the demand cascade in the corpus profilers
`profile_corpus_error.py` and `dive_cert.py` compared our PE/CO2 against
the lodged EPC figures using the UK-average RATING cascade, but the EPC
lodges CO2/PE on the postcode DEMAND cascade (SAP 10.2 Appendix U p.124,
now wired into Sap10Calculator.calculate in fc7c4d2d). That confounded the
DEMAND-vs-COST triage: a cert whose demand actually reproduced on local
weather looked "PE off" purely from the climate difference and was
mislabelled DEMAND-side. Switching the PE/CO2 lens to `cert_to_demand_
inputs` (SAP still from the rating cascade) re-classifies the corpus
outside-0.5 set 261/42 -> 211/92 DEMAND/COST — ~50 certs are genuinely
cost-side (e.g. 10091578598: SAP +7.81 but PE +1.6 / CO2 -0.04). Sharpens
the hunt for the subtle widespread SAP term.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:21:00 +00:00
Khalim Conn-Kowlessar
26106505be chore(scripts): add corpus SAP-accuracy profiler + per-cert dive tools
profile_corpus_error.py buckets signed SAP error by raw-API feature and
lists worst over/under-raters with the PE/CO2-vs-cost split (COST-side vs
DEMAND-side triage). dive_cert.py dumps one cert's lodged-vs-ours
SAP/CO2/PE + full intermediate line refs + mapped inputs. Both run on the
committed RdSAP-21.0.1 corpus (no /tmp sample needed). Used to find the
stone-wall, per-part-roof, ground-floor-flat and HP-water fixes this session.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:48:12 +00:00
Jun-te Kim
7f8bfa5d06 move overlas to its own thing 2026-06-18 10:04:14 +00:00
Jun-te Kim
1d392d8d87 ll overrides@ 2026-06-17 18:56:57 +00:00
Jun-te Kim
5939520b0d Add a cell-by-cell inspector for landlord-override → effective-EPC mapping
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:04:44 +00:00
Jun-te Kim
86b5387a05 Show lodged vs effective main wall per property in the modelling e2e run
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:15:46 +00:00
Jun-te Kim
d08c35ee03 Merge branch 'feature/hyde_make_it_more_accurate_with_tests' into feature/landlord-overrides 2026-06-17 09:43:28 +00:00
Jun-te Kim
d87718f316 Merge remote-tracking branch 'origin/main' into feature/hyde_make_it_more_accurate_with_tests
# Conflicts:
#	datatypes/epc/domain/mapper.py
2026-06-17 09:05:37 +00:00
Jun-te Kim
70ca56415e Merge branch 'main' of https://github.com/Hestia-Homes/Model into feature/landlord-overrides 2026-06-17 08:50:52 +00:00
Khalim Conn-Kowlessar
ea72ee97bf feat(scripts): add full AraFirstRunPipeline local runner
scripts/run_first_run_e2e.py runs the real Ingestion -> Baseline -> Modelling
pipeline against the DB by composing build_first_run_pipeline + dispatch_first_run
with the live source clients (the Lambda handler can't run locally — its
_source_clients_from_env still raises, #1136). Unlike run_modelling_e2e it runs
real ingestion (persists EPC/spatial/solar) and has no inspect-only mode, so it's
gated behind --confirm (preview otherwise); measure scoping comes only from the
Scenario's exclusions (the pipeline threads no --measures), and the modelling
batch is all-or-nothing, both documented.

Extract the shared env/engine/S3 plumbing into scripts/e2e_common.py (public
load_env/build_engine/s3_parquet_reader) so both runners share one source and
neither imports the other's privates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 23:45:23 +00:00
Khalim Conn-Kowlessar
694cdd9c23 feat(modelling): mark a Property as run via has_recommendations + updated_at
The new pipeline left no per-Property record of a run (the old engine set
property.has_recommendations and populated property_details_epc). Restore the
marker: PropertyRepository.mark_modelled sets has_recommendations (true when the
Plan carries measures, mirroring the old engine) and bumps updated_at, so a
first-run under the new process is identifiable as updated_at >= 2026-06-01.

ModellingOrchestrator marks each Property after its Scenarios (true if any
Scenario yielded a measure); run_modelling_e2e's --persist path marks it too
(its compute runs on in-memory fakes, so the DB UoW sets it directly). Adds the
has_recommendations/updated_at columns to the PropertyRow mirror.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 23:34:33 +00:00
Jun-te Kim
5669676917 Annotate full worklist with autonomous-run triage results
Every worklist UPRN now carries schema · engine SAP / lodged · flag. Tally:
64 healthy, 19 MVHR-not-credited (🚩 flag B), 6 heat-pump fuel-39 (🚩 flag A),
4 sparse/NOT MAPPABLE (), 3 Elmhurst-pinned. MVHR is the largest accuracy gap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:36:28 +00:00
Jun-te Kim
b68710c98f Flag heat-pump fuel-39 + MVHR-heat-recovery gaps for manual review
Autonomous-run triage of the moderate eng-vs-lodged gaps resolves them into two
patterns, both flagged for owner review (not auto-fixable):
- Heat-pump fuel code 39 mis-priced as gas (over-rates; both gap directions).
- MVHR heat recovery modelled as plain extract loss → systematic UNDER-rating
  (~8-12 SAP) on every full-SAP cert carrying a mechanical_vent_system_index_number.
  New memory mvhr-heat-recovery-not-modelled; needs the Appendix Q / PCDB MVHR
  efficiency model.
findings doc updated with the classification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:23:59 +00:00