Skip to content

[Bug]: Side chat lets users select Full access but silently runs its first turn as Supervised #28110

Closed

Description

@Wiktor102

What happened

When creating an empty side chat from the side panel, the composer lets the user enter a prompt, select a model, and explicitly select Full access before sending. The server nevertheless runs the first turn as Supervised, so the selected permission mode does not describe the permissions actually used.

Reported with Muse Spark / Meta models. Source inspection shows that the first-turn override is provider-independent; other providers have not been reproduced.

Steps to reproduce

  1. Open a thread and create an empty side chat from the side panel.
  2. In the side chat, enter a prompt that requires a shell command or file change.
  3. Select a Muse Spark model and explicitly select Full access in that side chat's composer.
  4. Send the first message.
  5. Observe approval requests despite the explicit Full access selection.

Expected behavior

The permission picker should accurately communicate the mode that will govern the turn.

If the first turn must be Supervised, make that restriction visible before sending and prevent the picker from implying that Full access will apply. Alternatively, if an explicit user selection is intended to override the default, honor that selection. The issue is the silent mismatch; it does not require removing the intentional first-turn restriction.

Source evidence

Inspected at commit 79f1fadfc6:

  • ThreadForkService.ts creates side chats in approval-required mode.
  • ChatView.tsx persists the explicitly selected runtime mode.
  • ProviderTurnStartService.ts overrides the effective mode to approval-required for the side chat's first turn or the turn receiving its initial context, without checking whether the user explicitly selected Full access.
  • ProviderTurnStartService.test.ts explicitly covers this restriction, including a provider switch, and expects later turns to follow the thread's mode.

The restriction was introduced intentionally in #26901. Its code comment says: "A side chat shares its parent's worktree; the turn that gets its context asks before acting."

Verification limits

The reproduction above is the user's report. The explanation was verified through source, existing tests, and git history. No additional live Muse turn or browser reproduction was performed while filing this issue. The user's installed version was not provided.

Filed on the user's behalf by GPT-6.1 Sol through the Codex harness in T3 Code.

Activity

  1. Wiktor102 commented on Oct 31, 2026

    @Wiktor102
    ContributorAuthor

    Additional finding: this can also break follow-up messages in a Muse side chat, beyond the permission-picker mismatch.

    Confirmed runtime failure

    The user reported a side chat whose follow-up displays:

    The provider could not start this turn. Retry the turn; if it keeps failing, check the provider setup and server logs.

    Read-only inspection of the matching side chat's persisted state and server trace confirms:

    • Model: muse-spark-1.3-contributor, reasoning effort max.
    • Stored thread permission mode: full-access.
    • Turn 1 completed, requested at 2026-10-31T11:37:03.644Z.
    • Turn 2 failed, requested at 2026-10-31T11:40:21.062Z.
    • The underlying error is ProviderAdapterTurnStartError, caused by ProviderAdapterProtocolError with detail Runtime policy changes require a fresh Muse host.
    • The runtime trace identifies T3 0.1.6-nightly.20261031.3969.

    Cause

    Source inspection at 79f1fadfc6 explains the failure:

    1. The side chat's first turn is forced to Supervised, so its Muse host starts with approval-required.
    2. The thread retains the user's explicit full-access selection.
    3. On a later turn, the first-turn restriction no longer applies, so the effective policy becomes full-access.
    4. ProviderSessionManager.open returns the existing runtime for the session without reconciling its launch-time runtime policy.
    5. MuseAdapter.start rejects the turn because its requested mode differs from the host's launch mode.

    The user does not need to change permissions between messages to trigger this. The first-turn override itself creates the transition from Supervised to the selected Full access mode. The host must be restarted and the native session resumed when this transition requires it.

    Provider scope

    The first-turn override and the resulting mismatch with the picker are provider-independent. This follow-up failure is confirmed for Muse through the actual server trace.

    Other adapters handle permissions differently: Codex supplies approval/sandbox settings per turn, and Claude has session reconfiguration/recreation logic. Those source differences do not establish that every other provider is unaffected. No cross-provider runtime reproduction was performed.

    A search found no existing issue or PR specifically tracking this Muse side-chat follow-up failure. #20739 and #23232 concern Muse Auto mode and do not address this transition.

    Investigation by GPT-6.1 Sol through the Codex harness in T3 Code.

  2. ignaciomontenegroc commented on Nov 1, 2026

    @ignaciomontenegroc

    Additional report with Codex on Windows, collected on 2026-11-01.

    Reported behavior

    New side chats start in Supervised even though my saved default is Auto, so I have to change the mode manually each time. After selecting Auto or Full access in a side chat, I still encounter repeated permission prompts. Please include Codex in the affected-provider scope of this report.

    Verified environment

    • T3 Code desktop and bundled server: 0.1.6, confirmed from both installed ASAR package manifests and the live server API.
    • Windows 11, OS version 10.0.26100, x64.
    • Codex CLI: 0.166.0, using the configured local Codex binary.
    • Model: gpt-6.1-sol, high reasoning effort.
    • Saved defaultRuntimeMode: auto. The reporting chat also currently reports runtimeMode: auto.

    Sanitized local diagnostics

    Read-only inspection of the T3 state database found:

    • One Codex side chat currently saved as full-access: first run 2026-11-01 09:45:03.281Z–09:46:41.194Z. A command approval request was created at 09:45:12.674Z, and two mcp-elicitation requests followed during that first run. Its next two runs completed without entries in the runtime-request table.
    • Another Codex side chat currently saved as auto: first run 10:01:23.056Z–10:02:29.887Z, with four command approval requests and two mcp-elicitation requests. Its next two runs completed without entries in that table.
    • An unused Codex side chat is still saved as approval-required, despite the global Auto default.

    The saved mode is the mode at diagnostic collection time, not a historical snapshot proving the mode at every earlier request. The before-send mode selection is the user's report. MCP elicitation is listed separately because its presence alone does not establish a shell-approval policy failure.

    Matching release source

    The release tag v0.1.6 still contains both behaviors:

    Expected behavior and limits

    Remember or honor my preferred mode for new side chats, and make any enforced first-turn restriction clear in the picker before sending. Selecting Auto or Full access should accurately describe the effective permissions, subject to any explicitly disclosed restriction.

    These records support the first-turn mismatch tracked here. They do not establish that later Codex turns ignore Full access, and no new agent run was launched to reproduce it during collection. Claude was not tested. Raw databases, conversation text, project paths, credentials and unfiltered logs are not attached.

    Related usability request

    I would also like one keyboard shortcut that directly opens a new side chat, including when the right panel is closed, without first opening the panel and its New menu.

  3. aoppenh1-afk commented on Nov 1, 2026

    @aoppenh1-afk

    Additional report from T3 Code Desktop 0.1.7-nightly.20261101.4016 on macOS arm64.

    Creating side chats with /side starts them in Supervised mode despite my Full access settings. I encounter this with both Claude Code and Codex.

    Please provide either a separate default approval setting for side chats or an option to inherit the main thread’s approval mode. Making the first-turn restriction visible would clarify the current behavior, but would not address this preference.

    Read-only investigation found both side chats currently stored as approval-required, with their parent threads stored as full-access. Source at 7195b699547b538e49f758e314dde5c8c5d907cf explicitly sets that default in ThreadForkService.ts and enforces first-turn supervision in ProviderTurnStartService.ts.

    No settings or database records were changed, and no new live provider turn was run during investigation.

    Investigated by GPT-6.1 Sol through the Codex harness in T3 Code.

  4. ElliotDrel commented on Nov 1, 2026

    @ElliotDrel
    Contributor

    Note

    🤖 gpt-6.1-sol responding on behalf of Elliot

    Additional observed variant on Windows desktop with Codex / GPT-6.1 Sol: creating a side chat from a parent in Auto mode persisted the child as approval-required (Supervised). The child then requested approval for a read-only shell search and t3_thread_read. This was verified from local persisted state and the activity API, rather than inferred from the composer label. No explicit permission change was reported by the user.

    This adds the automatic inheritance/default case to the explicit Full access picker case above. Given the intentional first-turn restriction described in this issue, the UX should explain the mode change before sending and communicate which mode subsequent turns use. This observation does not establish that the intentional restriction itself is a bug.

    Private identifiers, local paths, conversation content, and screenshots have been omitted.

  5. ElliotDrel commented on Nov 1, 2026

    @ElliotDrel
    Contributor

    Note

    🤖 gpt-6.1-sol responding on behalf of Elliot

    Clarifying Elliot's requested behavior: a side chat should inherit the current parent thread's permission mode, including its first turn. Creating a side chat should not silently change Auto or Full access to Supervised. If the user explicitly changes the side chat's permissions, honor that selection.

    The shared-worktree rationale does not match the behavior Elliot wants: he has already chosen the parent's permissions and expects that choice to carry into the side chat. A warning explaining the forced restriction would not satisfy this request; the requested change is permission inheritance and removal of the unconditional first-turn override.

  6. exgota commented on Nov 1, 2026

    @exgota

    +1. I run full access on everything. Side chats should inherit the parent's mode, first turn included.

    If the worktree risk matters, make it a setting: side chat default, inherit or supervised.

  7. jaykaycodes commented on Nov 3, 2026

    @jaykaycodes

    Another location, on 0.1.6 and current main, with Claude Code on Linux (server) and the web client.

    There are two hardcoded overrides, not one. The server forces the first run (

    thread:
    projection.thread.lineage.sideChat === true &&
    (sideChatHandoff !== undefined ||
    !projection.runs.some((previous) => previous.ordinal < run.ordinal))
    ? { ...projection.thread, runtimeMode: "approval-required" }
    : projection.thread,
    ), and the web client also sends runtimeMode: "approval-required" when it sends a side chat's first message:

    runtimeMode: "approval-required",

    The client value is persisted on the thread, so the whole side chat stays Supervised, not just its first turn. In our thread store, every side chat is approval-required while all 694 other user and subagent threads are full-access, which matches our "Default permissions for new threads" setting. The Claude process for each later turn starts with --permission-mode default, against bypassPermissions for normal threads. Subagents a side chat delegates also land in approval-required.

    Suggested fix: send the parent thread's runtime mode (or the default from settings) from useSideChat.ts and drop the server override, or make it a setting as suggested above.

  8. KorenKrita commented on Nov 3, 2026

    @KorenKrita

    +1. A side chat should inherit the parent thread's current permission mode, including its first turn.

    If I've set the parent to Full access or Auto, opening /btw / /side should not quietly drop me to Supervised. Then I get approval prompts for read-only actions such as reading the parent thread. If I explicitly change the mode in the side chat, honor that selection instead.

    A separate side-chat default (as in #29300) is useful, but I'd like "inherit from parent" to be an option, ideally the default. Forcing Supervised on the first turn defeats the point of a quick aside.

  9. ondrej-merkun commented on Nov 4, 2026

    @ondrej-merkun

    +1

  10. satyalyadav commented on Nov 4, 2026

    @satyalyadav
    Contributor

    Additional reproduction on 0.1.8-nightly.20261104.4179, with the OpenCode provider.

    What happened

    Created a side chat, set its composer to Full access, and sent the first message. The mode change was accepted and the thread persisted runtimeMode: "full-access", but the first reply still asked for approval on every shell command and file read.

    Timeline (UTC, 2026-11-04)

    • 19:25:33 side chat created in approval-required
    • 19:30:04.593 thread.runtime-mode.set to full-access accepted, thread projection updated
    • 19:30:04.673 first run created (ordinal 1), provider OpenCode
    • 19:30:13.044 first command approval request; 5 more command requests and 2 file-read requests followed through 19:33:13.804
    • 19:30:23.465 one request answered with allow-for-session; later requests still appeared
    • 19:35:17.881 first run completed

    The live OpenCode session had shell * ask, edit * ask, and external_directory * ask rules installed while the thread said Full access, so the provider received the supervised policy.

    Environment

    • Desktop client 0.1.8-nightly.20261104.4179, Windows
    • Server 0.1.8-nightly.20261104.4179, local, WSL2 Linux, Node v26.12.1
    • Provider OpenCode, opencode-go/deepseek-v4.1-flash

    Source

    At release commit 9e85538 for this build, apps/server/src/orchestration-v2/ProviderTurnStartService.ts (around line 703) replaces the thread mode with approval-required for a side chat's first run or a run receiving its initial context. It does not check whether the user chose Full access. apps/server/src/orchestration-v2/ThreadForkService.ts line 117 creates side chats in approval-required.

    The docs already say a side chat's first reply asks before acting, so the restriction may be intended. The bug is that the picker reports Full access and the server silently uses Supervised.

    Still present on main as of commit 95e53a5.

    Reported by DeepSeek V4.1 Flash through a T3 Code triage session.

  11. hamu-dev commented on Nov 6, 2026

    @hamu-dev

    Confirmed, and I traced the mechanism in source at main 337c5858. The desktop app, the local server, and the linked environment's server all run 0.1.8-nightly.20261105.4205.

    Three choices combine here:

    1. The client hardcodes the first turn's mode. apps/web/src/components/chat/useSideChat.ts starts every side chat turn 1 with runtimeMode: "approval-required", whatever the picker shows.

      // The server asks before edits on a side chat's first turn whatever mode is sent.
      runtimeMode: "approval-required",
    2. Pi keeps one mode for the life of the session. packages/provider-pi/src/server/adapter.ts declares supportsRuntimeModeSwitchInSession: false, documented as "Restart on mode changes so the permission hook retains one immutable lifetime policy". Switching the picker to Full access affects turn 2, after the restart. The running turn stays approval-required.

    3. Pi's injected hook exempts only read-only-annotated tools. In packages/provider-pi/src/server/mcpExtensionSource.ts, the pi.on("tool_call", …) handler returns early only for full-access, known read-only builtins, or MCP tools with readOnlyHint: true. Everything else prompts.

    Also, t3_thread_read, which the UI shows as "Reading thread", is annotated Tool.Readonly, false in apps/server/src/mcp/toolkits/orchestrator/tools.ts because reading a child's final result marks it delivered. Pure thread reads prompt too, although the comment in useSideChat.ts says the intent is "asks before edits". #23918 may be related. It reports the same tool prompting repeatedly.

    One design question. Pi aims to be a minimal coding agent and has no permission system of its own. mcpExtensionSource.ts says it directly: "Pi deliberately leaves permission policy to extensions." T3 injects the whole policy, which is fine, but the side chat then overrides an explicit user choice for an entire turn. On pi the override cannot be lifted mid-turn, because the mode is frozen per session. The user already picked a mode in the composer, so the forced first turn adds little protection. If turn 1 must stay guarded, two smaller fixes would keep most of the value: exempt read-only-annotated MCP tools such as t3_thread_read, or show the running turn's effective mode in the composer instead of the thread mode.

    Environment. linux x64, WSL2 Debian. Desktop app 0.1.8-nightly.20261105.4205 against a local server. The side chat forked from a parent thread on a linked environment, both servers on the same nightly. Provider pi, custom instance, zai/glm-5.3-flash, orchestration protocol v2.

    Workaround. Approve once per side chat. From turn 2 the session restarts under Full access and stops prompting. A regular thread avoids the forced first turn.

    Filed by: glm-5.3-flash (zai) via the pi coding agent, t3 triage on the user's machine.

  12. ThatOneToast commented on Nov 6, 2026

    @ThatOneToast

    Additional user feedback: I observed that switching permission modes (Supervised, Auto, Bypass/Full access, etc.) did not seem to take effect during a /side question using Astra. Please make the selected mode take effect when supported. If switching is unavailable in that situation, gray out the unavailable options and explain why in the interface. I usually run normal chats in bypass mode, so I cannot say whether normal chat has the same problem. I have not independently verified whether this was limited to the first side-chat turn or a later turn.

  13. juliusmarminge commented on Nov 9, 2026

    @juliusmarminge
    Member

    Thanks for the detailed reports. #31114, merged as 725cfc9, removes the first-turn Supervised override and honors the side chat’s selected mode, including when context is delivered. Please open a separate issue if mode switching still fails on a current build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions