- Tomorrow's grid block is drawn to where control stops charging. A cheap run
is sized for all batteries together; a slower one is still below
`charge_to()` when it ends and control plans the next cheap slots. The tab
asks `modetrade.energy()` and `priceruns.plan()` with the packs at the
curve's level and extends the run, so the curve charges as long.
- Each battery's block ends where it is at its own level (grid) or at the
floor (give). The curve puts a point where a battery reaches its charge
level inside a step.
- `homeview.mode_runs(ahead=f, rp=...)` reads each block at the level the
curve has when it starts, with Home's own filter and MIN_KWH: no give block
at the floor, no grid block at the planned level. Home never passes either.
- `no_tomorrow` names the hour from `solarfc.BELL_FROM_H`, where the curve
stops.
- test_ux54.py part 7 compares control (`_mode_roles()` every 15 minutes) with
the tab with no tolerance, and adds the cloudy / floor case.
No decision, command, timing or option key changes.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC