Skip to content

cmux NEXT: a remote chat connects again (one attach at a time, no "too many attached agent tabs") - #29295

Merged
teamleaderleo merged 1 commit into
feat-cmux-nextfrom
fix/remote-attach-serialize
Oct 31, 2026
Merged

teamleaderleo merged 1 commit into
feat-cmux-nextfrom
fix/remote-attach-serialize

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

A remote agent chat (a Cloud machine, or one reached over SSH) never connected. Its tab showed connecting: Error: too many attached agent tabs and an empty transcript, although cmux cloud start-session had started the chat and Claude was running. This blocks the NEXT Cloud demo flow.

Cause

  • cmux-tui reserves a tab's attach slot while that attach connects to acpmux (state.reserved in server/agent_session_attach.rs). It refuses a second attach of the same tab on the same connection while the first is still connecting, with agent_session.limit, whose message is "too many attached agent tabs".
  • cmux-next: a chat's first frame waits on one daemon round trip #27755 ("a chat's first frame waits on one daemon round trip") made the page send its session list (_acpmux/watch) and its chat attach (_acpmux/attach) at the same time.
  • On a remote chat, RemoteAcpmuxWire turns both into agent-session-attach on one AgentSessionAttachClient connection, each in its own task. The second request always reaches the daemon while the first is still reserved. It is refused, and the page's connect fails.
  • The daemon side has not changed since then, so a newer cmux-tui on the machine does not help.

Fix

AgentSessionAttachClient.attach sends one attach at a time per client. A later attach waits for the earlier one to answer, then goes out and is answered as a page of the live attachment (the daemon's "already attached in the same mode" path). The fix is in the app, so it also works against the cmux-tui already deployed on existing machines. If the caller cancels, the call it is waiting on is cancelled too.

Risk: a remote chat's list read now waits for one attach round trip after the chat's own attach. That costs one round trip on open, against a page that never opened before. Local chats do not use this client.

Tests

AgentSessionAttachClientConcurrencyTests uses a fake daemon that holds each attach for 300 ms and refuses a second one with agent_session.limit meanwhile, as cmux-tui does. Two attaches are asked together, and both must answer with no refusal. The test was run on the fleet, both on base with only the test added (expected red) and at this head (expected green), together with the existing AgentSessionAttachClientPresenceTests and AgentSessionAttachClientObserverTests.

🤖 Generated with Claude Code

Agent session: agent session

cmux-tui reserves a tab's attach slot while the attach connects to acpmux
and refuses a second attach of that tab on the connection meanwhile
(agent_session.limit, "too many attached agent tabs"). Since #27755 the
page asks its session list (_acpmux/watch) and its attach together, and the
remote wire turns both into agent-session-attach on one connection, so a
Cloud or SSH machine's chat never connected. The later attach now waits for
the earlier one and is then a page of the live attachment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-aa0f0a21b40fda1441b8
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review a4a0599: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr29295 -f ref=fix/remote-attach-serialize -f platform=macos -f backend_mode=local

Shipped in:

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 31, 2026

Copy link
Copy Markdown

Found 11 test failures on Blacksmith runners:

Failures

Test View Logs
1 runner guard check(s) failed:/1 runner guard check(s) failed: View Logs
test_big_red (main.FleetRuleLints.test_big_red)/
test_big_red (main.FleetRuleLints.test_big_red)
View Logs
test_every_blacksmith_linux_label_fails_over (main.BlacksmithLinuxFailoverTest.test
_every_blacksmith_linux_label_fails_over)/
test_every_blacksmith_linux_label_fails_over (main.BlacksmithLinuxFailoverTest.test
_every_blacksmith_linux_label_fails_over)
View Logs
test_every_upload_is_short_lived_and_small_or_allowlisted (main.WorkflowTests.test_
every_upload_is_short_lived_and_small_or_allowlisted)/
test_every_upload_is_short_lived_and_small_or_allowlisted (main.WorkflowTests.test_
every_upload_is_short_lived_and_small_or_allowlisted)
View Logs
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='generate
-nightly-deltas', attempt='3')/
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='generate
-nightly-deltas', attempt='3')
View Logs
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='sign-nig
htly-identity-legacy', attempt='3')/
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='sign-nig
htly-identity-legacy', attempt='3')
View Logs
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='verify-n
ightly-identity-legacy', attempt='3')/
test_no_retry_attempt_of_any_workflow_takes_an_owned_label (main.Wiring.test_no_ret
ry_attempt_of_any_workflow_takes_an_owned_label) (workflow='nightly.yml', job='verify-n
ightly-identity-legacy', attempt='3')
View Logs
test_pkill (main.FleetRuleLints.test_pkill)/
test_pkill (main.FleetRuleLints.test_pkill)
View Logs
test_the_allowlist_has_reasons_and_no_stale_entries (main.WorkflowTests.test_the_al
lowlist_has_reasons_and_no_stale_entries)/
test_the_allowlist_has_reasons_and_no_stale_entries (main.WorkflowTests.test_the_al
lowlist_has_reasons_and_no_stale_entries)
View Logs
test_the_tree_classifies_every_macos_job (main.RoutingTableTests.test_the_tree_clas
sifies_every_macos_job)/
test_the_tree_classifies_every_macos_job (main.RoutingTableTests.test_the_tree_clas
sifies_every_macos_job)
View Logs

...and 1 more test failures. View all on Blacksmith

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at a4a0599

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at a4a0599

Visual verdict: no images; Leo tries the build

  1. [P1][follow-up] [AgentSessionAttachClient.swift:135-139] Cancelling a queued attach does not actually cancel it. The non-throwing wait has no cancellation check, and LineTransport.request waits on a non-cancellable continuation, so the cancelled task can still send a stale attach after the previous request completes and may return success to its cancelled caller.

  2. [P2][follow-up] No after screenshots were provided, so visual comparison was unavailable.

Follow-ups:

  • [P1][follow-up] Make queued attach waits and the underlying request cancellation-aware.
  • [P2][follow-up] Provide after screenshots for visual review.

@teamleaderleo teamleaderleo removed the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 31, 2026
@teamleaderleo
teamleaderleo merged commit 79e9919 into feat-cmux-next Oct 31, 2026
225 of 240 checks passed
@teamleaderleo
teamleaderleo deleted the fix/remote-attach-serialize branch October 31, 2026 12:50
cmux-bot Bot added a commit that referenced this pull request Nov 1, 2026
…never sent (#29387) (#29388)

The one-at-a-time attach queue (#29295) did not check for cancellation after
the wait, so a cancelled attach was still sent once the earlier one answered,
and it had already replaced the client's event handler. It now checks after
the wait and sets the handler only when the attach goes out.


Agent-Session: https://cmux.com/deeplink/agent?id=aid-aa0f0a21b40fda1441b8

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — a4a05991 Deployed Oct 31, 2026 by teamleaderleo via namespace autofix #9556
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant