Skip to content

cmux-next sidebar: every row shows its pull request badge, not only with the session tree on - #23495

Merged
teamleaderleo merged 5 commits into
feat-cmux-nextfrom
leo/sidebar-pr-badges
Oct 21, 2026
Merged

teamleaderleo merged 5 commits into
feat-cmux-nextfrom
leo/sidebar-pr-badges

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

This is slice S3 of Leo's sidebar-organization ask (item A, the PR badge). It builds on #21814 (the session tree's pull request badges). The owner of #21836 cleared it: the only overlap is two small spots next to each other, and whichever PR lands second takes the conflict.

What changes

Every workspace row now carries its pull request badge: a glyph and a count, in the most urgent state's color, with the hover card. Before this, the badge only drew with sidebar.sessionTree on.

  • Unchanged: the tree's nesting, guide lines and Command-number keycaps still need sidebar.sessionTree, and manual order is untouched.
  • How: SidebarSessionTreeFeed also runs for the badges and publishes them apart from the tree state (SidebarSessionTree.pullRequests). The layout draws them whether or not the tree is on.
  • Redraws: a badge change redraws the list, and a group fold keeps its members' badges. The first review caught both.
  • Cost: by default, gh now runs for anyone with agent chats, not only people who turned the tree on. It uses the reader the chat header's chip already shares: two calls at a time, never prompting, at most once every five minutes per folder or URL, with one batched GraphQL read for URLs. A failed read, including a missing or logged-out gh, keeps the last answers and backs off by doubling, up to 80 minutes.
  • Toggle: Debug toggle sidebar.pullRequestBadges, on by default. Turning both it and the tree off stops the feed and its gh pr view checks, as before.

Tests

Tests/CmuxNextAppTests/SidebarPullRequestBadgeTests.swift (committed first) covers three things:

  • the feed publishes badges but no tree while the tree is off;
  • a row draws its badge with no nesting and no keycaps;
  • a badge that arrives or leaves after the first draw is drawn;
  • the layout carries the badge in manual order.

No capture: a capture slot has no GitHub credentials, so no row there gets pull request data. The badge view and its drawing are unchanged from #21814, and the view-level tests above cover a drawn badge with the tree off.

Observed / Not run

  • Ran:
    • scripts/cmux-next/prepush-gate.py: no new violations.
    • Fleet compile-check --app: passed on 6d8ca2b.
    • Independent review: BLOCK at 6d8ca2b (redraw and fold), fixed in c510bb2.
  • Not run locally: the Swift suites, which run in this PR's CI.

Changelog

  • Changed: Sidebar rows show their pull request badge even with the session tree off.

Agent session: cosmic-gray

🤖 Generated with Claude Code


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


Summary by cubic

Every sidebar row now shows its pull request badge even with the session tree off; previously the badge only drew when sidebar.sessionTree was enabled.

  • The session tree feed now runs just for the badges and publishes them separately from tree state (SidebarSessionTree.pullRequests).
  • A new Debug toggle, sidebar.pullRequestBadges, is on by default; the tree's nesting, guide lines, and Command-number keycaps still require sidebar.sessionTree.
  • A badge change redraws the list, and folding a group keeps its members' badges.
  • gh now checks pull requests for anyone with agent chats, not only tree users: two concurrent calls, never prompting, at most once per five minutes per folder or URL, with backoff (doubling, up to 80 minutes) on failure.
  • Tests cover the publish path, a row's badge with the tree off and in manual order, and badges that arrive or leave after first draw.

Written for commit 5bcbcd0. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 2 commits October 21, 2026 07:59
… with the session tree on

The session tree feed now also runs for the badges (Debug toggle sidebar.pullRequestBadges,
on by default) and publishes them apart from the tree, so a row shows its pull requests while
nesting, guide lines and keycaps stay behind sidebar.sessionTree. Manual order is untouched.

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

Owned by chief-sidebar on cosmic-gray · session

@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 5bcbcd0: 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=pr23495 -f ref=leo/sidebar-pr-badges -f platform=macos -f backend_mode=local

Not verified: macOS jobs did not run: compile and app tests were skipped on 5bcbcd09dc; ci-status is green without them.

CI passes on 5bcbcd09dc (run 39654562065 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

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); base red: the same failure on the base 8c47a2e; does not block

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

Copy link
Copy Markdown
Collaborator Author

Review (claude-review-subagent): BLOCK at 6d8ca2b

Read from a local worktree at the head; nothing built or run.

Blocking

  1. When the tree is off, a badge change never redraws the list. In SidebarView+Observation.swift render(_:), RenderState.pullRequests is part of the equality, so a change gets past guard state != lastState. But rowsChanged checks lastState?.tree != state.tree and history, not pullRequests. So listChanged is false and nothing reloads. The new value goes into lastState and is never drawn.

    • With the tree on this works, because the badges are inside tree. With it off (the new default path), a gh answer that arrives after the first draw does not show until something unrelated reloads the list. The same goes for a badge going away and for the tunable being turned off.
    • Fix: add || lastState?.pullRequests != state.pullRequests to rowsChanged, or patch the rows whose badge changed.
    • The test doesn't catch this. aRowDrawsItsBadgeWithTheTreeOffInManualOrder sets SidebarSessionTree.shared.pullRequests before it builds the view and then calls list.reload itself. A test that sets the map after the first renderNow(), calls renderNow() again and expects the badge, would be red at this head.
  2. Folding a group drops its members' badges. SidebarListView+Fold.swift foldGroup builds options from model.listOptions(), which never sets pullRequests. SidebarLayout.fold rebuilds every member row with o.rowContent(...), so a group's members lose their badge when it is opened or closed, and get it back only at the next full reload.

    • With the tree on this was already true (no sessionTree or keycaps on that path either), but this PR turns the badge on for everyone, so it is now on the default path.
    • Fix: in foldGroup, add o.pullRequests = SidebarSessionTree.shared.pullRequests; the keycaps could be added there too.
    • The other places that build layout options are fine. Row patches (SidebarRowIndex uses options(includeGap: true)), in-place reorder, drag and tab drop all go through options(includeGap:). SidebarModel+VisibleRows and +ItemOrder only need order and parents, and the badge does not change row height (metrics.height(for:) doesn't read it).

Checked, fine

  • RenderState.init has a single init, and it sets pullRequests.
  • Reading the tunable in the feed is observed: Tunable.value registers an Observation dependency on its key, as in SidebarLaneStatus. With nests || ... short-circuiting, the tunable is not tracked while the tree is on, which is correct because the badges come from the tree then.
  • publish keeps SidebarSessionTree.state nil while the tree is off, so keycaps (options(includeGap:)), ItemOrder and VisibleRows (via state?.parents) and nesting stay tree-only. SidebarChatHistoryFeed has its own sessionTree guard and does not depend on this feed. The hover card reads the row's content.
  • Cost: the feed and SidebarPullRequestStore now run for everyone. The store runs at most two gh reads at a time, only for folders and URLs of workspaces with agent chats, with a 300 s recheck of open or draft PRs. That seems acceptable, but the PR body should say that the default now makes gh calls for every user with agent chats. It should also confirm that a missing or unauthenticated gh fails quietly and does not retry in a tight loop.

Tests

  • child.frame.minY > parent.frame.minY || child.frame.maxY < parent.frame.maxY only checks that the two frames differ, which two separate rows always do. Either drop it or assert what was meant, for example that lane sits right after other at depth 0 (the layout test already covers that).
  • The keycap isHidden checks hold: with the tree off, rowContent never sets keycap, and the test's DesignSettings() leaves sessionTree off.
  • publish and the layout test are fine.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

I read the fixup commit (6d8ca2b..c510bb2) and re-checked the whole PR diff against merge-base ed547f0. Local git only; I did not build or run anything.

Both earlier blockers are fixed

  1. SidebarView.render: rowsChanged now includes lastState?.pullRequests != state.pullRequests, and RenderState snapshots SidebarSessionTree.shared.pullRequests. With the tree off, a badge change now reaches showModelChange → reload(fromModel: true).
  2. foldGroup sets o.pullRequests = SidebarSessionTree.shared.pullRequests, so a spliced fold builds member rows that keep their badges. With the tree on, the fold's options have no sessionTree, which was already true before this PR. The fallback pullRequests[ws.id] reads the same map, because publish always writes pass.state.pullRequests, so the badges still match.

No other place draws rows without the badges. All row drawing goes through options(includeGap:): displayLayout, drag, tab drop, in-place reorder and the SidebarRowIndex patch path. That function sets pullRequests, and so does the fold. The other SidebarLayoutOptions() builders are SidebarModel+VisibleRows and SidebarModel+ItemOrder. They only compute row order and keycap order and never draw row content, so they don't need the badges.

The new test aBadgeThatArrivesLaterIsDrawn should pass:

  • On the first renderNow(), lastState is nil, so both rowsChanged and selectionChanged are true, and render takes the list.reload(... fromModel: true) branch. apply creates views for rows inside realizationRect(), the same way the explicit list.reload does in the first test, so rowViews is populated. The observe() Task does not run before then, because the test never suspends.
  • On the second and third renderNow(), only rowsChanged is true (the selection did not change), so render calls showModelChange. holdsModelChangeNow is false because window == nil, so it reloads. apply runs configure(view, row:) on every existing row view. configureSessionTree then calls pullRequests.configure(shown.pullRequests), which sets badge and isHidden right away, with no animation in between.
  • let row = { try #require(...) } followed by try row() is valid. The closure is inferred as () throws -> WorkspaceRowView and stays on the main actor, #require works inside closures, and #expect(try ...) accepts throwing expressions.
  • The meaningless frame assertion is gone.

Nits (not blocking)

  • The badge tests read and write the process-wide SidebarSessionTree.shared. .serialized only orders tests inside this suite. If another suite running in parallel leaves shared.state non-nil, rowContent would take sessionTree.pullRequests before options.pullRequests. Resetting SidebarSessionTree.shared.state = nil in the setup would close that gap.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

@cursor

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

…bar-pr-badges

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentLanes/SidebarSessionTreeFeed.swift
@cursor

cursor Bot commented Oct 21, 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 5bcbcd0

Scope: only the conflict resolution in the second base merge (5bcbcd0) against #23531, read with local git (git diff 5bcbcd09^2 5bcbcd09, git diff c510bb24 5bcbcd09). Nothing built or run.

  • SidebarSessionTreeFeed.swift: the resolution is a faithful union. Base's readsPullRequests(sections) / pass.showsTree = sections.sessionTree are kept; the PR adds || SidebarTunables.pullRequestBadges.value to the guard and replaces the inline tree write with publish(_:to:), which writes tree.state only while showsTree (same as base) and always writes tree.pullRequests. With the tree off, tree.state stays nil exactly as on base.
  • Red CI (SidebarSessionTreeFeed+Checks.swift, unchanged by the merge): checksFailing still guards on readsPullRequests(sections) (tree || Priority view), not on the badges toggle. With badges on and both tree and Priority off, the reads now run, but checksFailing still returns false, so the Priority view's Red CI and SidebarLaneStatus's failing-checks input report nothing base wouldn't. SidebarPriorityRedCITests expectations (!checksFailing / !readsPullRequests with both off) still hold.
  • No leftover nests reference anywhere in Packages/macOS code (git grep '\bnests\b' finds only unrelated comments). The only Pass( constructions are the feed's Pass(state:asks:) and the tests' Pass(state:asks:showsTree:), which matches the memberwise init order state, asks, showsTree.
  • SidebarTunables is a public enum in CmuxNextSidebar, which the feed already imports publicly.

Nits, not blocking: the checksFailing doc comment ("which run while the tree or the Priority view is on") no longer says that the badges also keep the reads running. Separately, with only badges on, a row's badge can show failing while the lane-status failing-checks chip stays off. That is base's gating, kept on purpose; it's worth a follow-up only if the two should agree.

@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026

Copy link
Copy Markdown

Found 9 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpaa4t19ir/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpd6zao4f0/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
test_a_file_a_test_reads_selects_that_test (main.PullRequestTiers.test_a_file_a_tes
t_reads_selects_that_test)/
test_a_file_a_test_reads_selects_that_test (main.PullRequestTiers.test_a_file_a_tes
t_reads_selects_that_test)
View Logs
test_a_shared_module_selects_its_dependents (main.PullRequestTiers.test_a_shared_mo
dule_selects_its_dependents)/
test_a_shared_module_selects_its_dependents (main.PullRequestTiers.test_a_shared_mo
dule_selects_its_dependents)
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

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

cmux-next guards / cmux-next localization debt ratchet is red on 17 of 18 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
teamleaderleo merged commit bd60f6f into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the leo/sidebar-pr-badges branch October 21, 2026 19:38
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 22, 2026
Conflicts with the Done fold (#23633), every row's PR badge (#23495) and machine marks (#22763):
- Loose rows: the tree's rows (depth, chevron, roll-up) go through foldingDone, which leaves
  them as they are while the tree is on, so the Done fold and the tree compose.
- SidebarSessionTree keeps base's pullRequests beside the folds; the list and observation read
  both `drawn` (the tree with folds) and `pullRequests`.
- WorkspaceRowView adds base's machineMark and this branch's fold button and roll-up.

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
teamleaderleo added a commit that referenced this pull request Oct 22, 2026
Every conflict takes the base side. The PR's own changes are dropped here and the
status grouping is ported again in the commits after this one:
- superseded and removed: the row status marks (WorkspaceStatusMarksView,
  WorkspaceRowStatusMarks, WorkspaceRowView+StatusMarks; replaced by the row status
  words of #23390 and the PR badges of #23495) and the agent-parent links and elbow
  (SidebarAgentLink*, SidebarElbowView, SidebarMapping+AgentLinks and their tests;
  replaced by the session tree of #21814 and #22778);
- re-added on top: the status sections behind the Debug toggle.

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
…the Priority view's states (port of #20905)

Debug toggle sidebar.groupByStatus, off by default (off, the list lays out exactly as
before). On, every computer's rows sit under the Priority view's states in its tier
order and words: Needs you, Done, Failed (failed or lost), CI failing, Working, Idle.

No classifier of its own: SidebarStatusSection reads what the row feed already gives
each row from AgentPriorityRanking through SidebarLaneStatus, its chip
(SidebarWorkspace.agentChip) and, without one, its working mark (agentWorking).
Inside each section rows keep their manual order. The active row keeps its section
until another row is active; Needs you never folds; turning the toggle off forgets
the held row and the folds (#20905 review). Grouped lists lock drag reorder, as
Group by Folder does. Headers reuse the Priority view's localized words, so no new
strings.

Dropped from #20905 as superseded: the row status marks (#23390 row words, #23495 PR
badges) and the agent-parent elbow (the session tree, #21814 and #22778).

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
lawrencecchen added a commit that referenced this pull request Oct 22, 2026
…achine marks patch in place

Since Oct 21 every acpmux lane event (each agent step, a few a second per working agent) mapped
every sidebar row that shows a chat again: each row's mapping read the whole AgentLaneStore.lanes
dictionary (sidebar.laneStatus and sidebar.rowStatus on by default, #23390; the Now: line, #23474),
and the pull request badge feed, on by default since #23495, re-ran its pass over every workspace,
tab and lane on each event too.

- AgentLaneStore keeps one observable cell per session: rows read lane(session) and are told about
  their own lanes only; the badge feed reads links(session) (folder, pull requests, spawnedBy, peer,
  chat), which a new step or state leaves alone. lanes stays for whole-store readers.
- A pull request badge change patches the rows whose badge changed instead of laying the list out
  again (SidebarView render).
- The hover card is not rebuilt (timeline read, refit) when only the hovered row's step changed:
  the card does not show it.
- A row's machine mark image is drawn again only when the mark or its size changes (#22763 made a
  new NSImage on every configure).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 22, 2026
…kspaceRow.pullRequest (off by default) (#23989)

* cmux NEXT sidebar: pull request indicators on rows follow sidebar.workspaceRow.pullRequest (off by default)

Leo 2026-10-21: "REMOVE THE DONE, REMOVE THE TIME BY DEFAULT, REMOVE PR INDICATORS BY DEFAULT".

The read pull request badge (glyph + count, #23495) ignored the row element, so rows drew it
with sidebar.workspaceRow.pullRequest off. Now every pull request mark on a workspace row (the
hook text badge, the read badge with or without the session tree, an expanded row third line,
workspaces-as-tabs rows) follows the element, off by default, and the badge reads ask GitHub
nothing while no row shows them. The hover card keeps the pull request.

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

* cmux NEXT sidebar: badge view tests render the design first; reads follow the resolved kinds (review)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 22, 2026
…ebug toggle, off) (#20905)

* test: Group by Status behind Debug toggles (sections, live moves, marks, elbow children)

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

* feat(cmux-next): group the sidebar by status behind a Debug toggle

Ports #20851 off the Labs registry (Lawrence via Leo 10-15: no Labs; opt-in
looks are Debug settings toggles, off by default). sidebar.groupByStatus
lays rows under Needs you / Working / Done / No agent with counts, live
moves and a held active row; sidebar.statusElbow nests child agent sessions
with the CLI connector. Status marks on every row in that mode. No
cmux.json key, Settings choice or action changes.

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

* test: Group by Status review cases: asking child in a folded section, elbow off links nothing, patched child keeps its elbow

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

* fix: Group by Status review: asking trees under Needs you, no lane reads with the elbow off, patches keep the elbow, toggle-off forgets holds and folds

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

* refactor(cmux-next): agent links live in CmuxNextAgentLanes so CmuxNextApp stays under its size cap

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

* chore(next): PR autofix at 9e95df5

- regenerated Packages/macOS/CmuxNext/ci-target-graph.json

Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38714367151

* refactor(cmux-next): the row writer's link work lives in CmuxNextSidebar so CmuxNextApp does not grow

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

* test(cmux-next sidebar): Group by Status sections follow the Priority view's states (red)

Ported from #20905's SidebarStatusGroupingTests onto current feat-cmux-next: rows sit
under the Priority view's states in its tier order and words, from the state the row
already carries (agentChip, the working mark), in manual order inside each section;
off by default the list is as before; the active row waits; Needs you never folds;
turning the Debug toggle off forgets holds and folds; and one case runs acpmux lanes
through SidebarLaneStatus to show the sections come from AgentPriorityRanking.

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

* feat(cmux-next sidebar): Group by Status behind a Debug toggle, from the Priority view's states (port of #20905)

Debug toggle sidebar.groupByStatus, off by default (off, the list lays out exactly as
before). On, every computer's rows sit under the Priority view's states in its tier
order and words: Needs you, Done, Failed (failed or lost), CI failing, Working, Idle.

No classifier of its own: SidebarStatusSection reads what the row feed already gives
each row from AgentPriorityRanking through SidebarLaneStatus, its chip
(SidebarWorkspace.agentChip) and, without one, its working mark (agentWorking).
Inside each section rows keep their manual order. The active row keeps its section
until another row is active; Needs you never folds; turning the toggle off forgets
the held row and the folds (#20905 review). Grouped lists lock drag reorder, as
Group by Folder does. Headers reuse the Priority view's localized words, so no new
strings.

Dropped from #20905 as superseded: the row status marks (#23390 row words, #23495 PR
badges) and the agent-parent elbow (the session tree, #21814 and #22778).

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

* test(cmux-next sidebar): a workspace marked Done shows under its Priority state while grouped by status, not in the Done fold

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

* refactor(cmux-next sidebar): Group by Folder's buckets move to SidebarLayout+Folder so SidebarLayout.swift does not grow

The Group by Status hook added six lines to SidebarLayout.swift (over its 400-line cap);
this moves the folder bucketing out, a net shrink against base.

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

* test(cmux-next sidebar): a status section lists every row past sidebar.groupRowLimit, with no Show more row

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

* test(cmux-next sidebar): Group by Status tests name CmuxNextSidebar.SidebarSection (CmuxNextDaemon has one too) and type the row keys

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: cmux-autofix[bot] <cmux-autofix[bot]@users.noreply.github.com>
lawrencecchen added a commit that referenced this pull request Oct 22, 2026
…achine marks patch in place

Since Oct 21 every acpmux lane event (each agent step, a few a second per working agent) mapped
every sidebar row that shows a chat again: each row's mapping read the whole AgentLaneStore.lanes
dictionary (sidebar.laneStatus and sidebar.rowStatus on by default, #23390; the Now: line, #23474),
and the pull request badge feed, on by default since #23495, re-ran its pass over every workspace,
tab and lane on each event too.

- AgentLaneStore keeps one observable cell per session: rows read lane(session) and are told about
  their own lanes only; the badge feed reads links(session) (folder, pull requests, spawnedBy, peer,
  chat), which a new step or state leaves alone. lanes stays for whole-store readers.
- A pull request badge change patches the rows whose badge changed instead of laying the list out
  again (SidebarView render).
- The hover card is not rebuilt (timeline read, refit) when only the hovered row's step changed:
  the card does not show it.
- A row's machine mark image is drawn again only when the mark or its size changes (#22763 made a
  new NSImage on every configure).

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

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 5bcbcd09 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