Model/packages
Khalim Conn-Kowlessar f502db8c74 Slice 95: API mapper TFA from per-bp dims + window area 2dp rounding — cert 001479 to 1e-4
The end-to-end production cascade `from_api_response → cert_to_inputs →
calculate_sap_from_inputs` now hits cert 001479's worksheet continuous
SAP 69.0094 at abs < 1e-4 (was +0.000584). Two fixes:

1. API mapper: `from_rdsap_schema_21_0_{0,1}` computes `total_floor_
   area_m2` as Σ per-bp `sap_floor_dimensions[*].total_floor_area.value`
   (cert 001479: 30.45+30.77+5.37+1.92 = 68.51), not the lodged scalar
   (rounded integer 69). `water_heating_from_cert` reads `epc.total_
   floor_area_m2` directly for occupancy N (Appendix J), which propagates
   to HW kWh (+6.31 → ~0), Appendix L lighting (+0.98 → 0), and internal
   gains (+25.72 W·months → 0).

2. Cascade window area rounding per RdSAP 10 §15 "Rounding of data"
   (p.66): "All element areas (gross) including window areas: 2 d.p."
   `solar_gains.py` and `internal_gains.py` now round `w * h` to 2 d.p.
   to match the existing `heat_transmission.py` pattern (line 344).
   Closes the residual solar gains delta (+1.50 W·months → 0) that
   became dominant once TFA was fixed.

Re-pinned 5 golden cert residuals where TFA + area rounding shifted
output: 0240 (SAP -14→-15, PE +14.6650→+17.8450, CO2 +0.8060→+1.0097),
6035 (PE +48.2971→+49.5139, CO2 +1.1016→+1.1423), 8135 (PE -2.4194→
-2.4072, CO2 -0.0198→-0.0195), 2130 (PE -38.1521→-38.1666), 0390
(PE +1.6837→+1.6962, CO2 +0.0637→+0.0639).

New test: `test_api_001479_full_chain_sap_matches_worksheet_pdf_
exactly` formalises Layer 4 of the validation stack as a 1e-4 gate.

Pyright net-zero (mapper.py 33).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 09:30:41 +00:00
..
domain Slice 95: API mapper TFA from per-bp dims + window area 2dp rounding — cert 001479 to 1e-4 2026-05-26 09:30:41 +00:00
fetchers added potential file scaffolding: 2026-05-15 10:56:53 +00:00
repos added potential file scaffolding: 2026-05-15 10:56:53 +00:00
utils added potential file scaffolding: 2026-05-15 10:56:53 +00:00
README.md added potential file scaffolding: 2026-05-15 10:56:53 +00:00

Shared packages

Workspace packages consumed by services/*. Each package is its own Python distribution with its own pyproject.toml; services import via the workspace dependency mechanism ({ workspace = true }).

Package Purpose
domain/ Shared domain types — Property, BaselinePerformance, Plan, Scenario, EpcPropertyData, etc. No persistence, no IO, no business logic.
repos/ Persistence layer — one repo per aggregate. Owns the SQL. Depends on domain.
fetchers/ External API clients (gov EPC, Ofgem, Google Solar, etc.). Depend on domain for response shapes.
utils/ Cross-cutting infra — logging, S3, CloudWatch URL builders, SQS task helpers.

Adding a new shared package

Only when a real second consumer materialises. Don't pre-shatter (repos-epc, repos-property, ...) — split when a deployment needs to drop a dep, not before.

See ../ara_backend_design.md §11 for the broader monorepo layout and ../CONTEXT.md for the domain glossary that names the types living in domain/.