From bc2f6c8a8215db31e914ca93b250e0232db2c077 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 21 Jul 2026 10:05:55 +0000 Subject: [PATCH] =?UTF-8?q?Sell=20no=20works=20to=20a=20dwelling=20already?= =?UTF-8?q?=20at=20the=20goal=20band=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- orchestration/modelling_orchestrator.py | 11 +++++++++-- .../test_modelling_goal_band_floor.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/orchestration/modelling_orchestrator.py b/orchestration/modelling_orchestrator.py index 69e88feac..ed324e975 100644 --- a/orchestration/modelling_orchestrator.py +++ b/orchestration/modelling_orchestrator.py @@ -491,10 +491,17 @@ def _objective_for( def _target_sap(scenario: Scenario) -> Optional[float]: """The SAP rating the Optimiser repairs toward — the floor of the goal - band for an INCREASING_EPC goal, else None (no SAP target).""" + band for an INCREASING_EPC goal, else None (no SAP target). + + On the **continuous** scale, because that is the currency every figure the + Optimiser compares it against is in. The dwelling is in the goal band once + its *published* rating is, which happens half a point below the integer + floor — target the integer and a dwelling publishing at the floor reads as a + fraction short, and the Optimiser buys works toward a band it is already in + (#1654).""" if scenario.goal != PortfolioGoal.INCREASING_EPC.value: return None - return float(Epc(scenario.goal_value).sap_lower_bound()) + return Epc(scenario.goal_value).sap_lower_bound_continuous() def _best_practice_key(option: MeasureOption) -> int: diff --git a/tests/orchestration/test_modelling_goal_band_floor.py b/tests/orchestration/test_modelling_goal_band_floor.py index 3238fa477..63210345b 100644 --- a/tests/orchestration/test_modelling_goal_band_floor.py +++ b/tests/orchestration/test_modelling_goal_band_floor.py @@ -40,3 +40,18 @@ def test_dwelling_published_at_the_goal_band_is_sold_no_works() -> None: # Assert — nothing to buy: the goal is already met. assert plan.measures == () assert plan.cost_of_works == 0.0 + + +def test_dwelling_below_the_goal_band_is_still_taken_to_it() -> None: + # Arrange — the same cert with an uninsulated loft scores a continuous + # 37.349, published SAP 37: band F, genuinely short of band D. Lowering the + # target by half a point must not let the package stop short of the band. + below_band_d = _dwelling("loft_001431_before.pdf") + + # Act + plan: Plan = run_modelling(below_band_d, goal_band="D", print_table=False) + + # Assert — real works, and they carry the dwelling into band D. + assert plan.measures != () + assert plan.cost_of_works > 0.0 + assert plan.post_retrofit.sap_continuous >= 54.5