Repository navigation
Move Review viewer comments into a main-process slice with anchoring - #336
Merged
Merged
Conversation
Comments are keyed by worktree path, persisted to config.json, and pruned when the worktree is removed. Each comment records the commit and line it was written against plus a snippet of that line, so refreshReviewAnchors can follow it as new commits land or mark it outdated when the line is gone. Main generates ids and computes the snippet itself, so later main-side callers only need file/line/side. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ReviewPane drops its local comment state and the clear-on-selection effect; comments now come from useReviewComments and mutate over IPC. ReviewDiffPane places each comment by snippet so commit/range views still draw it on the right code, lists unplaceable (outdated / old-side) comments above the diff, and adds resolve/reopen plus author labels. Send to Agent and Copy include only open comments, with side and SHA. Also fixes view zones being drawn into the previous, disposed editor after a file switch — the effect now depends on the editor instance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 1 of the agent-reviewer work: Review viewer comments move out of `ReviewPane` `useState` and into a persisted `reviews` slice. Nothing agent-facing is built here. The aim is a data model that main-side code (MCP tools later) can write to directly.
Data model (`src/shared/state/reviews.ts`)
`reviews.byPath[worktreePath].comments: ReviewComment[]`, where each comment has:
Events: `commentAdded`, `commentDeleted`, `commentStatusChanged`, `replyAdded` (reducer only, no UI yet), `anchorsUpdated` (batched), `worktreeRemoved`. Single-item patches use `findIndex` + `slice` (anti-pattern #3). The renderer reads through a per-worktree `useReviewComments(path)` hook (anti-pattern #4).
The slice persists to `config.reviews` the same way `pinned`/`aliases` do, is sanitized on boot, and loses a worktree's entry when that worktree leaves the list.
One correction to the brief: the review diff never shows working-tree content. Whole-branch mode is merge-base..HEAD (`getFileDiffSides(…, 'branch')`), and commit and range modes are commit-to-commit. So a comment always anchors to a real SHA: HEAD or the selected tip for the new side, the diff base for the old side. There's no "working tree vs committed" flag to record.
Main computes the snippet itself (`src/main/review-comments.ts`). `addReviewComment` resolves the SHA for that side of the current view and reads the line with `git show`. A caller only supplies `{file, line, side, body, view?}`, which is the shape step 2's `add_review_comment` MCP tool needs.
Outdated detection (`src/shared/review-anchor.ts`)
There's no poller and no subscriber. `reviews:refreshAnchors(worktreePath, file?)` runs when the Review pane opens and when a file is selected:
Old-side comments point at the diff base, which doesn't move as the author commits, so they are never outdated.
When drawing, `ReviewDiffPane` places each comment by snippet against the content on screen. That way a commit or range view (whose content differs from HEAD) still shows it on the right code. A comment it can't place goes into a collapsible "N comments not on a line in this diff" list above the diff, greyed out, and is never deleted. That covers outdated comments, old-side comments (inline diff mode has no click target for removed lines yet) and lines that don't exist in the selected revision.
Reviewed checkmarks stay per-viewer renderer state
The "viewed" checkmarks are my progress through this file set. They still reset when the commit selection changes, because the progress is relative to the files in view. Sharing them properly would need content-hash invalidation (GitHub resets "viewed" when a file changes). A review agent has no use for them either, so I left them out of the slice.
UI
Testing
🤖 Generated with Claude Code