Fleet event drawer — Forgejo/Cursor-grade diff review viewer #1009

Closed
opened 2026-05-09 10:34:25 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As an operator reviewing an agent's diff in the right drawer's Diff review tab, I want the diff viewer to match the visual quality and ergonomics of Forgejo's PR diff (or Cursor's inline diff) — file tree, syntax highlighting, sticky headers, word-level intra-line marks, expandable context — so that I can read multi-file diffs without losing context or eyeballing plain monospace text.

Background

Current implementation: apps/web/src/components/agent/run-diff-review.tsx (lines 240-340). Renders unified or split mode in a <table> with two line-number columns, a +/- marker column, and the line text. Background tints bg-success/10 / bg-error/10 mark added/removed lines. No syntax highlighting, no file tree, no expand-context affordance, no word-level intra-line diff. LCS is capped at 1000 lines per side (line 36-77).

Operator review (2026-05-09) called out the gap vs. Forgejo PR diff and Cursor's inline diff.

Acceptance criteria

File tree sidebar

  • Left rail listing every changed file as a tree (collapsible directory nodes, file leaves with add/remove counts).
  • Click a leaf scrolls the diff pane to that file's hunk; active file highlighted.
  • Hidden below md breakpoint (per apps/web/CLAUDE.md mobile policy); replaced by an inline file dropdown.

Hunk rendering

  • @@ hunk separators rendered as a distinct row with the hunk header (@@ -A,B +C,D @@ context) in text-text-dim.
  • Expandable context: between non-adjacent hunks, render a "show 20 more lines" / "show all" affordance that fetches the surrounding context from the source blob and inlines it.
  • Tabular line numbers (tabular-nums), monospace; gutter background distinct from line background so it doesn't blend on long lines.

Syntax highlighting

  • Per-line syntax highlighting via Shiki (preferred — already covers the Tokyo Night palette) keyed off the file extension.
  • Highlight tokens preserved across +/-/context lines without breaking the bg tint.
  • Falls back to plain text for unknown extensions / files >5k lines (perf cap).

Sticky file headers + collapse

  • Each file's header sticks to the top of the scrollable diff pane while that file's hunks are in view (position: sticky).
  • Header shows path, add/remove counts, expand/collapse chevron, and a "view raw" link.
  • Collapse hides all hunks for that file and remembers the state in URL query (?collapsed=path1,path2).

Word-level intra-line diff

  • On add/remove line pairs (within the same hunk segment), compute a word-level diff and highlight changed runs with a darker bg tint inside the line-level tint.
  • Pure-add / pure-remove lines (no pair) skip the word diff.
  • Algorithm: token split on \b, LCS on tokens, capped at 200 tokens per line.

Soft-wrap toggle + copy line

  • Toolbar toggle: soft-wrap vs. no-wrap (no-wrap is default to match Forgejo).
  • On hover over a line, a "copy" button appears in the gutter and copies the line text (no marker) to clipboard.
  • Both affordances honour prefers-reduced-motion (no transitions when disabled).

Tests

  • Storybook fixtures for: single-file unified, multi-file unified, split mode, oversize-file (>1000 lines, hits the cap), unknown-extension fallback, word-level diff edge cases (full-line replacement, prefix-only change, suffix-only change).
  • Snapshot or visual-regression test for the file tree at < md and ≥ md breakpoints.
  • Unit test for the token-level LCS asserting the 200-token cap.

Out of scope

  • Server-side diff generation (already produces the input shape).
  • Accept/reject hunk affordances — already in place at run-diff-review.tsx:346, untouched.
  • Tool-widget rework — sibling story.
  • Inline review comments / threading.

References

  • Conversation 2026-05-09 — operator review of fleet drawer Diff review tab.
  • apps/web/src/components/agent/run-diff-review.tsx:240-340 — current unified + split renderers.
  • apps/web/src/components/agent/run-diff-review.tsx:36-77 — LCS hunk builder + 1000-line cap.
  • apps/web/CLAUDE.md — token utilities, mobile breakpoints, reduced-motion policy.
## User story As an operator reviewing an agent's diff in the right drawer's `Diff review` tab, I want the diff viewer to match the visual quality and ergonomics of Forgejo's PR diff (or Cursor's inline diff) — file tree, syntax highlighting, sticky headers, word-level intra-line marks, expandable context — so that I can read multi-file diffs without losing context or eyeballing plain monospace text. ## Background Current implementation: `apps/web/src/components/agent/run-diff-review.tsx` (lines 240-340). Renders unified or split mode in a `<table>` with two line-number columns, a `+`/`-` marker column, and the line text. Background tints `bg-success/10` / `bg-error/10` mark added/removed lines. No syntax highlighting, no file tree, no expand-context affordance, no word-level intra-line diff. LCS is capped at 1000 lines per side (line 36-77). Operator review (2026-05-09) called out the gap vs. Forgejo PR diff and Cursor's inline diff. ## Acceptance criteria ### File tree sidebar - [ ] Left rail listing every changed file as a tree (collapsible directory nodes, file leaves with add/remove counts). - [ ] Click a leaf scrolls the diff pane to that file's hunk; active file highlighted. - [ ] Hidden below `md` breakpoint (per `apps/web/CLAUDE.md` mobile policy); replaced by an inline file dropdown. ### Hunk rendering - [ ] `@@` hunk separators rendered as a distinct row with the hunk header (`@@ -A,B +C,D @@ context`) in `text-text-dim`. - [ ] Expandable context: between non-adjacent hunks, render a "show 20 more lines" / "show all" affordance that fetches the surrounding context from the source blob and inlines it. - [ ] Tabular line numbers (`tabular-nums`), monospace; gutter background distinct from line background so it doesn't blend on long lines. ### Syntax highlighting - [ ] Per-line syntax highlighting via Shiki (preferred — already covers the Tokyo Night palette) keyed off the file extension. - [ ] Highlight tokens preserved across `+`/`-`/context lines without breaking the bg tint. - [ ] Falls back to plain text for unknown extensions / files >5k lines (perf cap). ### Sticky file headers + collapse - [ ] Each file's header sticks to the top of the scrollable diff pane while that file's hunks are in view (`position: sticky`). - [ ] Header shows path, add/remove counts, expand/collapse chevron, and a "view raw" link. - [ ] Collapse hides all hunks for that file and remembers the state in URL query (`?collapsed=path1,path2`). ### Word-level intra-line diff - [ ] On `add`/`remove` line pairs (within the same hunk segment), compute a word-level diff and highlight changed runs with a darker bg tint inside the line-level tint. - [ ] Pure-add / pure-remove lines (no pair) skip the word diff. - [ ] Algorithm: token split on `\b`, LCS on tokens, capped at 200 tokens per line. ### Soft-wrap toggle + copy line - [ ] Toolbar toggle: soft-wrap vs. no-wrap (no-wrap is default to match Forgejo). - [ ] On hover over a line, a "copy" button appears in the gutter and copies the line text (no marker) to clipboard. - [ ] Both affordances honour `prefers-reduced-motion` (no transitions when disabled). ### Tests - [ ] Storybook fixtures for: single-file unified, multi-file unified, split mode, oversize-file (>1000 lines, hits the cap), unknown-extension fallback, word-level diff edge cases (full-line replacement, prefix-only change, suffix-only change). - [ ] Snapshot or visual-regression test for the file tree at `< md` and `≥ md` breakpoints. - [ ] Unit test for the token-level LCS asserting the 200-token cap. ## Out of scope - Server-side diff generation (already produces the input shape). - Accept/reject hunk affordances — already in place at `run-diff-review.tsx:346`, untouched. - Tool-widget rework — sibling story. - Inline review comments / threading. ## References - Conversation 2026-05-09 — operator review of fleet drawer Diff review tab. - `apps/web/src/components/agent/run-diff-review.tsx:240-340` — current unified + split renderers. - `apps/web/src/components/agent/run-diff-review.tsx:36-77` — LCS hunk builder + 1000-line cap. - `apps/web/CLAUDE.md` — token utilities, mobile breakpoints, reduced-motion policy.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#1009
No description provided.