From 856c3cdb32bab89f51fe01a62eb533f830246a54 Mon Sep 17 00:00:00 2001 From: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:24:24 +0200 Subject: [PATCH 1/3] fix(web): pull request surface offers the checkout's PR The right panel's Pull request card only offered the thread's own PR, which requires the recorded thread branch to match the checkout. On a shared checkout that branch stays strict, so an agent that branches and opens a PR mid-thread left the card saying "No pull request on this branch yet" while the git menu's View PR opened that same PR in the panel. Fall back to the checkout's PR with the same gate View PR uses. Closes #8265 Co-Authored-By: Claude Fable 5 --- apps/web/src/components/ChatView.tsx | 22 ++++++++++++++++------ apps/web/src/components/RightPanelTabs.tsx | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index f0188af478c0..c652f362a97b 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4406,14 +4406,24 @@ function ChatViewContent(props: ChatViewProps) { linkedPullRequest: linkedThreadPullRequest, linkedPullRequestStatus, }); - // The right panel offers the thread's own change request, so it can only offer it once the - // branch has one; until then the picker says so rather than opening an empty panel. + // The right panel offers the thread's own change request, else the checkout's: the same one + // the git menu's "View PR" opens in this panel. A shared checkout keeps the recorded thread + // branch strict (#4460), so an agent that branches and opens a PR mid-thread leaves the thread + // without one while the checkout has it. Without either the picker says so rather than + // opening an empty panel. + const checkoutPr = gitStatusQuery.data?.pr ?? null; const addPullRequestSurface = useCallback(() => { - if (activeThreadPr === null) return; - openThreadPullRequest(activeThreadPr.number); - }, [activeThreadPr, openThreadPullRequest]); + if (activeThreadPr !== null) { + openThreadPullRequest(activeThreadPr.number); + } else if (checkoutPr !== null) { + openProjectPullRequest(checkoutPr.number); + } + }, [activeThreadPr, checkoutPr, openProjectPullRequest, openThreadPullRequest]); const pullRequestSurfaceAvailable = - supportsPullRequests && activeThreadPr !== null && threadRepository !== null; + supportsPullRequests && + (activeThreadPr !== null + ? threadRepository !== null + : checkoutPr !== null && activeProjectRepository !== null); // Primitive slice of the displayed PR for the settle-rule memos below: // resolveDisplayedThreadPr returns a fresh object every render, so memoize // on the fields the rules read instead of the object identity. diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index 9d057a3d2980..644b0b696b05 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -99,7 +99,7 @@ const SURFACE_DISABLED_REASONS = { terminal: "Terminal surfaces are only available from a project thread.", files: "Files are only available when a project is open.", diff: "Diff is only available for server threads in Git repositories.", - pullRequest: "This thread's branch has no pull request yet.", + pullRequest: "This branch has no pull request yet.", agents: "Agents are only available from a thread.", } as const; From 84ed0477f4ccccf8e68e6553a9882a66863767ce Mon Sep 17 00:00:00 2001 From: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:32:17 +0200 Subject: [PATCH 2/3] fix(web): only offer the checkout's open PR in the surface card Mirrors the git menu's View PR gate so a merged or closed PR on the checkout does not enable the card while the menu offers Create PR. Co-Authored-By: Claude Fable 5 --- apps/web/src/components/ChatView.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index c652f362a97b..2316f3710e72 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4406,12 +4406,12 @@ function ChatViewContent(props: ChatViewProps) { linkedPullRequest: linkedThreadPullRequest, linkedPullRequestStatus, }); - // The right panel offers the thread's own change request, else the checkout's: the same one - // the git menu's "View PR" opens in this panel. A shared checkout keeps the recorded thread - // branch strict (#4460), so an agent that branches and opens a PR mid-thread leaves the thread - // without one while the checkout has it. Without either the picker says so rather than + // The right panel offers the thread's own change request, else the checkout's open one: the + // same one the git menu's "View PR" opens in this panel. A shared checkout keeps the recorded + // thread branch strict (#4460), so an agent that branches and opens a PR mid-thread leaves the + // thread without one while the checkout has it. Without either the picker says so rather than // opening an empty panel. - const checkoutPr = gitStatusQuery.data?.pr ?? null; + const checkoutPr = gitStatusQuery.data?.pr?.state === "open" ? gitStatusQuery.data.pr : null; const addPullRequestSurface = useCallback(() => { if (activeThreadPr !== null) { openThreadPullRequest(activeThreadPr.number); From 21d2dc7d2f089923892108ea0870c41b9a1385cb Mon Sep 17 00:00:00 2001 From: Wout Stiens <71498452+StiensWout@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:36:37 +0200 Subject: [PATCH 3/3] fix(web): keep the checkout PR fallback off linked-PR threads A linked PR is the thread's own even while its detail is loading, so the surface card must not open the checkout's PR in that window. Co-Authored-By: Claude Fable 5 --- apps/web/src/components/ChatView.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 2316f3710e72..34bbf16724bd 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4409,9 +4409,13 @@ function ChatViewContent(props: ChatViewProps) { // The right panel offers the thread's own change request, else the checkout's open one: the // same one the git menu's "View PR" opens in this panel. A shared checkout keeps the recorded // thread branch strict (#4460), so an agent that branches and opens a PR mid-thread leaves the - // thread without one while the checkout has it. Without either the picker says so rather than - // opening an empty panel. - const checkoutPr = gitStatusQuery.data?.pr?.state === "open" ? gitStatusQuery.data.pr : null; + // thread without one while the checkout has it. A linked PR is the thread's own even while + // its detail is still loading, so the checkout never stands in for it. Without either the + // picker says so rather than opening an empty panel. + const checkoutPr = + linkedThreadPullRequest === null && gitStatusQuery.data?.pr?.state === "open" + ? gitStatusQuery.data.pr + : null; const addPullRequestSurface = useCallback(() => { if (activeThreadPr !== null) { openThreadPullRequest(activeThreadPr.number);