mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Closes 36 of the 50 mapper-vs-hand-built load-bearing divergences by
populating fields the Elmhurst mapper extracts but the original
cohort hand-built left at their `make_minimal_sap10_epc` / dataclass-
default values. Every change is cascade-equivalent — none alter
`_FIXTURE_PINS["000474"]` SapResult fields (all 11 1e-4 pins remain
GREEN against worksheet `SAP value 62.2584`).
Per-SapBuildingPart additions (Main, Ext1, Ext2):
- `wall_thickness_measured`: False → True. Summary §7 lodges Wall
Thickness 280 mm explicitly; the cascade doesn't read this field
(grep `wall_thickness_measured` across domain/sap/ returns no
consumer outside test fixtures), so flipping it is field-level-
only.
- `floor_type`, `floor_construction_type`, `floor_insulation_type_str`,
`floor_u_value_known`: surfaced from Summary §9 ("G Ground floor" /
"U Above unheated space" / "T Suspended timber" / "A As built" /
U-value Known = No). Strings carry the lodged text for cross-mapper
parity; cascade reads the int codes on SapFloorDimension.
- `roof_insulation_location`, `roof_insulation_thickness`: surfaced
from Summary §8 ("J Joists" + "100 mm"). Cascade's `u_roof` for
age B at thickness=100 returns the same 0.40 W/m²K as the age-B
default (thickness=None falls through to `_ROOF_BY_AGE['B']=0.40`),
so the cascade output is identical.
SapVentilation additions (all cascade-equivalent — `None` defaults to
0 throughout the §2 cascade chain):
- 6 explicit zero counts (`open_flues`, `closed_flues`, `boiler_flues`,
`other_flues`, `passive_vents`, `flueless_gas_fires`)
- `pressure_test="Not available"` (descriptive, no test was lodged)
- `draught_lobby=True` (the legacy field; cascade reads
`has_draught_lobby=False` which is set already, so True on the
legacy field has no cascade effect)
Top-level additions via `make_minimal_sap10_epc`:
- `extensions_count=2` (Slice 54 fix on mapper made this surface; the
hand-built was carrying the pre-Slice-54 hard-coded 0)
- `blocked_chimneys_count=0`, `dwelling_type="Mid-Terrace house"`,
`built_form="Mid-Terrace"`, `property_type="House"`
Post-construction mutations (helper doesn't expose these as kwargs):
- `has_conservatory=False`, `any_unheated_rooms=False`,
`number_of_storeys=2`, `hydro=False`, `photovoltaic_array=False`
Diff count: 50 → **14**. The remaining 14 are real semantic gaps for
the next slices to close:
Cat B (mapper needs to surface 7 fields):
- country_code (Elmhurst mapper produces None; should set 'ENG')
- sap_heating.water_heating_fuel (None vs 26 — gas main heating
should imply gas water heating fuel)
- main_heating_details[0].boiler_flue_type (None vs 2 — Summary
§14.1 lodges "Balanced" flue type)
- main_heating_details[0].emitter_temperature ('Unknown' vs 1)
- main_heating_details[0].main_heating_number (None vs 1)
- sap_ventilation.has_draught_lobby (None vs False)
- dual-encoded central_heating_pump_age int/str
Cat C (structural shape, 2 diffs):
- sap_windows: LEN 7 vs 5 (mapper 1:1 with §11 table vs hand-built
collapsed by glazing-type group, preserving total area —
cascade-equivalent but not field-equal)
- sap_building_parts[*].party_wall_construction: None vs 0
(cohort convention sentinel; the cohort 000474 docstring
established `0 = "Unable to determine"`)
Cat B handbuilt-needs (hand-built should add 2 fields the mapper
already surfaces):
- sap_heating.shower_outlets (mapper extracts 'Non-electric shower')
- sap_heating.number_baths (mapper extracts 1)
11 cohort cascade pins still GREEN; pyright net-zero (0 errors on
the touched fixture file). Tracer-bullet diff test stays RED with
14 divergences (was 50).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| src/domain | ||
| pyproject.toml | ||
| README.md | ||
domna-domain
Shared domain types — Property, Properties, BaselinePerformance, Plan, PlanPhase, Scenario, ScenarioPhase, ScenarioSnapshot, Recommendation, OptimisedPackage, EpcPropertyData, etc.
Boundary: types only. No persistence, no IO, no business logic. Other packages and services depend on domna-domain; this package depends on nothing internal.
Domain definitions live in ../../CONTEXT.md. New types added here must match the glossary terms.
Layout
src/domain/
├── __init__.py
├── property.py # Property, Properties, PropertyIdentity
├── site_notes.py
├── landlord_overrides.py
├── baseline_performance.py # lodged + effective pair (ADR-0004)
├── plan.py # Plan, PlanPhase, OptimisedPackage
├── scenario.py # Scenario, ScenarioPhase, ScenarioSnapshot (ADR-0005)
├── recommendation.py
├── geospatial.py
├── solar.py
├── anomaly_flags.py
└── ml/
├── __init__.py
├── transform.py # EpcMlTransform (versioned per §8.3)
└── schema.py
When datatypes/epc/domain/ folds in, the EPC schema types move under src/domain/epc/.