Skip to content

feat(desktop): worktree-aware sidebar grouping + composer/sidebar UX fixes#45273

Merged
OutThisLife merged 7 commits into
mainfrom
bb/sidebar-workspace-dedup
Jun 13, 2026
Merged

feat(desktop): worktree-aware sidebar grouping + composer/sidebar UX fixes#45273
OutThisLife merged 7 commits into
mainfrom
bb/sidebar-workspace-dedup

Conversation

@OutThisLife

@OutThisLife OutThisLife commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reworks desktop recents grouping and fixes a batch of composer/sidebar/thread UX papercuts.

Worktree-aware grouping — recents now nest as parent repo → worktree → sessions. Git identity is probed locally over a new hermes:fs:worktrees IPC (reads .git metadata directly, dedup'd per cwd), so the main checkout and its linked worktrees collapse under one repo regardless of directory naming. Unresolved cwds (remote backends, non-git dirs) fall back to a path-name heuristic. A repo with a single worktree collapses to one level instead of showing a redundant header.

Stable session order — rows order by creation time (started_at) and never reshuffle when a new message lands. New repos/worktrees surface at the top; vanished ones drop out of the persisted order.

Main-checkout labeling — the main worktree is labeled by its directory, not its transient current branch (which would misattribute past sessions to whatever's checked out now). Linked worktrees keep their branch label.

Generic drag-reorder — every sidebar list (repos, worktrees, sessions, pinned) reorders through one nesting-safe ReorderableList that owns its own DndContext, so collision detection can't cross levels. Drag handle replaces the leading icon; dragged rows are opaque, unscaled, shadowless, and vertical-only.

Thread fixes

  • Removed streaming autoscroll that rubber-banded — the tail pin and the virtualizer's own measurement adjustments fought for scrollTop. The one-time new-turn jump still lands a fresh message in view; the viewport stays put after.
  • User-message attachments render as a flow sibling below the sticky bubble (scroll away behind it naturally) instead of inside it with an IntersectionObserver/[data-stuck] collapse hack. Image refs stay thumbnails, file refs stay chips; no border.

Terminal

  • Crisp text via an opaque xterm canvas: allowTransparency was forcing the WebGL renderer off its opaque fast-path (grayscale-alpha glyphs → soft on every platform). VS Code keeps it off; our surface is opaque anyway. Base weight back to normal/bold (was Medium); dropped the now-unused Medium face + woff2.

Other fixes

  • Status stack shares the composer's border (transparent bottom border under a higher-z composer) instead of floating / double-bordering.
  • Queue panel: icon actions restored (edit / send-next / delete); removed the stray radio control.
  • Sidebar labels truncate against the rail (grid-cols-[minmax(0,1fr)]) so +/drag controls stay reachable.

Test plan

  • npm run typecheck (clean)
  • npx vitest run src/app/chat/sidebar/workspace-groups.test.ts (heuristic + git-authoritative grouping, disambiguation, main-checkout labeling)
  • Manual: multi-worktree repo nests; single-worktree repo collapses; sessions don't reorder on new messages; drag is vertical/opaque at every level; status stack fused; queue icons work; long labels truncate.
  • Manual (thread): stream a long reply parked at bottom — no bounce; new turn lands in view; attachments sit below the bubble and scroll behind it.
  • Manual (terminal): reopen the terminal pane — text is crisp, not heavy/blurry.

…fixes

Group recents as parent-repo → worktree → sessions using local git
metadata (probed over IPC, with a path-name heuristic fallback for
remote backends). Single-worktree repos collapse to one level. Sessions
order by creation time and never reshuffle on new messages.

Also: fuse the status stack to the composer border, restore icon actions
in the queue panel, fix sidebar label truncation and drag styling, hide
sticky-message attachments while pinned, and bump the terminal font.
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: bb/sidebar-workspace-dedup vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10880 on HEAD, 10882 on base (✅ -2)

🆕 New issues (1):

Rule Count
invalid-assignment 1
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

✅ Fixed issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:2891: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

Unchanged: 5704 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Mirror the session row: the repo/worktree header's leading glyph (repo
mark, or a new git-branch mark for worktrees) swaps to a grabber on
hover/drag instead of carrying a separate handle on the right — freeing
header width for the label and + button.
… rows

The repo and worktree header rows were ~identical after the handle move.
Fold them into one WorkspaceHeader (emphasis flag for the repo level) plus
a small WorkspaceAddButton, so the toggle/handle/count/+ wiring lives in
one place.
…rderableList

Every reorderable surface (repos, worktrees, sessions, pins) now drops in a
single ReorderableList that owns its own DndContext, so a drag only ever
collides with that list's own items — nesting "just works" without leaking
into the lists around or inside it. This replaces the shared DndContext +
id-prefix dispatch (parent:/group:) whose closestCenter collisions resolved
to a different-typed droppable and silently no-op'd worktree/repo drags.

- Delete groupDndId/parentDndId/parse* helpers and the monolithic
  handleAgentDragEnd/handlePinnedDragEnd; each list persists its new id order
  via a direct typed write (reorderParents/reorderWorktree/reorderSessions/
  reorderPinned).
- Sessions inside repos/worktrees are date-ordered and static (no drag),
  matching the "never reorder on new messages" rule.
- Add setPinnedSessionOrder; drop now-unused reorderPinnedSession.
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have labels Jun 13, 2026
The terminal looked soft/heavy on every platform because the xterm
Terminal was built with allowTransparency: true, which drops the WebGL
renderer's opaque fast-path and bakes glyphs as grayscale-alpha coverage
for compositing over a see-through canvas. Our surface (--ui-bg-chrome)
is opaque and withSurface already paints it, so transparency was pure
blur for no benefit — VS Code keeps it off too. Also drop the Medium
(500) base weight for normal/bold (400/700) to match VS Code's metrics,
and remove the now-unused JetBrains Mono Medium face + woff2.
…w user bubble

Streaming auto-follow chased content growth while parked at the bottom,
which rubber-banded — the tail pin and the virtualizer's own measurement
adjustments fought for scrollTop. Drop it; the one-time new-turn jump
already lands a fresh message in view and the viewport stays put after.

Attachments rendered inside the editable user bubble and were collapsed
via an IntersectionObserver + [data-stuck] CSS hack while the bubble was
pinned. Render them as a flow sibling BELOW the sticky bubble instead, so
they scroll away behind it naturally — no observer, no collapse. Image
refs still render as thumbnails, file refs as chips; no border. Removes
the now-unused useStuckToTop hook and its CSS.
@OutThisLife OutThisLife enabled auto-merge June 13, 2026 00:59
@OutThisLife OutThisLife merged commit a86b7b3 into main Jun 13, 2026
25 checks passed
@OutThisLife OutThisLife deleted the bb/sidebar-workspace-dedup branch June 13, 2026 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants