Skip to content

cmux NEXT sidebar: a slow group collapse save retries quietly, never a toast - #34405

Merged
teamleaderleo merged 2 commits into
feat-cmux-nextfrom
fix--group-collapse-timeout
Nov 4, 2026
Merged

teamleaderleo merged 2 commits into
feat-cmux-nextfrom
fix--group-collapse-timeout

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Leo, on a toast in the cmux NEXT sidebar: "the heck happened here?" The toast read:
"Collapse/Expand Workspace Group did not apply: update-personal-group: timed out: workspace_group.update (no reply within 2.0 seconds)".

What happened

Collapsing a group already showed the fold on the click (SidebarRows.fold). But when the daemon's reply to workspace_group.update missed the 2 s control deadline, the app treated the timeout as a failure: it dropped the fold, resynced the sidebar back to the old look and showed a "did not apply" toast, even though a timed-out command may still apply (ActionWorkFailure.mayHaveApplied). The daemon was slow to answer because the control channel was busy (idle personal.session.put churn; #33318 removed the identical saves at the source).

Fix

A fold is this window's look, so a slow save never undoes it or shows a notice:

  • SidebarRowEdits.saveFold (CmuxNextSidebar) holds the fold and sends the save; a reply that only missed its deadline is sent again in the background with Backoff (about 0.5, 1, 2, 4 s; SidebarFoldPersist), with no toast.
  • A later click on the same group stops the earlier fold's retries, so a stale value never overwrites the newer one.
  • After the last retry the hold is released quietly; the store's next echo shows what the daemon holds.
  • Only a real refusal (not connected, a rejected command) still drops the fold and reports, as before.
  • SidebarRows.fold (App) shrinks to a call into it (App lines -6).

Loop stop conditions: the retry task ends at the first reply, a refusal, a later click on the group, cancellation, or after 4 retries (at most about 7.5 s of waits).

Design spec: sidebar (plans/cmux-next/sidebar-owner.md); no visual change.

Changelog

Fixed: Collapsing or expanding a workspace group no longer shows a "did not apply ... timed out" notice or snaps back when the background service is slow to answer.

Tests

SidebarFoldPersistTests (new): a slow reply is sent again with no report and settles on the reply; a refusal reports once with no retry; a save that never answers gives up quietly after every retry; a later click stops the earlier fold's retries. Run with GroupHeaderClickTests and SidebarHostGroupTests on the fleet (cmux-ci run --class light --script scripts/ci/package-test-lane.sh --arg=suite ...); result in a comment below.

Observed / Not run

  • Observed: prepush gate clean; fleet suite run (see comment).
  • Not run: a live repro of the slow daemon in a DEV build.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

Fixes the cmux NEXT sidebar so collapsing or expanding a workspace group no longer shows a "did not apply ... timed out" notice or snaps back when the daemon is slow to answer.

The fold shows on the click; a save that misses the 2 s control deadline is retried quietly in the background (about 0.5, 1, 2, 4 s) with no toast. A later click on the same group stops earlier retries; after the last retry the hold is released quietly and the store's next echo shows what the daemon holds. Only a genuine refusal (not connected, a rejected command) still drops the fold and reports. SidebarFoldPersistTests cover retries, refusal, silent give-up, and a later click stopping earlier retries. CmuxNextWakeups is now imported publicly where Backoff appears in public signatures, and the test target depends on it.

Written for commit ac75c91. Summary will update on new commits.

View guided diff Turn on auto-fix

…a toast

Collapse/Expand Workspace Group already showed the fold at once, but when the
daemon's reply missed the 2 s control deadline, the fold was dropped, the
sidebar resynced back and a 'did not apply ... timed out' toast showed. A
timeout may still apply, so the save is now sent again in the background
(Backoff, about 0.5/1/2/4 s), skipped once a later click replaced the fold;
only a real refusal undoes the fold and reports. The loop lives in
CmuxNextSidebar (SidebarRowEdits.saveFold), not the App target.

Sidebar-Look: no visual change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64
@teamleaderleo teamleaderleo added risk:normal Risk tier (docs/ci/risk-tiers.md) leo-named-fix An obvious fix to something Leo named: lands on push, review runs in parallel labels Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

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

Review ac75c91: 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=pr34405 -f ref=fix--group-collapse-timeout -f platform=macos -f backend_mode=local

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base 26fd471; does not block

Shipped in:

…old's public signature)

Review (subagent) found the module's InternalImportsByDefault makes a plain
import internal, which Swift 6 rejects for a type in a public signature.

Sidebar-Look: no visual change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64
@blacksmith-sh

blacksmith-sh Bot commented Nov 4, 2026

Copy link
Copy Markdown

Found 36 test failures on Blacksmith runners:

Failures

Test View Logs
main.DeveloperIdAppTests.test_download_prints_the_active_profile_only/
test_download_prints_the_active_profile_only
View Logs
stubs: /System/Library/Frameworks/Security.framework/Versions/A/Security has no stub/
Security has no stub
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_CFRetain']/
CoreFoundation, missing 1: ['_CFRetain']
View Logs
stubs: CoreFoundation.tbd: install-name /System/Library/Frameworks/
CoreFoundation.framework/Versions/A/CoreFoundation, missing 1: ['_log2']/
CoreFoundation, missing 1: ['_log2']
View Logs
test_a_build_host_runs_every_piece_niced_and_capped (main.WebLintPrePushTests.test_
a_build_host_runs_every_piece_niced_and_capped)/
test_a_build_host_runs_every_piece_niced_and_capped (main.WebLintPrePushTests.test_
a_build_host_runs_every_piece_niced_and_capped)
View Logs
test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds (main.WebLintPreP
ushTests.test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds)/
test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds (main.WebLintPreP
ushTests.test_a_clean_pushed_commit_passes_whatever_the_working_tree_holds)
View Logs
test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it (main.WebLintPrePush
Tests.test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it)/
test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it (main.WebLintPrePush
Tests.test_a_clean_swift_only_push_runs_only_the_pieces_that_read_it)
View Logs
test_a_clone_with_no_reviewed_remote_lints_no_check_code (main.WebLintPrePushTests.
test_a_clone_with_no_reviewed_remote_lints_no_check_code)/
test_a_clone_with_no_reviewed_remote_lints_no_check_code (main.WebLintPrePushTests.
test_a_clone_with_no_reviewed_remote_lints_no_check_code)
View Logs
test_a_dry_run_lists_exactly_what_a_run_spawns (main.WebLintPrePushTests.test_a_dry
_run_lists_exactly_what_a_run_spawns)/
test_a_dry_run_lists_exactly_what_a_run_spawns (main.WebLintPrePushTests.test_a_dry
_run_lists_exactly_what_a_run_spawns)
View Logs
test_a_file_in_a_folder_above_a_package_is_check_code (main.WebLintPrePushTests.tes
t_a_file_in_a_folder_above_a_package_is_check_code)/
test_a_file_in_a_folder_above_a_package_is_check_code (main.WebLintPrePushTests.tes
t_a_file_in_a_folder_above_a_package_is_check_code)
View Logs

...and 26 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 (subagent claude-opus-5-5 medium, correctness): SHIP at ac75c91
Visual verdict: unchanged by this diff
Checked: the refusal path still settles, resyncs and reports; an older settle never clears a newer click's fold; the test continuations resume exactly once. An earlier BLOCK at 70be1c3 (internal import of CmuxNextWakeups under InternalImportsByDefault) is fixed at this head.
Fleet: package-test-lane.sh suite Packages/macOS/CmuxNext SidebarFoldPersistTests,GroupHeaderClickTests,SidebarHostGroupTests at ac75c91: package compiled, 5/5, 2/2, 4/4 passed.
Follow-ups: [follow-up] giveUp settles without a quiet resync (sidebar may show an unapplied fold until the next echo); [follow-up] collapse/expand/collapse within one backoff window can send the first fold's retry alongside the third's save (same value, harmless).

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

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

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

SHIP at ac75c91

Visual verdict: no images; Leo tries the build

  1. [P1][follow-up] SidebarRowEdits.swift:78 records timeout failures in any active DaemonCommandScope through DaemonService.failure, before the retry policy handles them. Therefore action.run callers still receive the timeout from scope.failures even if a retry succeeds, contrary to the silent-retry behavior. Use a non-reporting path for may-have-applied timeouts and cover an action.run case. Swift tests could not run because this box has no Swift toolchain.

Follow-ups:

  • [P1][follow-up] Suppress may-have-applied timeout failures from DaemonCommandScope settlement.

@teamleaderleo
teamleaderleo merged commit 8aece82 into feat-cmux-next Nov 4, 2026
159 of 168 checks passed
@teamleaderleo
teamleaderleo deleted the fix--group-collapse-timeout branch November 4, 2026 00:52
teamleaderleo added a commit that referenced this pull request Nov 4, 2026
…s quietly (#34630)

* cmux NEXT: no daemon intent error reaches a toast; a slow placement is sent again quietly

A timed-out or failed daemon intent showed its raw text as a notice:
"Move did not apply: set-personal-workspace: timed out: workspace.place
(no reply within 2.0 seconds)". Every notice for an ActionWorkFailure now
goes through one policy (ActionWorkFailure.notice(title:)): a missed
deadline or a lost connection shows nothing (the change is taken back and
the rows re-read), a daemon refusal shows only "<change> did not apply.",
and a reason in the person's words (a typed refusal, a disk-full reason)
shows as before. The registry's reporters and the app's refusal sites use
it (ActionRegistry.refuse(failure:)). A workspace placement whose reply
missed its deadline is sent again quietly on #34405's fold policy
(SidebarFoldPersist.resending) before the queue gives up and re-reads.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb01117327fc358e9ba1
Sidebar-Look: no visual change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CmuxNextSidebar: the fold save policy is nonisolated, so a placement's daemon connection can use it

Sidebar-Look: no visual change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb01117327fc358e9ba1

* cmux NEXT: a lost connection or a refusal with no title still says it did not apply

Review (subagent) found #26406's rollback-with-error tests and the diff-open
failure test rely on a not-connected failure showing a notice: a click is
never silently undone. Only a missed deadline is silent now; a refusal or a
lost connection shows "<change> did not apply." (or "That did not apply."
with no title), never the daemon's text.

Sidebar-Look: no visual change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb01117327fc358e9ba1

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift logic follow-up (tip watcher swift-logic row, STATUS 13027 "SWIFT LOGIC CULPRITS"; lead order).

This PR raised swift_logic_lines by +50 at its merge commit 8aece82: scripts/cmux-next/swift-logic-lines.py before and after the merge, with the same table (the tip's, c6be943). The largest declarations of the rise:

  • class SidebarRowEdits in Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarRowEdits.swift: +37 lines counted as Swift logic (its row counts it as logic)
  • enum SidebarFoldPersist in Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarFoldPersist.swift: +19 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)

plans/cmux-next/layer-ownership.md says Rust owns every state, list and rule and Swift is the platform shell. Please move the new logic of this PR in a follow-up: to Rust (the crate that owns the area; the owner lists in STATUS 12147-12165 name the target per area), or at least out of the app into its package. If a declaration above is platform code (AppKit, Core Animation, OS calls, strings, tokens, DEBUG tooling), reply here and the table gets a PLATFORM row with your reason instead.

The swift-logic row is a report, not a gate: nothing blocks on this comment.

This branch was previously deployed

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

Labels

leo-named-fix An obvious fix to something Leo named: lands on push, review runs in parallel risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants