feat(comments): reference a comment into the agent, and turn its answer into a reply draft - #228
Merged
Merged
Conversation
A reviewer''s comment is usually a claim -- is this actually a problem, does this path really run, was it handled elsewhere -- and settling it means reading the code the comment points at. That is what the agent is for, but the only way to hand it one was to paste the text into the chat box, dropping the anchor and the authorship on the way. The reference button attaches the comment as implicit context for the next question, so "is this right?" is a complete question. No IPC change was needed: agent:ask already carries referencedContext for the diff selection, and the two compose, since asking whether a comment is right about a selected region needs both. Cross-pane state goes in a store for the same reason the diff selection does: the comment surfaces and ChatPane are siblings with no common owner below App. Both comment surfaces get it, identically -- toggle to release, a chip with a clear button, released on send, cleared on PR switch. DraftZone does not: a draft is a comment not yet written by anyone else, so there is no claim to investigate. The glyph is the existing ShareIcon rather than something agent-flavoured, because that is already what "reference" looks like in this app (the finding reference button); one gesture should not have two icons. The prompt says what to do with the comment, not just what it says. Without that instruction a model tends to paraphrase the comment back instead of checking it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Investigating a comment usually ends in replying to it, and retyping the conclusion by hand was the remaining manual step. This needs the answer to know which comment it answers, so a referenced comment now hands off on send rather than being discarded: it detaches from the input bar but stays associated with the round it was asked in. The hand-off runs on every send, including unreferenced ones -- that is what ends a previous association, so an unrelated later answer never offers itself as a reply to an old comment. Memory only, one round: an association that outlived its round would attach an answer to the wrong comment, and that is worse than not offering the action at all. It produces a draft, not a posted reply. The words are the agent''s and publishing under the user''s name is the user''s call, so it lands in the same draft pool as every other pending reply -- editable, rejectable, published with the review batch. No IPC change: drafts:create already models a reply through replyTo, and the comment''s anchor carries over so an inline reply keeps its position in the diff. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ions The icon button sized itself to its glyph (line-height:1, its own padding) while the text buttons beside it size to a font-size line box, so it stood taller than the row it sits in. Both surfaces now take the same padding and font-size as the text buttons, so the line box -- and therefore the height -- is theirs; the inline zone simply stops overriding the shared rule it already belongs to. The svg is display:block so it does not sit on the text baseline and add descender space underneath. Co-Authored-By: Claude Opus 5 (1M context) <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.
A reviewer''s comment is usually a claim — is this actually a problem, does this path really run, was it handled elsewhere — and settling it means reading the code the comment points at. That is what the agent is for, but the only way to hand it one was to paste the text into the chat box, dropping the anchor and the authorship on the way. And once you had the answer, replying meant retyping it.
What it does
No IPC changes
Both halves land on existing contracts, which is most of why this stayed small:
agent:askalready carriesreferencedContextfor the diff selection. The comment formats into the same channel, and the two compose — asking whether a comment is right about a selected region needs both.drafts:createalready models a reply throughreplyTo, and the comment''s anchor carries over, so an inline reply keeps its position in the diff.Cross-pane state goes in a store for the same reason the diff selection does: the comment surfaces and ChatPane are siblings with no common owner below App.
Three decisions worth reviewing
The association is deliberately short-lived. "Use as reply" needs the answer to know which comment it answers, so a referenced comment hands off on send instead of being discarded — detached from the input bar, still tied to that round. The hand-off runs on every send, including unreferenced ones: that is what ends a previous association, so an unrelated later answer never offers itself as a reply to an old comment. Memory only, one round. An association that outlived its round would attach an answer to the wrong comment, which is worse than not offering the action.
It produces a draft, not a posted reply. The words are the agent''s; publishing under the user''s name is the user''s call. It lands in the same pool as every other pending reply — editable, rejectable, published with the review batch.
The prompt says what to do with the comment, not just what it says. Without that instruction a model tends to paraphrase the comment back instead of checking it.
Scope
Both comment surfaces get the reference button, identically — toggle to release, chip with a clear button, released on send, cleared on PR switch. DraftZone does not: a draft is a comment nobody else has written yet, so there is no claim to investigate. That boundary is deliberate rather than an oversight of the comment-surface parity rule.
The glyph is the existing
ShareIconrather than something agent-flavoured, because that is already what "reference" looks like in this app (the finding reference button) — one gesture should not have two icons. Thanks for catching that; my first pass used a robot icon, which drew the target where the established convention draws the action.Verification
lint/typecheck/test/buildpass.Two visual defects were found by running it, not by the gate — both mine, both fixed here, and worth stating because they show what the gate does not cover:
styles/features/chat.scsswhile probing a file, which shadowed thefeatures/chat/style directory that@use ''./styles/features/chat''resolves to. Every ChatPane style vanished — and the build passed, because an empty stylesheet is not an error. Removed, artifact rebuilt.display:blockso it does not add descender space.Beyond those, the interaction has not been exercised end to end against a live agent run — worth one pass to confirm the answer''s use as reply produces a draft anchored to the right comment.
🤖 Generated with Claude Code