Skip to content

feat(desktop): list every file in Files changed, with a filter, collapse all, and stage-cli's keys - #3304

Merged
luke-agent[bot] merged 6 commits into
mainfrom
feat/files-changed-list
Oct 18, 2026
Merged

luke-agent[bot] merged 6 commits into
mainfrom
feat/files-changed-list

Conversation

@dastratakos

@dastratakos dastratakos commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Files changed extras, E1 of the "Files changed extras" stack (based on #3245). Asked for: stage-cli's file filter, collapse / expand all, and keyboard navigation between files in the Pull request tab's Files changed pane, working in the unified view below 640px. stage-cli's Files changed is a list of every file, which is what collapse all and its keys act on, so the pane changes from one file at a time to that list (the orchestrator approved this shape).

  • One list of every file, drawn by Pierre's own CodeView (diff-view/index.ts's new mountList).

    • Each file has a sticky header: a fold chevron, the A/M/D/R letter, its path (old → new for a rename), and +/−.
    • Only files near the view are drawn and highlighted.
    • Files are listed in the tree's order (folders first, as Pierre's tree sorts), so J/K follow the tree's rows.
    • A file with no hunks (binary, too large, renamed with no changes) is drawn as what stands in their place: why it has none, and any of its review threads, across its width.
      • Pierre draws and measures file-level notes only above a line. So the bundle hands such a file one empty line (DiffListFile.lead), and hides that line, the old side, the gutter and the hatching in the shadow root.
      • The header stays one row. Pierre reserves a fixed height for it and keeps it sticky, so anything taller would throw off every file's position below it.
  • Filter. The tree's "Search files" field is the filter, as stage-cli's sits on its file picker.

    • The tab holds the query, so it narrows the list and the tree together, by path, ignoring case, matching exactly what the tree's search matches.
    • Choosing a file the filter leaves out, from the bar's crumbs (which list every changed file), clears the filter and scrolls the list to that file.
    • While the tree is hidden, a line over the list names the filter and offers Clear.
  • Collapse / expand all.

    • A bar button, with the ⇧; hint, folds or unfolds every file the filter keeps.
    • Each header's chevron folds its own file (;).
    • Deleted files, lockfiles, and files over 1,000 changed lines start collapsed, as GitHub keeps such diffs folded.
  • stage-cli's keys (changes-list.tsx):

    Key Does
    J / K next / previous file (a first press selects the file at the top)
    ; collapse or expand the selected file
    ⇧; collapse or expand all
    Esc clear the selection
    • A key handler on the Files changed view reads them, and an answered press goes no further.
    • J/K keep their Inbox meaning everywhere else in the window (#shared/shortcuts' plain J/K), and keys typed into a field stay the field's.
    • Esc is taken only while a file is selected. Otherwise it reaches the window's layered Escape.
    • ⌘F stays the tab's find.
    • The bar's breadcrumbs, ⋯ (copy name / patch) and the tree follow the selected file, or else the one at the top of the list.
  • Narrow. Below 640px the list is drawn unified, whatever the setting, as before.

  • feat(desktop): draw review threads on their lines in Files changed #3245's threads, moved onto the list.

    • Line threads are each file's annotations, with the same key → element contract; renderAnnotation now takes (path, key).
    • Inline threads keep feat(service,features,desktop): reply on, resolve, and unresolve a review thread as the member who presses #3308's Reply / Resolve (ThreadActions); its Files changed test is ported to the list.
    • Threads the diff draws no row for (THREAD_PLACE.ABOVE: outdated, on a line no hunk shows, or on a binary or too-large file) are Pierre file-level notes above the first hunk, on the side they count on.
    • Refresh changes also reads the threads again.
    • The single-file mount is kept for the Conversation's thread previews. It loses only its annotations, which nothing else used.

Also in this PR

The list's styles and #3245's inline thread card now read the --luke-* tokens. #3524 removed the old aliases (--hairline, --section-fill, --space-*, …), and without them the headers lost their borders, which put every file's position 1px off.

Known limit

⌘F finds only what Pierre has drawn. The list is virtualized, so files far from the view aren't searched until they come near, as with GitHub's own lazily drawn diffs. Every drawn file's shadow root is marked for the find, and new files are picked up as they scroll in.

Follow-up: search undrawn patches through the list's data.

Bundle budget

renderer/diff-view.js grows from 142,443 to 178,690 gzipped bytes (+36.2 KB), for Pierre's CodeView and virtualizer. That bundle is lazy (loaded with the first diff shown), and only its baseline is re-recorded.

Data cost

No new requests. readChanges already carries every file's patch: up to 300 files, and a patch over 100k characters arrives with no body. Pierre highlights only the files near the view, and a collapsed file draws only its header.

Screenshots

From a throwaway harness (fake window.luke, real diff bundle and stylesheet), since deleted.

Light, J pressed (selected file outlined) Dark, an inline thread and a binary file's notice
light dark
Collapse all (⇧;), one file opened again Filtered by the tree's search
collapsed filtered

Narrow (600px, tree hidden, split setting on, drawn unified):

narrow

Evidence

  • pnpm check:affected: typecheck passed. The lint step first failed on formatting and an unused suppression, both fixed. Re-run by hand after the fixes:
    • pnpm lint: 0 errors
    • pnpm knip: passed
    • pnpm discarded-effect: passed
    • ./scripts/repository-checks.sh: passed
    • pnpm exec vitest run src/renderer/tasks/ src/shared/ src/renderer/diff-view (apps/desktop): 83 files, 707 tests passed
  • New tests:
    • agent-changes-tab.test.ts:
      • every file is handed over in the tree's order
      • a file with no hunks says why in its header
      • deleted files and lockfiles start folded; a file's fold and Collapse all / Expand all turn them
      • the tree's search narrows the list, said over it while the tree is hidden, until cleared
      • J/K, ;, ⇧; and Esc inside the view
      • J outside the view still runs the Inbox's command, and inside it only steps files (fails without the press being stopped)
      • a key typed into the search is the field's
    • changes-model.test.ts: tree order, filter, start-collapsed rules.
  • Changed tests: the existing Files changed tests now read the list's props. The feat(desktop): draw review threads on their lines in Files changed #3245 thread tests (agent-changes-tab.test.ts, agent-pull-request-tab.test.ts) read per-file annotations.
  • LUKE_UPDATE_BUNDLE_BUDGET=1: diff-view.js only, as above.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens unchanged.
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
  • Gateway envelope goldens unchanged.
  • No new as type assertion.
  • No Effect.run* outside the edges.
  • No new raw async primitives.
  • No discarded Effect.
  • Test count: +9 in agent-changes-tab.test.ts and changes-model.test.ts (listed above).
  • No hand-rolled file replaced.
  • No CLAUDE.md/AGENTS.md sentence names a changed part.
  • PRIVACY.md unchanged. The list stays under ph-no-capture, and every word in a header is the repository's.
  • No dependency change.
  • Barrel/door rule untouched.

Notes

@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
luke-web Ignored Ignored Preview Oct 18, 2026 4:55pm UTC

Request Review

@luke-agent
luke-agent Bot changed the base branch from main to feat/pierre-inline-comments October 17, 2026 01:55
@luke-agent
luke-agent Bot force-pushed the feat/pierre-inline-comments branch from d6264ab to 2355be4 Compare October 17, 2026 01:57
@luke-agent
luke-agent Bot force-pushed the feat/files-changed-list branch from 99b0403 to dda7905 Compare October 17, 2026 02:05
@luke-agent
luke-agent Bot marked this pull request as ready for review October 18, 2026 15:58
devin-ai-integration[bot]

This comment was marked as resolved.

@luke-agent
luke-agent Bot force-pushed the feat/pierre-inline-comments branch from 2355be4 to 3f8d6e4 Compare October 18, 2026 16:09
@luke-agent
luke-agent Bot force-pushed the feat/files-changed-list branch from dda7905 to 8e70375 Compare October 18, 2026 16:33
@luke-agent
luke-agent Bot force-pushed the feat/pierre-inline-comments branch from 3f8d6e4 to a3264cc Compare October 18, 2026 16:34
Base automatically changed from feat/pierre-inline-comments to main October 18, 2026 16:42
dastratakos and others added 3 commits October 18, 2026 16:46
…e and expand all, and stage-cli's keys

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
…ice and threads, measured, not in its header

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
…luke design tokens

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@luke-agent
luke-agent Bot force-pushed the feat/files-changed-list branch from 8e70375 to 93d5c95 Compare October 18, 2026 16:47
dastratakos and others added 2 commits October 18, 2026 16:49
…lears the filter and is shown

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
…the tree's search does

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
…tes them

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@luke-agent
luke-agent Bot added this pull request to the merge queue Oct 18, 2026
Merged via the queue into main with commit 93eb4bf Oct 18, 2026
11 checks passed
@luke-agent
luke-agent Bot deleted the feat/files-changed-list branch October 18, 2026 17:13
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.

1 participant