Skip to content

Keep a way back to the plan after Self (manual) - #57

Merged
frahlg merged 4 commits into
mainfrom
cursor/restore-optimal-plan-mode-8480
Sep 12, 2026
Merged

frahlg merged 4 commits into
mainfrom
cursor/restore-optimal-plan-mode-8480

Conversation

@frahlg

@frahlg frahlg commented Aug 31, 2026

Copy link
Copy Markdown
Member

After choosing Self (manual), the Plan screen now keeps the active fallback visible, names its state, and offers Use the plan to restore the first primary planner mode. The manual drawer folds after a selection. Viewers can see the current mode but cannot change it.

Mode choices and Use the plan stay disabled while a request awaits its result, with Sending… on the requested mode. The store also refuses overlapping sends. This fixes the remaining review finding: two quick requests could share a control revision, so Core accepted the first and rejected the intended correction. Nothing queues or replays a control command.

Validation on current main: 35 focused Plan tests pass; npm run verify passes (1,033 tests, one skipped); shared registry and token checks pass. The first full run hit the existing escrow timing test's 5-second deadline during a concurrent Core run; the unchanged full suite passed after that load ended. Browser review against the local protocol simulator covered More ways → Self (manual), visible Sending state with disabled choices, confirmed In use, and Use the plan → confirmed Passive arbitrage. No physical device or deployment validation is claimed.


Note

Medium Risk
Changes site dispatch mode commands and concurrency guards on the client; mistakes could block valid switches or send conflicting control revisions to the box.

Overview
Plan screen when a manual fallback is active (e.g. Self (manual)): shows a short message and Use the plan, which switches to the box’s first primary mode (planHome, typically passive arbitrage). Viewers still see the message but not the action button.

Mode picker UX keeps the selected manual mode visible when the “More ways” drawer is closed, collapses the drawer after picking a manual mode, and labels the active choice with In use or Sending… so taps read clearly while other choices stay disabled during send.

PlanStore adds inManual / planHome (driven by shownMode for optimistic UI) and tightens setMode to ignore duplicate targets and any second call while a mode change is already sending, avoiding overlapping control commands. SimBox accepts an optional starting mode for tests; store and view tests cover the new flows.

Reviewed by Cursor Bugbot for commit 54fe612. Bugbot is set up for automated code reviews on this repo. Configure here.

Choosing a fallback hid the next step: the planner cards stayed on
the page but nothing said they were the way out, and the tap itself
only dimmed. A house already on Self (manual) now gets an In use
mark, Sending while the command is in flight, and a Use the plan
button that restores the first primary mode.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 31, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ftw-webapp 54fe612 Commit Preview URL

Branch Preview URL
Sep 12 2026, 10:20 AM

Choosing Self (manual) used to leave the extras open, so the way back
scrolled off under Idle, Peak and Charge. The selected fallback already
renders when the drawer is closed; fold the extras on the tap.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@frahlg
frahlg marked this pull request as ready for review August 31, 2026 04:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T04:58:03.918027Z 771ebcc Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 771ebccb72

ℹ️ 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".

Comment thread src/views/Plan.svelte Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 771ebcc. Configure here.

Comment thread src/lib/state/plan.svelte.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not approved: Cursor Bugbot was present but skipped, so the required automated-review signal did not complete successfully. Reviewers were assigned for human review.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor
cursor Bot requested review from Leitet and davmoz August 31, 2026 05:01
frahlg added a commit to srcfl/ftw that referenced this pull request Aug 31, 2026
Master replaced the Passive/Active strategy pair with the household
prefs on the Plan card -- the trust slider and the battery-sale
permission -- and renderModeCatalog now skips every planner_ key, so
the primary row renders empty and hides itself. That left no control
anywhere in the dashboard that starts planning again: once a house sat
in a manual mode it stayed there, while the card told it to "select a
planning strategy" that no longer exists. Only HA, the phone app or the
API could get it out. The phone app already shipped the answer
(srcfl/ftw-webapp#57); the dashboard never got it.

"Use the plan" appears on the card whenever a manual mode drives, and
hands the house to the planner mode its own preference implies. The
server owns that mapping -- GET /api/planner/prefs returns mapped_mode
-- so the button never decides whether this battery may sell. A prefs
read that fails or answers with anything else falls back to the passive
mode: permission to sell is a deliberate household answer, never a
default. The button routes through setMode, so the optimistic paint and
the pending-mode hold behave as they do for any tap, and it is disabled
with the planner's own reason when MPC cannot run, matching Replan.

Both manual sentences now name the button that exists.

Verified in a browser against a local box with the planner enabled:
export allowed -> planner_arbitrage; export not allowed ->
planner_passive_arbitrage (real mouse click); prefs read rejected ->
passive even though permission was on file; the button hides itself as
soon as the planner drives, and is dimmed with "not-allowed" when the
planner is off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi
frahlg added a commit to srcfl/ftw that referenced this pull request Aug 31, 2026
* fix: keep Manual… visible after leaving the planner

Simple view hid the fallback buttons behind .advanced-only, so a
house already on Self (manual) had no selected strategy and no way
back. The toggle and the button row stay on the Plan card, open when
the live mode is a fallback, and mark the tap before the POST.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

* fix(web): auto-open the manual drawer only on a mode change

The status poll runs every couple of seconds and carried the same mode
each time, so revealManualModes forced the drawer back open a second
after someone pressed Hide manual. Reveal now returns early when the
mode has not changed since the last reveal, which leaves an explicit
collapse alone while a move to a different manual mode still puts that
button on screen. The tracker is recorded only once the mode catalog
has painted: before that a missing button means "not rendered yet", and
recording it would make the catalog's own call a no-op and leave a
manual house with a closed drawer -- the bug this branch set out to fix.

A tap also holds its optimistic paint for up to four seconds, so a
status read already in flight with the previous mode can no longer
flash the old button back. The hold clears on server confirmation, on
expiry, or when the write fails.

Verified in a browser against a local box: a manual live mode opens the
drawer on load, Hide manual survives four polls, an external mode change
reopens it, and a tapped strategy stays marked from the tap onwards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi

* feat(web): give a manually-driven house a way back to the plan

Master replaced the Passive/Active strategy pair with the household
prefs on the Plan card -- the trust slider and the battery-sale
permission -- and renderModeCatalog now skips every planner_ key, so
the primary row renders empty and hides itself. That left no control
anywhere in the dashboard that starts planning again: once a house sat
in a manual mode it stayed there, while the card told it to "select a
planning strategy" that no longer exists. Only HA, the phone app or the
API could get it out. The phone app already shipped the answer
(srcfl/ftw-webapp#57); the dashboard never got it.

"Use the plan" appears on the card whenever a manual mode drives, and
hands the house to the planner mode its own preference implies. The
server owns that mapping -- GET /api/planner/prefs returns mapped_mode
-- so the button never decides whether this battery may sell. A prefs
read that fails or answers with anything else falls back to the passive
mode: permission to sell is a deliberate household answer, never a
default. The button routes through setMode, so the optimistic paint and
the pending-mode hold behave as they do for any tap, and it is disabled
with the planner's own reason when MPC cannot run, matching Replan.

Both manual sentences now name the button that exists.

Verified in a browser against a local box with the planner enabled:
export allowed -> planner_arbitrage; export not allowed ->
planner_passive_arbitrage (real mouse click); prefs read rejected ->
passive even though permission was on file; the button hides itself as
soon as the planner drives, and is dimmed with "not-allowed" when the
planner is off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi

* style(web): keep the Plan card's controls to a readable column

The card is as wide as the chart below it. A slider and four buttons
stretched across that width read as a banner rather than as something
to touch, and the help text under them ran to a line nobody wants to
follow. Slider, export row, manual drawer and the rules between them
now share a 560px column, prose caps at 70ch, and "Use the plan" takes
the accent and only the width its label needs -- so the card has one
obvious action instead of a full-width bar.

Moves that button's accent rule from style.css to app.css, beside the
Plan card's other prefs styling and modelled on #plan-export-allow; the
disabled state is left to the mode buttons' existing opacity rule. The
strategy hint is hidden while empty, so the planner no longer leaves a
bordered blank strip where a manual mode's description goes.

Checked in a browser at both themes, in a manual mode and under the
planner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1d4uknzs7QUv7nE9rW4fi

---------

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

@miravoss26 miravoss26 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds a way back from a manual mode (Self, Idle, Peak, Charge) to the plan in the Plan view, plus fixes a real race: PlanStore.setMode could let an earlier in-flight command's result paint over a later one's UI state.

  • Correctness: the #cmdGen sequence-number guard is the right fix for the race — each setMode call is tagged, and a stale call's callback bails if a newer one has since started. Test does not let an earlier mode change paint over a later one exercises this directly with a held promise + mocked site.command, which is a solid way to prove the ordering. inManual/planHome derive from shownMode rather than actualMode, matching the stated intent (optimistic UI, "hides the manual banner at once, rather than waiting for the box to confirm").
  • UI: viewer role is correctly excluded from the "Use the plan" button and the mode buttons stay disabled (covered by the does not offer Use the plan to a viewer test).
  • Security: no secrets, no new dependencies, no new network destinations — pure client-side state/UI change.
  • CI: green (one skipped Bugbot check, rest pass).

Safe to merge from my read.

…l-plan-mode-8480

Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_4a165923-a365-431e-ab67-46ef28b59fee)

@frahlg
frahlg merged commit cbc524d into main Sep 12, 2026
4 checks passed
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.

3 participants