Synthesis: the "GitHub view" default for code review
Date: 2026-07-01
Inputs: SPIKE-github-view-composite-diff-20260701-222935.md,
SPIKE-git-graph-view-20260618-220909.md (backlogged, reused here),
mockup code_review_panel_three_stack_mockup.svg, product discussion 2026-07-01.
The problem, in users' words
- "I just want to see what I would see in GitHub."
- "I just want to see what happens when I run git status."
The current DiffTypePicker forces users to translate those intents into git
mechanics (staged / unstaged / merge-base / all) before anything renders. No
option answers the GitHub question: merge-base (our own hint even says "Same
as GitHub's PR view") excludes the working tree, and the unstaged default
shows nothing to someone who just committed. Every possible default betrays one
of the two mindsets.
The resolution
Don't pick a better default — dissolve the choice. One comparison serves both mindsets simultaneously:
merge-base(origin/default, HEAD) → working tree + untracked = "what the GitHub PR would show if I pushed right now"
- The diff content answers the GitHub question. Every diff on screen means the same thing: changes since main. No exceptions, no per-file modes.
- The grouping answers the git-status question: three sections — Committed (muted), Changes (modified + added conjoined, staged dot), Untracked — exactly the mockup's three-stack panel.
Confirmed decisions from discussion:
- Every diff shows "since main." A file edited in an old commit and again
now appears once (in Changes) and its diff shows everything since main.
"Just since last commit" is NOT a toggle on this view — that intent already
exists as the
last-commitdiff type and lives in the advanced menu. - Viewed is untouchable. It's the app's most-used feature; the mockup
promotes the checkbox to the row's primary action. Existing
viewedFilesinfra carries over as-is. - Sections | Tree toggle, with a future third mode: Commits (the backlogged git-graph spike's Phase 1 — flat commit list + per-commit diff — slots in here with no viewer changes).
- Progressive disclosure: default screen has zero pickers. The "vs origin/main" label opens the existing BaseBranchPicker. An Advanced entry exposes today's full diff-type list. Nothing is deleted; it stops being the front door.
- Baseline honesty: we compare against
origin/main= GitHub as of last fetch. The startupls-remotecall already receives the remote tip SHA and throws it away; keep it, compare, and show a quiet "baseline is behind GitHub — fetch" banner when stale. That one banner is what makes "this is the GitHub view" a trustworthy claim. - Git only. jj and Perforce keep the current UI. Workspace mode keeps the current UI for now.
- Committed section default state (collapsed vs peek): feel it out during implementation; mockup mutes it at 55% opacity with a "124 more files" truncation, which suggests collapsed-with-count is the starting point.
Why this is cheap (spike findings, condensed)
The three-stack panel is one new git diff type plus a status sidecar, not a new diff engine:
- The server's single-snapshot state machine (one
currentPatch, one fingerprint) fits a composite comparison as-is. runGitDiff, fingerprinting, file-content retrieval, staging, the freshness probe, and the agent context builder each need one newcasealong an existing seam (~6 small additions, verified line-by-line in the spike).- The section partition comes from
git status --porcelain(already run for fingerprints) +git diff --name-only <mb>..HEAD— shipped as a payload sidecar; the client groups files by it. - The Pierre diff viewer needs zero changes (re-confirmed; also the git-graph spike's key finding).
- Viewed, staging (
/api/git-add), annotations, and feedback export all work unchanged; annotations against mb→worktree have the same shape as today's merge-base annotations.
The genuinely new work is UI: the Sections panel component, the Sections/Tree toggle, the disclosure re-layering (pickers → Advanced), and the staleness banner.
Open questions carried into the spec
- Naming of the new
DiffTypeid and its user-facing label. - Where the fetch action lives when the baseline is stale (banner button →
git fetchserver-side, then re-switch). - Whether Sections view fully replaces FileTree as default or per-user preference persists (cookie, like other settings).
- Exact payload shape of the sections sidecar.