TARIFF-24 round 3: a run planned with a forecast keeps its gap to its end
checks / unit (pull_request) Successful in 51m57s
infra-pin / fresh (pull_request) Successful in 1s

Losing the solar forecast mid-run used to widen the gap at once and stop a
grid charge (and a sensor that went unavailable for a minute stopped and
restarted it). A run under way when the forecast is lost now keeps the gap it
was planned with until it ends (Controller.weather_held(), recorded by
_wx_track() each cycle a forecast is read); the wider gap applies from the next
run. The plan key holds the hold state so the plan rebuilds when it ends. Home's
mirror (homeview.trade_verdict) asks the same weather_held(now).

Tests: test_tariff24_weather.py part 4 (going: the charge continues to the run's
end, the next run is not_worth; flap of one and two reads: no stop, no restart;
Home agrees) and a test_modes_p4.py scenario that runs a forecast day at a gap
between 1x and 1.5x the cycle cost. DECISIONS wording follows.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
glenn schrooyen
2026-10-28 17:17:56 +01:00
co-authored by Claude
parent d424b862d8
commit 97686319f3
6 changed files with 191 additions and 42 deletions
+6 -4
View File
@@ -267,15 +267,17 @@ def threshold_eur_kwh(opts: dict) -> float:
return v
def weather_uncertainty(modes_on: bool, solar_fc) -> frozenset:
def weather_uncertainty(modes_on: bool, solar_fc, held: bool = False) -> frozenset:
"""The "no weather" doubt (x1.5) a trade must clear. TARIFF-24.
Battery modes read a solar forecast; with one read (`solar_fc` not None) the
doubt is gone. Everything else, and the modes without a forecast, keep it.
One rule for the run plan, the charge gate and Home's mirror of it. See
doubt is gone, and `held` (a run planned with a forecast is under way, see
`Controller.weather_held()`) keeps it gone until that run ends. Everything
else, and the modes without a forecast, keep it. One rule for the run plan,
the charge gate and Home's mirror. See
DECISIONS/TARIFF-24-modes-need-the-tariff-task.md.
"""
if modes_on and solar_fc is not None:
if modes_on and (solar_fc is not None or held):
return frozenset()
return frozenset({Uncertainty.NO_WEATHER})