feat: link pull requests to threads - #8160
UI Consistency: No findings
All clear
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.
Reviewed the in-scope web changes (apps/web/src/**): ChatMarkdown.tsx, ChatView.tsx, Sidebar.tsx, LegacySidebar.tsx, ThreadStatusIndicators.tsx, chat/externalLinkContextMenu.ts, lib/openPullRequestLink.ts, state/pullRequests.ts and their tests.
Findings-relevant checks performed:
- No new or modified rendered controls that reconstruct
Button,Input,Select,Toggle, orMenu; the new link/unlink affordances are entries in the existing native context-menu contract (ContextMenuItem), reusingexternalLinkContextMenuItemsand the existing failure-reporting path. - No CSS, Tailwind, theme-variant, mask, or scroll/virtualization changes; no class strings overriding primitive geometry, focus rings, or hit targets were introduced.
- Sidebar PR indicators keep the existing
prStatusIndicator/resolveChangeRequestPresentationpresentation path; the synthesizedsourceControlProvideronly feeds kind-based presentation, so labels, icons, and colors are unchanged. - Verified the newly gated
vcsEnvironment.statusqueries (LegacySidebar.tsx,ThreadRowLeadingStatus) are used only for PR resolution in those rows, so disabling them for linked-PR threads removes no other visible indicator; the v2Sidebar.tsxrow still queries git status for its branch-mismatch indicator. - The failure feedback gap flagged in the previous run is now addressed:
reportFailuresurfaces link/unlink errors throughtoastManager.add(stackedThreadToast(...)), consistent with the other user-invoked failure paths inChatMarkdown.tsx.
🔍 Agent activity — 17 tool calls
💭 Checking the scoped files under apps/web/src, the changes look like logic and data flow rather than styling, with no new CSS or shared controls beyond a native context menu, so there's likely nothing to flag. The earlier concern about missing error feedback in ChatMarkdown also appears resolved now that the diff includes a toastManager.add call for failures. I want to quickly double-check the ordering of the new "Link to thread" context menu item against other menus, and confirm the toast usage in ChatMarkdown is consistent with how failures are reported elsewhere by looking at externalLinkContextMenu and the current head files.
1. browse_code — apps/web/src/components/chat/externalLinkContextMenu.ts
2. git_tools — stackedThreadToast
💭 With that resolved, I'm scanning the rest of the changed code for UI consistency issues, but most changes are logic-only. I want to double-check the toast usage in ChatMarkdown to make sure the stacked thread toast behaves correctly.
3. browse_code — apps/web/src/components/ChatMarkdown.tsx
4. browse_code — apps/web/src/components/ChatMarkdown.tsx
💭 With that finding covered, I'm scanning the rest of the diff for UI consistency issues, but most remaining changes look like state/logic rather than styling. I'm checking whether ChatView's derivation of threadRepository from the linked PR's repository could cause a mismatch wherever that repository is displayed. Now I want to verify the
useLinkedThreadPullRequesthook in ThreadStatusIndicators.tsx properly importsuseMemosince it's being used there.
5. browse_code — apps/web/src/components/ThreadStatusIndicators.tsx
💭 Now I want to check resolveChangeRequestPresentation with a provider whose kind comes from detail.provider and an empty baseUrl, to see how the presentation logic handles the provider kind type and whether an empty base URL affects the displayed host or icon.
6. browse_code — apps/web/src/sourceControlPresentation.ts
💭 I notice the synthesized provider uses the raw provider key like "github" instead of a display name like "GitHub", which could cause casing inconsistencies wherever providerName is shown in the UI, like tooltips saying "Open in github" instead of "Open in GitHub". I want to check how resolveChangeRequestPresentation and its consumers actually use this field.
7. browse_code — In packages/shared/src/sourceControl.ts, show resolveChangeRequestPresentation and getChangeRequestTerminology implementations, including how provider.name and provider.kind are used and what providerName defaults are. Also list web UI call sites that display providerName (e.g. getSourceControlPresentation(...).providerName) to the user.
💭 I'm tracing how the synthesized provider object flows downstream—checking that its kind field is sufficient for prStatusIndicator, then following how linkedPullRequestStatus propagates through ChatView into resolveDisplayedThreadPrProvider and onward to the source control presentation logic.
8. git_tools — resolveDisplayedThreadPrProvider|displayedPrProvider|getSourceControlPresentation(
9. browse_code — What is the type of the provider field on PullRequestDetail in packages/contracts (WS_METHODS.pullRequestsDetail response)? Is it SourceControlProviderKind ("github" | "gitlab" | ...)? Show the schema definition.
💭 I'm tracing where prProvider gets used after being derived as the lowercase kind—checking Sidebar.tsx around line 906 and how ChatView consumes the linkedPullRequestStatus provider field, to see whether it feeds into a status indicator or a display name.
10. browse_code — apps/web/src/components/Sidebar.tsx
💭 I'm checking whether the provider name gets used anywhere it could actually render, since only the kind matters for prStatusIndicator. I want to look at where ChatView passes linkedPullRequestStatus to see what consumes it around line 4300-4400.
11. browse_code — apps/web/src/components/ChatView.tsx
💭 I'm trying to figure out where ChatView's threadRepository field actually gets used for display, since I don't see a providerName shown anywhere. I need to check around the pullRequestSurfaceAvailable logic and search for other consumers of threadRepository.
12. git_tools — threadRepository
💭 I'm checking whether the repository/projectId plumbing in the right panel is consistent, then looking at a UI edge case: the ChatMarkdown context menu gates the "link" action on thread pull request linking capability but doesn't apply the same gate to the "unlink" action, which seems like an inconsistency worth flagging. Overall though, this diff is mostly data plumbing rather than shared UI primitives, styling, or layout, so there isn't much to raise from a UI-consistency angle beyond the error feedback point noted earlier. Actually, I do want to check one more thing: gitStatus queries appear disabled when a thread has a linked PR, which could remove other indicators like branch mismatch or dirty-state icons in the sidebar rows that depend on that same data. I should look at ThreadRowLeadingStatus more closely to see if this is a real regression.
13. browse_code — apps/web/src/components/ThreadStatusIndicators.tsx
💭 I see gitStatus is used only for the PR case there. Now checking whether SidebarThreadRow uses gitStatus.data elsewhere, like for branch mismatch or dirty state, when the query is disabled due to a linked PR—I need to look at lines 400-560 of LegacySidebar to confirm.
14. browse_code — apps/web/src/components/LegacySidebar.tsx
💭 Let me check if there are other references to gitStatus.data within the LegacySidebar's SidebarThreadRow to make sure I'm not missing anything.
15. git_tools — gitStatus
16. git_tools — gitStatus
💭 I'm checking that the v2 Sidebar still queries gitStatus for linked PRs, keeping the branch mismatch indicator intact, while the command palette and LegacySidebar disable that query since they don't need it elsewhere. Now I'm comparing how the v2 Sidebar versus LegacySidebar handle linked PR display, since the v2 version prioritizes the linked PR through resolveDisplayedThreadPr. I also want to look at how the change request presentation for linked PRs is built in the v2 Sidebar, and separately check the native context menu for external links to see if "Link to thread" is ordered consistently with other menu builders like the pull request link context menu, particularly around conventions for separators and item ordering.
17. git_tools — ContextMenuItem<
💭 I'm checking existing menu label conventions like "Copy Link" and "Open in system browser" to see if the new "Link to thread"/"Unlink from thread" labels fit stylistically—capitalization is already inconsistent elsewhere, so this isn't a real finding. Overall the diff looks like straightforward data plumbing rather than a UI issue. Tracing the error path confirms the thrown "pull request not available" error correctly propagates to reportFailure and surfaces as a toast, and the silent-return unlink case for mismatched PRs seems fine too. I'm also checking the new atom family export in pullRequests.ts and whether exporting useLinkedThreadPullRequest from a component file rather than a state module breaks any conventions—doesn't seem like a real issue, just consistent with how the module is already organized. The one perf note is that each sidebar row with a linked PR triggers its own 30s polling query, but since the atom family dedupes by key, this isn't a genuine finding. Given the conflict between the instruction to output exactly "All clear" and the requirement to return structured JSON, I'll follow the JSON schema but set the summary text to "All clear" with a success state since there are no real findings.
Agent Credits: 383 credits