From 285fc038d7eea92731ff149c21f4c2119c6d40e0 Mon Sep 17 00:00:00 2001 From: Alejandro Perez Date: Mon, 6 Jul 2026 17:18:11 +0100 Subject: [PATCH] app: adopt agent findings as review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An 'Add to review' action on finding rows (FindingsPanel + Briefing) converts a finding into a local comment at its anchor, with the agent's severity/title/rationale and an honest provenance footer. Posting to the human's PR still rides the existing guarded Mirror / Submit-review flows — two deliberate clicks between agent output and GitHub (§9). Idempotent: an adopted finding shows Added and cannot double-post. --- app/src/components/BriefingFindings.tsx | 37 +++++++++ app/src/components/BriefingTab.tsx | 26 ++++++ app/src/components/DiffView.tsx | 28 +++++++ app/src/components/FindingsPanel.test.tsx | 50 ++++++++++++ app/src/components/FindingsPanel.tsx | 39 +++++++++ app/src/lib/finding-comment.test.ts | 99 +++++++++++++++++++++++ app/src/lib/finding-comment.ts | 58 +++++++++++++ 7 files changed, 337 insertions(+) create mode 100644 app/src/lib/finding-comment.test.ts create mode 100644 app/src/lib/finding-comment.ts diff --git a/app/src/components/BriefingFindings.tsx b/app/src/components/BriefingFindings.tsx index 48f87e3..e955c76 100644 --- a/app/src/components/BriefingFindings.tsx +++ b/app/src/components/BriefingFindings.tsx @@ -33,6 +33,14 @@ interface BriefingFindingsProps { * Briefing tab list. */ readonly limit?: number; + /** + * Adopt a finding as a review comment (explicit click; outward posting still + * rides the guarded Mirror / Submit-review flows). Omitted by read-only + * surfaces (the board preview rail) and when the gate is not InReview. + */ + readonly onAdopt?: ((finding: ReviewFinding) => void) | undefined; + /** Ids of findings that already have an adopted comment. */ + readonly adoptedIds?: ReadonlySet | undefined; } // --------------------------------------------------------------------------- @@ -55,9 +63,13 @@ function locationLabel(finding: ReviewFinding): string { function FindingRow({ finding, onJumpTo, + onAdopt, + adopted, }: { readonly finding: ReviewFinding; readonly onJumpTo: (path: string, side: DiffSide, line: number) => void; + readonly onAdopt?: ((finding: ReviewFinding) => void) | undefined; + readonly adopted: boolean; }) { const meta = severityMeta(finding.severity); const [start] = finding.range; @@ -94,6 +106,27 @@ function FindingRow({ > {locationLabel(finding)} + {onAdopt !== undefined && + hasLine && + (adopted ? ( + + Added ✓ + + ) : ( + + ))} {hasLine ? ( + ))} {hasLine ? (