Skip to content

[design-doctor effort high] clone of sourcebot#2: [design-doctor test] sourcebot-1154: Commit diff viewer#12

Closed
rohanneilkapoor wants to merge 15 commits into
bench/source-pr-base/design-doctor-feature-parity-expanded-20260610-152904Z/sourcebot-1154from
bench/design-doctor-effort-ab-20260617-160421/high/sourcebot-pr2
Closed

[design-doctor effort high] clone of sourcebot#2: [design-doctor test] sourcebot-1154: Commit diff viewer#12
rohanneilkapoor wants to merge 15 commits into
bench/source-pr-base/design-doctor-feature-parity-expanded-20260610-152904Z/sourcebot-1154from
bench/design-doctor-effort-ab-20260617-160421/high/sourcebot-pr2

Conversation

@rohanneilkapoor

@rohanneilkapoor rohanneilkapoor commented Jun 17, 2026

Copy link
Copy Markdown

Design Doctor reasoning-effort A/B clone for #2.

Variant: high for source-only design-system audit, visual QA audit, spacing/typography audit, and designer pass/redesign agent.

This branch adds a no-op commit on top of the original PR head so the file contents are equivalent while GitHub checks stay isolated to this test PR.

Original PR body:

Softlight Overview

Current PR UI

Design Score: 1/5

Suggested fixes

  • Line up the change-summary bar with the commit details and file list so the page reads as one clean left edge.
  • Match the diff header's close control to the other small action icons so the header feels consistent.
  • Size the preview banner's close control to match the other small icons nearby.
  • Keep the diff header tidy when author or date text is longer so it never crowds the change summary or close control.

Redesign

The commit diff screens felt cramped and slightly unfinished, with mismatched edges and busy metadata; the pass lined everything up to one column, calmed the details, and made the special states read clearly.

  • Every header, summary bar, and file row now shares one clean left edge with steadier spacing.
  • Commit controls became real buttons, icons share one size, and the 'previewing an old revision' and 'commit description' states now read clearly.

Fresh clean test PR for hosted Design Doctor rerun testing.

Benchmark note: Commit diff viewer with full and focused views.

Do not merge. This PR exists so Design Doctor can be run against a clean pull request with no prior review artifacts.

Note

Add commit diff viewer to the code browser

  • Adds a full commit diff view (FullCommitDiffPanel) and a focused per-file diff view (FocusedCommitDiffPanel) accessible via /-/commit/<sha> routes in the browse UI.
  • Clicking a commit row in the history panel navigates to the commit diff page; the short SHA in history rows links directly to the full commit diff.
  • Renders a syntax-highlighted split diff with line numbers, intra-line change highlighting, and a virtualized file list for large diffs via LightweightDiffViewer and FileDiffList.
  • Extends the /api/diff endpoint and get_diff MCP tool to accept an optional path parameter to scope diffs to a single file.
  • Blob routes gain a diff=true&ref=<sha> query mode that renders the focused file diff instead of source; a preview banner appears when viewing a file at a non-current ref.
  • Extracts shared code highlighting utilities into packages/web/src/lib/codeHighlight.ts and adds truncateSha to packages/web/src/lib/utils.ts.
  • Behavioral Change: the bottom panel (history/tree) is hidden on commit routes; react-grab scripts no longer load by default in development (requires DEBUG_ENABLE_REACT_GRAB=true).
📊 Macroscope summarized 0a36376. 33 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

brendan-kellam and others added 15 commits April 28, 2026 10:32
Adds a `commit` pathType to the browse routes
(`/browse/<repo>@<branch>/-/commit/<sha>[/<file>]`) that renders a
placeholder CommitDiffPanel. Refactors browse path helpers into a
discriminated `BrowseProps` union so commitSha is required only for
pathType: 'commit'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires up @codemirror/merge (via react-codemirror-merge) inside
CommitDiffPanel with a static before/after demo. Adds a CodeDiff
component that owns its language extension + view ref so each pane
can reconfigure its language compartment independently.

Also gates the react-grab dev scripts behind DEBUG_ENABLE_REACT_GRAP
so they don't load on every dev page render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the CodeMirror MergeView-based commit diff rendering with a DOM
based split-view that renders directly from git's hunks, inspired by
Chrome DevTools' DiffView. Per-file editor instances and the matching
getFileSource fetches are gone — a 50-file commit drops from ~100
network requests to 0, and per-row render cost from a full editor mount
to a synchronous Lezer highlight + grid emit.

- New `LightweightDiffViewer` builds a single 2-column subgrid with
  hunk headers spanning both sides; each cell uses `subgrid` so line
  numbers, markers, and content align across all rows.
- Pure helpers split out: `hunkParser` (body string → DiffLine[]),
  `splitPairing` (DiffLine[] → SplitRow[]).
- `presentableDiff` from @codemirror/merge supplies character-level
  intra-line diff highlighting on paired modifications.
- Lezer highlight code lifted from `lightweightCodeHighlighter` into
  `lib/codeHighlight` so both files share the helper.
- Drop `react-codemirror-merge` and `commitDiffEditor`. Long lines wrap
  via `whitespace-pre-wrap break-words` + `minmax(0, 1fr)` on the grid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- File path header now sticks to the top of the scroll viewport while
  scrolling through that file's diff, using the negative-yOffset trick
  to compensate for the virtualizer's translateY positioning. Same
  pattern as searchResultsPanel/fileMatchContainer.
- Lightweight diff viewer's grid uses `minmax(<min>, max-content)` for
  line-number and marker columns so they don't collapse to zero width
  when one side of the diff is entirely blank (fully-added or
  fully-deleted files), keeping the right pane aligned across files.
- Drop the column gap between left and right panes and instead draw a
  `border-r` separator on the left cells for a cleaner divider.
- Hunk header gets an optional className so the first hunk renders with
  just `border-b` (the file header above already provides the top
  border), while subsequent hunks render with `border-y` between them.
- Drop the per-row footer padding in the virtualizer; rows now sit
  flush against each other.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New `DiffStat` component renders GitHub-style additions/deletions
  counts with a 5-square indicator scaled log-ish to total change size.
  Added on the right of each file row header and on the right of the
  "N files changed" subheader for the commit total. Hidden when there
  are no line-level changes (pure renames).
- Each file row gets a `CopyIconButton` next to the path (copies
  newPath, falling back to oldPath) and a `CommitActionLink` that
  opens the file at the commit. Deleted files link to the old path
  at the parent commit so the user lands on the file's last existing
  state rather than a 404.
- `repoName`, `commitSha`, and `parentSha` are plumbed from the panel
  through `FileDiffList` to `FileDiffRow` to support the new link.
- `computeChangeCounts` is memoized per file in the row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nchoring

History panel rows in both the bottom panel and the commits page are now
clickable — they navigate to the matching commit diff via router.push,
with closest('button, a') short-circuit so inner action buttons keep
their own behavior. Bottom-panel history rows also highlight via
bg-accent when their commit is the one currently being viewed.

Commit diff header now uses AuthorsAvatarGroup + getCommitAuthors +
formatAuthorsText, matching latestCommitInfo and historyRow — co-authors
parsed from the commit body show up correctly.

When the URL trailing path matches one of the commit's files, that file
is moved to the top of the FileDiffList rather than scrolled to. Avoids
estimateSize-based scroll inaccuracy and works regardless of which side
of a rename the URL points to.

Lightweight diff viewer short-circuits with "Diff too large to display"
for files containing lines over 1000 chars, matching the cutoff in
lightweightCodeHighlighter.

PathHeader's breadcrumb measurement reserved 175px for "copy button and
padding"; the actual reservation needed is ~40px. Reduced so breadcrumbs
no longer collapse prematurely on wide layouts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Lift `truncateSha` (was a private helper in getDiffToolComponent) to
  `lib/utils` so PathHeader can reuse it. The branch/ref display now
  renders a 40-char SHA as `abc1234`, preserving any `^` / `~N` suffix.
- Hide the `·` separator and the path's CopyIconButton when there's no
  path (repo root). Previously a dangling `·` and copy button rendered
  with nothing between them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a `path` query/tool parameter to restrict diff output to changes
touching a single file via git's `-- <pathspec>` separator. Refactors
the route handler to use the shared `getDiffRequestSchema`.

Fixes SOU-1154 (sourcebot-dev#1154)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move single-file commit diffs from `/-/commit/<sha>/<path>` to
  `/-/blob/<path>?ref=<sha>&diff=true`, keeping the user's browsing
  revision in the URL. `/-/commit/<sha>` still renders the full
  multi-file diff.
- New `FocusedCommitDiffPanel` with status row (file status badge +
  authors + relative commit date + "View full commit" + DiffStat +
  exit-X) and path-filtered `getDiff` so only the single file's diff
  is fetched.
- New preview banner in `CodePreviewPanel` when `?ref=` is set, with a
  close button that strips the param.
- Make `PathHeader`'s revision clickable, linking to that ref's full
  commit view.
- New `HoverPrefetchLink` defers Next.js prefetching until hover; used
  in history rows to avoid firing many prefetches on render.
- Hide the bottom panel on `/-/commit/` views.
- Extract `getFileStatus` / `StatusBadge` to a shared `fileStatus.tsx`.
- Workaround Radix Tooltip + RSC re-render bug (drop `asChild` from
  `<TooltipTrigger>`, add `key={commitSha}`) so X / Browse-files
  buttons survive client navigation between commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines +47 to +54
const onCopyPath = useCallback(() => {
const pathToCopy = file.newPath ?? file.oldPath;
if (!pathToCopy) {
return false;
}
navigator.clipboard.writeText(pathToCopy);
return true;
}, [file.newPath, file.oldPath]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low commitDiffPanel/fileDiffRow.tsx:47

navigator.clipboard.writeText(pathToCopy) returns a Promise that is ignored. The function returns true synchronously before the async operation completes, so if the clipboard write fails (e.g., permission denied in non-secure contexts), the CopyIconButton still shows a success indicator to the user. Consider awaiting the Promise and returning whether it succeeded.

-    const onCopyPath = useCallback(() => {
-        const pathToCopy = file.newPath ?? file.oldPath;
-        if (!pathToCopy) {
-            return false;
-        }
-        navigator.clipboard.writeText(pathToCopy);
-        return true;
-    }, [file.newPath, file.oldPath]);
Also found in 1 other location(s)

packages/web/src/app/(app)/browse/[...path]/components/commitDiffPanel/commitHashLine.tsx:22

onCopyHash returns true synchronously before navigator.clipboard.writeText completes. If the clipboard operation fails (permission denied, insecure context, etc.), CopyIconButton will still show the success checkmark because onCopy() already returned true. The return value should reflect the actual outcome of the async operation, but currently it cannot.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/web/src/app/(app)/browse/[...path]/components/commitDiffPanel/fileDiffRow.tsx around lines 47-54:

`navigator.clipboard.writeText(pathToCopy)` returns a Promise that is ignored. The function returns `true` synchronously before the async operation completes, so if the clipboard write fails (e.g., permission denied in non-secure contexts), the `CopyIconButton` still shows a success indicator to the user. Consider awaiting the Promise and returning whether it succeeded.

Evidence trail:
packages/web/src/app/(app)/browse/[...path]/components/commitDiffPanel/fileDiffRow.tsx lines 47-54 (onCopyPath callback ignores Promise, returns true synchronously); packages/web/src/app/(app)/components/copyIconButton.tsx lines 8-21 (onCopy typed as () => boolean, success indicator shown based on synchronous return value)

Also found in 1 other location(s):
- packages/web/src/app/(app)/browse/[...path]/components/commitDiffPanel/commitHashLine.tsx:22 -- `onCopyHash` returns `true` synchronously before `navigator.clipboard.writeText` completes. If the clipboard operation fails (permission denied, insecure context, etc.), `CopyIconButton` will still show the success checkmark because `onCopy()` already returned `true`. The return value should reflect the actual outcome of the async operation, but currently it cannot.

@rohanneilkapoor

Copy link
Copy Markdown
Author

Closing this non-draft setup batch; replacement A/B test PRs will be opened as draft to keep production review from consuming sandbox capacity.

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.

2 participants