Skip to content

feat(tui): FILES sidebar panel with click-to-select and file drill-in - #365

Merged
gnanam1990 merged 2 commits into
mainfrom
feat/files-sidebar
Jul 2, 2026
Merged

feat(tui): FILES sidebar panel with click-to-select and file drill-in#365
gnanam1990 merged 2 commits into
mainfrom
feat/files-sidebar

Conversation

@kevincodex1

@kevincodex1 kevincodex1 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

Adds a FILES section to the TUI's right context sidebar (between PLAN and ACTIVITY) showing the workspace files the session has touched — newest first, with an A/M/✗ status badge, an aggregated +added −removed diffstat per file, a pulsing row for the file whose write is streaming right now, and a +N more overflow trailer.

Why: while an agent works, the question users actually have is "what is it changing right now, and what has it changed so far?" Today the transcript only answers that by scrolling back through tool cards; this panel answers it at a glance and gives every file a direct path to its diffs.

Interaction

  • First click on a row selects the file — accent ▸ on the row, its edit cards tint in the chat, and the transcript scrolls to the most recent one. Esc clears the selection.
  • Second click opens a drill-in view (reuses the subchat pattern): the chat column swaps to the file's stacked full-depth edit cards (edit N of M); f toggles to the syntax-highlighted on-disk file with ▎ markers on session-added lines, d back to diff, Esc returns to the chat at its saved scroll position. d/f only fire while the composer is empty, so typing is never hijacked.

Data sources

  1. changedFiles carried by write_file/edit_file/apply_patch results — persisted to the session payload and restored on rehydrate, so the panel survives /resume. The roster is derived on demand from transcript rows (the same pattern as the swarm AGENTS roster), so it can never drift from the chat.
  2. A git sweep for mutations the tool stream can't see — agents that scaffold via exec_command/bash (npm create, heredocs) or delegate to subagents. A baseline git status --porcelain --untracked-files=all snapshot at startup hides pre-existing dirt; re-sweeps after each command-tool result and at turn end merge newly dirty paths, with a git diff HEAD --numstat diffstat. Sweeps are single-flight, 3s-timeboxed, and latch off in non-git workspaces. Git-only files open the drill-in directly on the full-file view (they have no edit cards to stack).

Implementation notes

  • The drill-in swaps the body inside transcriptBodyItems and replaces the pinned title bar with a one-line nav, so the scroll engine, viewport, and mouse hit-testing all stay consistent with no special-casing.
  • The selection tint is part of the render-cache key, so selecting/deselecting a file can't serve stale cards.
  • FILES renders below PLAN, so existing plan-step click offsets are untouched; its own hit list accounts for the sections above it.

Checklist

  • The linked issue already has the issue-approved label.
  • go build ./..., go vet ./..., and go test ./... pass locally.
  • gofmt clean.
  • Tests added/updated for the change (and run under -race where relevant). — 22 new tests across files_panel_test.go, file_view_test.go, and files_git_sweep_test.go, including a sweep test against a real temporary git repo; go test -race ./internal/tui/ passes.
  • UI changes include screenshots or a short recording where possible. — terminal captures below.

Summary by CodeRabbit

  • New Features
    • Added a FILES sidebar that lists touched workspace files with change counts, plus a live “editing” indicator.
    • Added a drill-in file view with diff and full modes, including line numbers, truncation for long files, and session-based change markers.
    • The FILES sidebar is interactive: selecting a file highlights related transcript cards and supports click-to-open.
    • Added git-backed detection for workspace mutations that may occur outside normal tooling.
  • Bug Fixes
    • File view now preserves/restores the parent chat scroll correctly and exits cleanly with key controls.
    • Hover, selection, and nested view interactions are now consistently synchronized.

Add a FILES section to the right context sidebar showing the files the
session has touched — newest first, with A/M status badges, aggregated
+/− diffstats, and a pulsing row for the file being written right now.

Clicking a row selects the file (accent marker, edit cards tint in the
chat, transcript scrolls to the latest edit); a second click opens a
drill-in view: the chat column swaps to the file's stacked edit cards,
`f` toggles to the syntax-highlighted on-disk file with markers on
session-added lines, `d` back to diff, Esc returns to the chat.

The roster is fed from two sources: changedFiles carried by
write_file/edit_file/apply_patch results (persisted per session, so it
survives /resume), and a git sweep — baseline snapshot at startup,
re-check after command tools and at turn end — so files created through
bash/exec_command scaffolding or subagents show up too.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Zero automated PR review

Verdict: No blockers found

Blockers

  • None found.

Validation

  • [pass] Diff hygiene: git diff --check
  • [pass] Tests: go test ./...
  • [pass] Build: go run ./cmd/zero-release build
  • [pass] Smoke build: go run ./cmd/zero-release smoke

Scope

Head: b8d23f1ce285
Changed files (14): internal/tui/file_view.go, internal/tui/file_view_test.go, internal/tui/files_git_sweep.go, internal/tui/files_git_sweep_test.go, internal/tui/files_panel.go, internal/tui/files_panel_test.go, internal/tui/hover.go, internal/tui/model.go, internal/tui/render_cache.go, internal/tui/rendering.go, internal/tui/session.go, internal/tui/sidebar.go, and 2 more

This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR adds a FILES sidebar backed by transcript and git-derived touched-file tracking, plus a drill-in file view with diff and full-file modes. It also wires selection hover, tinting, scroll handling, and key/navigation behavior into the TUI.

Changes

FILES Sidebar and File Drill-in Feature

Layer / File(s) Summary
Transcript changedFiles plumbing
internal/tui/transcript.go, internal/tui/session.go, internal/tui/model.go
Adds changedFiles to transcript rows, rehydrates it from session payloads, and populates it during tool-result row construction.
FILES sidebar aggregation and rendering
internal/tui/files_panel.go, internal/tui/files_panel_test.go
Aggregates touched files from transcript rows, renders clickable FILES rows with live pulse and overflow handling, and adds selection/scroll helpers with tests.
Git sweep detection and merge
internal/tui/files_git_sweep.go, internal/tui/files_git_sweep_test.go, internal/tui/model.go
Parses git status/numstat output, merges baseline/live sweeps into touched-file state, and schedules sweeps at startup and during turn handling.
File drill-in view
internal/tui/file_view.go, internal/tui/file_view_test.go, internal/tui/model.go, internal/tui/transcript_selection.go
Adds diff/full file drill-in rendering, mode switching, scroll restoration, and transcript-body/key handling for entering and exiting the view.
Hover, tinting, and sidebar wiring
internal/tui/hover.go, internal/tui/rendering.go, internal/tui/render_cache.go, internal/tui/sidebar.go
Adds FILES-row hover targets, selected-file card tinting, cache-key separation, and the FILES block in the context sidebar.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TranscriptSelection
  participant Model
  participant FileView
  User->>TranscriptSelection: click FILES row
  TranscriptSelection->>Model: selectFile(path) / openFileView(path)
  Model->>FileView: openFileView(path)
  FileView->>FileView: render diff or full body
  FileView-->>Model: fileViewBodyItems(width)
  Model-->>User: show file nav bar and body
Loading
sequenceDiagram
  participant Model
  participant GitSweepCmd
  participant Git
  participant FILESSidebar
  Model->>GitSweepCmd: baseline sweep on Init
  GitSweepCmd->>Git: git status --porcelain
  Git-->>GitSweepCmd: dirty paths
  GitSweepCmd-->>Model: gitSweepMsg(baseline)
  Model->>Model: handleGitSweepMsg()
  Model->>GitSweepCmd: maybeGitSweep() on turn completion
  GitSweepCmd->>Git: git status + git diff --numstat
  Git-->>GitSweepCmd: dirty paths + diffstat
  GitSweepCmd-->>Model: gitSweepMsg(live)
  Model->>FILESSidebar: refresh touched files
Loading

Possibly related PRs

  • Gitlawb/zero#83: Shared transcript row/tool-result metadata changes in transcript.go, session.go, and rendering paths.
  • Gitlawb/zero#160: Related through the render-cache and row-rendering plumbing used for selection tinting.
  • Gitlawb/zero#227: Both touch transcript_selection.go and transcript body layout behavior.

Suggested reviewers: gnanam1990, Vasanthdev2004

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a FILES sidebar with click-to-select and drill-in behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (3)
internal/tui/file_view.go (1)

189-201: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Exact trimmed-text matching will over-mark common/duplicate lines.

changed[strings.TrimSpace(lines[i])] (built in fileViewChangedLines, Line 219) matches purely by line content. Any on-disk line whose trimmed text happens to equal an added line — very common for short lines like }, }(), return nil, blank-brace lines, etc. — gets the accent gutter marker even though it was never touched. The doc comment at Line 159-160 frames this as "a stale marker just doesn't highlight," but the more common failure mode is the opposite: marking unrelated, unchanged occurrences of a common short line throughout the file.

A cheap mitigation: skip very short/low-signal lines (e.g. length < 4-5 chars, or lines consisting only of punctuation) when populating fileViewChangedLines, since those are the lines most likely to collide.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/file_view.go` around lines 189 - 201, The gutter marker logic in
fileViewChangedLines/file_view.go is over-matching duplicate short lines because
it keys only on strings.TrimSpace(lines[i]). Update the changed-line tracking to
ignore very short or low-signal lines when building the changed set, so common
tokens like braces, blank lines, and simple returns do not get marked across
unrelated occurrences. Keep the fix localized to fileViewChangedLines and the
marker check used in the display loop.
internal/tui/files_git_sweep_test.go (1)

173-201: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Static analysis: nil context.Context passed to gitSweepCmd.

golangci-lint flags gitSweepCmd(nil, dir, true) (Line 173) under SA1012; the same pattern recurs at Lines 182 and 198. gitSweepCmd does guard against nil internally, but passing context.TODO() here is idiomatic and silences the linter without changing behavior.

🔧 Suggested fix
-	baseline := gitSweepCmd(nil, dir, true)().(gitSweepMsg)
+	baseline := gitSweepCmd(context.TODO(), dir, true)().(gitSweepMsg)
...
-	sweep := gitSweepCmd(nil, dir, false)().(gitSweepMsg)
+	sweep := gitSweepCmd(context.TODO(), dir, false)().(gitSweepMsg)
...
-	if msg := gitSweepCmd(nil, t.TempDir(), false)().(gitSweepMsg); msg.ok {
+	if msg := gitSweepCmd(context.TODO(), t.TempDir(), false)().(gitSweepMsg); msg.ok {

(requires adding "context" to imports)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/files_git_sweep_test.go` around lines 173 - 201, The test is
passing a nil context into gitSweepCmd, which triggers SA1012 in the calls used
in files_git_sweep_test.go. Update the test to use a non-nil context such as
context.TODO() for each gitSweepCmd invocation, and add the context import so
the existing gitSweepMsg assertions and gitSweepCmd behavior remain unchanged.

Source: Linters/SAST tools

internal/tui/files_git_sweep.go (1)

148-156: 🩺 Stability & Availability | 🔵 Trivial | ⚖️ Poor tradeoff

Transient timeout permanently disables the sweep, same as a real "not a repo" failure.

A hung/slow git (hitting gitSweepTimeout) and a genuine non-git workspace both set gitSweepUnavailable = true with no retry. For the timeout case this is a recoverable condition that will now never resurface for the rest of the session. Worth distinguishing "no git here" (permanent) from "git call failed/timed out" (retryable) so a momentarily slow filesystem/lock doesn't permanently blind the FILES sidebar to shell-created files for the session.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/files_git_sweep.go` around lines 148 - 156, The timeout path in
handleGitSweepMsg currently marks gitSweepUnavailable true for every failed
sweep, which makes a transient gitSweepTimeout behave like a permanent non-repo
failure. Update the git sweep handling in model.handleGitSweepMsg (and any
related gitSweepMsg fields/creation sites) to distinguish a real “not a repo”
result from a timeout or other retryable git failure, so only the permanent case
sets gitSweepUnavailable while timeout/temporary failures leave it eligible to
retry later.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/file_view.go`:
- Around line 161-176: The full-file path in renderFileViewFull still reads the
entire file into memory before applying fileViewMaxLines, which defeats the
render freeze safeguard. Change renderFileViewFull to bound the read up front by
using a streaming or limited-read approach, then stop once fileViewMaxLines
lines are collected before any full strings.Split-like processing; keep the
existing target resolution and error handling intact.

In `@internal/tui/files_git_sweep_test.go`:
- Around line 37-45: The TestParseGitNumstat case is using a fabricated rename
record and not covering the real numstat rename format, so update it to use an
authentic git --numstat rename entry handled by parseGitNumstat and assert the
expected map key for the renamed file. Keep the existing checks for normal and
binary entries, but replace the bogus "R\told.go -> pkg/new.go" line and add an
assertion that the "old.go => pkg/new.go" path is parsed into the correct
destination entry.

In `@internal/tui/files_git_sweep.go`:
- Around line 198-217: The git-only entries returned by gitTouchedFiles are not
ordered by recency, so older sweep results can appear before newer ones when
merged into the FILES tail. Update gitTouchedFiles in model to sort m.gitTouched
newest-first by created before building touchedFile entries, then keep the
existing merge flow with touchedFiles so the combined list stays consistently
ordered.
- Around line 104-142: parseGitNumstat is still relying on cutRename, which only
handles porcelain-style “old -> new” paths and will miss git --numstat rename
output like brace-mangled paths, so renamed files never get matched. Update the
git diff collection in files_git_sweep.go to use --numstat -z and parse the
NUL-delimited rename format, or add rename-aware parsing inside parseGitNumstat
that understands brace-mangled numstat paths. Keep unquoteGitPath and the
files[i].path matching logic aligned with the new parsing so renamed entries
resolve correctly.

In `@internal/tui/files_panel.go`:
- Around line 153-159: The overflow count in the files sidebar is using the full
files slice length even though the live row is skipped in the loop, so the “+N
more” label can be inflated. Update the logic in the files panel rendering flow
around the loop that builds the sidebar rows in the code path using files, live,
shown, and maxSidebarFiles so the count excludes the live entry when f.path
matches live. Adjust the remaining-count calculation to use only the non-live
items that could still be shown, keeping the displayed overflow text consistent
with what is actually rendered.
- Around line 52-68: The file summary aggregation in files_panel.go is using
planDiffStat(row.detail) for every entry in row.changedFiles, so each touched
file gets the full patch totals instead of its own stats. Update the per-file
accumulation logic in the touchedFile/index loop to derive adds and dels for
each individual path before adding them to files[at], using the existing
row.changedFiles handling and related symbols like planDiffStat, touchedFile,
and resultRowCreatedFile as the place to split by path.
- Around line 74-78: The ordering logic in files_panel.go currently reverses
first-seen order, which does not keep the most recently touched file first when
a file is revisited. Update the sorting in the files panel logic around the
files slice to order entries by lastRowIndex descending instead of reversing the
slice, so the newest touch always appears first. Use the existing file item
structure and the code path that builds files in the files panel to locate the
change.

In `@internal/tui/model.go`:
- Around line 1083-1089: The file-view shortcut handling in the main key
dispatch is intercepting modal keys before the permission/spec/MCP/picker
branches. Update the key handling around m.fileView.active, composerValue(), and
keyText(msg) so the d/f and Esc shortcuts only apply when no blocking modal is
open, matching the same modal-state checks used by the permission and picker
cases. Make the same guard change in both affected key-handling branches so
modal deny/Esc behavior is not hijacked by file drill-in mode.

In `@internal/tui/sidebar.go`:
- Around line 100-102: sidebarHasContent currently only checks touchedFiles(),
so it can miss an in-progress live edit and suppress the FILES pulse. Update
sidebarHasContent in sidebar.go to also treat a non-empty liveEditingPath() as
content, alongside the existing touchedFiles() check, so the sidebar shows
content as soon as the first live write starts.

In `@internal/tui/transcript_selection.go`:
- Around line 1271-1281: The FILES click handling in transcript_selection.go
reopens the currently active file and silently resets its view state. Update the
click branch around m.fileRowAtMouse so that when m.fileView.active is true and
the clicked path matches m.fileView.path, it does not call openFileView(path);
instead preserve the current fileView mode and chat scroll state, only switching
views when the clicked file is different. Keep the behavior for a different file
path by still using openFileView, and add coverage for re-clicking the same open
file after switching to full mode.

---

Nitpick comments:
In `@internal/tui/file_view.go`:
- Around line 189-201: The gutter marker logic in
fileViewChangedLines/file_view.go is over-matching duplicate short lines because
it keys only on strings.TrimSpace(lines[i]). Update the changed-line tracking to
ignore very short or low-signal lines when building the changed set, so common
tokens like braces, blank lines, and simple returns do not get marked across
unrelated occurrences. Keep the fix localized to fileViewChangedLines and the
marker check used in the display loop.

In `@internal/tui/files_git_sweep_test.go`:
- Around line 173-201: The test is passing a nil context into gitSweepCmd, which
triggers SA1012 in the calls used in files_git_sweep_test.go. Update the test to
use a non-nil context such as context.TODO() for each gitSweepCmd invocation,
and add the context import so the existing gitSweepMsg assertions and
gitSweepCmd behavior remain unchanged.

In `@internal/tui/files_git_sweep.go`:
- Around line 148-156: The timeout path in handleGitSweepMsg currently marks
gitSweepUnavailable true for every failed sweep, which makes a transient
gitSweepTimeout behave like a permanent non-repo failure. Update the git sweep
handling in model.handleGitSweepMsg (and any related gitSweepMsg fields/creation
sites) to distinguish a real “not a repo” result from a timeout or other
retryable git failure, so only the permanent case sets gitSweepUnavailable while
timeout/temporary failures leave it eligible to retry later.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c778130c-683a-4a39-a5fb-0bbce3bcb231

📥 Commits

Reviewing files that changed from the base of the PR and between 02f0c09 and 0b85359.

📒 Files selected for processing (14)
  • internal/tui/file_view.go
  • internal/tui/file_view_test.go
  • internal/tui/files_git_sweep.go
  • internal/tui/files_git_sweep_test.go
  • internal/tui/files_panel.go
  • internal/tui/files_panel_test.go
  • internal/tui/hover.go
  • internal/tui/model.go
  • internal/tui/render_cache.go
  • internal/tui/rendering.go
  • internal/tui/session.go
  • internal/tui/sidebar.go
  • internal/tui/transcript.go
  • internal/tui/transcript_selection.go

Comment thread internal/tui/file_view.go
Comment thread internal/tui/files_git_sweep_test.go
Comment thread internal/tui/files_git_sweep.go
Comment thread internal/tui/files_git_sweep.go
Comment thread internal/tui/files_panel.go Outdated
Comment thread internal/tui/files_panel.go Outdated
Comment thread internal/tui/files_panel.go
Comment thread internal/tui/model.go Outdated
Comment thread internal/tui/sidebar.go Outdated
Comment thread internal/tui/transcript_selection.go
Review fixes for the FILES panel / drill-in / git sweep:

- touchedFiles: split multi-file diffs per file (perFileDiffStats) so an
  apply_patch spanning several files no longer charges the whole patch's
  +/- totals to every file it touched; order by lastRowIndex descending
  so a re-touched file lists first (reversing first-seen order kept it in
  its original slot).
- sidebarFileLines: filter the live-writing row out before computing the
  "+N more" trailer so the skipped entry no longer inflates the count.
- git sweep: run `git diff --numstat -z` and parse the NUL-terminated
  rename records (counts + preimage + postimage) — plain --numstat
  brace-mangles renamed paths ("src/{old => new}"), so their diffstat
  never matched a porcelain path and renamed files stayed at 0/0;
  gitTouchedFiles now yields newest detection first to match the
  roster's ordering.
- file view: stream the full-mode read and stop at fileViewMaxLines
  (os.ReadFile loaded a multi-GB file wholesale before truncating — the
  exact freeze the cap exists to prevent); re-opening the file already
  being viewed is a no-op so a stray re-click can't bounce full mode
  back to diff or reset scroll; skip sub-4-char lines in the changed-line
  markers so common braces/returns don't mark unrelated occurrences.
- keys: gate the drill-in's d/f and Esc handling on noBlockingModal so a
  permission prompt / ask-user / wizard keeps its own key handling.
- sidebar: a live in-flight write counts as content, so the FILES pulse
  shows for the session's first mutation.
- tests: numstat test now feeds real -z record shapes and asserts the
  rename postimage key; new coverage for per-file stats, re-touch
  ordering, live-row overflow, same-file reopen, truncation, modal
  gating, live-write content, and a real-repo rename sweep.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/tui/file_view_test.go (1)

267-288: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test only exercises f, not d, despite the doc comment claiming both.

The comment says "with a permission prompt up, Esc and the d/f shortcuts belong to the prompt — the drill-in must not swallow them", but only f is sent to Update. If a regression only affects the d branch (e.g., separate case handling d before the modal-guard check), this test won't catch it.

🧪 Add the missing `d` case
 	updated, _ := m.Update(tea.KeyPressMsg{Code: 'f', Text: "f"})
 	m = updated.(model)
 	if m.fileView.mode != fileViewDiff {
 		t.Fatal("f with a permission prompt up must not switch file-view modes")
 	}
+	m = m.setFileViewMode(fileViewFull)
+	updated, _ = m.Update(tea.KeyPressMsg{Code: 'd', Text: "d"})
+	m = updated.(model)
+	if m.fileView.mode != fileViewFull {
+		t.Fatal("d with a permission prompt up must not switch file-view modes")
+	}
 	updated, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyEsc})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/file_view_test.go` around lines 267 - 288, The permission-prompt
key-handling test only covers the f shortcut, so it can miss regressions in the
d path even though the doc comment says both should be blocked by the modal.
Update TestFileViewKeysDeferToBlockingModal in file_view_test.go to also send a
d keypress through m.Update and assert it does not change fileView.mode while
pendingPermission is set, alongside the existing Esc check, so the guard
behavior is verified for both drill-in shortcuts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/tui/file_view_test.go`:
- Around line 267-288: The permission-prompt key-handling test only covers the f
shortcut, so it can miss regressions in the d path even though the doc comment
says both should be blocked by the modal. Update
TestFileViewKeysDeferToBlockingModal in file_view_test.go to also send a d
keypress through m.Update and assert it does not change fileView.mode while
pendingPermission is set, alongside the existing Esc check, so the guard
behavior is verified for both drill-in shortcuts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 43f6ac84-5c4d-41fd-86b9-7c309264065a

📥 Commits

Reviewing files that changed from the base of the PR and between 0b85359 and b8d23f1.

📒 Files selected for processing (8)
  • internal/tui/file_view.go
  • internal/tui/file_view_test.go
  • internal/tui/files_git_sweep.go
  • internal/tui/files_git_sweep_test.go
  • internal/tui/files_panel.go
  • internal/tui/files_panel_test.go
  • internal/tui/model.go
  • internal/tui/sidebar.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • internal/tui/sidebar.go
  • internal/tui/files_git_sweep_test.go
  • internal/tui/file_view.go
  • internal/tui/model.go
  • internal/tui/files_git_sweep.go
  • internal/tui/files_panel.go

@gnanam1990

Copy link
Copy Markdown
Collaborator

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@gnanam1990
gnanam1990 merged commit 142c548 into main Jul 2, 2026
7 checks passed
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.

3 participants