Model/packages
Khalim Conn-Kowlessar 729229ed61 Slice 33: §13a Primary Energy — Table 12e monthly cascade wiring
Adds Table 12e (p.195) monthly PE factors for electricity to
`tables/table_12.py` + `pe_monthly_factors_kwh_per_kwh(fuel_code)`
helper. Mirrors slice 32's CO2 cascade — same spec text, same
shape: electricity end-uses use Σ(kWh_m × PE_m); non-electricity
fuels keep the annual Table 12 / RdSAP10 Table 32 (p.95) factor.

Calculator now consumes per-end-use PE factors on `CalculatorInputs`
(`secondary_heating_primary_factor`, `pumps_fans_primary_factor`,
`lighting_primary_factor`, `electric_shower_primary_factor`). Defaults
to None → fall back to the global `space_heating_primary_factor` /
`other_primary_factor` (synthetic path). Fixes the stale 1.969 default
to RdSAP10 Table 32 standard-electricity PE = 1.501.

`_effective_monthly_factor(monthly_kwh, monthly_factors)` generalises
the slice-32 weighting helper; `_effective_monthly_co2_factor` and the
new `_effective_monthly_pe_factor` are thin wrappers over it.

Includes the electric-shower kWh in the PE total — closes the audit
loop opened by slice 30 (electric shower had fuel cost + CO2 but no PE
contribution).

§13a cascade pins NOT added — §13a appears only in the Demand-SAP
block (postcode climate); our cascade pins live against the Rating-SAP
block (UK-average climate). The Demand-SAP postcode cascade is a
separate scope, intentionally deferred. The calculator's existing
`primary_energy_kwh_per_yr` SapResult output now uses the spec-correct
PE factors but stays UK-average climate.

Verification (000474):
  pumps_fans  effective PE factor = 1.5128 (PDF: 1.5128 ✓)
  lighting    effective PE factor = 1.5338 (PDF: 1.5338 ✓)
  pumps_fans  PE = 242.0480 kWh (PDF: 242.0480 ✓)
  lighting    PE = 214.6527 kWh (PDF: 214.6527 ✓)

Wider regression: 1490/1490 PASS — zero failures.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 08:36:07 +00:00
..
domain Slice 33: §13a Primary Energy — Table 12e monthly cascade wiring 2026-05-24 08:36:07 +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/.