Skip to content

🐛 Fix Claude permission mode drift between session state and web UI#145

Merged
Robdel12 merged 1 commit intomainfrom
mission/robdel12-orbitdock#135
Mar 24, 2026
Merged

🐛 Fix Claude permission mode drift between session state and web UI#145
Robdel12 merged 1 commit intomainfrom
mission/robdel12-orbitdock#135

Conversation

@Robdel12
Copy link
Copy Markdown
Owner

Summary

  • The web UI was using approvalPolicy (Codex concept: ask/auto-edit/auto-full) to display Claude's permission mode pill, instead of the actual permission_mode (default/plan/acceptEdits/bypassPermissions/dontAsk) that the server already emits
  • When Claude entered plan mode during a live session, the status pill would still show the old approval policy value — users couldn't tell which mode was actually active
  • The server contract was already correct (emits permission_mode in both REST SessionState and WS SessionDelta), but the web frontend never consumed it

Changes

  • stores/sessions.js — Add permission_mode to handleSessionDelta so WS delta updates flow into the session store
  • pages/session.jsx — Replace approvalPolicy local state with permissionMode seeded from selected.value?.permission_mode (updated via store deltas); PATCH /api/sessions/:id/config now sends permission_mode instead of approval_policy
  • components/input/message-composer.jsx — Status pill now renders Claude permission modes with correct labels (Plan Mode, Default, Accept Edits, Bypass, Don't Ask) and cycles through real modes on click
  • components/input/provider-controls.jsxClaudePermissionPicker options updated to match real Claude permission modes
  • tests/stores/sessions.test.js — 4 new tests covering permission_mode delta application, null-clear, preservation when absent, and resume propagation

What didn't change

  • No server changes — the server already models permission_mode correctly through the connector event system, persistence, and broadcasts
  • No native (Swift) changes — the Swift client already uses permissionMode throughout (reducer, store events, ClaudePermissionPill UI)

Test plan

  • All 85 web unit tests pass (including 4 new permission_mode tests)
  • Lint passes on all changed files (0 new errors)
  • Manual: start a Claude session, enter plan mode → verify the status pill updates to "Plan Mode"
  • Manual: exit plan mode → verify the pill returns to the correct active mode
  • Manual: reconnect/resume a session → verify the pill shows the correct current mode

Closes #135

The web UI was reading `approvalPolicy` (a Codex concept with values
`ask`/`auto-edit`/`auto-full`) instead of Claude's actual
`permission_mode` (`default`/`plan`/`acceptEdits`/`bypassPermissions`/
`dontAsk`). The server already emits permission_mode in both REST
SessionState and WS SessionDelta, but the web frontend never consumed
it — so the mode pill could show stale or wrong state even when Claude
entered plan mode during a live session.

Changes:
- sessions store: propagate `permission_mode` through delta handler
- session.jsx: seed and track `permission_mode` from the store instead
  of `approvalPolicy`; PATCH `/config` with `permission_mode`
- message-composer.jsx: render status pill from `permissionMode` with
  correct Claude mode labels (Plan Mode, Accept Edits, Bypass, etc.)
- provider-controls.jsx: update ClaudePermissionPicker options to
  match real Claude permission modes
- Add unit tests for permission_mode delta, null-clear, preservation,
  and resume propagation

Native (Swift) was already correct — no changes needed there.

Closes #135
@Robdel12 Robdel12 merged commit 94d1b09 into main Mar 24, 2026
3 checks passed
@Robdel12 Robdel12 deleted the mission/robdel12-orbitdock#135 branch March 24, 2026 05:22
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.

🐛 Fix Claude live permission mode drift between session state and UI

1 participant