Skip to content

fix(plan): shrink, not grow, the source window in the export swap's partial combine (#5423) - #5447

Merged
springfall2008 merged 1 commit into
mainfrom
fix/swap-export-partial-combine-5423
Oct 9, 2026
Merged

springfall2008 merged 1 commit into
mainfrom
fix/swap-export-partial-combine-5423

Conversation

@chalfontchubby

Copy link
Copy Markdown
Collaborator

(Posted by Claude on Rik's behalf.)

Closes #5423

Problem

A manual demand override for 19:00-19:30 was not respected: the plan exported inside it, and at 19:05 the inverter was put into timed export until a later recompute moved the export to 19:30.

The log attached to #5423 shows the cause. find_charge_window split 19:00-19:30 out as its own window correctly, but each fresh plan then started the export window inside it:

Recompute Export window planned
18:35 19:15-20:30
18:45 19:10-20:30 (adopted, then reused at 18:55 and 19:00)
19:05 19:05-20:00, plus an overlapping 35-minute 19:55-20:30

Cause

optimise_swap_export's Partial combine branch moves export time from an earlier window into a later, trimmed one. It lengthened the earlier window by the amount moved (amount_to_move + window_length) instead of shortening it, and unlike the plain Swap branch it has no previous_end clamp. The earlier window's start therefore slid back into the slot before it. The manual-override guards only check whether a window's start minute is a manual time, so the stretched 19:30 window passed them and exported through the demand slot.

Fix

The earlier window now shrinks by what the target gains (window_length - amount_to_move), so the move conserves export time, as the Full combine branch already does. The new length is always at least one minute in this branch, because Full combine is taken whenever the two windows fit together.

Tests

  • New regression case in tests/test_optimise_swap_export.py: a manual slot, then an export window, then a trimmed later export window. It fails on main (the middle window is pushed back into the manual slot) and passes with the fix.
  • ./run_all --quick: only the random golden test changes, for 3 of its 20 scenarios (metric 1164.54 → 1164.47, 628.40 → 628.36, 477.07 → 477.35). random passes on main without the fix. cases/random_results.json is updated with those values only; runtimes are left as they were.

Not in this PR

The plain Swap branch (around plan.py:4135) can still stretch a window back to the previous window's end, past its own original start, into an empty gap. It stops at an adjacent manual window, so it can't reproduce #5423, and I've left it alone.

🤖 Generated with Claude Code

…artial combine (#5423)

When optimise_swap_export partially combined an export window into a later,
trimmed one, it lengthened the earlier window by the amount moved instead of
shortening it, with no clamp at the previous window's end. The earlier
window's start then slid back into the slot before it. With a manual demand
override in that slot, the guards (which only check a window's start minute)
missed it, and the plan exported through the override - in #5423 a 19:30
window was pushed back to 19:05-19:15 inside a 19:00-19:30 demand slot, and
the inverter was put into timed export at 19:05.

The earlier window now shrinks by what the target gains, so the move
conserves export time as the full combine already does. The random golden
results change for 3 of 20 scenarios accordingly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused arithmetic correction is consistent with adjacent combine logic and has targeted regression coverage.

0 open findings

What changed in this PR

Fixes export-window partial combining so manual demand overrides remain respected.

Changes:

  • Conserves export duration by shrinking the source window.
  • Adds a regression test for issue #5423.
  • Updates affected random-scenario baselines.
File Description
apps/​predbat/​plan.py Corrects partial-combine window arithmetic.
apps/​predbat/​tests/​test_optimise_swap_export.py Tests manual-slot protection.
coverage/​cases/​random_results.json Updates expected planning results.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@springfall2008
springfall2008 merged commit 0dab350 into main Oct 9, 2026
3 checks passed
@springfall2008
springfall2008 deleted the fix/swap-export-partial-combine-5423 branch October 9, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Predbat set to manual Demand but planned (and executed) to force export

3 participants