From 2d2a51b47125bd58fdb48475837fc4a6ab7b9acb Mon Sep 17 00:00:00 2001 From: Aditi Chauhan Date: Wed, 8 Jul 2026 11:24:18 +0530 Subject: [PATCH 01/10] fix: scope reviews tab to open PRs --- .../components/SessionInspector.test.tsx | 15 ++++++---- .../renderer/components/SessionInspector.tsx | 29 ++++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/frontend/src/renderer/components/SessionInspector.test.tsx b/frontend/src/renderer/components/SessionInspector.test.tsx index 86709d15f6..5fc633af37 100644 --- a/frontend/src/renderer/components/SessionInspector.test.tsx +++ b/frontend/src/renderer/components/SessionInspector.test.tsx @@ -424,19 +424,22 @@ describe("SessionInspector reviews tab", () => { expect(await screen.findByText("claude-code")).toBeInTheDocument(); }); - it("shows eligible and up-to-date PR review rows", async () => { + it("shows eligible and up-to-date open PR review rows", async () => { mockCommonGets([approvedReview], "reviewer-pane", [ reviewState(3, "needs_review", "abc123"), reviewState(4, "up_to_date", "def456"), + reviewState(5, "ineligible", "ghi789"), ]); - renderWithQuery(); + renderWithQuery(); await openReviewsTab(); + expect(screen.getByText("Open pull requests")).toBeInTheDocument(); expect(await screen.findByText("Reviewable change 3")).toBeInTheDocument(); expect(screen.getByText("#3")).toBeInTheDocument(); expect(screen.getByText("Reviewable change 4")).toBeInTheDocument(); expect(screen.getByText("#4")).toBeInTheDocument(); + expect(screen.queryByText("Reviewable change 5")).not.toBeInTheDocument(); expect(screen.getAllByText("Not run")).not.toHaveLength(0); expect(screen.getAllByText("Approved")).not.toHaveLength(0); expect(screen.getByRole("button", { name: "Re-run review" })).toBeInTheDocument(); @@ -466,7 +469,7 @@ describe("SessionInspector reviews tab", () => { expect(onOpenReviewerTerminal).not.toHaveBeenCalled(); }); - it("shows one shared terminal action", async () => { + it("shows a stop action instead of allowing rerun while review is running", async () => { mockCommonGets([approvedReview], "reviewer-pane", [ reviewState(3, "running", "abc123"), reviewState(4, "up_to_date", "def456"), @@ -478,9 +481,9 @@ describe("SessionInspector reviews tab", () => { ); await openReviewsTab(); - await waitFor(() => expect(screen.getAllByText("Open terminal")).toHaveLength(1)); - expect(screen.getAllByRole("button", { name: /review/i })).toHaveLength(1); - await userEvent.click(screen.getByRole("button", { name: /open terminal/i })); + await waitFor(() => expect(screen.getByRole("button", { name: "Review running" })).toBeDisabled()); + expect(screen.queryByRole("button", { name: /re-run review/i })).not.toBeInTheDocument(); + await userEvent.click(screen.getByRole("button", { name: /stop review/i })); expect(onOpenReviewerTerminal).toHaveBeenCalledWith({ handleId: "reviewer-pane", harness: "codex" }); }); diff --git a/frontend/src/renderer/components/SessionInspector.tsx b/frontend/src/renderer/components/SessionInspector.tsx index 34a16862e8..f8c7987f2a 100644 --- a/frontend/src/renderer/components/SessionInspector.tsx +++ b/frontend/src/renderer/components/SessionInspector.tsx @@ -628,16 +628,23 @@ function ReviewPanel({ return

Loading reviews...

; } - const latest = reviewStates.find((review) => review.latestRun)?.latestRun; + const openPRURLs = new Set( + sortedPRs(session) + .filter((pr) => pr.state === "open") + .map((pr) => pr.url), + ); + const openReviewStates = reviewStates.filter((reviewState) => openPRURLs.has(reviewState.prUrl)); + const latest = openReviewStates.find((review) => review.latestRun)?.latestRun; const harness = latest?.harness || config?.reviewers?.[0]?.harness || "claude-code"; const terminalEnabled = Boolean(reviewerHandleId && onOpenTerminal); - const aggregateVerdict = sessionReviewVerdict(reviewStates); - const runAction = reviewSessionRunAction(reviewStates, isTriggering); + const aggregateVerdict = sessionReviewVerdict(openReviewStates); + const reviewRunning = openReviewStates.some((reviewState) => reviewState.status === "running"); + const runAction = reviewSessionRunAction(openReviewStates, isTriggering); const runDisabled = isTriggering || - reviewStates.length === 0 || - reviewStates.some((reviewState) => reviewState.status === "running") || - reviewStates.every((reviewState) => reviewState.status === "ineligible"); + openReviewStates.length === 0 || + reviewRunning || + openReviewStates.every((reviewState) => reviewState.status === "ineligible"); return (
@@ -669,10 +676,10 @@ function ReviewPanel({
- {reviewStates.length === 0 ? ( -

No review state loaded yet.

+ {openReviewStates.length === 0 ? ( +

No open pull requests to review.

) : null} - {reviewStates.map((reviewState) => ( + {openReviewStates.map((reviewState) => ( ))}
@@ -684,7 +691,7 @@ function ReviewPanel({ type="button" >