Skip to content

cmux-next sidebar: a long group or list shows its first rows then Show N more - #23671

Merged
teamleaderleo merged 21 commits into
feat-cmux-nextfrom
leo/sidebar-show-more
Oct 22, 2026
Merged

teamleaderleo merged 21 commits into
feat-cmux-nextfrom
leo/sidebar-show-more

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

This branch is built on #23633 (the Done fold); until that merges, the diff here includes it. The S5 commits: dc4d3f2 (the test), e212336, then d770b56 (test) and d6c52f8 (fix) for the review's finding, c903dc2 (the string catalog kept in base order) and 80da4b3 (off by default).

This is slice S5 of Leo's sidebar-organization ask (item A, per-group "Show more").

What changes

A group's members, or a section's loose rows, longer than the row limit show their first rows, then a "Show N more" row. Click it to list every row, with a "Show fewer" row at the end that folds them again.

  • Always shown: rows that need you (the Priority view's needs-you state, SidebarWorkspace.agentChip) and the active workspace stay shown past the limit, in their order.
  • No "Show 1 more": a list one row over the limit shows whole.
  • With the Done fold: Done workspaces fold first (cmux-next sidebar: workspaces marked Done fold into one Done (N) row #23633) and count toward neither the limit nor "Show N more"; the Done row comes after the Show more row.
  • Not limited: while filtering, with the session tree, in Group by Folder (as for the Done fold), or while a drag runs (drops resolve by the drawn rows' model indexes, as for the Done fold).
  • A section's groups always show: its limit counts only its loose workspaces; groups and items are never hidden behind its Show more row (the first review's BLOCK, fixed in d6c52f8 after its red test d770b56).
  • What redraws: a row starting or stopping to need you is a row move past the limit (SidebarModel.movesRows, moved to SidebarModel+RowMoves.swift). A group past the limit folds by a full layout instead of the splice. Changing the limit lays the list out again.
  • The row: the same quiet chevron row as "Done (N)" (SidebarDoneFoldRowView), no drop target, no rename; its list's menu on right-click. Open state is the list's view state (SidebarListView.openShowMore).
  • Setting: Debug tunable sidebar.groupRowLimit, 0 (off) by default; set it (10 reads well) to turn Show more on. A default of 10 hid rows that existing behavior depends on (SidebarCloseWhileScrolledTests scrolls to row 20 of 40 and failed on a display host at d6c52f8), so turning it on by default is its own change.
  • Strings: "Show %lld more" and "Show fewer", in all 21 locales.

Capture

14 loose workspaces, the limit set to 10 through debug.tunables, "Task 01" active: the first 10 rows, the active row kept past the limit, then "Show 3 more".

Capture steps-5f31262a71 at 1db910810772 (fleet build, capture mini, text checked for private data)

Light Dark
light dark

The fix after it (d6c52f8) changes only sections that hold groups, so this capture still shows the head's behavior.

Tests

Tests/CmuxNextAppTests/SidebarShowMoreTests.swift (committed first):

  • a long group shows its first rows then Show more, which counts the rest;
  • rows that need you and the active one stay shown;
  • an open list shows every row then Show fewer;
  • one row over the limit shows whole;
  • 0 turns it off;
  • Done workspaces fold below Show more;
  • loose rows limit too;
  • groups past a section's limit stay shown (with the active workspace inside one);
  • a long group is not spliced;
  • the strings.

Red then green on the fleet (scripts/ci/run-swift-testing-suites.sh Packages/macOS/CmuxNext): groupsPastASectionsLimitStayShown fails at d770b56 and passes at d6c52f8. The fleet compile passed at 1db9108; the compile at 80da4b3 is running.

Takes back #23633: not a take-back. S5 adds .showMore to S4's case .doneFold line in SidebarRowViewPool.swift, so the Show more row reuses the done-fold row view; S4's behavior is unchanged.

Changelog

  • Added: A long sidebar group or list shows its first rows and a "Show N more" row.
    Agent session: cosmic-gray

🤖 Generated with Claude Code

teamleaderleo and others added 10 commits October 21, 2026 11:28
…at the end of their list

A group's members and a section's loose rows keep their manual order; the ones marked Done
(Mark as Done, SidebarTaskStatus.done) list behind one "Done (N)" row at the end, which a
click opens below it. The active workspace keeps its place. No fold while filtering or with
the session tree. Debug toggle sidebar.doneFold, on by default.

The row helpers visible/listsTabs/disclosure move from make onto SidebarLayoutOptions so
SidebarLayout.swift shrinks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd1-a2ac-74f1-85e7-0322693c12bd&host=cosmic-gray
…pace selected elsewhere shows

Review of #23633: drops resolve by the drawn rows' model indexes, so a drag lays the list out
with every Done workspace in its place. A selection patch whose new active workspace is listed
but not drawn hands over to a layout, which keeps the active workspace in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd1-a2ac-74f1-85e7-0322693c12bd&host=cosmic-gray
…w N more

Past sidebar.groupRowLimit rows (Debug tunable, 10 by default, 0 shows all) a group's members
or a section's loose rows show their first rows, the ones that need you and the active one,
then a "Show N more" row; a click lists every row with a "Show fewer" row. Done workspaces
fold first and count toward neither. The rows show whole while a drag runs, a group past the
limit folds by a full layout, and needing you is a row move past the limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd1-a2ac-74f1-85e7-0322693c12bd&host=cosmic-gray
…bar-done-fold

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarTunables.swift
# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarTunables.swift
@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 5e0c538: 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=pr23671 -f ref=leo/sidebar-show-more -f platform=macos -f backend_mode=local

Pending: CI is running on 5e0c5383e2 (run); the result below was for 594ce43f90 and no longer applies.

Last result: Passes: CI passes on 594ce43f90.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); it is rewritten when this head's CI completes.

red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: red check: Checks job structure is not red on the base ca294a9; do not merge until green; see lane-rules

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by chief-sidebar on cosmic-gray · session

@teamleaderleo teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-whu9i created for this PR by the cmux coordinator.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): BLOCK at 1db9108

Scope: only what S5 adds, git diff d77cefa143b6..1db910810772 (read locally, not built or run).

Blocking: the loose-list limit hides whole groups, along with the active workspace or a row that needs you inside them.
SidebarLayout.swift (the guard byFolder else branch) runs foldingDone/limiting over nodes, which are all of a section's top-level nodes: loose workspaces, items and groups (nested child groups are section nodes too). limiting keeps an entry past rowLimit only when workspace(entry.index) is the active workspace or .needsYou. That closure returns nil for a .group node, so every group after position 10 goes behind "Show N more". This applies by default, because the tunable defaults to 10, in any section with 12 or more top-level nodes:

  • When the active workspace is in a hidden group, it never gets a row. patchSelection sees displayed.row(for: .workspace(newActive)) == nil with model.lists(newActive) true, so it returns false and does a full reload. That rebuilds the same layout, and the row is still missing. The comment says "The active workspace keeps its place", but the code doesn't do that. Every selection change then costs a full reload.
  • A hidden group's .needsYou members stay hidden. That defeats the point of the needs-you exception.
  • "Show N more" counts groups as one row each, not the rows hidden inside them.
  • A parent group can stay shown while its child-group nodes are hidden, which splits the nested block.
    looseRowsLimitToo tests only plain workspaces, so it misses this.
    Fix options: (a) limit only workspace and item entries in the loose list and always keep group nodes, or (b) treat a group entry as kept when any of its members is active or .needsYou, and keep a child group with its parent. Either way, replace the workspace: closure in limiting with a stays: (Int) -> Bool closure. Add a test with ≥12 top-level nodes where a group past the limit holds the active workspace.

Checked, OK

  • Group limiting: shown.count > rowLimit + 1 gates it. The count on the row is shown.count - kept.count, which equals the hidden entries. When nothing would be hidden, the list comes back unchanged. Done folds first, and the "Show more" entry sits before "Done (N)". isLastInGroup is right: the last drawn entry gets it (Show more, or Done when present). Item and link members of a group count toward the limit and can be hidden. That's acceptable, since an item has no active or needs-you state.
  • agentChip path: SidebarLaneStatus.applying sets row.agentChip inside the SidebarRowFeed mapping. A lane or mark change remaps the row → onChange → SidebarRows.patch → patchWorkspaces. movesRows sees the .needsYou flip and returns false → show() → setSections → a full layout. So a row that newly needs you does come out from behind Show more. (While rowLimit > 0, any needs-you flip causes a full relayout, even in lists that aren't limited. That's acceptable.)
  • Splice guard: group.members.count <= rowLimit + 1 caps the layout's shown list, because shown ⊆ members. So whenever the layout would draw a Show more row, the splice is refused. Some refusals are unnecessary (done rows, open lists), which is safe.
  • Drag: (foldsDone, rowLimit) = (false, 0) keeps model indexes intact. The Rust resolver, DocDrag, rename, context menu, mouse, row pool and gutter all handle .showMore.
  • Keyboard and Cmd-number go through the model. A hidden workspace that becomes active (in a group's own list) is shown through the patchSelection reload, the same as Done.
  • Tunable: Double .number, range 0...100, step 1, .count (same pattern as agentPairCap). rowLimit clamps at ≥0. The observation state relays the list out when the value changes. It's listed once in all.
  • Strings: sidebar.showMore.title (Show %lld more) and sidebar.showMore.fewer are in all 21 locales, translated. %lld is in every value, and no non-en value equals the English.

Nits

  • The first time the hidden-active case triggers a reload, the previously active row (a hidden one) stays drawn until the next full layout. This is the same as Done; it's harmless.

@blacksmith-sh

This comment has been minimized.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): SHIP at d6c52f8

Read git diff 1db910810772..d6c52f877acf against the surrounding make, SidebarLayout+DoneFold, +SessionTree and +Fold code, in a separate worktree. I did not build or run anything.

The blocker is fixed

  • Loose-list call site: limits: { !isGroup(nodes[$0]) }. isGroup is the local func declared just above the byFolder guard in the same section-loop scope, so it is in scope. It captures nothing, and both closures are non-escaping.
  • limiting now gates on the count of limits entries only. Entries where limits is false go straight to kept without advancing n. Groups, child groups (with parent set, they are still .group section nodes) and section items therefore can't be hidden or counted.
  • A workspace inside a group that is active or needs you is never touched by the section limit, because the whole group always emits. Inside a group, foldingDone uses the default limits (all entries), so group-level behaviour is unchanged.
  • The count is right. shown.count - kept.count counts only hidden limits entries, because non-limited entries are always kept. The "one row over" guard (limited > rowLimit + 1) and the open state (shown + [showMore]) are consistent with it.

The test's expected order matches make
Here is how make handles the test. nodes is m0 to m11, then a and b. The limited count is 12, which is more than 11. m0 to m9 are kept (n < 10). m10 and m11 are hidden; neither is active nor needs you, and the active row is b1, which is inside b. a and b are kept. The result is [m0..m9, a, b, (showMoreIndex, 2)]. emit for a group appends its header and then its members (a1, b1). After that, appendFold appends the Show more row last. That equals members(0..<10) + [.group(a), .workspace(a1), .group(b), .workspace(b1), .showMore(looseList)]. Without the fix, a and b would have been n = 12 and n = 13 and hidden, so the test is a real red.

Unaffected

  • isLastInGroup: loose rows pass last: false, and the group-member path is unchanged.
  • openGapIfNeeded: the call sites didn't change.
  • The splice guard in SidebarLayout+Fold keys on group.members.count against rowLimit for the group's own Show more row. It doesn't depend on the section limit, so it stays consistent. A group in a section that has a loose Show more row is now always drawn, so position(of:) finds it. The section's Show more row comes after it and shifts with the other following rows.

Nits (none block)

  • When opened, the hidden loose rows reappear between m9 and the first group, while the closed list shows groups before the Show more row. Groups therefore move down on expand. That is expected, but could be mentioned in the PR body.
  • This predates the PR: a drag gap whose index is a hidden loose row only opens at nodes.count, because openGapIfNeeded only matches emitted indices.
  • The doc comment "a section's groups and items always show" describes the caller, not foldingDone itself. It would read better as "e.g. a section's groups and items".

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): SHIP at c903dc2

Scope: only the new commits since the last SHIP (d6c52f8..c903dc2: merge 814cd17 of #23633's head 1a7130a, then c903dc2). Read with local git and a Python json comparison; nothing built.

  • Merge 814cd17: its tree is identical to d6c52f8 (git diff d6c52f8 814cd17 is empty). The only thing 1a7130a brought was the catalog reorder, and the merge kept this branch's catalog, so it added no other change. 1a7130a is now an ancestor.
  • c903dc2 touches only CmuxNextSidebar/Resources/Localizable.xcstrings (1918/1918 lines, a reorder). git diff d6c52f8..c903dc2 touches nothing else.
  • The parsed catalog at c903dc2 equals the one at d6c52f8: same keys, same values, same top-level fields. Only key order changed.
  • Against the merge base cb27a38 (git diff --numstat origin/feat-cmux-next...c903dc2): 393 additions, 0 deletions, one hunk. That is three keys of 131 lines each: sidebar.doneFold.title, sidebar.showMore.title ("Show %lld more") and sidebar.showMore.fewer ("Show fewer"), each with 21 localizations. (The request expected 262 lines, but three new keys at 131 lines each make 393, which is correct.) No base key was removed or changed, and base key order is kept.
  • The file parses as JSON and ends with a newline, like base.

No findings.

@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Found 11 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpdq16wfsb/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpmo5ur9fk/summary-missing.json (live):/summary-missing.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
nightly cmux-tui resolve/nightly cmux-tui resolve View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules)
View Logs
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')/
test_every_submodule_free_checkout_on_an_owned_runner_resets_submodules (main.Reuse
dWorkspaceSubmodules.test_every_submodule_free_checkout_on_an_owned_runner_resets_submo
dules) (job='web-bundles')
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.

A limit of 10 by default hid rows that existing behavior depends on
(SidebarCloseWhileScrolledTests scrolls to row 20 of 40). Ship the limit as an
opt-in Debug tunable; turning it on is its own change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd1-a2ac-74f1-85e7-0322693c12bd&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): SHIP at 80da4b3

Delta c903dc2..80da4b3, read with local git only, nothing built.

  • The diff is the one commit and one file, SidebarTunables.swift: sidebar.groupRowLimit default: 10 becomes default: 0, and the doc comment says 0 is the default for now. Nothing else changed.
  • With a default of 0, nothing is limited:
    • SidebarTunables.rowLimit is max(0, Int(value)), so it is 0. SidebarModel copies it into o.rowLimit (SidebarModel.swift:520). SidebarLayoutOptions.rowLimit already defaults to 0, and drag/external drops still force 0.
    • limiting (SidebarLayout+DoneFold.swift:53) has guard o.rowLimit > 0, ..., so it returns shown unchanged and adds no Show more entry.
    • The splice guard (SidebarLayout+Fold.swift:39) has o.rowLimit == 0 || ..., so the incremental splice path is open again, as it was before the feature.
    • movesRows (SidebarModel+RowMoves.swift:9) flips on needs-you only when SidebarTunables.rowLimit > 0, so a needs-you change no longer forces a relayout.
    • The observation state (SidebarView+Observation.swift) still lays the list out again if someone changes the tunable.
  • SidebarShowMoreTests builds its own SidebarLayoutOptions with o.rowLimit = limit (default 10) and calls SidebarLayout.make directly. It never reads SidebarTunables, so the new default does not affect it.
  • No generated file records the default. git grep groupRowLimit outside Sources/ finds only SidebarShowMoreTests.swift, and nothing in json, md, sha256, docs/ or schemas/. The tunable reaches Debug settings only through its descriptor (SidebarTunables.swift:199).
  • This fixes the cause of the display-host failure at d6c52f8: tests with long lists, such as SidebarCloseWhileScrolledTests with 40 loose workspaces, resolve the tunable to its default and now keep every row.

No findings.

@cursor

cursor Bot commented Oct 22, 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next crash-class rules / cmux-next crash-class rules is red on 10 of 10 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): SHIP at 9333d3e

Base-merge review, checked with local git only (no build). Previous SHIP was at 80da4b3.

(a) The -s ours merge of the S4 squash dropped nothing.

  • a4c95338^ = 5f9025c (the base the author merged in step 1). 1a7130a is an ancestor of 80da4b3.
  • The squash tree equals git merge-tree --write-tree 5f9025c 1a7130a exactly (empty diff). So the squash is S4's head on base: the same 23 files, +486/-52, as merge-base..1a7130a. The patch-ids differ only because base moved 5 of those files (SidebarLayoutMetrics, SidebarTunables, SidebarModel, SidebarListView+Layout, SidebarView+Observation), and those base edits are pull request badges and folding only.
  • A real merge of a4c9533 into 2daabe5 conflicts in 21 S4 files. Every conflict is S4's version against S5's extension of it (.showMore cases, appendFold, rowLimit guards). git merge-tree -X ours 2daabe5 a4c95338 gives tree 1baa047, which is the tree of 7bf0a15. So no non-conflicting hunk of the squash was left out, and 2daabe5..7bf0a15 has no diff.

(b) S5's delta is unchanged. The changed lines of git diff 783c2068 9333d3e and git diff 1a7130a 80da4b3 are identical, over the same file list (23 files, +494/-48). For S4's files, 80da4b3..9333d3e shows only the 5 base-only edits above.

(c) Base composes with S5.

  • Since S4, base's sidebar changes add the pullRequests badges (options field, tunable, observation state, options()/fold paths) and SidebarModel.folding in place of setSections on collapse. Neither touches row keys, fold ordering or rowLimit. Base added nothing to the sidebar after the squash.
  • SidebarRowKey has no new base cases (only .doneFold and .showMore besides the old ones).
  • Every .doneFold switch site at the head also handles .showMore: RustSidebarRow (key encoding and resolvable), SidebarEmptyArea, SidebarDocDrag, SidebarInlineRename ×2, ContextMenu, Drag, Layout (gutter and configure), Mouse (hit test, plus its own click case at :146), RowViewPool.
  • Drag still turns off both folds: (o.foldsDone, o.rowLimit) = (false, 0) in SidebarListView+Layout.swift:75.

(d) Catalog. CmuxNextSidebar/Resources/Localizable.xcstrings is 262 added and 0 removed against 783c206, and it parses as valid JSON at the head.

Observed / Not run

Observed: the git tree, diff and merge-tree comparisons above, at 9333d3e. Not run: any build or test. Swift compile and tests stay with CI.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol): BLOCK at 9333d3e

  • Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarLayout+DoneFold.swift:36-44,59: the active-row exception is only applied when SidebarLayout.make runs. With rowLimit = 10 and 12+ rows, select row 11, then click row 0 (or select a Done workspace and then click a normal row). The selection path accepts an in-place patch when the new row is already visible, so it does not rebuild the layout; the old active row remains rendered past “Show more” or outside the Done fold until an unrelated structural reload. This leaves stale rows visible and violates the active-row/fold behavior described by the PR.
  • Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarLayout.swift:412-447: the Group by Folder branch emits every loose workspace directly and never calls foldingDone. With Group by Folder enabled, one machine, no filter/session tree/drag, rowLimit = 10, and more than 11 loose workspaces, all loose rows remain visible and no “Show N more” row appears, contrary to the PR’s section-loose-row behavior.

The tests cover pure layout cases but do not cover either active-exception removal or Group by Folder. I checked the exact merge-base diff, the relevant whole sidebar/layout/view/model files, the added tests and localization catalog, and re-read the live PR head; I did not build or run suites.

@cursor

cursor Bot commented Oct 22, 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): SHIP at 5e0c538

Independent re-review at the head. The delta from 594ce43 (the previous SHIP) is comments only. Diff against base ca294a9: 24 files, all in the sidebar package plus SidebarShowMoreTests. SidebarLayout.swift is 461 lines on both base and head.

Codex BLOCK at 9333d3e, judged at this head:

  1. The old active row stays visible after a click: documented behavior, not a defect. patchSelection is unchanged from base, where an active Done workspace kept out of "Done (N)" also stays in place. "A click moves no row" is the design from cmux-next sidebar: a click moves no row, and a move changes the order once #22960: refolding on click would move the clicked row under the cursor. Selection, hit testing, drag indices and the Show more count all stay consistent. A newly active row that is hidden forces a reload (SelectionPatch.swift:27). The doc comment now says this.
  2. No limit in Group by Folder: the S4 Done fold on base skips this branch too. SidebarLayout.swift:407 now says "no Done fold, no row limit", and the PR body now lists it under Not limited.

Fleet compile at this head: cmux-ci compile-check --app job 7069d250ce95fa1c6f112c15 passed.

Observed / Not run

Observed: git diffs, the base and head sources, all callers of patchSelection, and wc -l. Not run: builds and tests on the Mac (CI covers them).

@teamleaderleo
teamleaderleo merged commit f14426c into feat-cmux-next Oct 22, 2026
@teamleaderleo
teamleaderleo deleted the leo/sidebar-show-more branch October 22, 2026 01:47
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

base-red-watch: cmux-next guards / cmux-next CI guard group went red on feat-cmux-next in https://github.com/manaflow-ai/cmux/actions/runs/39707744016 (first red at f14426c, last green at ec749fa). Suspect: #23671 (commit f14426c). If it is yours, fix forward on feat-cmux-next.

teamleaderleo added a commit that referenced this pull request Oct 22, 2026
Brings in Show more (#23671, f14426c). Every switch over SidebarRowKey takes
.status and .showMore; Group by Status's movesRows now runs its status check, then
the base's SidebarModel.movesRows(from:to:groupsByFolder:listsTabs:) (folder, Done
fold, row limit, listed tabs), so the base rules live in one place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd1-a2ac-74f1-85e7-0322693c12bd&host=cosmic-gray
teamleaderleo added a commit that referenced this pull request Oct 22, 2026
Conflicts:
- SidebarLayout.swift: the loose rows keep the tree walk (treeRows) and take
  base's row limit (#23671): foldingDone gets limits:, and every negative
  entry (Done, Show N more) draws through appendFold.
- WorkspaceRowContent.swift: treeFold/rollUp beside base's chip, which is
  now only for the accessibility label (#23767).
- WorkspaceRowView.swift: base's subviews without elapsedLabel (#23812),
  plus treeFoldButton and rollUp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d2c-88e4-7fc2-b58e-9a55abdaced8&host=cosmic-gray
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

This branch was successfully deployed

2 inactive (1 outdated) deployments
ci-routing-agent — 5e0c5383 Deployed Oct 22, 2026 by teamleaderleo
artifacts — 80da4b38 Deployed Oct 21, 2026 by teamleaderleo
sentry-dsyms — 80da4b38 Deployed Oct 21, 2026 by teamleaderleo
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