Commit graph

173 commits

Author SHA1 Message Date
Daniel Roth
8b7d32433e
Merge pull request #1492 from Hestia-Homes/feature/abri-api-integration
Abri API integration: abandon job
2026-07-08 10:53:21 +01:00
Daniel Roth
84d0e1e0d5 Date an abandonment to the deal's own dates, not now() 🟩
date_abandoned now resolves to the third failed attempt's confirmed
survey date, falling back to its last submission date, rather than the
processing date. This dates the OpenHousing cancellation to when the
job actually lapsed even if the trigger message lags or redelivers.

- domain: abandonment_date() encodes the confirmed-survey -> last-
  submission fallback
- DealAbandonment carries both dates; abandon_job raises
  AbandonmentDateUnknownError when a deal has neither
- last_submission_date now flows through the trigger message and request
- the injected clock is dropped: nothing reads now() any more

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:51:39 +00:00
Khalim Conn-Kowlessar
8dd125f199 Review nitpicks: pids_with_default naming, empty-batch guard, truthful fake 🟪
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 16:44:23 +00:00
Khalim Conn-Kowlessar
0eaf6fa99c A property's first plan becomes its default whatever the scenario says 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 16:13:47 +00:00
Daniel Roth
8aa2841546 Dispatch the abandon flow last for a fired deal-change 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 15:46:00 +00:00
Daniel Roth
db5ff971d8 Accept an abandon_job flow carrying the deal outcome 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 15:42:34 +00:00
Daniel Roth
c0e444fccb abri_api not abri 2026-07-07 14:40:33 +00:00
Daniel Roth
1085384f21 Merge branch 'main' into feature/abri-api-integration 2026-07-07 14:08:52 +00:00
KhalimCK
9ff4de0563
Merge pull request #1481 from Hestia-Homes/feature/modelling-trigger-run
Modelling Run Distributor: POST /v1/modelling/trigger-run
2026-07-07 14:36:45 +01:00
Daniel Roth
7ad0dc0595 Merge branch 'main' into feature/abri-api-integration 2026-07-07 12:46:17 +00:00
Khalim Conn-Kowlessar
bf0d630a8f An attach-mode partial failure persists successes then records the failure 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:56:57 +00:00
Khalim Conn-Kowlessar
7709518431 An attach-mode batch models under the supplied sub_task without children 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:53:26 +00:00
Daniel Roth
58199a1c03 The abri lambda dispatches queue messages through the Abri orchestrator 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:21:39 +00:00
Daniel Roth
a33dd43271 One message dispatches the fired Abri flows in a fixed, retry-safe order 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:10:30 +00:00
Daniel Roth
1c5a43df56 One message dispatches the fired Abri flows in a fixed, retry-safe order 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:09:20 +00:00
Daniel Roth
8daaa0974d A trigger message validates the fields each fired Abri flow needs 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:05:25 +00:00
Daniel Roth
c281456164 A trigger message validates the fields each fired Abri flow needs 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:04:55 +00:00
Khalim Conn-Kowlessar
64f7d7ad8b Thread the historic-EPC reader through the first-run composition root 🟩
Off by default like the other two prediction collaborators; the pipeline
turns on Expired-Enhanced Prediction by passing a resolver over the
historic S3 backup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:41:56 +00:00
Daniel Roth
7852928181 delete test data file 2026-07-03 13:38:09 +00:00
Daniel Roth
0c3fbe5853 rename dodgy address 2026-07-03 13:37:58 +00:00
Daniel Roth
87ac00d499 Correct St Helier Avenue spelling to match SharePoint folder names
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 12:14:46 +00:00
Daniel Roth
781251eb07 updated address list 2026-07-03 11:59:01 +00:00
Jun-te Kim
100949073f refetch_solar=False models with stored Solar insights and never calls Google 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 14:21:46 +00:00
Jun-te Kim
0fa47b1047
Merge pull request #1409 from Hestia-Homes/fix/property-type-leading-token-guard
Guard property_type to its leading dwelling-type token
2026-07-02 10:00:03 +01:00
Jun-te Kim
88bae2166f Guard property_type to its leading dwelling-type token
The landlord property-type description is a "<dwelling type>: <built form>: <floor>"
split whose leading token IS the dwelling type; the built-form tail is not. The
LLM occasionally over-read the tail and flipped the type — a handful of
"Bungalow: EndTerrace" / "Bungalow: MidTerrace" dwellings were stored as House.

Adds property_type_guard (claims the recognised leading token: House / Bungalow /
Flat / Maisonette / Park home; defers unrecognised phrasings to the LLM) and wires
property_type through a GuardedColumnClassifier, so the built-form tail can never
flip the type and the live path is deterministic.

Applied the scoped backfill to portfolio 796 (Hyde): 3 rows corrected from House
back to Bungalow. No enum migration needed — the targets are original members.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:24:37 +00:00
Jun-te Kim
5330bc20d9 Add individual wood-logs main-fuel archetype (API 6 / RdSAP Table 32 code 20)
MainFuelType had no individual wood-logs member — only "biomass (community)" —
so the LLM classifier funnelled "Solid Fuel: Wood Logs" into the community fuel,
inventing a community heat network the dwelling isn't on (and mislabelling the
connection). main_fuel had no deterministic guard at all, so nothing caught it.

Verified against domain/sap10_calculator/docs/specs: RdSAP 10 Specification
Table 32 lists "wood logs" as a solid fuel (code 20, 0.028 kgCO2e/kWh); the
calculator's input scheme (the gov EPC API fuel enum) codes it 6 -> Table 32 20
(sap_efficiencies._API_TO_TABLE32), and water_heating_overlay already pins the
same fuel to 6. So _FUEL_CODES["wood logs"] = 6 is confirmed, not guessed.

Adds MainFuelType.WOOD_LOGS + the _FUEL_CODES entry, a main_fuel_guard mirroring
water_heating_guard (claims the "wood log" token; dual fuel keeps its own member
since it has no "wood log" substring), and wires main_fuel through a
GuardedColumnClassifier so the live path is deterministic.

Applied the scoped backfill to portfolio 796 (Hyde): 21 rows off
"biomass (community)" -> "wood logs". property_overrides (TEXT) only; the
classifier-cache pgEnum member is deferred to the FE Drizzle migration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:00:24 +00:00
Daniel Roth
0488696df8
Merge pull request #1397 from Hestia-Homes/fix/1376-hhrsh-baseline-archetype
Add the HHRSH baseline archetype so it stops scoring as old storage (#1376)
2026-07-01 15:41:52 +01:00
Khalim Conn-Kowlessar
598aac1556 Route main-heating overrides through the HHRSH guard before the LLM 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:32:14 +00:00
Khalim Conn-Kowlessar
36ead3ca1d Route water-heating overrides through the deterministic guard before the LLM 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:09:12 +00:00
Khalim Conn-Kowlessar
1500725d1d Guard the glazing classifier so an aggregate mix keeps the cert per-window glazing 🟩
Wires GuardedColumnClassifier(glazing_mix_guard, <llm>) into the glazing column so a
structured percentage mix deterministically resolves to MIXED (no overlay), while
uniform and varied phrasings fall through to the LLM (#1376, ADR-0042).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 11:07:45 +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
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
Khalim Conn-Kowlessar
dbcd2e3840 Run the fuel-mismatch check on every Property's resolved overrides 🟩
Wire flag_fuel_mismatch into the two override-resolution paths (the property
repository and the modelling-e2e handler), keeping overlays_from a pure mapping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:21:32 +00:00
Daniel Roth
a7ecb0eaec add local handler and orchestrator 2026-06-30 13:58:41 +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
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
4764bc7c15 Batch plan saves reduce RDS CPU during bulk modelling runs 🟪
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 15:08:47 +00:00
Daniel Roth
9f0dd067f8 Merge branch 'main' into feature/batch-save-and-delete-epc 2026-06-29 14:38:57 +00:00
Daniel Roth
b1406bb482 Skip re-saving EPC data when it was read from DB unchanged
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 14:03:23 +00:00
Daniel Roth
66fa08af19 update comment 2026-06-29 13:33:48 +00:00
Daniel Roth
0fa1b9001c Batch EPC writes in _flush_writes: two save_batch() calls instead of N save() calls 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 13:09:56 +00:00
Daniel Roth
17a9f0aafc refetch_epc=False skips API entirely; EPC-less properties go straight to prediction path
When refetch_epc=False and no stored lodged EPC exists, the handler no longer
falls back to a live EPC API call — it treats the property as EPC-less and
hands it to the prediction path. This keeps REFETCH_EPC (lodged path) and
REPREDICT_EPC (prediction path) cleanly independent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 10:24:27 +00:00
Daniel Roth
5c3bde0cf5 Update trigger script and local invoker to use refetch_solar, refetch_epc, repredict_epc 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 10:17:20 +00:00
Daniel Roth
a940c94b33 Handler pre-fetches stored EPCs and routes per-property via refetch_epc flag 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 10:13:51 +00:00
Daniel Roth
c51ca47467 Rename no_solar → refetch_solar and add refetch_epc, repredict_epc flags to TriggerBody 🟩
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 10:12:21 +00:00
Khalim Conn-Kowlessar
1e3c401b38 Resolve the Solar throttle gap from env with a 32-wide fallback 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:04:39 +00:00
Khalim Conn-Kowlessar
85e203f366 Resolve the Solar throttle gap from env with a 32-wide fallback 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 16:03:42 +00:00
Jun-te Kim
b1ff711260 perf(modelling_e2e): batch SubTask bookkeeping to stop per-property writes
Even after batching the data writes, the handler still wrote to the DB per
property through the orchestrator's SubTask bookkeeping: create + start +
complete each self-committed, and _cascade re-listed every sibling and re-saved
the parent on every transition — ~5 writes per property plus an O(N^2) cascade.

- TaskOrchestrator.run_subtasks: create all children in one INSERT, run each
  (failures isolated per child), then persist all terminal states in one bulk
  save and cascade the parent once. Children go WAITING -> terminal; the
  transient IN_PROGRESS row is never written.
- SubTaskRepository.create_many / save_many (bulk INSERT / bulk fetch + update).
- _cascade short-circuits when the Task is already FAILED (terminal) — skips the
  sibling roll-up entirely.
- modelling_e2e handler fans out via run_subtasks instead of per-property
  create_child_subtask + run_subtask.

Per N-property batch the SubTask bookkeeping drops from ~5N writes + an O(N^2)
cascade to ~2 writes + 1 cascade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:26:42 +00:00
Jun-te Kim
de5e9a2362 perf(modelling_e2e): bulk reads and batch writes to cut RDS load
The handler fired ~2+2N read round-trips and N+N write transactions per
SQS batch, pinning RDS CPU under ~32 concurrent containers on pool_size=1.

Reads: merge the duplicate property query and add overrides_for_many /
SolarRepository.get_many so overrides, solar, and property rows each load
in one query (2+2N -> 3).

Writes: buffer each modelled property's persistence intent in memory
(_PropertyWrite) during the loop, then flush the whole batch in one
PostgresUnitOfWork with a single commit, and run the baseline orchestrator
once for all written ids (N+N -> 2 transactions). Per-property modelling
failures stay isolated in the loop; the batch write is all-or-nothing and
retried via SQS (saves are idempotent upserts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 18:43:42 +00:00