cmux NEXT: Debug toggle turns on suggested tasks for agents (cx-lo9yf)
A new Debug Settings toggle, Suggested tasks (agent.suggestedTasks), lets agents in cmux NEXT suggest follow-up tasks that you start as child chats beside the current one. Debug Settings exist only in DEV and NIGHTLY builds, and the toggle is off by default. With it on, the acpmux daemon the app starts gets ACPMUX_OFFER_TOOLS=1. acpmux then gives every local session, whatever the harness (Claude, Codex or any ACP agent), the cmux-sessions MCP server with offer_session (and suggest_tasks once acpmux ships it). With it off, the daemon starts exactly as before. There is no Labs setting involved. Bead cx-lo9yf; this is the app half of the suggested tasks and nested child sessions contract.
How it works
AgentPaneTunables.suggestedTasksis aTunable<Bool>toggle in the agent pane's Debug Settings section, listed inAgentPaneTunables.all.AcpmuxHosttakes anoffersSessionToolsclosure and reads it at each daemon start, the same way it reads the Computer Use variables. By default the closure readsAgentPaneTunables.suggestedTasks.value, soCmuxNextApphas no net change, which keeps it under its size cap.AcpmuxEnvironment.offersSessionToolsthen putsACPMUX_OFFER_TOOLS=1into the daemon's spawn environment (AcpmuxDaemonLauncher.spawnEnvironment).- Each agent page gets the toggle the same way it gets preview features. On the old host that's
window.cmuxAcpmuxBridge?.applySuggestedTasks?.(on). On the page host it's asuggestedTasksevent. The page gets it at load, at handshake and whenever the toggle changes. A singleAgentPaneSuggestedTasksinstance inCmuxNextAgentPaneobserves the tunable and pushes to every page it has seen, holding them weakly. The page side ofapplySuggestedTasksis in the web half.
When a toggle takes effect
acpmux reads ACPMUX_OFFER_TOOLS from its own process environment, which is fixed when the daemon starts. A toggle applies to the next daemon this app starts: after acpmux stops or crashes, or when an app update hands off the old daemon. The running daemon keeps the value it started with. The app never restarts the daemon on a toggle, so running chats are left alone. Relaunching the app on its own isn't enough if the daemon outlives the app. The page push, by contrast, is live.
Not changed
- The pane allowlist.
_acpmux/offer_respondalready allowsoutcomeas a plain param, and neither the SwiftknownParamsnorcmux-agent-pane-policy/policy.jsonlists outcome values, so outcome"here"passes as is. - Settings strings and the settings export. The toggle is a Debug Settings tunable, not a cmux.json setting.
- The Chief home's daemon, which the Chief host starts separately.
Verification
AcpmuxOfferToolsTests drives AcpmuxHost.handshake against a stand-in acpmux that records the ACPMUX_OFFER_TOOLS it was started with. The host reads the toggle from a TunableStore the way the app reads it. The test checks three things: with the toggle on the daemon gets 1, by default it doesn't get the variable, and a toggle between two daemon starts applies to the second start.
- Red, from the first version of this PR, which used the same spawn boundary with a Labs flag: on
63b40a6b27a6(test commit7bd808674d2eplus its test isolation fix), the "on" case recorded["unset"] == ["1"]and the toggle case recorded["unset", "unset"] == ["unset", "1"]. Every other suite passed. The fix commit1eed1730bad7added the spawn environment line, and the test passed at7969e0f84d9a. - After the Labs-to-Debug-toggle rework, the test was rewritten to use the tunable in
45201e1123ec. That commit was green on arrival, because the spawn plumbing it tests already existed, so it has no separate red. - Green, at
a5e75db451b0before the move out ofCmuxNextApp:AcpmuxOfferToolsTestspassed in a full suite run (fleet step df502b5caa4c). The step exited 1 only forSidebarInsertWhileDisplayAsleepTests. That sidebar motion suite runs only on hosts with an awake display and fails there at this branch's base too. This PR doesn't touch it, and full Swift suites no longer gate merge. - At head
5d24d635c85d, after the move:AcpmuxOfferToolsTestspassed (fleet step df33a5d8ff6b), and the Release compile succeeded (fleet step 10d367112d3c). The suite step exited 1 only forRapidWorkspaceCreateTests, which this PR doesn't touch. - Local checks:
check-app-size.shis ok, with no netCmuxNextApplines.lint-ios-package-conventions.shis clean.check-no-godfiles.sh --base <merge base>passed on every touched file,crash_ratchet.pyis ok, andcheck-concurrency.shreports only two existing violations in files this PR doesn't touch. - Not run: a live DEV build. Nothing here is visible until an agent calls
offer_session, and the page side is the web half.
Changelog
none
🤖 Generated with Claude Code