Skip to content

cmux-next: a new workspace draws at its place from the first frame; add Before Current Workspace - #23071

Open
austinywang wants to merge 93 commits into
feat-cmux-nextfrom
feat-cmux-next-new-workspace-placement
Open

austinywang wants to merge 93 commits into
feat-cmux-nextfrom
feat-cmux-next-new-workspace-placement

Conversation

@austinywang

@austinywang austinywang commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

This adds Before Current Workspace (workspaces.newPlacement = "beforeCurrent") alongside Top, After Current Workspace, and Bottom. The app captures the current workspace before asynchronous creation and sends that placement to capable daemons, to align the preview with persisted order. Final-order assertions are strict; four per-frame assertions still document known intermittent row jumps.

Top and Bottom retain the current group's first/last-slot behavior. Before/After Current fall back to the machine section's top when the selected workspace is Home, pinned, absent, or on another machine. Explicit Above/Below placements keep their existing fallback. Failed creates release their placement ledger entries, including agent entrypoints. Before Current also preserves group slots when dense saved positions must be renumbered. Placement calculations and transient ledger state live in the Bridge domain; window/machine wiring stays in the app.

The base's ordered pending-placement queue, cold-sidebar anchor deferral, shared document refresh, indefinite late-terminal-start handling, first-tab chat behavior, and remote-close baseline are preserved.

Size: First-frame placement requires a coordinated app, daemon, protocol-binding, localization, and regression-test change; splitting it would leave those placement rules inconsistent.

Takes back #26153: replaces its inline failed-create pending-placement cleanup in WorkspaceSpawn.swift with the shared NewWorkspacePlacements.forget helper. The helper still removes the pending entry and registration order, and also releases the placement ledger. The ordered queue and shared placement sequencing remain intact.

Validation

  • Rust regressions reproduced the group-start, pinned-current and Before Current group-order defects before their repairs. The new dense-position regression also fails against the old implementation and passes after reading both bounds after row moves.
  • On rbx at 37869556602714dd37a5d7a9f7cc9d7f1cdd667b, formatting, 45 focused placement tests, and clippy for cmux-tui-core --all-targets -D warnings passed.
  • Swift red-before: fleet 162aa7637e51a34472460b3b reproduced missing-current fallback and failed-first-tab cleanup; e33acb70687a488d0de6252d reproduced trailing-group corruption and two registration leaks at their expected assertions.
  • Fleet settings export step 4fe8b5d563f4954b500aadba compiled all native test targets and passed four managed-preference plus six settings-schema tests on 2881639c1d62eda40d8226bee48af3a701725f14. Its generated patch restores the base's sidebar text-size entry and theme copy.
  • Swift fleet ba3e178df2439353c90dc633 passed all 11 requested suites (46 executed tests) at c86bcabdb57ccdf57b83dedd4d6b04c37b6ac709. Exact-head fleet step 556201a3433cf1233b755242 also passed all 11 suites at aaf91a901c9411ada04d13b63bcc16f38700d647 (exit 0).
  • Head 42aaf9034c2c39e9772ae5a523003539cb514f21 merges base 5aee3770f46ec7534f81fac338bd549aa3b261b5 and applies the fleet-generated schema. Export step cb6ee59849c1ca5095e4568d compiled all native test targets and passed all four managed-preference and six settings-export tests at its parent 37869556602714dd37a5d7a9f7cc9d7f1cdd667b. The generated delta is one localization key; it does not change the settings reference text.
  • Exact-head fleet step fe842e7101806ae9e74da2b6 passed all 11 focused Swift suites (46 tests, exit 0) at 42aaf9034c2c39e9772ae5a523003539cb514f21; summary artifact sha256:1a5547860c1e4f7aa2f5a79a4c6695b139aaaaf92da201f2707e9e5569b33198.
  • SDK generation, scoped Swift syntax, diff whitespace and the current-head pre-push static gate pass. Fresh independent exact-head review: SHIP. Automatic exact-head fleet app compile af95a3fe1965909c4c0b04d8 completed successfully. The fleet Release compile check and defaults guard rerun also passed.

Focused Swift command (on the fleet):

cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref SHA --arg=suite --arg=Packages/macOS/CmuxNext --arg=SidebarDocNewWorkspaceTopTests,CmdNRowSlotSuites,NewWorkspacePositionTests,RapidWorkspaceCreateTests,AgentTeamsLaunchTests,NewWorkspaceGroupIndexTests,NewWorkspaceInSectionTests,ColdCmdNRowSlotTests,ColdCmdNWindowRowsTests,CmdNSlowDaemonKeepsWorkspaceTests,CreateTerminalLateStartTests --env CMUX_CI_XCODE_APP=/Applications/Xcode_26.6.app

Focused Rust command (on rbx):

cargo nextest run --locked -p cmux-tui-core -p cmux-tui-util -E 'test(sidebar_doc_order) | test(personal_order) | test(mixed_order) | test(workspace_create_current) | test(placement)'

Observed / Not run

Observed: red-before regressions; Rust placement tests and clippy at 37869556602714dd37a5d7a9f7cc9d7f1cdd667b; all 11 scoped Swift suites (46 tests) at current head 42aaf9034c2c39e9772ae5a523003539cb514f21; fleet compilation of test targets and passing settings exporters at 378; SDK/syntax/static checks; earlier independent SHIP and visual reviews. The current head adds only the generated localization-key repair after the 378 base merge.

Not run: OS 14/15 interaction checks and controlled placement-latency measurements. Freestyle web validation is unavailable because this Mac lacks its runner configuration; no heavy web checks were run locally for this repair.

Native capture at aaf91a901c9411ada04d13b63bcc16f38700d647, fleet build 4fc178e1d193307352013c50: all eight fixture steps passed. Independent visual review passed light and dark; the stills show Before Two immediately before selected Two. The capture mini's text scan and the trusted main-branch privacy check approved both images before upload. These stills predate the latest base merge and schema-only repair; they do not establish latency or a before/after comparison. No new runtime change followed that base merge, so no recapture was requested for the schema-key repair.

Light Dark
Before Current Workspace, light Before Current Workspace, dark

Inherited failures: base-red evidence covers Chief eval_upsell and the Rust panic-ratchet debt outside this PR. Release-notary fails the same two RunsOnFallbackTests as base run; this PR changes neither workflows nor the routing tests. Only PR-caused failures are repaired here.

Performance

No perf numbers: the frame-order sampling and behavioral regressions establish placement correctness, not an input-to-frame latency distribution. No performance improvement is claimed.

Changelog

Added: Before Current Workspace as a new workspace position, with consistent initial sidebar placement and failure cleanup.

austinywang and others added 7 commits October 20, 2026 22:45
…y frame (red)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… selected; add Before Current Workspace

- workspaces.newPlacement gets beforeCurrent (app slot, settings choice and strings, daemon slot)
- a create that waits for the daemon (link, folder, browser workspace) reads the rule at the
  request, not after its hop
- a window showing a top page has no current workspace (the parked one is not selected)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- top-page test uses History (Home is no longer a top page)
- quick-press test requires each press to select its workspace
- daemon list order: the current workspace anchors only from the machine section and never as
  Home; the fallback stays below a leading Home row
- rustfmt; document the top-page exception and the daemon's own first place

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…me and state; rustfmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lawrence 2026-10-18 on NIGHTLY: the new row drew above the Accounts &
billing group, then moved below Scratch. Red: on the sidebar document the
placement goes to the personal order, which the document does not show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in the turn it lists (cx-qbktz)

From #21914: the document took the
placement (SidebarDocWiring.handle(.reorder), since #22593), but the sidebar
rebuilt shown only an observation turn later, so a new row drew in the
document's unplaced tail, after every group, for a frame, then jumped to its
slot. SidebarBridge.place now rebuilds shown in the same turn
(SidebarDocStore.reshow). Unlike 21914's version, reshow rebuilds only shown:
no adopt and no remote-close check over a stale machine set (its review's
finding 1).

Co-authored-by: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g presses and give the daemon the test's settings

- SidebarDocStore keeps the items of the last show (lastShownItems) for the remote-close check,
  so a reshow in between no longer hides a remote workspace that closed meanwhile
- the quick-press test samples the sidebar while the presses run
- the daemon reads the test's cmux.json (CMUX_NEXT_CONFIG_FILE)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang austinywang added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
@austinywang
austinywang temporarily deployed to cmux-tui-merge-tree October 21, 2026 06:37 — with GitHub Actions Inactive
@austinywang

Copy link
Copy Markdown
Contributor Author

Correctness review (subagent), findings and resolution

Round 1, at 92bd0653ceb05: REVISE.

# Finding Resolution
1 BLOCKER: the top-page test showed Home, which has not been a top page since the docked Home. Fixed in 564781820e24: the test uses History.
2 SHOULD-FIX: with a page shown, the app (no current workspace) and the daemon (its active workspace) pick different anchors. Documented in NewWorkspacePlacements.rule. The app places the row in the same turn the window lists it.
3 SHOULD-FIX: with a page shown, top and bottom no longer keep the new workspace in the parked workspace's group. Intended: no workspace is selected then. Documented in docs/configuration.md.
4 NIT: Rust sort_workspaces with beforeCurrent could put not-yet-placed rows before Home or among pinned rows. Fixed: the current workspace anchors only from the machine section and never as Home, and the fallback is below a leading Home row.
5 NIT: generated schema and MDM files are stale. Left to the PR autofix. Not hand-edited, per CLAUDE.md.
6 NIT: the quick-press test assumed each press selects its workspace. Fixed: the test now requires it.

Round 2, at 6fd8d72b0d671 (after folding in #21914): PASS.

The reviewer traced the path. reshow runs inside reconcileMembership, from the workspace-list hook, after the mirror applied the move and bump() changed the projection's version key. The sidebar's rows pass reads shown one hop later.

# Finding Resolution
1 SHOULD-FIX: reshow overwrote shown, which the next show used as its remote-close baseline. A remote workspace that closed between them could keep its document item. Fixed in e3879dbe62e7: lastShownItems is set only by show and cleared on deactivate.
2 SHOULD-FIX: the quick-press test did not sample during the presses. Fixed: it samples during the key-repeat gaps.
3 NIT: the test daemon read the runner's own settings. Fixed: CMUX_NEXT_CONFIG_FILE points it at the test's file.
4 NIT: 21914's test uses absolute indexes and visible rows for before (a guess, not reproduced). Kept as Lawrence wrote it; it is a follow-up if it flakes.
5 NIT: Rust Top still lists before a leading Home row; this predates the branch. Out of scope.
6 NIT: no Rust test for the document-order fallbacks. Follow-up.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

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

Review 0500d56: 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=pr23071 -f ref=feat-cmux-next-new-workspace-placement -f platform=macos -f backend_mode=local

Unclear: web / react-apps-check failed: no known signature; failed step: Check webview test shards.

CI failed on d7d50b4463 (run 41790329533 attempt 1): 2 code, 1 unknown.

Job Verdict Why
web / Web tests (1/4) code a web test failed
web / react-apps-base-check (7) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs next-docs.test.ts cmux-next docs > the settings reference is fresh against the settings schema: failed (job)
  • seen on other PRs new-tab-live-resize.test.ts webkit: the cards page follows a live resize: failed (job)
  • seen on other PRs new-tab-live-resize.test.ts webkit: the default page follows a live resize: failed (job)
  • seen on other PRs new-tab-live-resize.test.ts webkit: the threads page follows a live resize: failed (job)

A web test can import code this PR changes without being one of its files: python3 scripts/ci/web_test_verdict.py --pr 23071 --file web/tests/next-docs.test.ts checks its import graph (on Linux, in a sandbox) and its failures on other branches.

Matched log lines
web / Web tests (1/4): (fail) cmux-next docs > the settings reference is fresh against the settings schema [3.36ms]
web / react-apps-base-check (7): (fail) webkit: the cards page follows a live resize [5518.03ms]

Not re-run automatically: web / Web tests (1/4), web / react-apps-base-check (7), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 0ae1413 to compare; do not merge until green; see lane-rules

Tour of 57f5261eb1 (run): no media. The tour job failed before the tour ran (build or setup); the run log has the output.

Default changes

No defaults change at 65a56347714a.

@teamleaderleo

Copy link
Copy Markdown
Collaborator

cmux-next guards / defaults-snapshot is red on 21 of 25 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@blacksmith-sh

This comment has been minimized.

@austinywang

Copy link
Copy Markdown
Contributor Author

Base finding, not from this PR: GroupHeaderNewWorkspaceTests.groupHeaderPlusMakesTheNewWorkspaceInThatGroup fails at base 511423d1500cf (step 2b312b9954a2fc4cb46673e4) as at this head: headerID(of: group.id, in: sidebar) → nil after 30 s. RapidWorkspaceCreateTests.fiftyCmdNDrawEachRowAtItsPressInPressOrder also fails at base (step b118eb13fa19948ffa556a1c).

Status at head e3879dbe62e7 (step 443e54ac48ea89d0ed6157cf):

  • Pass: beforeCurrent, the History-page case and cmdNRowStaysWhereItDrewAtThePress.
  • Still failing: top and the afterCurrent cases. The confirmed row draws once at the bottom, then moves to its slot. This happens on the personal-order path too, not only the sidebar document. Diagnosis is in progress; this PR stays a draft until those pass.

…rent workspace

The daemon placed a new workspace by workspaces.newPlacement against the session's
active workspace, a legacy default the app's windows never move. With afterCurrent or
beforeCurrent its first place was beside another workspace, which showed for a frame
before the app's placement moved it (Austin: "it thinks I selected a different
workspace"). create-workspace now takes current: the workspace key the creating window
shows. The app sends it from every create that places by the setting, and the daemon
places the new row against it: beforeCurrent/afterCurrent beside it, and top/bottom
inside its group (right after it, last), as the app does. An older daemon ignores the
field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang temporarily deployed to cmux-tui-merge-tree October 21, 2026 07:40 — with GitHub Actions Inactive
…create name none

Review of cba8533 (REVISE):
- the create's client current is captured into WorkspaceCommitIntent at prepare and
  re-scoped around its apply, as EffectCommitKind::Patch carries the placement, so it
  survives the commit moving to the journal writer thread (cx-ags0)
- create-workspace takes places_by_setting: the client places by the setting with
  current, or with none when its window shows a top page; before, a create from Home
  named no current and the daemon fell back to its active workspace
- the app sends the rule (WorkspaceCreation placedBy:); a wire test of create-workspace
  over JSON; the command spec lists both params; stale comment in NewWorkspacePlacements.rule

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang temporarily deployed to cmux-tui-merge-tree October 21, 2026 07:55 — with GitHub Actions Inactive
…ewhere goes first, not last

sync_row anchored a new workspace after its previous row in the personal order; when
that row was not a sibling in the document (Home in its own section, a pinned row, a
row the document does not place), the new row went to the end of the machine section.
With top (right after Home) and beforeCurrent the confirmed row drew at the bottom for
a frame before the app's placement moved it. sync_row now anchors after the nearest
earlier sibling, else first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…document places it

Fleet traces: the confirmed row of a new workspace still drew once at the bottom when
the workspace list reached the app before the document placed it. Two client-side
causes, both fixed:
- SidebarDocStore.show adopted every unplaced live workspace at the end of its section;
  a workspace the window is about to place (pendingPlacements) now gets its adopt with
  that placement's move instead (placesItself)
- PendingWorkspaceRows dropped the press row as soon as the window listed the workspace,
  while the document still listed it last (unplaced); the press row now stands in until
  the document places it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang temporarily deployed to cmux-tui-merge-tree October 21, 2026 20:36 — with GitHub Actions Inactive
… a workspace

It kept a create's press row for as long as the sidebar document did not place the
workspace, and fleet step bb243d5833cfb7061e3c7617 showed no create settling at all
(every NewWorkspacePositionTests setup and RapidWorkspaceCreateTests timed out).
The document's auto-adopt skip (placesItself) stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang
austinywang temporarily deployed to cmux-tui-merge-tree October 21, 2026 21:07 — with GitHub Actions Inactive
Fleet step at 2425b76 (placesItself alone): quick Cmd-N with afterCurrent now drew
out of place too, so the skip does not help; back to the code of 68c91e1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fleet cb6ee59849c1ca5095e4568d at 3786955 compiled native test targets and passed all four managed-preference and six settings-export tests. Apply the exact generated schema; the only delta is the Look and Feel localization key.
@austinywang

Copy link
Copy Markdown
Contributor Author

Review (review_23071): SHIP at 42aaf90

Fresh correctness-first subagent review of PR #23071, owner manaflow-ai, agent review_23071, base 5aee3770f46ec7534f81fac338bd549aa3b261b5 and the exact head above: no correctness findings remain.

The generated schema matches fleet artifact SHA-256 fac5a9487f326dde1bceb6885850fd5fd79945ac22c5537c99f24fa4d9a0e025 and the merged source. Placement capture, daemon context, fallback, group ordering, dense-position respace and failed-create cleanup remain intact. The merged base is an ancestor. No PR-owned changes affect the failing acpmux, cmux-tui, cmux-automations or Omnibar selector inputs.

The primary agent independently checked the exact generated delta, worktree, remote head and plain-push gate. Fleet generation compiled native test targets and passed four managed-preference and six settings-export tests at parent 37869556602714dd37a5d7a9f7cc9d7f1cdd667b; 45 focused Rust tests, formatting and scoped clippy passed on rbx at that parent. The current commit changes only the generated localization key. The reviewer ran no additional tests. Automatic exact-head app compile af95a3fe1965909c4c0b04d8 is running. Earlier native visual PASS and captures are at aaf91a901c9411ada04d13b63bcc16f38700d647; no current-head capture or latency claim is made.

@austinywang

austinywang commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor Author

Current head: 42aaf9034c2c39e9772ae5a523003539cb514f21; merged base: 5aee3770f46ec7534f81fac338bd549aa3b261b5.

  • Fresh independent SHIP was posted before restoring ready-to-land.
  • Exact-head Swift step fe842e7101806ae9e74da2b6 passed all 11 focused suites: 46 tests, exit 0. Summary artifact sha256:1a5547860c1e4f7aa2f5a79a4c6695b139aaaaf92da201f2707e9e5569b33198.
  • Exact-head app fleet compile af95a3fe1965909c4c0b04d8 completed successfully; artifact sha256:70236adeebd8d565bc877fff9e3e153a9617cfd0dd68f8f7dc4e4a8da0807598.
  • Defaults guard rerun passed after the receipt.
  • Native generator cb6ee59849c1ca5095e4568d passed four managed-preference and six schema tests, then its exact artifact supplied the one-key repair. No generated file was hand-edited.

The remaining failed logs were read on this head. Chief fails the same eval_upsell checkout assertion as the base job; the PR changes placement code elsewhere in that crate, not the failing test or skill. Clippy fails acpmux 692 > 686 and cmux-tui 836 > 831 indexing counts; both crate subtrees are identical at the merged base and head. Crash-class rules reports the same three Omnibar selector probes as base run; those inputs are unchanged.

The release-notary job has the two known RunsOnFallbackTests failures and an additional external Glaeda signing-hook-list freshness failure. The PR changes none of those test, hook-list or workflow inputs. The base run already shows signing-routing failures; the current hook hash is a moving external dependency, not a workspace-placement change.

Additional executed Windows base evidence: base job at dcc7e59db6a46bac9a28d66ec1b2e7003f35f6de fails with the same 35 cmux-automations Unix-only API errors. That crate is unchanged by this PR. This supersedes the earlier limitation that only skipped base artifact jobs had been found.

Autoland refreshed this head at 07:35Z and still classifies the Windows artifact job as its own red. Existing base repairs are Windows #29075 and Chief eval #28888. They are outside this PR. The base-red scanner currently leaves Chief and clippy entries without step signatures (steps: null), which its judge cannot excuse. No check was overwritten or waived, and no unrelated base fix was included.

WorkspaceSpawn.start: keep the base's row/rule split (New Workspace in New
Group draws its pending row at the setting's place) and this branch's
beforeCurrent exemption that keeps the current workspace for the rule.
@lawrencecchen

Copy link
Copy Markdown
Contributor

Merged feat-cmux-next into this branch to clear conflicts (merge commit d5208fa). One file had a conflict:

  • Packages/macOS/CmuxNext/Sources/CmuxNextApp/WorkspaceSpawn.swift (WorkspaceSpawner.start): I kept the base's row/rule split from 8e7abce. With it, New Workspace in New Group draws its pending row at the setting's place, and rule is only set when placesBySetting is true. I also kept this branch's beforeCurrent exemption: the current workspace is now cleared only when the placement is neither afterCurrent nor beforeCurrent. The merged condition is if !spawn.placesFromCurrent || !spawn.placesBySetting, row?.placement != .afterCurrent, row?.placement != .beforeCurrent { row?.current = nil }.

All other files merged with no conflict. prepush-gate: no new violations.

Fleet compile 30f4bee85d9fe107f564f45e: passed (CmuxNext, app, cmux-tui).

@lawrencecchen

Copy link
Copy Markdown
Contributor

Review (claude-rereview): FIX at d5208fa

The code is correct. The merge is correct. But this head has stale generated settings files, and they cause reds of this PR's own. Regenerate them, then get a new review at the new head.

Findings

  1. Stale settings exports at this head (PR's own red). schemas/settings/settings-schema.json, docs/mdm/com.manaflow.cmux.json, docs/mdm/com.manaflow.cmux.plist and docs/mdm/managed-preferences.md are the branch's copy from 42aaf90. The merge kept them through the cmux-generated-v1 merge driver, and nothing regenerated them. Against the merge base 625b1ca, the PR diff now takes back base changes. It removes browser.import.cookieBanner, browser.omnibar.fontSize and browser.omnibar.height. It adds back tabs.terminalFirst and sidebar.showWorkspaceTabs, which 74d73a3 removed. It changes the workspaces.autoArchive.style default from manual to suggest (for example, docs/mdm/managed-preferences.md:126 and docs/mdm/com.manaflow.cmux.json:4965). web/data/next-docs/settings-reference.generated.json has the base's content, so the two copies do not agree. These checks fail because of this:
    • cmux-next page strings generate: 84 strings missing for settings.tabs.terminalFirst and settings.sidebar.showWorkspaceTabs. This check passes at the feat-cmux-next tip and on other open PRs.
    • web / Web tests (1/4): cmux-next docs > the settings reference is fresh against the settings schema.
    • cmux-next web bundles (source-keyed cache): the build step failed. It passes on other open PRs, so the probable cause is the same stale input. I could not read its log because the run had not finished.
    • defaults guard: 5 of its 18 listed changes are these stale settings rows. The other 13 are the PR's real tunable-source changes. It also needs an exact-head receipt.
      Fix: let the PR autofix job action exports (Mac) (run 41206768721, queued) push the regenerated settings exports, or run scripts/cmux-next/regenerate-settings-exports.sh on the fleet. Do not hand-edit the files. After that, the only settings difference from the base must be beforeCurrent in the workspaces.newPlacement enum.

What I checked

  • Conflict resolution in Packages/macOS/CmuxNext/Sources/CmuxNextApp/WorkspaceSpawn.swift:55-57. The merged condition keeps the base's row/rule split (8e7abce). rule is set only when placesBySetting is true, and row still draws the pending row. It also keeps this PR's beforeCurrent exemption. current is kept for both before and after placements and cleared for the other placements. That matches the intent of both sides. The two failure paths (start catch at :82 and shown catch at :132) call NewWorkspacePlacements.forget. That releases the ledger as well as the pending entry and its order.
  • Other files that both sides changed (Package.swift, AgentHandlers.swift, WindowManager.swift, DaemonEndpoint.swift, server.rs, capabilities.rs, commands.md, daemon-capabilities.json, sidebar-owner.md, docs/configuration.md) merged by line with no lost side. CmuxNextSettings/Localizable.xcstrings is valid JSON after the merge.
  • New base code that uses .afterCurrent: no workspace placement switch misses .beforeCurrent. WorkspaceGroupHandlers.groupSlot switches on a different enum (the cmux.json group placement). The Rust sort_workspaces (sidebar_doc_order.rs:123-131) and personal_order.rs:273 handle BeforeCurrent.
  • Repo rules for the changed lines: no try!, no main-thread blocking, no new animation, dialog or font literals, and no shortcut changes. The PR changes no BSL server directories except the generated web/data/next-docs/settings-reference.generated.json. The author is a member, so CLA does not apply. The PR body has the takes-back note for cmux NEXT: resolve rapid bottom placements from current rows #26153, the risk label and the native capture.
  • Other non-green checks. nightly-guards / workflow-guard-tests / release-notary is a base red: it fails on PRs 29409, 29407 and 29401, and its annotations are pool-snapshot HTTP 403/502 errors. web / Web tests (3/4) cmux-machine-hygiene > keeps an artifact directory the repository tracks is a temp-directory ENOENT race in web/tests/vm-machine-hygiene.test.ts:64. This PR does not touch that test, so it is infra or flake. Guard status and Web status are wrappers for the checks above.

What I did not check

  • I did not run any tests or builds. The merge author reports fleet compile 30f4bee85d9fe107f564f45e as passed, and I did not check it again. I re-read the merge and the parts of the PR that touch it. I did not do a full line-by-line review again of the PR code that earlier SHIP receipts covered and that the merge did not change.
  • cmux-next fast tier, action exports (Mac) and publish the Windows daemon to R2 were still pending.

austinywang and others added 2 commits November 2, 2026 20:45
Conflicts resolved:
- Workspace creation now goes through the base's WorkspaceSpawner
  (createAndShow, AgentSessionWorkspace.expectPlacement); the placement rule
  and ledger ride on those paths. AgentSessionWorkspace sends its rule to the
  daemon only when no explicit slot is set, as WorkspaceSpawner does.
- windows.forgetCreate releases the placement ledger too
  (NewWorkspacePlacements.forget), so every base failure path frees it.
- NewWorkspaceDefaultSlot (moved to CmuxNextBridge here) gains the base's
  `named` flag (agents chat new --top).
- The unplaced-neighbour anchor reads the per-app SidebarDocument
  (services.sidebarDoc) instead of the removed SidebarDocWiring static.
- SDK bindings regenerated with cmux-tui/bindings/codegen/generate.py.
- Settings exports taken from the base; they are regenerated next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge routed WindowManager.forgetCreate through NewWorkspacePlacements.forget
to release the placement ledger too, which rewrote a line #30961 landed this
week (risk evidence's take-back hold). forgetCreate is back to the base's line;
WorkspaceSpawner's two failure paths release the ledger beside it, as they did
on this branch before the merge (an anchor `expect` armed for a create that
never ran). Creates that reach WorkspaceCreation release it there already.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WorkspaceCreation.swift: the base's a06897f moved withTerminal onto
EmptyWorkspaceRepair (repair.withTerminal); the PR's placement fields on the
create (placesBySetting, current, placement) stay on the calls.
CmdNRowSlotTests: the serialization comment names only the state that is still
process-wide (PendingWorkspaceRows.shared); the sidebar document is per app now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
austinywang and others added 5 commits November 2, 2026 22:16
Regenerated on the fleet (cmux-ci step 1e61b63af79672883880a155) from 74cc648.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The base's WorkspaceSpawner creates a workspace whose pin names a missing space in
the window's own space instead of refusing it, so the test now fails the create
through createAndShow's first-terminal step and checks the same release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts:
- Package.swift: CmuxNextBridge keeps the base's CCmuxAppFFI and this
  branch's CmuxNextSettings.
- AgentTabs+OptimisticWorkspace.swift, AgentSessionWorkspace.swift: the
  base's firstTabKeyed and this branch's placedBy/ledger both pass through.
- PersonalSidebar.swift: this branch's unplacedAnchor with the base's
  cached personal.workspacesInOrder.
- NewWorkspaceDefaultSlot.swift: the slot rules live in CmuxNextBridge on
  this branch; the base's #33045 change (an afterCurrent create always moves,
  so from Home it takes the top, #32731) is ported there and applies to
  beforeCurrent too. NewWorkspaceFromHomePageTests covers beforeCurrent.
- SDK bindings: regenerated with cmux-tui/bindings/codegen/generate.py --write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerated on the fleet (cmux-ci step b8e6abd5da7cb704e7061c84, artifact
sha256:40fc484ce6d8b55c16b2960847091a76514eb9e9caf00f92b4c037da15991658) from
0500d56. The merge had kept this branch's settings exports, dropping the
base's new settings rows; against the base they now differ only by
beforeCurrent (window.titlebar's default follows WindowTitlebarSetting.fallback,
as on the newer base).

NewWorkspaceFromHomePageTests: say which daemons anchor a before/after
current create to their active workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…acement ledger as it was

The test only compared groupAnchors, which a top create never sets, so it
passed with no release at all. It now also checks anchors and
placedByDaemon: a capable daemon's create marks it placed by the daemon,
and the failed first terminal must release that mark.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@austinywang

Copy link
Copy Markdown
Contributor Author

Review (review_23071): SHIP at d7d50b4

Correctness-first subagent review of PR #23071. Owner manaflow-ai, PR author austinywang, agent review_23071, base 0ae1413031d461ef95bb2913d1857af1e0738506 (feat-cmux-next as of this merge), exact head above.

Scope: 8b46709cc744e..d7d50b4463e72:

  • e9f43ca7ef41b: the failed-create test now fails createAndShow through its first terminal.
  • 0500d5641709b: merge of feat-cmux-next 0ae1413031d.
  • f203b05a7333a: fleet-regenerated settings exports.
  • d7d50b4463e72: the failed-create test checks the whole placement ledger.

Findings and resolution

Round 1, at 0500d5641709b: REVISE.

  1. SHOULD-FIX: the merge kept this branch's settings exports and dropped settings added on the base (agents.chats.sessionRecap, agents.promptCache, feed.needsYouInChief, the cloud.* and imessage.* rows, the updates page's appUpdate row). This caused the reds in web / Web tests (1/4) (settings reference count) and react-apps-base-check (appUpdateCard).
    • Fixed in f203b05a7333a: regenerated on the fleet, step b8e6abd5da7cb704e7061c84, artifact sha256:40fc484ce6d8b55c16b2960847091a76514eb9e9caf00f92b4c037da15991658.
    • Against the base, the exports now differ only by beforeCurrent. window.titlebar's default also changes to standard: the base's own exports were stale against its WindowTitlebarSetting.fallback = .standard, and the newer base has standard too.
  2. NIT: the doc comment in NewWorkspaceFromHomePageTests overstated which daemons anchor a before/after-current create to their active workspace. Fixed in f203b05a7333a.

Round 2, at f203b05a7333a: SHIP, one NIT.

  1. NIT: aFailedCreateAndShowReleasesItsPlacementRegistration compared only groupAnchors, which a top create never sets, so a ledger leak would pass. Fixed in d7d50b4463e72: the test also checks anchors and placedByDaemon. A capable daemon's create sets placedByDaemon, and the failure must release it.

Round 3, at d7d50b4463e72: SHIP. No findings.

  • Remaining limit: the test fails only when both release paths are gone (the defer in WorkspaceCreation.create and the spawner's catch).

Merge resolutions checked

  • Package.swift: CmuxNextBridge keeps the base's CCmuxAppFFI and adds CmuxNextSettings. There is no dependency cycle.
  • AgentTabs+OptimisticWorkspace.swift and AgentSessionWorkspace.swift: the base's firstTabKeyed and this branch's placedBy/ledger both pass through.
  • PersonalSidebar.swift: the base's cached personal.workspacesInOrder, plus this branch's unplacedAnchor.
  • Base change fix(sidebar): afterCurrent Cmd-N from Home places the new workspace at the top #33045 (under afterCurrent, the app always sends its own move, so from Home the new row takes the top) is ported into CmuxNextBridge/NewWorkspaceDefaultSlot.swift and extended to beforeCurrent. NewWorkspaceFromHomePageTests covers all four placements.
  • The SDK bindings were regenerated with cmux-tui/bindings/codegen/generate.py --write, and --check passes.
  • No other Swift or Rust switch over NewWorkspacePlacement misses beforeCurrent.

Known gap, outside this merge

NewWorkspacePlacement::from_wire (the per-create placement of the v2 workspace.create resource op) still takes only top, after_current and bottom. The setting, Cmd-N and the app's create-workspace path accept beforeCurrent.

Not checked

The reviewer did not build or run anything. The fleet runs are in the verification comment.

austinywang and others added 8 commits November 4, 2026 01:21
No conflicts. The generated SDK bindings check fresh (generate.py --check).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerated on the fleet (cmux-ci step 23e12b53c45807fb1a312cd3, artifact
sha256:c1e65e1cfc1ccbdacb51f2eb6af23de8397410d943ca512cbd0c6a49b8b31006)
from ebaee0e. Against the base 7cd4eb6 the exports differ only
by beforeCurrent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n in-flight create never lists it again

Regression tests that fail on 7fd2790 (the fix follows):
- NewRowOneSlotTests: bottom lists below a trailing group; every placement
  waits for the current row while the rows catch up; an anchor outlives
  more than 16 creates in flight and ends when placed or closed.
- CloseDuringCreateNoReappearTests: Cmd-N then Close Workspace with the
  daemon stopped never lists the closed workspace again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ws once at its slot

Close (the workspace came back for a second, then left):
- A close that takes an in-flight create hides the workspace itself
  (ClosingWorkspaces.hide(untilGone:)), not only its pending row: the
  store's copy listed in the row's place until the close landed.
- A close that went through keeps its row hidden until no store holds
  the workspace (releaseGone, in the sidebar's tracked rows pass), not
  until a reply that can precede the store (resync, reconnect, batch).
- Pending rows obey the close hide (PendingWorkspaceRows.shown).

New row (the row animated a second move):
- WorkspaceSlot.bottom without an anchor is last in the section, below a
  trailing group, where the daemon appends and the document lists it.
- Every placement waits for the current row while the rows catch up,
  not only beforeCurrent/afterCurrent.
- A neighbour anchor ends when the document places its workspace or the
  listed workspace is gone, never by a count prune that dropped the
  anchor of a create not yet sent.

No delay, debounce or throttle: each change shows in one frame.
Sidebar-Look: no visual change

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…top pending row waits for the current row

Fail on 0ea0e3c (the fix follows):
- WorkspaceLanesTests.aTakenCreateStaysOutstandingUntilItsCloseHasRun
- NewRowOneSlotTests.aTopPendingRowWaitsForTheCurrentRowWhileCatchingUp

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w slot

- A refused close of a taken create lists the workspace again
  (WorkspaceSpawn's lane close ends its hide on a failure); it stayed
  hidden until relaunch.
- A taken create stays outstanding while its close runs
  (WorkspaceLanes.closing): a rows pass in the gap between the create's
  end and its close released the hide, and the row showed again.
- A close that takes a create moves the window's selection at the press
  (InstantClose.begin), as any close does.
- A pending row checks the current-row wait before its slot: under top
  the slot fell back to the section's top and the row moved into the
  group once the rows caught up.

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>
…s lane

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Nov 5, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot 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.

@austinywang

Copy link
Copy Markdown
Contributor Author

Sidebar polish: closed workspaces never come back, new rows draw once

PR: #23071 · login austin@manaflow.ai · agent Claude Code (Opus 5.5) · base feat-cmux-next 7cd4eb6 (merged) · head 65a5634

Dogfood feedback: "sometimes it over animates more than necessary, sometimes it's not optimistic and the workspace comes back on the sidebar for a second before disappearing again."

Fixes (no delay, debounce or throttle; each change shows in one frame)

  • Close that takes an in-flight create (Cmd-N then Close Workspace): the workspace itself is hidden (ClosingWorkspaces.hide(untilGone:)), not just its pending row. Before, the store's own copy of the workspace was listed in the row's place until the close landed. The window's selection moves at the press (InstantClose.begin). If the close is refused, the workspace lists again.
  • Every close that goes through keeps its row hidden until no store holds the workspace (releaseGone, run in the sidebar's tracked rows pass). Before, the hide ended at a reply that can arrive before the store applies the close (resync, reconnect, or a batch close). A taken create also stays outstanding while its close runs (WorkspaceLanes.closing).
  • Pending rows obey the close hide.
  • New-row slot agreement:
    • WorkspaceSlot.bottom without an anchor is now last in the section, below any trailing group, where the daemon appends a new workspace and the document lists it.
    • Every placement waits for the current row while the rows catch up, not only beforeCurrent/afterCurrent. The pending row checks that wait before it resolves its slot.
    • Neighbour anchors end when the document places the workspace, or when the listed workspace is gone. The count prune that dropped the anchor of a create not yet sent is removed.

Red before, green after (fleet, Xcode 26.6, scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext …)

  • Red: the head's new tests on 7fd2790 (no fix), as scratch commit a8b912e / 7ba0a8a (refs since deleted):
    • CloseDuringCreateNoReappearTests fails: "listed again 20 times: while the create runs" (step b414aeef2fc39d5c8007da75).
    • NewRowOneSlotTests fails with 9 issues (step 02f4abd730b144d511712bc8): bottom index 2 instead of 3, anchors pruned to 0 of 20, top/bottom not waiting, top pending row drawn early.
  • Green on 65a5634 (step c12653e8a556cbd5f5025ac7): CloseDuringCreateNoReappearTests ("listed again 0 times"), NewRowOneSlotTests, WorkspaceLanesTests (new aTakenCreateStaysOutstandingUntilItsCloseHasRun) and RapidWorkspaceCreateTests.
  • Green on 3d4bfb4 (the head minus the last test-only commit): SidebarDocNewWorkspaceTopTests, CmdNRowSlotSuites, NewWorkspacePositionTests, RapidWorkspaceCreateTests, NewWorkspaceGroupIndexTests, NewWorkspaceInSectionTests, ColdCmdNRowSlotTests, ColdCmdNWindowRowsTests, CmdNSlowDaemonKeepsWorkspaceTests, CreateTerminalLateStartTests, NewWorkspaceFromHomePageTests, PlacementStaleRowsTests, PlacementWriteOrderTests, WorkspaceCloseSlowDaemonTests, WorkspaceCloseFlowTests, SidebarSelectionBatchCloseTests, OfflineWorkspaceCloseTests, WorkspaceLanesTests, PendingWorkspaceRowsRedrawTests, SidebarCloseSelectionTests (step 4fd3a82bfbbfd5f91221342f). Its only red was CloseDuringCreateNoReappearTests, from a test-timing bug that 65a5634 fixes.

Tagged build

23071-new-workspace-before-current, fleet job e6e5791a47a6d99b534e3875 at 65a5634, published to the Tag Opener (?check=1 installed).

Observed / Not run

  • Observed: the fleet suites above, and the prepush gate passing on every push.
  • Not run: a GUI frame trace of the new-row animation (the motion change rests on the slot agreement and its pure tests). The close test covers the New Tab page create path, not a terminal create (same lane and hide code).
  • Known: user_settings.rs from_wire lacks before_current (outside this merge, unchanged).

Review

  • First correctness review (subagent) on 0ea0e3c: found nothing blocking. Fixed in eaa45ca:
    • a refused close of a taken create stayed hidden;
    • the top pending row skipped the current-row wait;
    • an early release in the gap before the close;
    • the selection not moving.
  • Not changed, and why:
    • the 3 s placement wait applies only to daemons without workspace-create-current-v1;
    • bottom now lands below trailing groups by design (it matches the daemon and the document);
    • anchors of creates closed before they were listed are released by forget on create failure.
  • Re-review of the fix delta (0ea0e3c..65a5634): nothing blocks. Its note that a closed id can stay in the hide set until the next store change is harmless, because a reopen gets a new id.

Review (review_23071): SHIP at 65a5634

🤖 Generated with Claude Code

This branch had an error being deployed

1 failed (outdated) and 3 inactive (2 outdated) deployments
ci-routing-agent — 65a56347 Deployed Nov 5, 2026 by austinywang via wait for same-key tree publisher #114268
artifacts — 0ea0e3c3 Deployed Nov 5, 2026 by austinywang via publish tree-addressed cmux-tui #114031
sentry-dsyms — 0ea0e3c3 Deployed Nov 5, 2026 by austinywang via upload cmux-tui dSYMs to Sentry #114031
cmux-tui-merge-tree — 4fbb114d Deployed Oct 26, 2026 by austinywang via publish the merge tree #6623
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.

3 participants