From 6cc7cc3e4e81edd25152adff26b265ba3cc4b23f Mon Sep 17 00:00:00 2001 From: Apoorv Singh <68725597+aprv10@users.noreply.github.com> Date: Sun, 5 Jul 2026 17:48:15 +0530 Subject: [PATCH 1/8] fix(browser): remove excess padding around the inspector Browser tab (#2423) --- .../src/renderer/components/SessionInspector.tsx | 10 +++++++++- frontend/src/renderer/styles.css | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/frontend/src/renderer/components/SessionInspector.tsx b/frontend/src/renderer/components/SessionInspector.tsx index 9be031a8e..c22b997e9 100644 --- a/frontend/src/renderer/components/SessionInspector.tsx +++ b/frontend/src/renderer/components/SessionInspector.tsx @@ -125,7 +125,15 @@ export function SessionInspector({ ))} -
+
{view === "summary" ? : null} {view === "reviews" ? : null} {view === "browser" ? ( diff --git a/frontend/src/renderer/styles.css b/frontend/src/renderer/styles.css index eb419dde5..6bffd91d2 100644 --- a/frontend/src/renderer/styles.css +++ b/frontend/src/renderer/styles.css @@ -773,6 +773,18 @@ body.is-resizing-x [data-slot="sidebar-container"] { padding: 18px 18px 40px; } +/* Browser tab: the panel fills the rail edge-to-edge, so drop the body padding + and the panel's own border/radius so it sits flush against the resize handle. */ +.session-inspector__body.session-inspector__body--browser { + padding: 0; + overflow: hidden; +} + +.session-inspector__body--browser .browser-panel { + border: 0; + border-radius: 0; +} + /* Inspector resize handle (shadcn resizable separator, AO visual): a 7px * transparent grab strip whose centered 1px line lights accent on hover, drag * (rrp sets data-separator="active"), and keyboard focus. */ From cbaffd2cb409df21e8409905a2a924ec5fdf05b9 Mon Sep 17 00:00:00 2001 From: neversettle <41864816+neversettle17-101@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:40:45 +0530 Subject: [PATCH 2/8] fix: simplify kanban pr footer (#2374) --- .github/workflows/frontend-nightly.yml | 2 +- .../integration/pr-hydration.test.tsx | 101 ++++++++++--- .../OrchestratorReplacementDialog.tsx | 9 +- .../components/ProjectSettingsForm.test.tsx | 6 +- .../src/renderer/components/SessionsBoard.tsx | 143 +++++++++++------- frontend/src/renderer/components/Sidebar.tsx | 8 +- .../renderer/hooks/useWorkspaceQuery.test.tsx | 7 +- .../src/renderer/lib/restart-orchestrator.ts | 5 +- frontend/src/renderer/types/workspace.test.ts | 3 +- frontend/src/renderer/types/workspace.ts | 3 +- 10 files changed, 204 insertions(+), 83 deletions(-) diff --git a/.github/workflows/frontend-nightly.yml b/.github/workflows/frontend-nightly.yml index 7ad149c8f..35ec830fe 100644 --- a/.github/workflows/frontend-nightly.yml +++ b/.github/workflows/frontend-nightly.yml @@ -11,7 +11,7 @@ on: workflow_dispatch: inputs: important: - description: 'Mark this nightly as an important update (escalates the in-app restart prompt). Retro-flag an already-published nightly by re-running only the publish-feed job with this input set.' + description: "Mark this nightly as an important update (escalates the in-app restart prompt). Retro-flag an already-published nightly by re-running only the publish-feed job with this input set." type: boolean default: false diff --git a/frontend/src/renderer/__tests__/integration/pr-hydration.test.tsx b/frontend/src/renderer/__tests__/integration/pr-hydration.test.tsx index 4411716be..88b7088cb 100644 --- a/frontend/src/renderer/__tests__/integration/pr-hydration.test.tsx +++ b/frontend/src/renderer/__tests__/integration/pr-hydration.test.tsx @@ -38,20 +38,10 @@ function respondWithProjectAndPRs() { projectId: "proj-1", displayName: "fix the bug", harness: "claude-code", - status: "pr_open", + status: "draft", isTerminated: false, updatedAt: "2026-06-10T16:15:04Z", prs: [ - { - number: 278, - state: "open", - url: "https://github.com/aoagents/ReverbCode/pull/278", - ci: "passing", - review: "approved", - mergeability: "clean", - reviewComments: false, - updatedAt: "2026-06-10T16:15:04Z", - }, { number: 279, state: "draft", @@ -62,6 +52,46 @@ function respondWithProjectAndPRs() { reviewComments: false, updatedAt: "2026-06-10T16:20:04Z", }, + { + number: 278, + state: "open", + url: "https://github.com/aoagents/ReverbCode/pull/278", + ci: "passing", + review: "review_required", + mergeability: "clean", + reviewComments: false, + updatedAt: "2026-06-10T16:15:04Z", + }, + { + number: 280, + state: "open", + url: "https://github.com/aoagents/ReverbCode/issues/280", + ci: "passing", + review: "approved", + mergeability: "clean", + reviewComments: false, + updatedAt: "2026-06-10T16:25:04Z", + }, + { + number: 281, + state: "merged", + url: "https://github.com/aoagents/ReverbCode/pull/281", + ci: "passing", + review: "approved", + mergeability: "mergeable", + reviewComments: false, + updatedAt: "2026-06-10T16:30:04Z", + }, + { + number: 282, + state: "closed", + url: "https://github.com/aoagents/ReverbCode/pull/282", + ci: "passing", + review: "approved", + mergeability: "unknown", + reviewComments: false, + updatedAt: "2026-06-10T16:35:04Z", + }, ], }, ], @@ -179,11 +209,40 @@ beforeEach(() => { }); describe("PR hydration for a normal project (#251)", () => { - it("renders every session PR on the Board card instead of 'no PR yet'", async () => { + it("renders Board card PR numbers with lifecycle statuses only instead of 'no PR yet'", async () => { renderWithProviders(); - expect(await screen.findByText("PR #278 · open")).toBeInTheDocument(); - expect(screen.getByText("PR #279 · draft")).toBeInTheDocument(); + expect(await screen.findByRole("link", { name: "#278" })).toHaveAttribute( + "href", + "https://github.com/aoagents/ReverbCode/pull/278", + ); + expect(screen.getByText("open")).toBeInTheDocument(); + expect(screen.getByRole("link", { name: "#279" })).toHaveAttribute( + "href", + "https://github.com/aoagents/ReverbCode/pull/279", + ); + expect(screen.getByRole("link", { name: "#280" })).toHaveAttribute( + "href", + "https://github.com/aoagents/ReverbCode/pull/280", + ); + expect(screen.getByRole("link", { name: "#281" })).toHaveAttribute( + "href", + "https://github.com/aoagents/ReverbCode/pull/281", + ); + expect(screen.getByRole("link", { name: "#282" })).toHaveAttribute( + "href", + "https://github.com/aoagents/ReverbCode/pull/282", + ); + expect(screen.getByLabelText("#278, #280 open")).toBeInTheDocument(); + expect(screen.getByLabelText("#279 draft")).toBeInTheDocument(); + expect(screen.getByLabelText("#281 merged")).toBeInTheDocument(); + expect(screen.getByLabelText("#282 closed")).toBeInTheDocument(); + expect(screen.getByText("draft")).toBeInTheDocument(); + expect(screen.getByText("merged")).toHaveClass("text-accent"); + expect(screen.getByText("closed")).toHaveClass("text-error"); + expect(screen.queryByText("review pending")).not.toBeInTheDocument(); + expect(screen.queryByText("CI")).not.toBeInTheDocument(); + expect(screen.queryByText("Needs attention")).not.toBeInTheDocument(); expect(screen.queryByText("no PR yet")).not.toBeInTheDocument(); }); @@ -191,14 +250,13 @@ describe("PR hydration for a normal project (#251)", () => { respondWithAttentionPR(); renderWithProviders(); - expect(await screen.findByRole("link", { name: "PR" })).toHaveAttribute( + expect(await screen.findByRole("link", { name: "#278" })).toHaveAttribute( "href", "https://github.com/aoagents/ReverbCode/pull/278", ); - expect(screen.getByRole("link", { name: "conflicts" })).toHaveAttribute( - "href", - "https://github.com/aoagents/ReverbCode/pull/278/conflicts", - ); + expect(screen.getByText("open")).toBeInTheDocument(); + expect(screen.queryByText("changes requested")).not.toBeInTheDocument(); + expect(screen.queryByRole("link", { name: "conflicts" })).not.toBeInTheDocument(); }); it("lists every session PR on the PR page instead of being empty", async () => { @@ -206,7 +264,10 @@ describe("PR hydration for a normal project (#251)", () => { expect(await screen.findByText("#278")).toBeInTheDocument(); expect(screen.getByText("#279")).toBeInTheDocument(); + expect(screen.getByText("#280")).toBeInTheDocument(); + expect(screen.getByText("#281")).toBeInTheDocument(); + expect(screen.getByText("#282")).toBeInTheDocument(); expect(screen.queryByText("No open pull requests.")).not.toBeInTheDocument(); - expect(screen.getAllByText("fix the bug")).toHaveLength(2); + expect(screen.getAllByText("fix the bug")).toHaveLength(5); }); }); diff --git a/frontend/src/renderer/components/OrchestratorReplacementDialog.tsx b/frontend/src/renderer/components/OrchestratorReplacementDialog.tsx index c9f3817e6..8c342a789 100644 --- a/frontend/src/renderer/components/OrchestratorReplacementDialog.tsx +++ b/frontend/src/renderer/components/OrchestratorReplacementDialog.tsx @@ -41,13 +41,18 @@ export function OrchestratorReplacementDialog({
- Orchestrator replacement failed + + Orchestrator replacement failed + {error ?? "The project orchestrator could not be replaced."}
- diff --git a/frontend/src/renderer/components/ProjectSettingsForm.test.tsx b/frontend/src/renderer/components/ProjectSettingsForm.test.tsx index 8811eefb9..7098aad03 100644 --- a/frontend/src/renderer/components/ProjectSettingsForm.test.tsx +++ b/frontend/src/renderer/components/ProjectSettingsForm.test.tsx @@ -95,7 +95,11 @@ beforeEach(() => { putMock.mockReset(); postMock.mockReset(); putMock.mockResolvedValue({ data: { project: {} }, error: undefined }); - postMock.mockResolvedValue({ data: { orchestrator: { id: "proj-1-orch-2" } }, error: undefined, response: { status: 200 } }); + postMock.mockResolvedValue({ + data: { orchestrator: { id: "proj-1-orch-2" } }, + error: undefined, + response: { status: 200 }, + }); }); describe("ProjectSettingsForm", () => { diff --git a/frontend/src/renderer/components/SessionsBoard.tsx b/frontend/src/renderer/components/SessionsBoard.tsx index 30f4fde97..ae7f12e7f 100644 --- a/frontend/src/renderer/components/SessionsBoard.tsx +++ b/frontend/src/renderer/components/SessionsBoard.tsx @@ -18,9 +18,8 @@ import { OrchestratorIcon } from "./icons"; import { NewTaskDialog } from "./NewTaskDialog"; import { spawnOrchestrator } from "../lib/spawn-orchestrator"; import { restartProjectOrchestrator } from "../lib/restart-orchestrator"; -import { prDiffSummary, sessionPRDisplaySummaries } from "../lib/pr-display"; +import { prBrowserUrl, sessionPRDisplaySummaries } from "../lib/pr-display"; import { cn } from "../lib/utils"; -import { PRAttentionPanel, PRStatusStrip } from "./PRSummaryDisplay"; import { useUiStore } from "../stores/ui-store"; type SessionsBoardProps = { @@ -169,7 +168,13 @@ export function SessionsBoard({ projectId }: SessionsBoardProps) { type="button" >