Skip to content

Commit 5282391

Browse files
refactor(enphase): replace per-family write patches with a single reconcile pass
The previous commit on this branch (create-path retry, a pending-status debounce, and a bugfix for the debounce interacting badly with activation) kept revealing new problems in different places - and review surfaced a fourth, structural gap: a family being disabled can leave a stale, still-live window that a *different* family's write then collides with, which none of the per-family retry/prune machinery could see across families. That's the signal to stop patching and reconsider the architecture rather than add a fifth fix (systematic-debugging Phase 4.5). Replaces apply_battery_schedule with a single reconcile function, called both periodically (a new 5-minute tier in run(), so a missed/dropped write- switch trigger can't leave the cloud diverged from the plan indefinitely) and from the write switch as before: apply_battery_schedule: up to 3 read-clean-write attempts, short backoff between, then defer to the next periodic call or trigger. _reconcile_once: fresh read, then two phases - delete anything that must not survive (a family being disabled, or an enabled-but-moving family whenever more than one family is changing this pass) *before* any family writes anything, then write/activate what's still needed. The delete-vs-update-in-place split (see the design doc's "Update strategy") is what actually closes the cross-family gap: a new window for one family can otherwise collide with a different family's old, not-yet-updated window even when neither family's *new* windows overlap each other. Counting how many families are changing this pass is enough to decide - no interval- overlap math needed, and DTG/RBD are mutually exclusive by construction so it only has to reason about two families at a time, not three. Removed as no longer needed: _put_schedule_with_conflict_retry / _create_schedule_with_conflict_retry (two near-duplicate per-write retry helpers -> one outer retry), _write_and_activate, the pending-status debounce and its schedule_pending_since tracking, and the on-failure cache invalidation (every attempt re-reads from the cloud, so there is nothing local left to invalidate). Also adds a scripted live test harness (enphase.py --reconcile-sequence), driving a sequence of real schedule changes - including the cross-family case - against a real account using only midnight-05:00 windows and RBD (freeze-export) rather than a real DTG target, so nothing it does can actually charge from or export to the grid. Design: docs/superpowers/specs/2026-08-08-enphase-schedule-reconcile-design.md Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 9985d8f commit 5282391

3 files changed

Lines changed: 775 additions & 286 deletions

File tree

0 commit comments

Comments
 (0)