Repository navigation
cmux NEXT: resolve rapid bottom placements from current rows - #26153
Conversation
…sidebar rows No fix: the test fails on today's code. For the sidebar placement owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
web and size checks: green |
|
Bead |
|
Found 7 test failures on Blacksmith runners: Failures
|
|
Owned by an agent session · took over from an earlier session · session |
|
Hosted red comparison for the exact head |
|
Review (codex gpt-6-astra xhigh, next-review): BLOCK at 23d8e9a
|
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
|
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Orphaned: no activity for 15 h, and no lane holds a lease on it. Adopted by the orphan sweep: merged |
|
The defaults guard now passes at It took two gate fixes:
(The guard's sticky comment above didn't refresh on this run because of an installation rate limit; the check result is what counts.) |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40986973295 at daa9794 failed: cmux-next checks (god files, concurrency, crash safety, l10n). |
Resolve the personal placement queue (#26153) against the optimistic saves: PersonalGroupLife.commit keeps one request on the reply's connection with its `completed` callback, through `perform` so `failed` gets why; the queued placement settles through the queue and reports a failed save or a lost connection with the reorder's notice; the other callers keep the base's captured `ending` recheck and the PR's reported failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40985942029 at 373ec0c failed: cmux-next checks (god files, concurrency, crash safety, l10n). |
36 newer trunk commits; 11 conflicted files: - PersonalGroupLifecycle.commit: trunk #26153 (cleanup on the reply's connection after appliedThroughReply, completed callback) ported onto perf's off-main task with main-actor Steps. - WindowManager+Placement: trunk's ordered pendingPlacementOrder with perf's controllerBuildingIfWaiting. - PaneHostView: trunk's rest clip from the rest cell plus perf's !isOnRenderSpring. - SidebarListView: perf's docStore observation plus trunk's drawnSelectionOrder. - acpmux App.tsx: trunk #27541 (quiet start, one line past the deadline) onto perf's RetryBackoff (RECOVERING_RETRY_MAX_MS in hostRetry.ts). - settings search: perf's hidden rows plus trunk's scope/revision cache keys. - pane-perf-terminal.py: perf's omnibar-toggle/--tunable plus trunk's page action. - JoinConsent, acpmux hub mod list: both sides.
|
Shipped in:
|
|
Shipped in:
|
…ts trail the run The run's sidebar placements go through PersonalPlacementQueue (#26153), one after another. On a loaded runner that queue trails the run, which broke the upgrade in two ways: - The migration put each new workspace in its classic group right after the create, while the workspace's own slot placement (`.bottom`) was still queued. That placement landed afterwards, cleared the group again and deleted the group it emptied. The import now waits for the slot placement to be listed (bounded at 5 s) and through the queue before it returns, so the group write comes after it. - The simulator's settle() saw 0.5 s of quiet while placements were still queued, and verify() read the daemon's own order instead of classic's. PersonalPlacementQueue gains isIdle and drained(). The tests read the tree through AppServices.placementsSettled() (queue through, store caught up with the daemon), from ClassicUpgradeSimulator.settle() and the ClassicMigrationTests launch helper, and settle() no longer counts a busy queue as quiet. No retry, skip or longer timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…placements trail the run (#28362) * cmux-next tests: the classic upgrade check reads the order once queued placements land (red) A placement held ahead of the run keeps the personal placement queue busy past the settle window. settle() returns while the run placements still wait, and verify reads the daemon own order: red on current code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next: a classic upgrade keeps its groups and order when placements trail the run The run's sidebar placements go through PersonalPlacementQueue (#26153), one after another. On a loaded runner that queue trails the run, which broke the upgrade in two ways: - The migration put each new workspace in its classic group right after the create, while the workspace's own slot placement (`.bottom`) was still queued. That placement landed afterwards, cleared the group again and deleted the group it emptied. The import now waits for the slot placement to be listed (bounded at 5 s) and through the queue before it returns, so the group write comes after it. - The simulator's settle() saw 0.5 s of quiet while placements were still queued, and verify() read the daemon's own order instead of classic's. PersonalPlacementQueue gains isIdle and drained(). The tests read the tree through AppServices.placementsSettled() (queue through, store caught up with the daemon), from ClassicUpgradeSimulator.settle() and the ClassicMigrationTests launch helper, and settle() no longer counts a busy queue as quiet. No retry, skip or longer timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ck (#28425) (#28430) theFirstLaunchBringsEverythingOnce("multiWindow") fails intermittently on base and on unrelated PRs: workspaces show in swapped order at ClassicUpgradeSimulationTests.swift:45 and :52. The sidebar placements a run queues (#26153) trail it on a loaded runner. The fix is #28362. Until it lands, that one case's verify runs inside withKnownIssue (isIntermittent) naming #28425. Every other case and check is unchanged. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…r 0.5 s of quiet (#28425) (#28526) * cmux-next: classic upgrade checks wait for placements to land, not for 0.5 s of quiet (#28425) ClassicUpgradeSimulator.settle() treated 0.5 s with no visible change as done. Since #26153 a classic import places each new workspace at its slot through the sidebar document (a `sidebar.apply` move, not the personal placement queue that #28362 waits for), so on a loaded runner a move or an adopt could still be on its way after the quiet window: the check then read an order or a group the late move changed (#28331 attempts 1 and 2, #28425). Product: SidebarDocStore counts the changes and adopts it sent and not yet answered, and exposes isSettled and settled() (event-driven: each reply and load end resumes the waiters). The classic import waits for it after the personal queue, so a workspace's group write is sent after its slot move is committed on the daemon, on the document path too. Tests: settle() and the ClassicMigrationTests launch helper read the tree only once every completion signal holds: the personal queue through, the document settled, the store applied through an event barrier taken after those replies, no live workspace still waiting for its new-workspace placement, and the document projection current. No quiet window; a hang guard records an issue naming what is still in flight. SidebarDocSettledTests covers the new signal. SidebarDocStore.swift: the remote protocol, its reply and SidebarDocUnsettled move to SidebarDocRemote.swift (no change), so the file shrinks. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: time the classic import's wait for the sidebar document (#28425) The import now waits for its slot move's reply before each group write. ClassicUpgradeSimulationPerfTests records that wait per imported workspace through a DEBUG bench span (BenchSpans, nothing recorded in release) and prints n, sum and p50/p95/max per profile (CLASSIC-SIM-PERF-SETTLE). The perf suite also holds the one SidebarDocStore (.ownsSidebarDocStore), as the other live-daemon suites do. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: the parked check waits for the shells to exit, not for settle()'s quiet window (#28425) backgroundWorkspacesStartTheirTerminalsWhenFirstShown read the parked state right after settle(). `park-tabs` answers before the shells exit; a tab shows dead with `relaunch` only once its host exited. The 0.5 s quiet window that settle() no longer has covered that by chance; without it the last workspace (scratch) read "not parked: [(false, nil)]" in 5 of 10 runs at 7f80b7d (step 815e7963). The check now reads once every background tab shows parked (the daemon's tab-exit events), with a 60 s hang ceiling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: forced-order red for #28425, sidebar document moves held past any quiet window ClassicUpgradeHeldDocumentTests holds every sidebar document change and adopt (the classic import's slot moves) for 4 s before it reaches the daemon, as a loaded runner's slow reply does. The check must read the tree only once those moves have landed. The test seam is a `wrapping:` parameter of SidebarDocWiring.start (default: the daemon remote as is), passed by ClassicUpgradeSimulator(documentRemote:). The red is on a scratch never-merge ref (this test over the base logic: settle() with its 0.5 s quiet window and the import without the document wait); this commit and the branch head are the green. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: the held-document red holds each move until someone waits for it, with no clock (#28425) The 4 s hold was still a clock. HeldRemote now holds every sidebar document change and adopt until someone waits in SidebarDocStore.settled() (the store's onSettledWait test seam releases them; one sent while someone waits goes on at once). The test reads, in the turn settle() returns in, how many are still held: a settle that does not wait on the document returns with moves held (red, every time); the new one cannot return until they are released and answered (green). placementsSettled() now awaits the store's settled() instead of polling isSettled. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: a placement wait that hangs names what is pending (#28425) placementsSettled() keeps the event-driven SidebarDocStore.settled() wait, with a 60 s hang guard (a ceiling, not a quiet window): if the store has not settled by then, the recorded issue says what is pending, from the store's new pendingDescription (changes and adopts unanswered, a running load, changes a load must settle, waiters). The held-document test prints it in its failure too. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux-next tests: fix the compile of the held-document test and the placement wait (#28425) Compile 6af24f9b at 08910ed failed: - ClassicUpgradeHeldDocumentTests.swift:73: the trailing closure matched ClassicUpgradeSimulator.init's `ssh:` parameter (String), not `documentRemote:`; it is passed by label now. - AppServices+PlacementsSettled.swift:41,50: `pendingDescription` is internal to CmuxNextSidebar; the helper imports it @testable. Also: the held remote's `waiting` is typed @mainactor, the local in release() no longer shadows it, and after the read nothing more is held (shutdown's changes go through). The await on the settled wait is its own statement. Sidebar-Look: no visual change Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Heads-up from #30961 (chat-open latency): it moves this PR's failure-path line in |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
HOLD: defaults-guard receipt reconciliation remains outstanding. The shared Swift and sidebar dogfood holds are lifted.
Rapid bottom placements can persist in the wrong order when rendered sidebar rows lag the store. Pending placements retain registration order and refresh the normal rows projection once per window. Personal placement plans share one queue across windows: optimistic rows update immediately; each plan uses the store after the preceding placement and any empty-group deletion have applied on the same connection. Failed writes stop dependent queued placements and release command-scope tickets. A placement skipped because its window or workspace is gone settles its pending edit and allows subsequent placements to continue.
Addresses the stale-rendered-row reproduction in #26152. The broader ordering race remains under separate investigation; this PR does not claim to resolve it. The reported example is: “The stale rendered list resolves index 1, producing
[k1,k3,k2]; expected[k1,k2,k3].” The empty-rendered-list guard is preserved. Tab drops capture both neighboring row/item identities before their asynchronous create, so a refresh cannot reinterpret a saved numeric gap.Risk: this changes cross-window personal placement sequencing and group cleanup timing. Captured source group IDs are rechecked after the move; pinned groups and groups with another live member remain. No new timer or observer is introduced. Each queued operation releases its scope ticket on success or failure, and the final completed operation clears the queue tail.
Validation
Current head:
051c630fd560b2961c19fcd893485b68a10c49f2. The last merged base is8e36e526f9c592b30333ff8d0d1dd506fb6f45e8(merge commit9166d799d735b59fda5245dbb6bf899440467a14).18ae60bcare historical evidence only.2ac597eefc4c1b25f0235566compiled and passed all five suites:PlacementStaleRowsTests,PlacementWriteOrderTests,WorkspaceGapTests,ModelMatrixPersonalOrderTests, andNewWorkspaceInGroupTests, including skipped versus failed queue outcomes. Script exit code was 0; the controller job remains failed because the requested output artifact path did not exist. Test-summary SHA-256:dbf5a61bdc42858477ab71e1b42726113a9882d70c683cec5b92c2ed02a6f34f. This is passing behavioral evidence, not a green controller-job claim.8d3046df5118aca153aba2efat test-onlycf168eaf2dba5c5682e11a89c1cac6d12d8654cccompiled, then failed persisted-order/write-order assertions. It remains the reproduction; its GUI-gated no-result is excluded.811fd5597cf9626d40bb1fd1completed; artifact SHA-256d2a25029d16dc8dfb7bba3416503b6ec5777c71de9b41882bac9530d7c16be6c. A successful build alone is not a structural dogfood interaction result.40785685307, attempt 3, job123715584296. It still reports a missing exact-head review. The existing member SHIP above is accepted by bothreceipt_verdictand completeapprovalreplayed from the trusted base guard against the live review payload. Gate-owner reconciliation is outstanding; no exemption or green hosted result is claimed.Screenshots
After at the exact head: real native AppKit gallery fixtures exercise production placement with a scripted daemon and stale rendered rows. Managed native suite
2c3bc831ab5d49d3e1a02a0dcompiled and passed its one gallery test with no skips. All four captured states paint first/second/third, and the recorded daemon write uses index 2. The PNGs are unedited 300 × 320 transparent fixture captures; light ink has low contrast in viewers that render transparency as black. These are native sidebar fixture screenshots, not whole-app dogfood captures. Tesseract OCR through the shared privacy checker, with the private terms list, passed all four files; its canary was correctly refused.cf168eaf)051c630f)Before is the existing native fixture run
64698b493dbe2916a500c4d1at test-onlycf168eaf2dba5c5682e11a89c1cac6d12d8654cc, showing first/third/second with write index 1. Those four published images were re-read with the same privacy/OCR check. Current after artifact SHA-256:d0a6fc1ff7feb82afb18cb72b355a117ecbeeb52da2f0b435d838c49961c9c94. Historical18ae60bcafter images are superseded by the exact-head captures above.Performance
The following Classic rows are observed assertion issue counts, not failing-pass counts or causal performance improvements. Both jobs ran
scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext Classicfor ten consecutive iterations (24 suites / 107 tests, default Swift Testing parallelism, classlight, CPU 6). There was no deliberate load generator; concurrent work is unknown. Basec8f95c77c316d7112c56c59712e36074edd7c7b8used a cold worker and locally built daemon tree68640f91; head051c630used a different warm worker and published daemon tree181771c0. Both jobs failed. These observations are not a controlled A/B experiment and do not establish that this PR fixes terminal parking or the remaining ordering race. A paired run with matched worker, filters and concurrency is pending separately.Separate timing receipts used
scripts/measure/instant-new-surfaces.sh --runs=12, classexclusive: basee275db3f6916daa1bf86e1e2b45d8927b9194f11, job6d54e43cc5e8a83312a72af9, and exact head051c630, job29709636a3a301b0e19c25cf, both completed with exit 0. They ran on different hardware (14 versus 10 logical CPUs), and source/daemon trees differ. These are adjacent interaction timings from the same harness, not a controlled placement-latency comparison; positive and negative deltas must not be attributed to this fix. Head timing artifact SHA-256:293eb1f3637186f4e3168bc1fdaabfa1001c5b268709d40f828213b65d477143.Duplicate #26947 is closed as superseded by this canonical PR.
Agent session: agent session