Switching the per-session permission mode from Auto to Bypass is not honored by the next turn. This reproduces in both a plain chat session (no Goal) and a running task. After the switch, the next turn still executes under the managed/ask boundary: Bash is still sandboxed and the model is still prompted for approval, even though the picker shows Bypass. The boundary the next turn actually runs under is not refreshed to the newly committed configuration before it executes.
Expected: a permission change is observed by the next turn that starts after it, before that turn's first tool call.
How to reproduce
- In any session (a plain chat, no Goal required), switch the permission picker from Auto to Bypass.
- Send / continue so a new turn runs; issue a Bash command or a filesystem write.
- Observed: the command is still sandboxed / the model is still asked to approve; the turn still runs under the managed boundary.
Note: more frequent on long-running/multi-turn tasks — under an active Goal the continuation keeps the session claim busy, which widens the failure window — but it also reproduces in a plain session, so this is not Goal-specific.
Environment
- Maka version or commit:
98bdd6cf8 (main)
- OS and version: macOS 26.5.2
- Surface: Desktop
- Node.js version, if running from source: v26.7.0
Logs, screenshots, or additional context
Root cause (code-traced, high confidence; a regression test is still needed to pin the exact sub-mechanism):
- Tools decide sandboxing/approval from the
executionBoundary they read at call time (packages/runtime/src/tool-runtime.ts readExecutionBoundary; packages/runtime/src/builtin-tools.ts boundary.kind === 'bypass').
- The Auto → Bypass switch commits a new configuration via
transitionSessionConfiguration, but the next turn does not observe it: ctx.permissionMode is frozen in the backend/composer at build time (tool-runtime.ts this.input.header.permissionMode; execution-model-composition.ts composer), and ensureActive reuses the backend generation across turns, only bumping cachedHeader (packages/runtime/src/runtime-kernel.ts).
- Under an active Goal, the continuation's immediate next-turn admission is a frequent trigger: the switch can be dropped as
session_busy while a successor claim is held. That is an amplifier, not the root cause.
Open question for the regression test: whether the next turn fails to see the new boundary because the boundary write is dropped/raced, or because tool-time reads are cached. See the assignee's plan in the comments for a full proposed fix (queued quiescent commit + boundary-derived permissionMode + revision guard).
Switching the per-session permission mode from Auto to Bypass is not honored by the next turn. This reproduces in both a plain chat session (no Goal) and a running task. After the switch, the next turn still executes under the managed/ask boundary: Bash is still sandboxed and the model is still prompted for approval, even though the picker shows Bypass. The boundary the next turn actually runs under is not refreshed to the newly committed configuration before it executes.
Expected: a permission change is observed by the next turn that starts after it, before that turn's first tool call.
How to reproduce
Note: more frequent on long-running/multi-turn tasks — under an active Goal the continuation keeps the session claim busy, which widens the failure window — but it also reproduces in a plain session, so this is not Goal-specific.
Environment
98bdd6cf8(main)Logs, screenshots, or additional context
Root cause (code-traced, high confidence; a regression test is still needed to pin the exact sub-mechanism):
executionBoundarythey read at call time (packages/runtime/src/tool-runtime.tsreadExecutionBoundary;packages/runtime/src/builtin-tools.tsboundary.kind === 'bypass').transitionSessionConfiguration, but the next turn does not observe it:ctx.permissionModeis frozen in the backend/composer at build time (tool-runtime.tsthis.input.header.permissionMode;execution-model-composition.tscomposer), andensureActivereuses the backend generation across turns, only bumpingcachedHeader(packages/runtime/src/runtime-kernel.ts).session_busywhile a successor claim is held. That is an amplifier, not the root cause.Open question for the regression test: whether the next turn fails to see the new boundary because the boundary write is dropped/raced, or because tool-time reads are cached. See the assignee's plan in the comments for a full proposed fix (queued quiescent commit + boundary-derived
permissionMode+ revision guard).