acpmux: a new chat starts at the default, not the last mode picked in a running chat

Merged
TE
11d ago
+238-491

Ready. Codex (gpt-6.1-sol, xhigh) review: SHIP at b44e72820bb902fdb2fa7980bdf12aff79a777e2.

Leo-ask: ask-16f0b7197f

Leo, 2026-10-21: "i think starting in full access is ok cuz the default for new chats != whatever u just temp set in an existing running chat" and "u can set default in other ways". (Earlier in the ask: "by default, we just want to be allowing tons of bullshit, right? ... That's the fucking ethos.")

Takes back #21734: its "latest choice wins" rule. A mode picked in a running chat became the start mode of every new chat (Lawrence 2026-10-14: "should always use the latest user selected one"). Leo now says a temporary pick in a running chat is not the default.

What changes

  • A mode picked in a chat applies to that chat only. acpmux no longer saves it as lastPermissionMode, and new chats no longer start from it.
  • New chats start, as before, at the MDM/team-forced value, else config.json defaultPermissionMode, else the agents.defaultPermissionMode setting (default Full Access). With sessions.allowFullAccess off, full access still starts as Standard.
  • The explicit ways to set the default all still work: Settings > Agents > Agent Chat > Permission Mode for New Chats (and cmux config set agents.defaultPermissionMode), MDM/team values pushed by the app, and acpmux config.json defaultPermissionMode. There is no other "set as default" action for the permission mode.
  • A lastPermissionMode left in config.json by an older build is ignored. An old start-mode.json still loads.
  • The pending-chat mode chip (webview) no longer copies a pick from another chat.
  • Settings help text: "What a new chat may do without asking. A mode you pick in a chat applies to that chat only." I wrote the 21 locale strings myself; they need a check.
  • Not touched: the acpmux PermissionPolicy, policy narrowing, presets, folder profiles, Web chats, and the model/effort picks.

Tests

  • tests/start_mode.rs: a_pick_in_a_chat_holds_for_that_chat_and_new_chats_start_in_the_default (replaces the latest-pick test); start-mode answer and watcher tests updated.
  • tests/start_mode_settings.rs: a_last_permission_mode_an_older_build_saved_is_ignored (new); the settings-file test now checks that a pick changes only its chat; spent-pick test removed.
  • webviews/test/agent-pane-start-mode-chip.test.ts: the chip shows the default, not another chat's pick.

Command: cmux-ci run --class light --script scripts/ci/cargo-test-selected.sh --arg=--manifest-path --arg=cmux-tui/Cargo.toml --arg=-p --arg=acpmux --arg=--test --arg=start_mode --arg=--test --arg=start_mode_settings --arg=--test --arg=full_access_setting --ref <sha>. The isolated fleet queue stalled for hours, so PR CI at the head is the evidence: the start_mode, start_mode_settings and full_access_setting tests pass there.

Observed / Not run

  • Observed: rustfmt clean on the changed Rust; pre-push gate passed.
  • Observed: PR CI at the head runs the cargo tests above and they pass.
  • Generated settings-schema.json and docs/mdm are left to the autofix.

Base reds (warnings, not this PR)

  • remote_guard_codex_bridge (2 tests): the test config sets "permissionPolicy": "ask" and a new chat starts in full access, so refuse_wider_mode (#23639, in base) refuses it. This PR does not touch the test, policy_mode.rs or the policy check.
  • instructions_in_both_modes (MCP instructions length cap), prompt_redraw_fish_two_line (fish timed out waiting for a terminal reply) and server_stop_uses_identify_fence: all in crates this PR does not touch.

No capture: behaviour of the start mode plus one Settings help string; covered by the tests above.

Changelog

Changed: a mode you pick in a running chat no longer becomes the start mode of new chats; set the default in Settings.

Agent session: Air-Blue

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Takes back the "latest choice wins" rule: a mode picked in a running chat now applies to that chat only, and new chats start at the default instead of inheriting it.

  • New chats start at the MDM/team-forced value, config.json defaultPermissionMode, or the agents.defaultPermissionMode setting (Full Access by default), as before.
  • A leftover lastPermissionMode saved by an older build is ignored; an old start-mode.json still loads.
  • The pending-chat mode chip no longer adopts a pick made in another chat.
  • The Settings help text (all locales), settings-schema.json, and MDM exports now describe the per-chat rule; the generated defaults stamp passes.

Migration

  • No action needed; any lastPermissionMode in config.json is simply ignored and dropped at the next save.