Skip to content

fix(plan): clip export windows with no SoC above reserve - #4434

Merged
springfall2008 merged 1 commit into
mainfrom
fix/export-window-stuck-at-reserve
Aug 4, 2026
Merged

fix(plan): clip export windows with no SoC above reserve#4434
springfall2008 merged 1 commit into
mainfrom
fix/export-window-stuck-at-reserve

Conversation

@chalfontchubby

Copy link
Copy Markdown
Collaborator

Summary

  • clip_export_slots had a "clip off, nothing achievable" check that compared a window's predicted soc_max against its own requested limit (limit_soc). For a window asking to drain to 0%, limit_soc is 0, and soc_max can never be below that (the battery physically can't go below reserve) - so that branch could never fire, and the window fell into the "clip up" branch instead, surviving in the plan with a near-zero limit that's technically "on" but physically a no-op.
  • Now clips the window off whenever its SoC forecast never rises above reserve anywhere in the window, regardless of what limit was originally requested.
  • Fixes Predbat plans to export when battery is empty #4171 - confirmed against the reporter's own debug.yaml: the exact live plan state (export_window_best/export_limits_best as computed by their instance) had a window at 23:50-00:00 stuck at a 0% export target while the battery was already flat at the 4% reserve for the whole evening. Forcing that window on vs off in a replay produces an identical metric - proof no real energy ever moved, it was purely a display/plan-entry artifact.

Test plan

  • Added test_normal_export_clipped_off_when_soc_never_above_reserve - the Predbat plans to export when battery is empty #4171 regression case
  • Added test_normal_export_clipped_up_when_soc_above_reserve_with_zero_limit - guards that genuine clip-up behaviour is untouched when there's real energy above reserve
  • ./run_all --quick passes with no regressions
  • ./run_pre_commit passes (ruff, black, cspell, markdownlint, full test suite)
  • Verified directly against the reporter's live plan state (plan_preclip): the window that was target: 0.0 now clips to 100.0

🤖 Generated with Claude Code

…ose below their own limit

For #4171: an export window whose SoC forecast never rises above the
battery reserve throughout its span has nothing exportable, but
clip_export_slots' existing "clip off" check only compared soc_max
against the window's own requested limit_soc. For a window asking to
drain to 0%, limit_soc is 0, which soc_max (always >= reserve) can
never be below - so that branch could never fire, and the window fell
into the "clip up" branch instead, surviving with a near-zero limit
that is technically "on" but physically a no-op (execute.py already
clamps any discharge target to the reserve floor).

Confirmed via a reporter debug.yaml that this produces a real,
harmless-but-confusing "planned to export from an empty battery" plan
entry: toggling the window on vs off in a replay produces an
identical metric, proving no real energy ever moved.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@springfall2008
springfall2008 merged commit e950156 into main Aug 4, 2026
2 checks passed
@springfall2008
springfall2008 deleted the fix/export-window-stuck-at-reserve branch August 4, 2026 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Predbat plans to export when battery is empty

2 participants