diff --git a/apps/web/src/components/cloud-agent-next/PrHoverCardContent.tsx b/apps/web/src/components/cloud-agent-next/PrHoverCardContent.tsx index 2afdbe9c37f..b890ec47858 100644 --- a/apps/web/src/components/cloud-agent-next/PrHoverCardContent.tsx +++ b/apps/web/src/components/cloud-agent-next/PrHoverCardContent.tsx @@ -58,6 +58,12 @@ export function PrHoverCardContent({ pr, sessionId, gitBranch }: PrHoverCardCont const trpc = useTRPC(); const queryClient = useQueryClient(); const state = normalizePrBadgeState(pr.state); + // A verified link whose per-PR cache row has not synced yet renders with + // state `unknown` and no title. The Refresh action must stay reachable for + // it, or a missed webhook leaves the session's own PR stuck without live + // state. (An unverified link never reaches this component: the server shows + // no PR for it.) + const awaitingSync = pr.state === 'unknown'; const headShaShort = pr.headSha?.slice(0, 7) ?? null; const truncatedTitle = truncatePrTitle(pr.title, 80); @@ -85,6 +91,12 @@ export function PrHoverCardContent({ pr, sessionId, gitBranch }: PrHoverCardCont PR #{pr.number} + {awaitingSync && ( +

+ Pull request status has not synced yet. Refresh to fetch the latest status from GitHub. +

+ )} + {truncatedTitle && (

{truncatedTitle}

)} @@ -115,7 +127,7 @@ export function PrHoverCardContent({ pr, sessionId, gitBranch }: PrHoverCardCont
- {!isWithinRefreshThrottle(pr.lastSyncedAt) && ( + {(awaitingSync || !isWithinRefreshThrottle(pr.lastSyncedAt)) && (