cmux NEXT sidebar: chat history (Earlier) and pinning under the session tree

Merged
TE
16d ago
+1582-6

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.sessionTree on:

  • Earlier: chats that no open workspace on this Mac shows (ended, closed, or never opened here) stay listed under the tree in a quiet, foldable Earlier block, newest first. It shows 20 at a time, with Show More for the next page. Each row has the chat's title and a faint age. There's no kind icon, and rows are compact.
  • Pinned: a row's right-click menu pins or unpins the chat. Pinned chats list above the workspaces in pin order. Pins and the Earlier fold persist in UserDefaults.
  • Resume: clicking a row resumes the chat through the app's shared Open Chat path (chatsOpener.open(key)).
  • Cost: it reads metadata only from acpmux's chat index (the Chats feed mirror). It never loads a transcript. The index is read lazily and stops once the page plus one more chat is found, so hundreds or thousands of chats cost one short pass. Rows are made only for the shown page.
  • A chat counts as live, and so stays out of Earlier, when an agent tab in an open workspace runs an acpmux session that continues it (the lane's new chat key, harness:sessionId, which mirrors acpmux's session_chat_key).
  • Filtering hides both blocks. There's no project or repo grouping (turned off in the 10-08 meeting).

Testing

  • SidebarChatHistoryTests (boundary tests): paging and Show More, the live and pinned exclusions, the fold, pin persistence across a fresh SidebarChatHistory on 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.
  • Swift build and test run in CI. This Mac is shared and heavily loaded, so nothing was built locally.

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. SidebarChatHistoryTests drives the real views.

🤖 Generated with Claude Code

Agent session: cosmic-gray


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


Summary by cubic

Adds chat history and pinning to the session-tree sidebar, behind the same sidebar.sessionTree flag (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.

  • Pinning runs the registered sidebar.chat.togglePin action, so the row menu, the palette, and cmux action run share one handler; the menu row is retitled Pin or Unpin for its chat.
  • Reads metadata only from acpmux's chat index, lazily and stopping after one page, so hundreds or thousands of chats cost one short pass; no transcripts load.
  • A chat stays out of Earlier while an agent tab in an open workspace runs a session that continues it.
  • A group fold now lays the list out again while either history block shows, so opening or closing a group no longer shifts workspace rows under Earlier or leaves a gap.