Commit graph

597 commits

Author SHA1 Message Date
Daniel Roth
d7648fd5e0
Merge pull request #1514 from Hestia-Homes/feature/abri-api-integration
Map Hubspot outcomes to their Abri abandonment reason codes
2026-07-08 15:46:28 +01:00
Daniel Roth
4ac4dd8683 Collapse cancelled/no show to HubSpot's single 'Cancelled / No Show' value
'Cancelled' and 'no show' were separate strings in the outcome vocabulary,
but HubSpot only ever emits the one dropdown value 'Cancelled / No Show' -
so neither phantom string could ever match. Replace both with the real
value (mapped to NOACCESS, best-guess pending client), which also fixes the
long-standing differ mismatch: the abandonment trigger now actually fires on
Cancelled / No Show. Drops the now-unused REQT enum member.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 14:33:59 +00:00
Daniel Roth
9a669dfcea Map every unsuccessful outcome to a reason code (best-guess, client to confirm)
Complete the outcome-to-code table so all five UNSUCCESSFUL_OUTCOMES map:
cancelled -> REQT (new enum member) and no show -> NOACCESS join the
existing three. Only no answer -> CARDED is firm; the rest are best-guesses
for client confirmation, noted inline with alternatives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 14:28:47 +00:00
Daniel Roth
693356a220 Map Abri abandonment outcomes to their reason codes
Replace the CARDED placeholder in abandon_reason_for_outcome with the
real outcome-to-code table from the client: No Answer->CARDED,
Tenant Refusal->CRA (ambiguous, client follow-up pending),
Not Viable->NOACCESS. Only these three outcomes trip the abandonment
trigger today; any empty/unrecognised outcome raises
UnmappableOutcomeError since abandon_reason is mandatory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 14:14:06 +00:00
Jun-te Kim
f0bd5b9674
Merge pull request #1503 from Hestia-Homes/worktree-rdsap-glazing-bug
Derive multiple_glazed_proportion for 16.x certs with explicit glazing wording
2026-07-08 15:06:33 +01:00
Jun-te Kim
430ac9eaa4 Derive multiple_glazed_proportion for 16.x certs with explicit glazing wording
Property 753950 (uprn 100021969385, cert 0141-2860-6891-9124-5625,
SAP-Schema-16.2) hard-failed modelling_e2e: RdSapSchema17_1 requires
multiple_glazed_proportion as a non-optional int, and this 16.x cert omits
the field entirely, lodging only the multiple_glazing_type="ND" sentinel.

The cert's own window.description ("Fully double glazed") states the
glazing extent unambiguously, so _normalize_sap_schema_16_x now derives
0/100 from "single"/"double" wording when the field is absent, mirroring
the existing single-glazed multiple_glazing_type cascade. This is
worklist P4 (.claude/skills/expand-sap-accuracy-corpus/worklist.md) —
a flat default was tried previously and reverted because making such
certs mappable at all pulls them into the EPC-prediction donor pool and
tips near-tie similarity matches; deriving from explicit text (rather
than a blind default) was the suggested unblock.

Re-measured the component-accuracy gate as the worklist asked: it drops
(has_hot_water_cylinder 0.8687->0.8586, cylinder_insulation_type
0.3333->0.1667, door_count residual 0.3131->0.3333) via the same
donor-pool-composition mechanism as the prior #1245/ADR-0037
re-baselines, not a prediction-logic loosening. Re-baselined the floors
with that rationale recorded inline.
2026-07-08 11:53:51 +00:00
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
e906c8fc98 Scope latest-per-Document-Type per property, each in its own folder 🟩
Pins behavior delivered with the tracer slice (the group key is
(landlord_property_id, document_type)) — no red phase; discriminating: a
global-by-type dedupe would drop one property's file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:15:44 +00:00
Khalim Conn-Kowlessar
63933db529 Name the packaged file by Document Type with the original extension 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:06:51 +00:00
Khalim Conn-Kowlessar
34c48d4adc Skip and report a document with no Document Type 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:05:44 +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
5d0a7751e6 A small-roof house gets Sub-Ladder solar Options instead of nothing 🟩
End-to-end pin at the generator seam (recommend_solar) — passed on first
run since option construction is unchanged by design (ADR-0058).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:09:18 +00:00
Khalim Conn-Kowlessar
024a01b128 The Dwelling-Roof Cap bounds Sub-Ladder rungs too 🟩
Pins that the unchanged cap regime (min of 0.7×Google and the ADR-0038
budget) flows into ADR-0058 derivation — no red phase; the tracer
implementation passed the already-min'd cap through.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:08:28 +00:00
Khalim Conn-Kowlessar
1756976d7e A roof capped below two panels is still offered no PV 🟩
Pins the ADR-0058 install floor delivered with the tracer slice (rung_max
< 2 returns empty) — no red phase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:07:39 +00:00
Khalim Conn-Kowlessar
5a382948d5 Sub-Ladder rungs never take from north planes 🟩
Pins behavior delivered with the tracer slice (derivation starts from the
north-dropped remainder) — no red phase; the mutation is discriminating
(a kept north panel would win fill-by-generation and shift the yields).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:07:18 +00:00
Khalim Conn-Kowlessar
0b33f7dc65 Sub-Ladder rungs fill from the highest-yield segment first 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:06:10 +00:00
Khalim Conn-Kowlessar
79d7743bb1 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:03:43 +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
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
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
561b8b078b Test names state the surviving failure-recovery behaviors 🟪
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:12:12 +00:00
Khalim Conn-Kowlessar
3d643965b5 A failed batch sub_task restarts for a re-run 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:05:34 +00:00
Khalim Conn-Kowlessar
1c7b71bcce 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:03:28 +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
Khalim Conn-Kowlessar
71bdd080c0 Expired-pairs integration gate: frozen single-file corpus + ratcheting floors 🟩
30 pairs (28 deterministically scoreable) from the 2,000-postcode sweep,
frozen as ONE anonymised raw-payload JSON (pairs + cohorts + actuals — a
thousand per-cert files would drown the PR diff). The gate replays the
whole conditioning path offline — mapper, conditioning, selection,
synthesis, comparison — in ~9s; floors are the measured values, tighten-
only. comparable_from_payload is extracted from the corpus loader so both
fixture formats share one payload->ComparableProperty path; the builder
(build_expired_pairs_corpus.py) refreezes from the raw-JSON disk cache.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 13:05:18 +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
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
355c1e7d2f Age band conditions within one band; the floor-area band widens to ±20% 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:06:45 +00:00
Khalim Conn-Kowlessar
c79cd777e5 Legacy register fuel descriptions resolve to modern main_fuel codes 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 10:03:09 +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
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
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
04810896e0 A community override keeps an assessor-observed Group 3 control 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:33:40 +00:00
Khalim Conn-Kowlessar
2bfda711d8 Community-heating overrides default to Group 3 control 2313 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 16:32:15 +00:00
Khalim Conn-Kowlessar
128981289a 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:05:04 +00:00
Khalim Conn-Kowlessar
f604672ae0 Electric underfloor codes resolve their SAP 10.2 Table 12a Grid 1 rows 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:57:37 +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
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
2c660bdb5d Abri unparseable confirmed time fails loudly rather than silently booking all day 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:33:12 +00:00
Daniel Roth
eccc03f9f2 Abri confirmed time at or after midday books the afternoon slot 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:32:49 +00:00
Daniel Roth
fcdab30b73 Abri confirmed time before midday books the morning slot 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:31:51 +00:00
Daniel Roth
da4caea407 Abri booking with no confirmed time books an all-day appointment 🟥
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 14:31:12 +00:00
Khalim Conn-Kowlessar
1925cdd65d An incomplete heating companion set raises instead of logging 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:21:34 +00:00