feat(desktop): draw review-thread previews with Pierre's diffs

Merged
DA
3d ago
+379-194

Summary

Stacked on #3221 and #3229, both merged. This PR is now one commit on main.

It does what the developer asked: use @pierre/diffs for every diff in Luke, the same way stage-cli does.

  • A review thread's code preview is now drawn through the same PierreDiff wrapper as Files changed (tasks/file-diff.tsx). The view is unified, lines are tinted whole (stage-cli's previews turn inline word diffs off, because they're partial hunks), and the thread's own lines are lit with Pierre's selection in the code's blue.
  • threadPreview now writes the excerpt as a patch of the thread's file (a diff --git head, plus a hunk header counting only the rows kept), together with the selection. It is built the way stage-cli's buildReviewCommentPreviewPatch / getReviewCommentSelectedLines are. A side the excerpt holds no line of is written empty, as git writes one (-0,0).
  • The diff contract adds selected (Pierre's setSelectedLines) and excerpt. An excerpt uses Pierre's simple separators, so it doesn't open with "N unmodified lines".
  • Deleted for good: diff-rows.tsx, the exports of patchHunks/DIFF_ROW/DiffRow and of CodeLineNumber/BLANK_LINE_TEXT, and the preview's .code-line[data-diff] CSS.

Evidence

  • changes-model.test.ts covers the excerpt patch and selection for a thread on a removed line, a range across both sides, and a new file's first added lines (empty old side), plus the hunk-end fallback and unreadable hunks.
  • agent-pull-request-tab.test.ts checks that a thread's preview hands the diff bundle the excerpt, its selection, a unified look, and changed words off.
  • I rendered the preview on its own under the panel's CSP. Before switching excerpts to simple separators it opened with "9 unmodified lines". expandUnchanged, which stage-cli sets, draws nothing without the file contents.
  • Typecheck, biome, oxlint and knip are clean.

Invariants

  • Every behavior change has a test that fails without it.
  • No new as assertion, no Effect.run*, and no raw async primitives.
  • The hand-rolled diff rows are deleted.
  • Test count: the 3 threadPreview row tests are rewritten as 4 patch tests (+1).

Notes

  • Next in the stack: stage-cli's full diff settings, then inline review comments in Files changed as Pierre annotations.

Made with Luke


Summary by cubic

Draws review-thread previews in the Pull request tab's Overview with @pierre/diffs, the same renderer Files changed uses, replacing the hand-rolled diff rows.

A thread's preview is written as an excerpt patch of its file — a diff --git head plus a hunk header counting only the kept rows — with the thread's lines as Pierre's selection, drawn unified like stage-cli's previews with inline word diffs off. Review threads are read over GitHub's GraphQL on the App's installation token, capped at 100 threads and 50 comments each, and PRIVACY.md now says so. The hand-rolled diff rows (diff-rows.tsx, patchHunks, and the DIFF_ROW exports) are deleted.

Tests cover excerpt patches for threads on removed lines, ranges across both sides, empty old sides, and hunk-end fallbacks.