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>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-07 22:09:18 +00:00
parent 024a01b128
commit 5d0a7751e6

View file

@ -14,7 +14,11 @@ from domain.geospatial.planning_restrictions import PlanningRestrictions
from domain.modelling.generators.solar_recommendation import recommend_solar
from domain.modelling.product import Product
from domain.modelling.recommendation import Recommendation
from domain.modelling.solar_potential import SolarPotential
from domain.modelling.solar_potential import (
SolarPanelConfiguration,
SolarPotential,
SolarRoofSegment,
)
from repositories.product.product_repository import ProductRepository
from tests.domain.modelling._elmhurst_recommendation import (
parse_recommendation_summary,
@ -242,3 +246,46 @@ def test_infeasible_potential_yields_no_recommendation() -> None:
# Act / Assert
assert recommend_solar(baseline, _StubProducts(), north_only) is None
def test_small_roof_house_gets_sub_ladder_options_instead_of_nothing() -> None:
# ADR-0058 end-to-end at the generator seam — the 824/1278 audit's
# property-750701 shape: Google max 5 (cap 3.5), ladder starting at 4,
# which yielded NO recommendation before Sub-Ladder Configurations.
# Arrange — an eligible house with a small-roof Solar Potential.
baseline = _eligible_house()
small_roof = SolarPotential(
panel_capacity_watts=400.0,
max_array_panels_count=5,
configurations=(
SolarPanelConfiguration(
panels_count=4,
yearly_energy_dc_kwh=1278.0,
segments=(
SolarRoofSegment(
segment_index=0,
panels_count=4,
azimuth_degrees=180.0,
pitch_degrees=30.0,
yearly_energy_dc_kwh=1278.0,
),
),
),
),
)
# Act
recommendation: Optional[Recommendation] = recommend_solar(
baseline, _StubProducts(), small_roof
)
# Assert — rungs 2 and 3 x {no battery, battery} = 4 competing Options,
# each overlay's array peak power matching its rung (0.8 / 1.2 kWp).
assert recommendation is not None
assert len(recommendation.options) == 4
peak_powers = sorted(
sum(a.peak_power for a in o.overlay.solar.photovoltaic_arrays)
for o in recommendation.options
)
assert peak_powers == [0.8, 0.8, 1.2, 1.2]