Skip to content

fix(octopus): split a slot around a fully-contained overlap instead of losing its remainder - #4504

Merged
springfall2008 merged 1 commit into
mainfrom
fix/octopus-dispatch-overlap-order
Aug 13, 2026
Merged

fix(octopus): split a slot around a fully-contained overlap instead of losing its remainder#4504
springfall2008 merged 1 commit into
mainfrom
fix/octopus-dispatch-overlap-order

Conversation

@chalfontchubby

Copy link
Copy Markdown
Collaborator

Summary

Fixes #4497 - fetch.py merges the HA Octopus Energy integration's completed_dispatches ahead of planned_dispatches unconditionally. load_octopus_slots()'s overlap dedup loop processes slots in that order, but could only ever trim one edge of a slot against an already-decoded slot, or drop it entirely if it was fully contained within an already-decoded one - it had no path for the reverse case, where a new slot fully contains an already-decoded one.

A short completed historical interval sitting inside a much longer still-active planned interval therefore truncated the planned interval down to whatever sliver preceded the completed interval, silently discarding its entire future remainder. Example from the report: a planned 07:59-16:00 dispatch containing a 08:00-09:00 completed interval collapsed to 07:59-08:00 - already in the past by the time it's evaluated, so the car plan lost its whole future charging window despite a valid ready-by time and SoC gap.

Reported by @cparmar with an exact repro payload and precise code line references - I traced it through the actual code before touching anything and it checks out exactly as described (see verification note below).

The fix

The overlap resolution now subtracts each already-decoded slot's span from the new slot's remaining segments, which can produce zero, one, or two pieces - the two-piece case is the one that was missing:

  • Zero pieces: the slot is fully covered by an existing slot (unchanged from before - fully removed)
  • One piece: a simple edge overlap (unchanged from before - single trim, same kwh)
  • Two pieces (new): the slot fully contains an existing one - now correctly split into a before-piece and after-piece instead of losing everything after the first overlap check

kwh is only rescaled proportionally when a slot is actually split into multiple pieces, mirroring the proportional scaling decode_octopus_slot() already does a few lines above for forecast-window capping. The pre-existing single-edge-trim behaviour (and its energy value) is left exactly as before, so the existing hard-coded regression expectations in test_octopus_slots.py's sample_bad test are unaffected.

Verification

Hand-traced the reporter's exact example against the pre-fix code and reproduced the failure precisely (planned slot's end trimmed to the completed interval's start, future remainder never restored). Added a regression test reproducing it exactly; confirmed it fails without the fix (got 1080 - only the unrelated later dispatch survived, the contained one's future remainder was gone) and passes with it.

Test plan

  • New test in test_octopus_slots.py: completed dispatches fully contained within a planned dispatch - future remainder survives with correctly-scaled kwh, non-overlapping dispatches untouched
  • Verified the new test fails without the fix and passes with it (temporarily reverted octopus.py only, re-ran)
  • Existing test_octopus_slots, multi_car_iog, add_now_to_octopus_slot, octopus_slots_change tests pass unchanged
  • ./run_all --quick passes
  • ./run_pre_commit passes

🤖 Generated with Claude Code

…f losing its remainder (#4497)

fetch.py merges the HA Octopus Energy integration's completed_dispatches
ahead of planned_dispatches unconditionally. load_octopus_slots()'s overlap
dedup processes slots in that order, but could only ever trim one edge of
a slot against an already-decoded one, or drop it entirely if fully
contained - it had no path to split a slot that fully CONTAINS an
already-decoded one. A short completed historical interval sitting inside
a much longer still-active planned interval therefore truncated the
planned interval down to whatever sliver preceded the completed interval,
silently discarding its entire future remainder (e.g. a planned
07:59-16:00 dispatch containing a 08:00-09:00 completed interval collapsed
to 07:59-08:00, already in the past). Reported with an exact repro and
code trace by @cparmar.

The overlap resolution now subtracts each already-decoded slot's span from
the new slot's remaining segments, which can produce zero, one, or two
pieces - the two-piece case is the one that was missing. kwh is only
rescaled proportionally when a slot is actually split into multiple
pieces; the existing single-edge-trim behaviour (and its energy value)
is unchanged, preserving the existing hard-coded regression expectations
in test_octopus_slots.py.

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.

Pull request overview

This PR fixes overlap-deduplication in load_octopus_slots() so that when a new Octopus dispatch slot fully contains an already-decoded slot, the new slot is correctly split into “before” and “after” segments (instead of being truncated and losing its future remainder). This directly addresses Issue #4497’s reported case where completed historical dispatches (merged ahead of planned dispatches) could collapse an otherwise-valid future charging window.

Changes:

  • Update apps/predbat/octopus.py overlap handling to subtract all previously-decoded slot spans from the incoming slot, allowing 0/1/2 resulting segments and proportionally scaling kWh only when an actual split occurs.
  • Add a regression test in apps/predbat/tests/test_octopus_slots.py covering “completed slots fully contained within a planned slot” and asserting the future remainder survives with correctly-scaled kWh.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
apps/predbat/octopus.py Fix overlap deduplication to support the containment/split case and preserve future remainder segments.
apps/predbat/tests/test_octopus_slots.py Add regression coverage reproducing the containment overlap scenario from #4497.

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

@springfall2008
springfall2008 merged commit 3050004 into main Aug 13, 2026
3 checks passed
@springfall2008
springfall2008 deleted the fix/octopus-dispatch-overlap-order branch August 13, 2026 19:42
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.

HA Octopus v19 overlapping completed/planned dispatches truncate future car plan

3 participants