Repository navigation
cmux NEXT sidebar: chat history (Earlier) and pinning under the session tree - #22323
Conversation
…(sidebar.sessionTree) Claude desktop's Code tab, behind a setting that is off by default: a workspace whose agent another workspace's agent started (acpmux spawnedBy) lists under it on a thin guide line, each row carries its pull requests (the branch PR of each session folder, as the chat header's chip reads it) in a green, orange or purple badge, and the first rows show their Command-number keycaps. The Command-1...9 order follows the drawn order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting # Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Localizable.xcstrings
- regenerated webviews/src/pages/settings/generated/strings.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39176969610
CmuxNextApp may not grow: the feed moves to CmuxNextAgentLanes (the app passes its workspaces), and the gh pull request reader moves next to its model in CmuxNextAgentPane so the chat chip and the sidebar share it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g' into feat/next-sidebar-session-nesting
…idebar-session-nesting
The moved gh reader's process holder carries its reviewed crash-allow (only the thread-safe isRunning and terminate() cross threads), and the sidebar asks each folder's pull request at most every five minutes, so it never stalls the chat header's chip on the two shared gh slots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated only: the fleet settings export (cmux-ci step b05e67a26082185e11778f94, run-swift-testing-suites.sh export-settings at 7ad7c4e; CmuxNextSettings is unchanged since), the defaults snapshot (defaults_guard.py snapshot) and the settings page strings (gen-strings.mjs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting # Conflicts: # schemas/settings-export/settings-schema.sources.sha256 # schemas/settings/settings-schema.json
…er the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…merge Generated only: the fleet settings export (cmux-ci step 69f7e53cebcd649429577bcd, run-swift-testing-suites.sh export-settings at 215bf61; CmuxNextSettings is unchanged since), the defaults snapshot (defaults_guard.py snapshot) and the settings page strings (gen-strings.mjs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting # Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextAgentActivity/AgentActivityLane.swift
…idebar-session-nesting Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e red: it no longer has raw font sizes) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The base merge in 08374a3 left both try #require(AgentActivityLane.of(...)) calls without their closing parenthesis, so CmuxNextAppTests did not build (fast tier: "the tests do not build"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idebar-session-nesting
…g' into feat/next-sidebar-session-nesting
…openAppLink (base red: CmuxNextAppTests did not build) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- regenerated docs/mdm/com.manaflow.cmux.json - regenerated docs/mdm/com.manaflow.cmux.plist - regenerated docs/mdm/managed-preferences.md - regenerated schemas/settings-export/settings-schema.sources.sha256 - regenerated schemas/settings/settings-schema.json - regenerated Packages/macOS/CmuxNext/ci-target-graph.json - regenerated web/data/cmux-shortcuts.generated.json - regenerated cmux-tui/crates/cmux-app-host/generated/cmux-app.d.ts - regenerated schemas/defaults/cmux-next.json Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39215245191
# Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Logic/SidebarLayoutMetrics.swift # docs/mdm/com.manaflow.cmux.json # docs/mdm/com.manaflow.cmux.plist # docs/mdm/managed-preferences.md # schemas/defaults/cmux-next.json # schemas/settings-export/settings-schema.sources.sha256 # schemas/settings/settings-schema.json
…idebar-session-nesting
…ounts them all (#21823) * acpmux: test that a session lists the pull requests gh pr create opened Red: pullRequests is absent, so the summary has [] (no detector yet). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: record the pull requests each session opens; the sidebar session tree counts them A tool call whose command runs `gh pr create` is remembered until it ends; the github.com pull URLs its output prints join SessionMeta.pull_requests, once each, and SessionSummary exposes them as optional pullRequests. CmuxNext parses them on AgentActivityLane and SidebarSessionTreeFeed reads each with `gh pr view <url>` beside the folder's branch PR, counting each pull request once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: count only a shell call whose whole command is gh pr create, and only the URL it prints Review fixes for #21823: a grep or echo mentioning gh pr create, or a chained gh pr create && gh pr view 9, no longer records links. The command is parsed (quotes, $( ), heredocs) and must be gh pr create after cd steps and env prefixes; only the last output line that is just a pull URL is kept, preferring rawOutput.stdout when the harness separates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: a failed gh pr create records no pull request gh exits 1 when the branch already has a pull request and prints its URL; that call opened nothing. Review nit from coord-2 on #21823. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): a gh pr create URL counts only once its call completes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: a gh pr create URL counts only when its call completes A harness that streams gh's "already exists: URL" in an in_progress update before the failed one recorded that pull request; the URL is now held per call and recorded on completed only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): AgentActivityLane.of takes no title Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(acpmux): gh pr create counts after && steps and with 2>&1 Red: a bare & splits `2>&1` and `&>file` into two commands, and only cd may precede gh, so the usual `git push && gh pr create --fill 2>&1` is never recorded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * acpmux: gh pr create counts after && steps and with 2>&1 A redirect's & (2>&1, >&2, &>file) no longer splits the command, and steps joined to gh by && may precede it, so `git push && gh pr create --fill 2>&1` records its pull request. ;, ||, | and & before gh still don't count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT sidebar: pull request hover card on the session tree's PR badge (#21959) * cmux NEXT sidebar: pull request hover card on the session tree's PR badge Hovering a row's pull request badge lists each pull request its sessions opened (acpmux pullRequests plus the folder's branch PR), newest first: title, a state pill (Conflict / Checks failed / Checks passing / Draft / Merged / Closed), owner/repo #N and +adds -dels; a click opens it in the focused pane's browser. It scrolls past eight lines. The badge gains a red failing status. Live state comes from one batched gh api graphql read per refresh (aliased pullRequest fields, 50 per query) instead of one gh pr view per URL. Debug Settings toggle sidebar.pullRequestCard, on by default; native gallery entry with conflict, checks-failed, mixed, all-merged and empty fixtures; strings in 21 locales. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT sidebar: pull request card review fixes A failed GraphQL read keeps the last answers (only a null alias clears one); the query pins --hostname github.com and other hosts fall back to gh pr view per URL; the card follows its badge when the row is reused or its pull requests change; a hidden badge never makes the panel and resets its hover; the workspace card and the pull request card dismiss each other; rows take first mouse; same-moment pull requests list by number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT sidebar: pull request card opens only PR pages; settled PRs are read once; failing reads back off The card opens a URL only when it is https://github.com (or the user's GH_HOST) /<owner>/<repo>/pull/<n> with nothing else. A merged or closed PR's URL is not asked again; a URL whose read failed waits freshness doubled per failure, up to 16x. Failed checks show red before a conflict. Review fixes from coord-2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT sidebar: import Foundation for the PR item host check (ProcessInfo, URLComponents) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): the PR store re-reads open PRs on its own, re-asks closed ones, and keeps answers on partial GraphQL errors Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * cmux NEXT sidebar: re-read open PRs every five minutes while shown, re-ask closed ones, keep answers on partial GraphQL errors Review findings on #21814/#21959: a badge never refreshed once its session went idle, so CI that failed later stayed green; a reopened PR never came back; an SSO or resource-limit error nulled good answers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next): only an open pull request keeps the sidebar's recheck Red: a folder never settles, so with the tree on the store re-reads every folder every five minutes, branches with no pull request included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(next): the sidebar rechecks only open pull requests, and forgets unshown ones - The five-minute recheck stays armed only while the tree shows an open or draft pull request. A folder never settled, so before this every session folder was re-read with gh every five minutes, branches without a pull request included. - Answers, read times and failure counts for folders and URLs the tree no longer shows are dropped on each pass instead of growing for the app's life. - The card's state pill uses Metrics.chipCornerRadius, not a capsule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…er the merge The merge kept stale copies of the shortcuts export, the devbox rebake list and the agent-session spec, and a second openAppLink in the test host. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aletteKey.toggleActions) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g' into feat/next-sidebar-session-nesting
|
Bead |
|
Owned by orphan-sweep on cosmic-gray · session |
#21814 (the session tree this was stacked on) landed as bab4a82, so its files take feat-cmux-next's version; only this PR's own commit (72a582c, chat history and pinning) is applied on top. AgentActivityLane keeps base's unread/project fields beside the new chat key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review (claude-opus review subagent): BLOCK at 883eff5 The feature logic holds up. Three reds on this head come from this PR's own files, so it can't land as it stands. All three are small fixes. Blocking (this PR's own reds)
The other failures in What I checked and found correct
Non-blocking
Still sensible against the current base: yes. It builds on the merged session tree (#21814) and the existing Open Chat path, and it adds no new connection or poller. |
…arlier animates through Motion.sidebar - SidebarChatHistoryView placed the blocks with Motion.animate(.move, in:), which base removed (every animation names its category now); it uses Motion.sidebar.animate, like the rest of the sidebar. - A history row's Pin/Unpin menu ran its own selector, which check-menu-actions.py rejects. The row's menu now comes from ActionRegistry.makeContextMenu(for: .sidebarItem, target: sidebar-item:<chat key>, entries: [sidebar.chat.togglePin]), retitled Pin or Unpin for the row's chat. SidebarChatHistoryFeed.bind binds the action to the history's pins; the App binds it where it starts the feed. New action title in all 21 locales; generated action exports are left to the autofix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
The public @observable class's conformance needs the module imported publicly (fleet app compile, job bea228bd3cfa). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
|
Review (claude-opus review subagent): BLOCK at 983c18a The three items from the 883eff5 review are fixed, and the action wiring is correct. One bug in the feature's own layout path remains: folding a workspace group leaves the Earlier and Pinned blocks where they were. That is the only blocker, and the fix is a few lines. Blocking
Answers to the specific questions
Non-blocking
Capture (not part of the code verdict): the description still has no capture ("Screenshot to follow"). Guards run locally on the exported head and on the merged base: |
This comment has been minimized.
This comment has been minimized.
…n all-static enum The conventions check refused the namespace enum SidebarChatHistoryMenu. The menu factory is now an instance hook on the history the rows already read, like onOpen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
|
Review (claude-opus review subagent): BLOCK at 1ca6506 The new menu hook is correct and the 883eff5 blockers stay fixed. The one blocker from the 983c18a review is still open: neither commit since then (9f75c7f, the base merge, and 1ca6506, the hook move) touches the fold path. Blocking
The earlier blockers
The new hook (1ca6506)
Generated files, strings, registry
Should-fix (not blocking)
Checked against: merge base 4a6ef5b and current |
…ry blocks show The fold splice moved the rows but not pinnedChatsY/earlierChatsY, so opening a group pushed workspace rows under Earlier and closing one left a gap. With either block placed, SidebarLayout.fold now declines and the list takes its full layout. Test included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (claude-opus review subagent): SHIP at 6a733e1 6a733e1 is one commit on top of 1ca6506, which I reviewed in the comment above. It fixes the one blocker left from that review: a group fold no longer leaves the Earlier and Pinned blocks behind. Nothing else in the code changed, so the rest of the 1ca6506 review still holds. The fold fix
Still true from the 1ca6506 review
Should-fix (not blocking)
CI on this head was pending with 0 failures when I looked. I ran no builds or tests here. |
Two conflicts, both additive: - WorkspaceRowContent keeps base's Priority `chip` (#23390) beside the tree's `treeFold` and `rollUp`. - SidebarView+Observation keeps base's chat history state (#22323) and reads the tree as `SidebarSessionTree.shared.drawn` (live state plus the folds). 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
|
Shipped in:
|
…yle everywhere else sidebar.chat.togglePin (#22323) kept "Pin or Unpin Chat" while every other toggle reads X/Y; it is keyboard-only, so Keyboard Shortcuts settings showed it. All 21 locales follow their Pin/Unpin Chat in Priority… wording; the row's right-click menu still says Pin or Unpin by the chat's state. plans/cmux-next/action-surfaces.json is generated; PR autofix regenerates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray
…est covers every action (#23722) * test(cmux-next): every action title, keyboard-only too, uses one toggle style (red) PaletteMenuVocabularyTests checked the X/Y toggle style only on palette actions, so the keyboard-only sidebar.chat.togglePin kept "Pin or Unpin Chat", which Keyboard Shortcuts settings shows. The toggle rule now covers every catalog action; red on that title. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * cmux NEXT sidebar: Pin or Unpin Chat is Pin/Unpin Chat, the toggle style everywhere else sidebar.chat.togglePin (#22323) kept "Pin or Unpin Chat" while every other toggle reads X/Y; it is keyboard-only, so Keyboard Shortcuts settings showed it. All 21 locales follow their Pin/Unpin Chat in Priority… wording; the row's right-click menu still says Pin or Unpin by the chat's state. plans/cmux-next/action-surfaces.json is generated; PR autofix regenerates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=cosmic-gray * test(cmux-next): the toggle style holds after a title's prefix too (red) Palette: Show or Hide Actions and Developer Tools: Start or Stop Performance Recording slipped past the start-anchored pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=huge-blue * cmux NEXT palette: Show/Hide Actions and Start/Stop Performance Recording, the toggle style Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bd2-60d2-70e1-8179-d3aa717c8828&host=huge-blue --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Parity gap #6 in manaflow-ai/cmuxterm-hq#2569: the sidebar has no persistent session list. This builds on the session tree (#21814, behind
sidebar.sessionTree, off by default) and stays behind the same flag. The flag default is unchanged.What it does
With
sidebar.sessionTreeon:chatsOpener.open(key)).chatkey,harness:sessionId, which mirrors acpmux'ssession_chat_key).Testing
SidebarChatHistoryTests(boundary tests): paging and Show More, the live and pinned exclusions, the fold, pin persistence across a freshSidebarChatHistoryon the same defaults, layout placement (Pinned above the first computer, Earlier under the last, nothing while filtering or with the tree off), and row click and menu actions through the real views.Proof
No capture: Earlier and Pinned sit behind
sidebar.sessionTree(off by default) and list only chats in acpmux's chat index. A capture slot's fresh HOME has no chats, so a capture would show an empty block.SidebarChatHistoryTestsdrives the real views.🤖 Generated with Claude Code
Agent session: cosmic-gray
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Adds chat history and pinning to the session-tree sidebar, behind the same
sidebar.sessionTreeflag (default unchanged).With the flag on, chats that no open workspace shows stay listed in a foldable Earlier block, newest first, 20 at a time with Show More; pinned chats list above the workspaces in pin order. A row's right-click menu pins or unpins a chat, and clicking a row resumes it through the shared Open Chat path. Pins and the Earlier fold persist in UserDefaults.
sidebar.chat.togglePinaction, so the row menu, the palette, andcmux action runshare one handler; the menu row is retitled Pin or Unpin for its chat.Written for commit 6a733e1. Summary will update on new commits.