Skip to content

Add research documentation on unified diff UX and external tool references - #2807

Open
sinelaw wants to merge 19 commits into
masterfrom
claude/unified-diff-viewer-ux-73crvq
Open

Add research documentation on unified diff UX and external tool references#2807
sinelaw wants to merge 19 commits into
masterfrom
claude/unified-diff-viewer-ux-73crvq

Conversation

@sinelaw

@sinelaw sinelaw commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds comprehensive research and reference documentation to inform the design of Fresh's diff and review experience. Three new documents are added:

  1. unified-diff-experience-design.md — A detailed design specification and research synthesis for consolidating Fresh's seven fragmented diff surfaces into one coherent review experience
  2. gitlens-readme.md — Reference documentation from GitLens (VS Code extension) showing patterns for Git integration and PR review workflows
  3. zed-git.md and zed-agent-panel.md — Reference documentation from Zed editor demonstrating modern approaches to diff viewing, staging, agent integration, and multi-threaded AI workflows

Key Changes

  • Design specification (unified-diff-experience-design.md):

    • Diagnoses current fragmentation: seven diff surfaces across three generations with inconsistent chrome, keybindings, and renderers
    • Synthesizes field research across ~40 tools (magit, lazygit, VS Code, JetBrains, Zed, GitHub, GitLab, Gerrit, and agent-era reviewers)
    • Proposes unified architecture: one diff renderer, one review container, one in-buffer lens with task-focused entry points
    • Defines four task-shaped doors (Review Changes, Review Branch/PR, History, Review Agent Work) that share rendering and navigation
    • Outlines phased migration (phases 0–4) with Part I (review UX) prioritized over Part II (external integrations)
    • Documents review-specific patterns (viewed marks, comment anchoring, interdiff, noise suppression) and agent-era requirements (keep/reject verbs, checkpoints, comment-as-prompt)
  • External tool references:

    • GitLens patterns: blame annotations, commit graph, launchpad (PR hub), worktrees, cloud patches
    • Zed patterns: unified diff view style preference, project diff as editable multibuffer, file history, staging workflows, git worktrees, agent panel with checkpoints and multi-threading

Notable Details

  • The design explicitly separates Part I (rendering, navigation, review state) from Part II (agent feedback, comment dispatch, forge sync) to clarify priorities and dependencies
  • Research covers both traditional VCS tools and 2025–26 agent-era reviewers, capturing emerging patterns like comments-as-prompts, keep/reject overlays, and checkpoint-based undo
  • Documents both what converged across the field (one renderer, one container, in-buffer lenses) and what remains unsolved (local interdiff over agent iterations, TUI fatigue mitigation)
  • Includes concrete wireframes and interaction examples grounded in Fresh's existing chrome and tmux-based testing methodology

This is a design and research document only — no code changes to Fresh itself. It serves as the specification for future implementation phases.

https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL

claude added 19 commits July 26, 2026 19:15
Raw upstream doc dumps (GitLens README, Zed agent-panel and git docs) left
in the tree by an earlier research session; committed as-is so the research
inputs travel with the branch. A fourth file was a saved '404: Not Found'
page and was deleted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…iner, four doors

Diagnoses the seven overlapping diff surfaces (Review Diff, Review Range/
Stash, Review PR Branch, Git Log, Side-by-Side, Live Diff, Blame + three
hunk-nav and two gutter systems), distills field research across ~40 tools
(magit, lazygit, tig, jj, delta, difftastic, diffview.nvim, hunk, Zed,
VS Code, JetBrains, Gerrit, Reviewable, Graphite, GitHub 2025-26, Conductor,
Superset, Linear Diffs, difit/diffx/tuicr/revdiff, ...), and proposes a
single architecture:

- one Diff Renderer (stack/split, syntax + intraline everywhere)
- one Review Session container parameterized by (source, lens, verbs,
  state), with comments, viewed marks, and a per-commit lens replacing the
  separate PR-Branch mode
- one in-buffer Lens merging live-diff, git-gutter, and diff-nav
- four task-shaped doors: Review Changes, Review Branch/PR, History,
  Review Agent Work (new orchestrator entry point), behind a single
  Review… picker
- an agent loop: severity-tagged comments dispatched to sessions, review
  IPC, and iteration interdiff as the long-term differentiator

Includes a phased migration plan (0-3), rename/deletion table, and risks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…hatch, feedback-transport resilience, keep/reject guardrails

Reevaluates the unified diff-experience design against a deep-research pass
on what agent-era users praise and complain about:

- TUI fatigue: adopt the field's local-web escape hatch, but via Fresh's
  existing parity-tested web bridge ("Open this review in the browser",
  same session/state, no second implementation) — new section 3.8
- feedback loop: dual transports for agent exchange (rich IPC path plus a
  file-based .review/ outbox/inbox fallback, since sandboxed agents
  demonstrably can't reach local daemon ports)
- keep/reject context blindness: file-level default granularity, a
  related-changes nudge, and a leftover-noise scan for agent diffs
- marathon reviews: persist read position, fold layout, and unsent comment
  drafts with the session, not just comments and viewed marks
- review inbox across agent sessions in the picker; megamerge review
  explicitly deferred

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…agent/external comms)

Part I — the priority — is the review experience itself: navigation,
baselines, lenses, doors, layouts, comments-as-notes, and marathon-review
persistence. It ships identically in TUI and web via the existing scene
parity discipline, so the dedicated web-escape-hatch section is replaced by
a parity constraint (no review feature may land as TUI-only logic).

Part II — explicitly lower priority and orthogonal by construction — now
holds everything that talks to the outside world: comments-as-prompts /
send-to-session, review IPC with the file-based transport fallback,
agent-seeded reviews, pause-on-review, guided-review outlines, and forge/PR
sync. Door 4 is reduced to pure UI (baseline + keep/reject verbs); the
iteration-interdiff lens stays in Part I as baseline-selection UX.

Phasing reflects the split: phases 0-3 are Part I only; new Phase 4 is
Part II.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
Nine frames grounded in the real chrome captured during the tmux
exploration: the Review Session container in stack and split layouts
(worktree door), the Review Branch door in flattened and per-commit
lenses, the History door with its shared-renderer detail pane, the agent
door with baseline picker and related-changes nudge dialogs, the Review…
picker palette, and the buffer lens with a hunk expanded in place.

Each frame annotates what it encodes (enclosing-context hunk headers,
copy-safe bodies, session-wide counters, viewed/kept progress, comment
severity badges, lens-stable comments) so the wireframes double as the
spec for the chrome contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
Replaces the chrome-conservative Part I presentation with a clean-slate
UI built purely from the research lessons (the prior draft stays in git
history as the low-risk fallback, per the new §3.12 migration note):

- two lines of chrome total: a scope bar (base ⟶ target · lens · burn-down
  gauge) and a context line that doubles as the action receipt
- no separate picker, History tab, or fixed comments column: doors become
  scope presets inside the workspace's scope-choosing state; History is
  the commits lens over a wide scope; comments live inline plus a notes
  projection of the one navigator rail (files/commits/notes, cycled)
- the stream is a magit-style section document with sticky context
  header, depth presets, persistent folds, chip-row verbs on the focused
  section (the only mutation surface, doubling as the keymap hint),
  format-only dimming, generated-file quarantine, and interactive
  unchanged-context separators
- three-key review loop: Space = mark-and-advance burn-down, Enter =
  zoom (scope → file → hunk → real buffer portal), Esc = back out;
  completion and resume states designed explicitly
- one view transient with sticky options; runnable ? help; Z undo with
  command echo for every mutation
- verb sets bound by scope target (stage / keep-reject / read-only) with
  the agent guardrails re-expressed in the new chrome

Ten new wireframes cover: reading state, scope-choosing, lens menu,
rail projections, line selection, comment compose, completion, resume,
view transient, buffer portal, and the agent reject receipt. Stale
door/section references in Parts II, phases, and rename table updated
to the scope-preset vocabulary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…ce, and adoptions

Two designers were given only the task list and research evidence (the
existing Fresh UI and this doc's workspace design withheld) and asked to
design the review TUI from scratch. Both independently converged with the
workspace on the same skeleton — comparison-as-identity, section tree,
selection-drives-preview, relabeling verbs, hash-keyed viewed marks,
resume-leads-with-delta, undo over confirmation, runnable help — which
de-risks the §3 core.

The section presents each alternative's distinctive ideas with one
representative frame and a verdict table, keeps the genuine differences
explicit (chips vs hint bar, cycling rail, in-workspace presets), and
ends with the adoption list: uppercase-escalation keymap rule, C conclude
verb, runnable-help-as-palette, persisted undo journal via git objects,
waiting-on-you session ordering, narrative default order for agent
scopes, live-update queueing, symbol-graph reject guard, last-review
default target, interdiff pseudo-commit, noise out of the progress
denominator, command log, and the sub-100-col zoom model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…Appendix A

Section 3 is now the design of record with the blind-redesign adoptions
folded in: C conclude verb, uppercase-escalation keymap rule, runnable
help-as-palette, git-object undo journal surviving restarts, waiting-
on-you session ordering with sparklines, narrative default file order in
agent scopes, live-update queueing (content never moves under the
cursor), symbol-graph reject guard, since-my-last-review as the default
reopened target, interdiff pseudo-commit after force-pushes, noise
excluded from the progress denominator, the command log, the sub-100-col
zoom model, and the wide-screen anchored comments rail.

Mouse operation is now first-class throughout: verb rows are clickable
buttons that print their keys, every scope-bar segment is a button,
hover reveals checkboxes and per-row actions, context-expanders and
scrollbar-map markers are click targets, right-click menus mirror every
verb, and a dedicated mouse-story section (3.10) states the parity rule
- no keyboard-only and no mouse-only paths - while keeping the two-line
chrome budget.

The two independent redesigns move from §3.13 to Appendix A with
cross-references updated; §3.14 records provenance and the two questions
left to prototyping (section buttons vs hint bar, h/l granularity
ladder).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…eraction captions

A click-by-click progression through a full agent-session review with no
key pressed at any point: menu bar → Review menu → scope-choosing rows →
workspace → lens dropdown → commits strip → hunk verb button → symbol-
graph guard buttons → undo receipt → live-queue badge → rail-projection
dropdown → notes rail → note jump with comment-box buttons → hover-
checkbox completion → conclude summary. Each frame is separated by a
caption stating exactly what the user clicked. Cross-linked from the
mouse-story section (3.10).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…r + hover ⊕ gutter button

Comments were already line-anchored by design; state it explicitly: the
comment verb follows the same ladder as every verb (line / range / hunk /
file), single-line is the base case, anchors are stored at line
granularity and never widened to the hunk. Adds the direct mouse path —
hovering any diff line reveals a ⊕ gutter button that opens the composer
anchored to exactly that line — and lists it in the mouse story.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…le, mark-and-collapse

States explicitly that the flat stream reviewed top-to-bottom is the main
flow the design optimizes (commits lens, history, zoom are secondary).
Marking a file reviewed now collapses it in place to its one-line header,
GitHub-style, so the stream shrinks into a to-do list as you scroll; the
sticky file header carries the file's own Reviewed button and fold
triangle so scroll-and-mark never leaves the stream; Space on a file
header or last hunk marks and collapses the whole file and advances to
the next unreviewed file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…of reviewed

- Reviewing a specific GitHub PR joins Part I as a primary scope: a PR
  picker (review-requested first, filterable) reachable from the preset
  row or by typing a PR number/URL; selection fetches refs/pull/N/head
  with no checkout, scopes to merge-base(PR base) -> PR head, imports
  existing threads as author-badged anchored comments, and C conclude
  becomes submit-to-GitHub with verdict choice, summary, and the draft
  list (severities rendered into comment bodies). Force-pushes surface as
  the interdiff pseudo-commit instead of a reset review. Part II 4.4
  narrows to the deeper sync (thread replies/resolution, live updates,
  viewed-state sync).
- Collapsed and reviewed are now explicitly independent states: the fold
  triangle collapses without marking (no checkmark, still unreviewed in
  the gauge and Space order); marking auto-collapses; unfolding never
  unmarks; both persist independently per scope across sittings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…tor integration

Answers the two open questions on the PR flow:

Checkout: a PR review never switches the user's working tree. Tier 0
(default) reviews entirely from fetched git objects — reading, marks,
comments, and submit need no checkout; Enter opens read-only
file-at-PR-head buffers. Tier 1 materializes a linked review worktree on
demand (scope-bar button, or offered at depth boundaries like LSP, edit,
run-tests) using the orchestrator's worktree machinery; the
workspace-trust prompt fires at materialization — when code could first
run, not when reading. Review state is keyed to PR identity (repo +
number + head-sha versions), never worktree paths, so materialization
and force-pushes carry marks forward.

Orchestrator: one worktree engine, one dock. A materialized PR review is
a workspace with a dock card (progress + checks) and normal lifecycle;
the PR picker and scope bar reuse the orchestrator's PR metadata
plumbing; an agent session with an attached PR is the same review seen
from two bases (merge-base vs session-start) via the scope-bar flip; the
reverse door (hand must-fix comments to an agent in the same worktree)
stays Part II.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…rries the flows

- The scope chooser shrinks to four rows and a prompt: the context-aware
  star row (this session's changes in an agent workspace / branch vs base
  on a feature branch, resuming since-my-last-review by default), working
  tree, pull requests, history. Stashes, ranges, and single commits are
  revspecs, not rows. Agent-session rows are gone from the chooser:
  reviewing an agent's work means clicking its dock card and opening
  Review there — the dock is the cross-workspace review inbox
  (waiting-on-you ordering and progress badges live on the cards).
- PR selection rides the orchestrator: if the PR branch is checked out in
  this workspace the review opens in place; otherwise a direct offer —
  'Checkout in a new workspace' (primary: standard worktree + trust flow,
  review opens inside, dock card appears) or 'Read here without checkout'
  (objects-only quick look; depth boundaries re-offer checkout).
  'Materialize' terminology dropped for plain 'checkout'.
- Removed cross-session cycling keys; walkthrough, phases, and rename
  table updated to the workspace-local model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
Adds unified-diff-experience-implementation-plan.md: milestones M0-M6
mapping the design onto this codebase — what each builds on (audit_mode,
git_log, live_diff, composite buffer, orchestrator, scene projections),
the short list of new host primitives (overlay layering, inline
actionable spans, sticky rows, rebindable composite Actions, per-hunk
streaming with cancellation, ref recording), per-milestone exit
criteria, cross-cutting workstreams (keybindings, testing, i18n, perf),
and the risk/sequencing picture.

Removes the raw third-party research dumps a previous session left in
docs/ (zed-git.md, zed-agent-panel.md, gitlens-readme.md) — their
relevant conclusions are already distilled into the design doc's
research section; only project-specific material stays in the repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…t toolkit

Investigated the widget framework (17 WidgetSpec kinds, host-owned
instance state, hit areas, keyboard+mouse dispatch, Settings already
migrated onto it) and the buffer decoration APIs before committing to
new host work. Findings change the build:

- Chrome (scope bar, chooser, rail, verb rows, transients, banners) maps
  onto existing widgets — click targets, hover/focus, retained state and
  web parity come free. Building it the audit_mode way (Raw panel content
  + byte-offset mouse_click math) would repeat what the git_log migration
  called the most error-prone part of that plugin.
- The diff stream should be a real editor buffer (WindowEmbed or
  buffer-group center panel), not panel content: syntax highlighting,
  folds, scrollbar markers, selection and search then come free, exactly
  as git_log already does with .diff-suffixed file-backed buffers.

Primitives re-scored: overlay-priority downgraded from API to rendering
strategy (fgOnCollisionOnly and extendToLineEnd already exist); sticky
rows dropped (audit_mode already ships a sticky panel slot); ref
recording dropped (plugins spawn git directly); inline actionable spans
kept but confined to in-diff-body affordances, and reduced to consuming
InlineOverlay.properties, which the data model already declares as click
target metadata but nothing reads; composite-key Actions and streaming
cancellation unchanged. Net: one new host capability instead of six.

Milestones, web-parity scope and the risk section updated accordingly,
with an M1 spike added to choose stream hosting.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…away

The default view is now the diff at full width: the navigator rail starts
collapsed behind a visible scope-bar toggle, so opening a review lands
straight on the thing the user came for. Clicking it expands, and the
choice persists per scope. Adds the collapsed default frame alongside the
expanded one, states progressive disclosure as the workspace-wide rule
(nothing hidden behind a key you must know), and updates the mouse-only
walkthrough to open collapsed and demonstrate the toggle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
…ghlighting claim

Read audit_mode's implementation before planning its replacement, and
corrected a wrong assumption in the process:

- Correction: rendering the stream from a .diff file-backed buffer gives
  diff-level scoping only, NOT per-token language highlighting. The
  embedded-region mechanism (EMBEDDING_SPECS) is a build-time table keyed
  on host-grammar scopes and can't be driven by a plugin, and its
  language token is a language name, not a path. Per-token highlighting
  in a composed unified stream therefore needs one narrow, scheduled host
  addition (per-byte-range language regions reusing the engine's
  composite parse snapshots), now listed as primitive #7 and deferred to
  M2; M0 ships only the cheap add/remove backgrounds.

- New section 4 records what must survive the migration: the single-pass
  build that emits rows, byte offsets, row-property maps and collapsible
  body ranges together; collapse as O(1) host fold registration with no
  rebuild; the plugin-side entryPropsByRow map (which exists to dodge a
  real getTextPropertiesAtCursor row-boundary bug); width-parameterised
  prebuild; the guarded sticky-header repaint; manual-refresh policy
  (auto-refresh on activation was removed for spawning git per panel
  switch); streamed SHA-cached git show. Plus the port-don't-rewrite list
  (staging engine with apply --cached and --check dry run, comment model
  and persistence, range/stash pipelines, repo resolution, i18n, e2e
  suites) and an explicit list of APIs considered and rejected because
  existing mechanisms cover them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
… plan's inventory

The section 1 row for git_log still described its .diff buffer as having
real syntax highlighting, which the section 2 correction contradicts —
it is diff-level scoping only. Aligns the wording and repoints the row's
role at what git_log actually contributes: the streaming/SHA-cache
pattern the commits lens reuses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01756Rh35n65zC4xHQcQAqBL
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