acpmux: a chat runs at most maxRunning of its sub-sessions at once (default 16); more wait queued, changed live
A chat's agent can start as many sub-sessions as its open limit allows (50), and they all run at once. Now acpmux runs at most maxRunning of a chat's sub-sessions at the same time (default 16). A start past it still creates the chat, and its first prompt waits queued (waitsForSlot) until a running one ends. A message to such a chat waits the same way.
It changes live, no restart:
- Raising the limit starts waiting sub-sessions at once.
- Lowering it stops nothing: running turns keep their slot; new ones wait.
- A settings file change wakes the waiting ones too, so
agents.subsessions.maxRunningapplies at once.
Where the value comes from, like the other sub-session limits: the chat's own value, an ancestor's, the chat's workspace's, the agents.subsessions.maxRunning setting, then the default. The workspace level is new: _acpmux/subsession/limits {workspaceId, maxRunning} (person only), kept in ~/.acpmux/subsession-workspaces.json.
Who sees and sets it:
_acpmux/info'ssubsessionLimitsgainsmaxRunning,maxRunningSource,runningandqueued; a session summary gainswaitsForSlot(left out when false)._acpmux/subsession/limits {sessionId, maxRunning}sets or clears (null) a chat's value: the person for any chat, or an ancestor within its own limit. A session never raises its own.- The agent:
set_session_limitstakesmaxRunning;list_sessionsshowsmaxRunning,runningandqueuedunderself;start_sessionsays when the new sub-session is queued. - CLI:
acpmux session limits NAME [--max N | --clear].
The person's own prompts, and chats the person started from a suggested task, never wait for a slot and hold none. The settings row in Settings and the app's stepper and context menu come in follow-up PRs; until the catalog row lands the daemon uses 16 (range 1 to 1000).
tests/subsession_runs.rs covers the queued start and its start when a slot frees, raising (a waiting one starts), lowering (running ones keep going, the next waits), the person's prompt passing the limit, the refusals (a session for itself, out of range, a workspace set by a session), and the workspace fallback and its saved file.
Changelog
Added: acpmux runs at most 16 of a chat's sub-sessions at once by default; more wait their turn, and the limit can be changed per chat, per workspace or in settings without a restart.
Observed / Not run
- Ran on huge-blue (Linux) at 62ee5f6 merged with feat-cmux-next f76419f:
cargo test -p acpmux --test subsession_runs(3 of 3 pass),cargo test -p acpmux --lib(563 pass),cargo clippy -p acpmux --all-targets -- -D warnings(clean). Protocol IR re-blessed (waitsForSlot) and the web types regenerated. tests/subsessions.rs:254("disconnected" vs "closed") is a base flake: it failed 5 of 6 runs at base f76419f and 3 of 6 at this head.- Ran here: rustfmt,
scripts/cmux-next/prepush-gate.py(no new violations). - Not run: the macOS acpmux tests and a live app. The app's stepper (#23990) and Settings/context menu (#24061) come separately.
Review fixes at 62ee5f6: a sub-session waiting for a run slot is neither ready nor done for wait_for_sessions (and is waited on by default); stopping or closing it withdraws its queued start, so it never runs later; the workspace file is written under its lock; a request naming both workspaceId and sessionId is refused.
Reds at 0bc7720 that are not this PR's: the SDK protocol contract (test_sdk_publish_conformance_runs_live_against_exact_built_binary, also red on #23990), release-notary, cmux-next checks, same-tree cmux-tui, Guard status and release rails (also red on #24061 and other PRs on the same base).
No capture: daemon-only change. The one webview file is the regenerated protocol type (waitsForSlot); no UI renders it in this PR. The stepper in #23990 has the screenshots.
Agent session: cosmic-gray
š¤ Generated with Claude Code