Repository navigation
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: b72ec48a44
ℹ️ 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".
| public var entry: PlanEntry { | ||
| PlanEntry.live(plan: plan.plan, points: loadpoints.points, windows: loadpoints.windows, prices: prices.prices, timeZone: loadpoints.zone.identifier, daylight: daylight) | ||
| PlanEntry.live(plan: plan.plan, points: loadpoints.points, windows: loadpoints.windows, prices: prices.prices, timeZone: loadpoints.zone.identifier, daylight: daylight, | ||
| levels: plan.forecast.compactMap { f in f.levelPct.map { (f.startMs, f.startMs + f.durationMs, $0) } }) |
There was a problem hiding this comment.
Do not apply cached levels to a fresh plan
On boxes that predate socPermille, reopening the app within the cached forecast horizon can combine a newly received plan with stale battery levels: PlanModel initializes forecastStamp from the persisted forecast, while Now calls plan.activate() without requesting a new forecast. Because this line matches that cached document to the fresh plan solely by timestamps, Now can report percentages from an earlier plan after the mode or forecast has changed. Only use a current-session forecast that corresponds to this plan, or omit the fallback level when its provenance cannot be established.
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>
Plan pass, change 2 of 5: the plan says where the battery ends up. Stacked on change 1 (#57). The box half is srcfl/ftw#1630, merged and in FTW v0.143.0-beta.1: each
plan.getslot now carriessocPermille, the level the planner expects at the slot's end.What changes
A finger on the strip or the dial reads the level with the rest of the quarter:
The sentence on Now says the level only when it is news: a charge that ends full (98 % or more), or a discharge that ends as low as the battery gets in the hours ahead. Else the line stays as short as it was.
The story under the dial says it for every move:
The lanes draw the level as a dashed line above the bars, with "batteriets nivå" in the legend.
Where the level comes from
The wire first:
PlanSlot.socPermillefromplan.get. A box older than v0.143.0-beta.1 sends none, so the app falls back to the planner'ssocin/api/mpc/plan, which it reads already. With neither, nothing says a level; the app never guesses one. The registry owns no plan field names, so nothing changes inprotocol/registry.yaml.Evidence
swift test: FTWShared 217 and FTWKit 367 tests green. New: a finger reads where the battery is; the level is said where it matters and not elsewhere; the dial's middle says it;socPermilleround-trips on the wire; the entry takes the level from the wire or else the planner.NowFitsTests11 of 11,PlanStripTests3 of 3,PlanDialTests3 of 3.Pictures
The plan view, dark, light and the largest text: each move says where it leaves the battery.
A finger across the strip on Now, then round the dial: the readout ends with the level.
The lanes, dark and light, with the level as a dashed line.
🤖 Generated with Claude Code