Commit graph

1006 commits

Author SHA1 Message Date
KhalimCK
22db9c43f3
Merge pull request #1497 from Hestia-Homes/feature/small-roof-solar-min-array
Sub-Ladder PV Configurations: small roofs get the array their caps allow (ADR-0058)
2026-07-08 12:50:41 +01:00
KhalimCK
bd24a789b9
Merge pull request #1498 from Hestia-Homes/feature/bulk-document-download
Bulk Document Download: emailed ZIP of a property set's documents (ADR-0059/0060)
2026-07-08 12:49:46 +01:00
Khalim Conn-Kowlessar
9ec7987e97 PR review: best-effort read path, true per-member streaming, race-safe 409, local email 🟩
Addresses PR #1498 review:
- A per-file read failure (missing/deleted object, or a bucket the role can't
  reach) is now a SkippedDocument(reason=unreadable), not a whole-run abort;
  an all-unreadable selection still fails (no empty package). Best-effort on
  the read path (ADR-0060).
- Each ZIP member is streamed to a temp file (S3DocumentDownloader.download,
  boto download_file) and added from disk, so a single multi-GB member never
  hits the heap — the 'never held whole in memory' claim is now true.
- The 409 double-submit guard is DB-arbitrated: the sub_task insert is
  conditional on the task having none, so a race creates only one.
- Local env gets a placeholder recipient email so the route is exercisable.
- PackageEntry carries landlord_property_id so a read failure can be reported.
- TODO noting the UploadedFile.s3_upload_timestamp typing fix.
Two new tests: per-file read failure skips-and-reports; address fallback flows
to the folder name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 11:08:46 +00:00
Khalim Conn-Kowlessar
b89b9fe944 Name the packaged file by Document Type with the original extension 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:07:25 +00:00
Khalim Conn-Kowlessar
bd928828e3 Skip and report a document with no Document Type 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:06:26 +00:00
Khalim Conn-Kowlessar
810e910961 Keep only the latest file of a Document Type in each property's folder 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:04:58 +00:00
Khalim Conn-Kowlessar
28b7b43372 Keep only the latest file of a Document Type in each property's folder 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:04:19 +00: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
fbedf4541b A small roof derives Sub-Ladder rungs below Google's smallest config 🟪
North-drop now runs once: the selection computes the usable (north-dropped)
ladder, feasibility filters it, and Sub-Ladder derivation consumes it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:10:37 +00:00
Khalim Conn-Kowlessar
c1a8c27bc1 Sub-Ladder rungs fill from the highest-yield segment first 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:06:30 +00:00
Khalim Conn-Kowlessar
1a34e788d1 A small roof derives Sub-Ladder rungs below Google's smallest config 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:05:37 +00:00
Daniel Roth
4c79fb3c8e update comment 2026-07-07 16:30:36 +00:00
Daniel Roth
d884edd456 Map a HubSpot outcome to an abandonment reason code 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 15:38:31 +00:00
Daniel Roth
2512d428a1 Map a HubSpot outcome to an abandonment reason code 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 15:38:10 +00:00
Daniel Roth
c206a76b22 Abandon a job through the relay canceljob route 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 15:30:24 +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
Khalim Conn-Kowlessar
cc4bf4394e Both postcode batchers share one group-preserving packing core 🟪
Review feedback (#1481): the address batcher and the Modelling Run batcher
implemented the same greedy packing; the core moves to
utilities/grouped_batching.py and both become thin wrappers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:24:02 +00:00
Khalim Conn-Kowlessar
c64bd8fd85 A recorded batch failure carries structured details onto the sub_task outputs 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:50:10 +00:00
Khalim Conn-Kowlessar
8a3c0f3e77 A recorded batch failure carries structured details onto the sub_task outputs 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:49:56 +00:00
Khalim Conn-Kowlessar
30e3054146 A failed batch sub_task restarts for a re-run 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:08:47 +00:00
Khalim Conn-Kowlessar
5b60717133 A run with finished and queued batches rolls up in progress, not waiting 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:04:50 +00:00
Jun-te Kim
bc1cca77db
Merge pull request #1356 from Hestia-Homes/feature/historic-epc-repository
Historic EPC repository: DDD port + resolver for address→UPRN
2026-07-07 10:56:33 +01:00
Daniel Roth
6335796d6e
Merge pull request #1471 from Hestia-Homes/feature/abri-api-integration
Abri OpenHousing DomnaRelay — GetTenantData vertical (tenancy signatories to HubSpot)
2026-07-06 16:15:36 +01:00
Daniel Roth
06354a166e Phone-number selection policy lives in the domain layer 🟪
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:47:37 +00:00
Daniel Roth
10636c1752 Runner-up number fills the contact's secondary phone number 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:28:56 +00:00
Daniel Roth
78fcba45e5 Abri tenancy signatory becomes an associated HubSpot deal contact 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:22:52 +00:00
Khalim Conn-Kowlessar
817c00720e The historic roof description conditions the cohort by form family 🟩
roof_construction codes group by FORM (empirical: 1=Flat 98%, 4/5/8=
Pitched 88-99%, 3=dwelling-above 100% over 7,974 certs; 7/9=premises-
above per #1452), so the filter matches families — an exact-code filter
would wrongly drop pitched neighbours lodged as 5/8. Historic prefixes
map to the same families; roof rooms and thatch stay unconditioned.
Harness ladder replay and telemetry mirror the new filter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 12:05:56 +00:00
Khalim Conn-Kowlessar
49c9f8181c The historic roof description conditions the cohort by form family 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:50:45 +00:00
Jun-te Kim
c238a0e6a0
Merge pull request #1449 from Hestia-Homes/feat/sap-corpus-campaign
fix(rdsap): RdSAP 10 Table 13 200/280mm solid-brick wall boundary
2026-07-06 12:25:17 +01:00
Khalim Conn-Kowlessar
38661c6bd7 Age band conditions within one band; the floor-area band widens to ±20% 🟩
Evidence (439-pair harness, PR #1466): historic-vs-new age band agrees
52% exactly but 90% within one band (assessors re-band, skewing newer);
TFA agrees 45% within ±5% but 82% within ±20%. Equality/±5% steered the
cohort toward stale values where they engaged and relaxed everywhere
else. Band definitions are public so the harness's ladder replay shares
one source of truth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:08:03 +00:00
KhalimCK
180863ed41
Merge pull request #1456 from Hestia-Homes/fix/electric-boiler-cpsu-companions
Electric boiler/CPSU overrides drag category 2 and the conservative Group 1 control (#1444 A+B for 191/192)
2026-07-06 12:07:25 +01:00
Khalim Conn-Kowlessar
1a11d0b900 Legacy register fuel descriptions resolve to modern main_fuel codes 🟩
Strip the pre-RdSAP-17 deprecation rider and alias the SAP-prefixed
forms before the code-table lookup. Raises the historic fuel resolution
rate from ~22% of pairs to ~92% of dump rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 10:03:50 +00:00
Khalim Conn-Kowlessar
9204228366 An expired historic cert conditions ingestion's prediction and labels it 🟩
Ingestion's lookup chain becomes: new EPC API -> historic backup by exact
UPRN -> plain prediction. A found record's stable attributes fill the
gaps Landlord Overrides left (overrides always win) and enrich the target
with age band / fuel / TFA band; the persisted predicted-slot row carries
source="expired". Reader unwired or shard miss -> behaviour unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:38:07 +00:00
Khalim Conn-Kowlessar
d2d696a1c5 Historic stable attributes condition cohort selection on the relax ladder 🟩
Age band (Table S1 letter), main fuel code, and a ±5% floor-area band —
the first numeric-tolerance filter — each ride _maybe_filter, so an
unresolved attribute (None) is inactive and a starving filter relaxes.
Existing callers pass no new fields and are behaviourally untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:26:00 +00:00
Khalim Conn-Kowlessar
248aa5ad6a Historic stable attributes condition cohort selection on the relax ladder 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:24:36 +00:00
Khalim Conn-Kowlessar
bbfcf1385b Resolve a historic EPC's stable attributes into cohort code spaces 🟩
property_type/built_form reuse the override code mapping; wall material
prefix -> RdSAP wall_construction; E&W age-band strings -> Table S1
letters; main_fuel display text (stripping " (not community)") -> modern
RdSAP-20/21 codes; TFA -> float. Unresolvable -> None (filter inactive).
Roof construction is deferred: its RdSAP code table isn't pinned in-repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:22:31 +00:00
Khalim Conn-Kowlessar
992950bd9f Resolve a historic EPC's stable attributes into cohort code spaces 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:21:41 +00:00
Daniel Roth
b2754baa04
Merge pull request #1463 from Hestia-Homes/feature/abri-api-integration
Abri OpenHousing DomnaRelay — Amend Appointment vertical (amendoptiappt)
2026-07-06 09:08:00 +01:00
Khalim Conn-Kowlessar
ab245de68d Merge remote-tracking branch 'origin/main' into feature/historic-epc-repository 2026-07-04 11:19:59 +00:00
KhalimCK
6dfaecc352
Merge pull request #1460 from Hestia-Homes/fix/table-12a-underfloor-rows
Electric underfloor codes resolve their Table 12a Grid 1 rows (ADR-0050 deferred follow-up)
2026-07-03 17:53:59 +01:00
KhalimCK
adcdce4271
Merge pull request #1462 from Hestia-Homes/fix/floor-u-value-gate
Floor insulation gated on the derived floor U-value (ADR-0051 floor arm)
2026-07-03 17:53:34 +01:00
Khalim Conn-Kowlessar
9153fa2523 A community override keeps an assessor-observed Group 3 control 🟩
The heat-network mirror of keep_existing_off_peak_meter: the override's
2313 default applies only when the replaced system's control is
cross-family (stale); an observed community control survives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:35:08 +00:00
Khalim Conn-Kowlessar
72ccc920c5 Community-heating overrides default to Group 3 control 2313 🟩
Per-axis choice (decided with Khalim): the kit axis concedes to the
evidence (community schemes skew modern; lodged community certs are
overwhelmingly thermostatted, none lodge 2301), the charging axis stays
flat-rate — usage-linked billing is scheme paperwork an override
cannot see.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:32:58 +00:00
Daniel Roth
2cfed0c33d Abri amend_job amends an OpenHousing appointment and returns the echoed booking 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 16:15:44 +00:00
Khalim Conn-Kowlessar
fb3516ee95 Floor insulation is withheld when it cannot lower the derived floor U 🟩
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:06:45 +00:00
Khalim Conn-Kowlessar
6c6be1a432 Electric underfloor codes resolve their SAP 10.2 Table 12a Grid 1 rows 🟩
421 slab -> Other storage heaters (0.00); 422/423 integrated -> 0.20;
424/425 screed/timber -> 0.90/0.50 — per the Grid 1 row labels that name
the codes (PDF p.184). Closes the None all-low-rate fallback that
over-credited 7-hour-metered underfloor dwellings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:00:40 +00:00
Daniel Roth
c0d36d1e67
Merge pull request #1458 from Hestia-Homes/feature/abri-api-integration
Abri DomnaRelay client — foundation + LogJob vertical (strictly typed)
2026-07-03 16:49:46 +01:00
Daniel Roth
f5fefd4d93 Abri job descriptions identify the visit as a Domna condition survey 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:34:05 +00:00
Daniel Roth
caffa5c4e1 Abri job descriptions identify the visit as a Domna condition survey 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:33:40 +00:00
Daniel Roth
cd29cbb0b8 Abri confirmed time before midday books the morning slot 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:32:15 +00:00