* feat: relocate review chunks and embed review in git panel
Move the AI-sorted review chunk navigator out of the global left sidebar
and into the review page's own main panel (sidebar keeps the thread list),
and surface the review main body inside the agent thread's Git > Review
sub-tab with an expand link to the full review page.
The review main body + side panel + helpers are extracted into a shared
ReviewMainBody component with "full" and "embedded" variants.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* chore: move ReviewTab into its own file
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: reviews page split view, add-to-chat, virtualization + perf
- Virtualize the diff (Pierre Virtualizer + worker pool), mirroring the agent
chat panel, so large PRs window rows instead of materializing every line.
- Split chat and diff into independent scroll containers and make chat
auto-scroll fully contained, so typing/streaming no longer moves the diff.
- Memoize FileDiffCard with stable callbacks so focusing a finding re-renders
only the affected card.
- Add a persisted unified/split diff toggle.
- Add highlight-to-chat: select lines (drag / shift-click) + gutter "+" to drop
a file:line snippet into the chat composer.
- Rebuild sidebar group rows: whole card scrolls to the group (incl. the
expanded explanation), Read explanation stays a separate toggle, memoized.
* feat: add-to-chat uses attachment pills + selection popup / ⌘L
Replace the raw-snippet injection with a Cursor-style flow:
- Selecting lines shows a floating "Add to Chat ⌘L" popup at the pointer; ⌘L
adds the current selection without it. Removes the auto-adding gutter "+".
- "Add to chat" now creates a removable attachment pill in the composer (and a
pill in the sent message bubble) instead of pasting raw text. The code is
still serialized into the message content so the model receives it as context.
* feat: restore gutter + drag-handle for line selection
Re-enable Pierre's gutter '+' as a click-and-drag line selector (with the
highlight growing as you drag) — the affordance that was lost when the
auto-adding gutter button was removed. It no longer auto-adds: the commit flows
through onLineSelected to the 'Add to Chat' popup / ⌘L.
* fix: live selection highlight while dragging + reposition Add to Chat popup
- Feed onLineSelectionChange into the controlled selection so rows highlight
live as you drag, not just on release (Pierre only paints the controlled
selection when the prop updates). Popup now fires on onLineSelectionEnd.
- Anchor the popup's bottom-left to the drag handle (drop horizontal centering)
so it no longer overlaps the '+' button.
* fix: anchor Add to Chat popup to gutter handle + click-away to unselect
- Position the popup from the gutter '+' handle's rect (in the diff shadow DOM,
placed on the selection's bottom line) instead of the pointer-release point,
which landed inconsistently. Falls back to the pointer if not found.
- Clear the line selection (and popup) on any outside pointer-down.
* fix: sidebar-collapse header overlap + PR review comments
- Lift useSidebarLayout to AgentsShell (single source), share collapsed via
context, and pad the reviews header left when the sidebar is collapsed so the
fixed collapse toggle no longer overlaps the header content.
- add-to-chat: collect each diff side separately so a selection that spans a
deletion->addition no longer pastes wrong-file lines (PR comment).
- chat: clear attachments after sending via a suggested prompt, so an attached
snippet isn't silently resent on the next message (PR comment).
* fix: anchored finding card positions to the right of the diff again
The virtualization refactor moved the card inside the main-width Virtualizer
scroller, so it clamped over the diff. Render it in the outer container as a
viewport-fixed card clamped to window width (right gutter / over the side panel,
like prod) and track the finding as the diff scrolls (rAF-throttled), hiding
when the finding scrolls out of view.
Lighter, more consistent type across the dashboard and agent UI:
unify title sizes, drop semibold/bold in chrome to medium, harmonize
stray text-sm to text-xs, normalize chat markdown headings, and enable
antialiased font smoothing (fixes heavy text on dark backgrounds).
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: AI-sorted PR review view with diff grouping
Group a PR's changed files into a logical top-to-bottom walkthrough via a best-effort structured-output LLM pass, kicked off concurrently with the reviewer run (~0 added latency) and persisted on reviewer thread metadata. Results render in the review UI behind an AI sorted / file tree toggle that persists across PRs; the view falls back to the file tree when groups are absent or stale.
Adds a grouping-model team default (inherits the Reviewer subagent model when unset) and the admin RolePicker for it.
* feat(reviews): richer AI-sorted explanations + sidebar polish
Sidebar group rows get Devin-style spacing (dividers, padding), a per-group file list (click a file to jump to its diff), inline-code chips in titles, and an accent Read explanation link.
Group explanations are now rich markdown: the grouping prompt feeds per-hunk line ranges and asks for inline code, a short code block, and [path:line](#loc=...) references. The Markdown renderer turns those #loc= links into in-page buttons that scroll the diff to the hunk and highlight the range, reusing the existing selectedLines path.
* fix(reviews): drop stale diff groups from the AI-sorted view
When groups were generated for a previous head, a persisted "ai" view in localStorage still rendered the outdated walkthrough. groupedView now returns null on diff_groups_stale, so the file-tree fallback is used and the view toggle hides until fresh groups arrive.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat(ui): flatten reviews file tree and refine pierre tree styling
Switch the reviews-page file tree off forced full expansion so it renders
as a compact, flattened directory tree (single-child chains merged into one
row) like the pierre "flattened directories" preset. Expand only the
selected file's ancestors so the active diff stays revealed. Refine the
shared tree theme: subtle accent-tinted hover/selection and a complete
git-status palette (renamed/untracked/ignored) plus search input fg.
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix(ui): neutralize pierre tree filenames and selection styling
Use neutral grey/white filename colors instead of git-status accents,
apply unsafe CSS overrides for selected-row contrast, and switch to
complete icons in both agent and review file trees.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* feat: render Reviews page diffs with pierre MultiFileDiff
The Reviews detail page used a hand-rolled hunk renderer with no syntax
highlighting. Switch it to the same pierre MultiFileDiff + theming the agent
chat git panel uses.
- review-diff API now returns full original/modified file contents instead of
hunks, via a shared build_pr_diff_files helper extracted from thread_api
- findings render as right-anchored markers (pierre line annotations); focus
highlight uses selectedLines; floating finding card still anchors to the marker
* feat: auto-collapse a review diff card when marked as viewed
* fix: URL-encode file path in Contents API fetch
Filenames containing reserved URL characters (#, ?) were truncated, so those
files rendered as empty/unrenderable. quote(path, safe='/') preserves the path
separators while escaping the rest.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
* fix: Reviews tab — anchored finding card, paginated list, file tree truncation
- Finding card now tracks the diff anchor while scrolling instead of staying
frozen in the viewport; auto-hides when its diff card collapses (including
collapse via mark-as-viewed) and on click outside
- Checks section capped with max height + scroll
- /reviews paginated (page size 20) with has_more, filtered to the current
user's PRs by default with an All toggle; PR author login now stored in
reviewer thread metadata
- File tree truncation marker overlapped filenames because the sidebar bg
was transparent; use the opaque sidebar color
* fix: finding card tracks anchor 1:1 while scrolling
Drop the vertical viewport clamp — it pinned the card at the clamp
boundary while the highlighted lines kept scrolling, breaking the
attachment.
* fix: anchor finding card with Base UI popover
Replace manual fixed-position tracking (laggy: setState per scroll
frame) with a Popover anchored to the finding's diff row. Floating UI
tracks the anchor outside React renders, so the card moves 1:1 with
the content and scrolls out of view with it. Unanchored findings keep
the fixed top-right card.
* fix: lock finding card to diff scroll
Replace the Base UI popover (async repositioning, paints a frame behind
native scroll) with a card absolutely positioned inside the scroll
container, so it scrolls with the diff in the same compositor frame.
Scroll moves to the ReviewBody root, side panel becomes sticky.
Position recomputes only on layout shifts via ResizeObserver.
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>