fix: map runtime modes to correct permission levels#1587
fix: map runtime modes to correct permission levels#1587juliusmarminge merged 12 commits intopingdotgg:mainfrom
Conversation
…pt-edits mode Sessions launched without --dangerously-skip-permissions crashed when switching away from full-access because the fallback always tried to restore bypassPermissions. Map each runtime mode to its proper Codex approval policy / sandbox pair and Claude SDK permission mode, and expose the new auto-accept-edits option in the UI. Fixes pingdotgg#1437 Fixes pingdotgg#1241
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
setRuntimeMode had an explicit allowlist that missed "auto-accept-edits", converting it to null. Replace with nullish coalescing since TypeScript already constrains the parameter to RuntimeMode | null | undefined.
juliusmarminge
left a comment
There was a problem hiding this comment.
seems mostly fine apart from the test
| for (const [runtimeMode, expectedBase] of [ | ||
| ["full-access", "bypassPermissions"], | ||
| ["approval-required", "default"], | ||
| ["auto-accept-edits", "acceptEdits"], | ||
| ] as const) { | ||
| it.effect(`restores ${expectedBase} permission mode after plan turn (${runtimeMode})`, () => { |
|
Julius, I also noticed that adding this mode caused the MCP tool approval bug to appear. I asked Claude if it is actually connected with the change I made, and here is the response:
Would you like me to fix that here as well, or create a new PR focusing on fixing the pre existing bug? |
|
File a new PR please 🙏🏽 |
apps/web/src/components/ChatView.tsx
Outdated
| void handleRuntimeModeChange( | ||
| runtimeMode === "full-access" ? "approval-required" : "full-access", | ||
| ); | ||
| const cycleRuntimeMode = useCallback(() => { |
There was a problem hiding this comment.
is a toggle button the best way? A select with a short description might be better?
https://coss.com/ui/docs/components/select#with-object-values
There was a problem hiding this comment.
Yeah maybe, let me check how it would look and I'll post a screenshot here so we can decide.
There was a problem hiding this comment.
It could work, wdyt?
ApprovabilityVerdict: Needs human review This PR changes how existing runtime modes map to permission levels (e.g., 'approval-required' now maps to more restrictive 'untrusted'/'read-only' instead of 'on-request'/'workspace-write') and adds a new 'auto-accept-edits' mode. These are significant runtime behavior changes affecting the permission/sandbox system that warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Co-authored-by: codex <codex@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6707b61. Configure here.
| "auto-accept-edits": "acceptEdits", | ||
| "full-access": "bypassPermissions", | ||
| }; | ||
| const permissionMode = runtimeModeToPermission[input.runtimeMode]; |
There was a problem hiding this comment.
Implicit undefined for approval-required lacks exhaustiveness safety
Low Severity
The runtimeModeToPermission map is typed as Record<string, PermissionMode> and intentionally omits "approval-required", relying on undefined to propagate through truthy checks and ?? "default" fallbacks. Unlike the Codex adapter's mapCodexRuntimeMode switch statement which gets TypeScript exhaustiveness checking, this string-keyed Record provides no compile-time guarantee that all RuntimeMode values are accounted for. If a new runtime mode is ever added, it would silently fall through to undefined / "default" behavior without any compiler warning. Making this a complete map over RuntimeMode (mapping "approval-required" explicitly to "default") would make the intent clear and get exhaustiveness checking from TypeScript.
Reviewed by Cursor Bugbot for commit 6707b61. Configure here.
…threadId (#2) * Raise slow RPC ack warning threshold to 15s (pingdotgg#1760) * Use active worktree path for workspace saves (pingdotgg#1762) * Stream git status updates over WebSocket (pingdotgg#1763) Co-authored-by: codex <codex@users.noreply.github.com> * fix(web): unwrap windows shell command wrappers (pingdotgg#1719) * Rename "Chat" to "Build" in interaction mode toggle (pingdotgg#1769) Co-authored-by: Julius Marminge <julius0216@outlook.com> * Assign default capabilities to Codex custom models (pingdotgg#1793) * Add project rename support in the sidebar (pingdotgg#1798) * Support multi-select pending user inputs (pingdotgg#1797) * Add Zed support to Open actions via editor command aliases (pingdotgg#1303) Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> * Closes pingdotgg#1795 - Support building and developing in a devcontainer (pingdotgg#1791) * Add explicit timeouts to CI and release workflows (pingdotgg#1825) * fix(web): distinguish singular/plural in pending action submit label (pingdotgg#1826) * Refactor web stores into atomic slices ready to split ChatView (pingdotgg#1708) * Add VSCode Insiders and VSCodium icons (pingdotgg#1847) * Prepare datamodel for multi-environment (pingdotgg#1765) Co-authored-by: justsomelegs <145564979+justsomelegs@users.noreply.github.com> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com> * Implement server auth bootstrap and pairing flow (pingdotgg#1768) Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@macmini.local> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com> * Use dev proxy for loopback auth and environment requests (pingdotgg#1853) * Refresh local git status on turn completion (pingdotgg#1821) Co-authored-by: codex <codex@users.noreply.github.com> * fix(desktop): add Copy Link action for chat links (pingdotgg#1835) * fix: map runtime modes to correct permission levels (pingdotgg#1587) Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> * Fix persisted composer image hydration typo (pingdotgg#1831) * Clarify environment and workspace picker labels (pingdotgg#1854) * Scope git toast state by thread ref (pingdotgg#1855) * fix build (pingdotgg#1859) * Stabilize keybindings toast stream setup (pingdotgg#1860) Co-authored-by: Julius Marminge <julius@macmini.local> * feat(web): add embeddable thread route for canvas tile hosts Adds /embed/thread/:environmentId/:threadId — a standalone route that renders the existing ChatView without the app sidebar chrome. This is the iframe target for t3-canvas agent shapes (see rororowyourboat/t3-canvas#3). - New file-based route embed.thread.\$environmentId.\$threadId.tsx - __root.tsx bypasses AppSidebarLayout for any /embed/* pathname so the environment connection + websocket surface + toasts still initialize but the sidebar/diff/plan chrome does not render - minimal=1 search param is parsed and wired to a data attribute on the container for future targeted CSS; chrome hiding (BranchToolbar, PlanSidebar, ThreadTerminalDrawer) stays as a follow-up pass - routeTree.gen.ts regenerated by the @tanstack/router-plugin --------- Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com> Co-authored-by: legs <145564979+justsomelegs@users.noreply.github.com> Co-authored-by: sonder <168988030+heysonder@users.noreply.github.com> Co-authored-by: Adem Ben Abdallah <96244394+AdemBenAbdallah@users.noreply.github.com> Co-authored-by: Kyle Gottfried <6462596+Spitfire1900@users.noreply.github.com> Co-authored-by: Jacob <589761+jvzijp@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com> Co-authored-by: Julius Marminge <julius@macmini.local> Co-authored-by: Klemencina <56873773+Klemencina@users.noreply.github.com> Co-authored-by: Oskar Sekutowicz <me.oski646@gmail.com> Co-authored-by: Noxire <59626436+noxire-dev@users.noreply.github.com>



What Changed
I fixed running Claude in Supervised mode. Fixing that also made me think we should adjust it for the Codex adapter. I also introduced a new mode inspired by the Claude CLI called “Auto accept edits”. I did not know how to handle the fix without adding this mode because having just "Supervised" which should be read only or full accept mode for the user (to my understanding), and "Full Access" which is a full bypass mode, is probably not enough for some users. Adding this one more mode was low hanging fruit for me, so I thought I could do it here as well. I tried to keep everything simple and focus only on fixing the bug and adding this one mode.
I am not sure if the change to the test, running it in a for loop, is necessary. I am open to suggestions about this and, of course, other changes I made.
I also noticed some other things that could be improved related to that change, but I did not want to make this PR big and difficult to review.
Why
Sessions launched without --dangerously-skip-permissions (Claude) crashed when switching away from full-access because the fallback always tried to restore bypassPermissions. Map each runtime mode to its proper Codex approval policy / sandbox pair and Claude SDK permission mode, and expose the new auto-accept-edits option in the UI.
Fixes #1437
Fixes #1241
Fixes #1609
UI Changes
The only change to UI is new "Auto-accept edits" mode added. Nothing else.
Checklist
Note
High Risk
Changes how runtime modes map to permission/sandbox levels for both Codex and Claude, which directly affects command/file-access enforcement and could unintentionally loosen restrictions if incorrect. Also introduces a new runtime mode that must be handled consistently across server, UI, and persistence.
Overview
Fixes runtime-mode permission mapping across providers and adds a new intermediate runtime mode.
RuntimeModenow includesauto-accept-edits, Codex runtime mapping is updated soapproval-requiredbecomesuntrusted/read-only,auto-accept-editsbecomeson-request/workspace-write, andfull-accessremainsnever/danger-full-access.Claude sessions now map
auto-accept-editsto SDKacceptEdits, and switching back fromplanrestores the correct base permission mode (defaulting todefault, notbypassPermissions). The web composer replaces the binary access toggle with a dropdown showing all three modes plus descriptions, and draft persistence/normalization is updated to accept the expandedRuntimeModeschema.Reviewed by Cursor Bugbot for commit 6707b61. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add 'auto-accept-edits' runtime mode and fix permission level mappings
'auto-accept-edits'as a validRuntimeModeacross the schema, store, server, and UI, sitting between supervised and full-access modes.codexAppServerManager.ts:'approval-required'now maps tountrusted/read-only,'auto-accept-edits'toon-request/workspace-write, and'full-access'tonever/danger-full-access.ChatView.tsxandCompactComposerControlsMenu.tsxwith a labeled dropdown that shows descriptions for all three modes.basePermissionModenow restore to'default'after a plan turn instead of'bypassPermissions'.Macroscope summarized 6707b61.