a4970d07d5
* feat(desktop): resolve a session's pull request A session row can say whether its work is open, merged or closed, and link to it. The join is the session's own repo + branch, asked of GitHub in one batched GraphQL request per repo (branch aliases, not a `gh pr list` page that a busy repo crowds ours out of), through the remote-aware git facade so a desktop on a remote gateway asks the backend's `gh`. Two ways a session's branch can't answer, both covered: - It ran on trunk. Fork PRs share our branch namespace, so asking about `main` badges a stranger's PR onto it — trunk is never asked about, and cross-repository PRs are dropped server-side either way. - It worked in a worktree, so the branch it recorded at start isn't where the PR came from. Creating a PR from the review pane binds the session to the branch it actually used, and for sessions that predate that, the PR is recovered from the transcript: `gh pr create` prints a bare PR url and nothing else, so a tool result whose whole output is one is a claim rather than a mention. Scanned read-only across profiles, once per session ever. * refactor(desktop): one profile glyph The rail, the profiles page and the session-row chip each drew the same tinted initial square from scratch, so a row tag could disagree with the rail about a profile's color. One component owns the square, its tint, and the home icon the default profile gets instead of a letter. * feat(desktop): sidebar filter menu The sessions header's project/list toggle was one binary choice standing in for a view. It becomes a menu: group by date, project or status; order by updated, created, status, tokens or cost; show tokens, cost, PR, profile or an always-visible timestamp per row; filter by status, pull request, project or archived. Everything persists, and one reset puts it all back. The pieces that make it read right: - Status groups reuse the date dividers rather than inventing a second separator, and a magnitude sort (tokens, cost) drops the calendar entirely — "Today" above the priciest session you have ever had is a lie. - Row metadata shares the trailing slot the kebab covers on hover, so only the last fact steps aside and the number you switched on stays readable. - A filter deepens the loaded page to 300 rows and hands the window back when cleared, so "merged PRs" doesn't quietly answer for the last 50. - Archived is a view of its own set, and dragging is still what picks a manual order — the menu only offers a way back out of one.