Repository navigation
feat(appproto): the plan carries the battery's planned level per slot - #1630
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1b11198aff
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if units.ValidFraction(a.SoC) { | ||
| soc := units.PermilleFromFraction(a.SoC) | ||
| slot.SocPermille = &soc |
There was a problem hiding this comment.
Omit SoC for batteryless plans
On an Energyplan site without home storage, buildMPC deliberately creates plans with CapacityWh == 0, and validation requires every Action.SoC to be zero. Because zero is a valid fraction here, every slot is serialized with socPermille: 0, falsely telling the app that an empty battery exists rather than omitting the unavailable level. Gate this field on the plan having positive battery capacity as well as a valid SoC.
Useful? React with 👍 / 👎.
…nst guessed, and the planning style as a scale (#58, #59, #60, #61) One squash for four stacked PRs, changes 2–5 of the plan pass Fredrik approved on 14 Oct 2026 (change 1 was #57): - #58: the planned battery level in the scrub, a dashed level line in the lanes and the dial's story (socPermille from srcfl/ftw#1630). - #59: one honest saving under the dial, against no battery, only when the plan ends near its start level. - #60: known against guessed: the dashed sun, hatched unpriced quarters, the style named when it is not balanced. - #61: the two levers at the foot of the plan view, the planning style as a detented scale (Fredrik's note 21), one command on release with the receipt, and only moved quarters cross-faded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plan an app reads now says where the battery ends up, not only what it does: each slot of
plan.get(and of the plan pushed after a command) carriessocPermille, the battery's planned level at the end of the slot, in thousandths.Why
Fredrik's plan design pass for the iPhone app (change 2 of 5, approved 14 Oct): "will it last the evening?" is the question people ask, and the lanes only show what the battery does. The phone's plan view could read the level from
GET /api/mpc/plan, but Now, the widgets and the Apple Watch read only the session plan. This adds one optional field there.What changes
protocol.PlanSlotgetsSocPermille *int64(socPermille, omitted when absent). Same name and unit as the FTW Cloud plan class indocs/protocol-cloud.md.appproto.planFromfills it frommpc.Action.SoC(the level at the end of the slot) withunits.PermilleFromFraction. A value that is not a finite fraction in [0, 1] is left out rather than sent as a guess.Evidence
TestPlanCarriesTheBatteryLevelAtEachSlotsEnd: levels 0.4, 0.6, 0.45 arrive as 400, 600, 450; a NaN level is left out.make verifygreen (vet, tests, build).Paired with the ftw-app change that reads it when present (link follows when it opens).
🤖 Generated with Claude Code