Skip to content

feat: pin a session to the top of the sidebar - #180

Merged
omartelo merged 2 commits into
mainfrom
feat/session-pin
Aug 7, 2026
Merged

feat: pin a session to the top of the sidebar#180
omartelo merged 2 commits into
mainfrom
feat/session-pin

Conversation

@omartelo

@omartelo omartelo commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What

Pin a session so it sorts to the head of its project's sidebar list and cannot be closed by accident.

  • Pin/unpin from the card's context menu, or from the pin that appears beside the × on hover. A pinned card keeps its pin on screen — it is both the mark of the state and the way to undo it.
  • A pinned card offers no way to close it: no ×, no Close session in the menu, no keep-or-remove dialog, and the Pulls screen refuses to remove a worktree that holds one (a toast says to unpin first, next to the existing dirty-checkout refusal).
  • The pin survives restarts — a pinned column on the session row.
  • Pinning a worktree's session carries its group to the top of the sidebar, since groupByWorktree buckets by first appearance.

How

The order has one owner. internal/store keeps the drag order (ORDER BY position, rowid) plus the flag; sortPinned lifts the pinned cards over that order at render time in SessionSidebar. Hoisting in the query as well would cost a session its slot on every reload — the frontend would hydrate from an already hoisted list and have nothing left to drop an unpinned card back into. That was a real bug caught while smoke-testing, not a hypothetical.

The close guard sits in useWorktreeClose.requestClose, not in the provider's closeSession: removing a worktree closes its sessions through that same primitive, and a PTY outliving git worktree remove takes the checkout with it. Pulls.removeWorktree refuses up front instead.

Test plan

  • gofmt -l . clean, go vet ./... clean, go test ./... green (25 packages)
  • pnpm check clean (13 pre-existing a11y warnings), pnpm test green (644), pnpm build succeeds
  • New coverage: sortPinned / setSessionPinned reducers (frontend), SetSessionPinned persistence and the untouched row order (backend)
  • Smoke-tested in a headless run of the real app (three sessions, dark theme):
    • pin hoists the card, the × disappears, the solid pin stays; a reload draws the same order
    • context menu reads Rename | Unpin | Pull request when pinned, Rename | Pin | Pull request | Close session when not
    • unpin returns the card to its old slot both live and after a reload, and the × comes back
    • no console errors

CHANGELOG.md [Unreleased] entry included.

The session you keep returning to drifts down the list as new ones open
above it, and the × sits one stray click away from ending it for good.

Pinning answers both. A pinned card sorts to the head of its project's
list and stays there across restarts, and it drops every close
affordance it had: no × on hover, no "Close session" in the context
menu, and the worktree it lives in refuses to be removed from the Pulls
screen. Unpin and all of it comes back, including the slot in the list
the card had before.

The order has one owner. The store keeps the drag order and the pin flag
and nothing else — `sortPinned` lifts the pinned cards over that order
when the sidebar draws. Hoisting in the query too would cost a session
its slot on every reload: the frontend would hydrate from an already
hoisted list and have no order left to drop an unpinned card back into.

Grouping falls out of the same list: groupByWorktree buckets by first
appearance, so pinning a worktree's session carries its group to the top
with it.

The guard behind the hidden affordances is in requestClose, not in the
provider's closeSession — removing a worktree closes its sessions
through that same primitive, and a PTY that outlives `git worktree
remove` takes the checkout down with it. Pulls refuses the removal
up front instead, the way it already refuses a dirty checkout.
@omartelo
omartelo merged commit dbadb8c into main Aug 7, 2026
3 checks passed
@omartelo
omartelo deleted the feat/session-pin branch August 7, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant