Skip to content

fix(host-service): stop misattributing cross-fork PRs to local workspaces#3625

Merged
Kitenite merged 3 commits into
mainfrom
pr-3261-detection-in-v1-sidebar
Apr 22, 2026
Merged

fix(host-service): stop misattributing cross-fork PRs to local workspaces#3625
Kitenite merged 3 commits into
mainfrom
pr-3261-detection-in-v1-sidebar

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Apr 21, 2026

Summary

Two workspace → PR match sites keyed on branch name alone, so any cross-fork PR whose headRefName collided with a local branch got attached. Example in the wild: PR #3261 (quueli/superset-windows:mainsuperset-sh/superset:main) showing up on every local main workspace.

Fixes:

  • apps/desktop/.../pr-resolution.ts (v1 sidebar usePRStatus / workspaces.getGitHubStatus): prMatchesLocalBranch now rejects PRs with isCrossRepository === true when the local branch has no fork-owner prefix. One-line gate; isCrossRepository was already fetched and typed, just never consulted.
  • packages/host-service/.../pull-requests.ts (_dashboard sidebar pullRequests.getByWorkspaces and v2 workspace review tab git.getPullRequest): matcher now keys on (headRepositoryOwner, headRepository, headRefName) tuples instead of branch strings. Adds upstreamOwner/upstreamRepo columns to the host-service workspaces table, populated during syncWorkspaceBranches by resolving the tracking remote using the same config fallback order as gh (branch.<n>.pushRemoteremote.pushDefaultbranch.<n>.remote). GraphQL query extended with isCrossRepository, headRepositoryOwner { login }, headRepository { name }.

Migration 0003_workspace_upstream_ref lives in packages/host-service/drizzle/ — local SQLite only, no Neon impact. Replaces the now-unused workspaces_branch_idx with composite workspaces_upstream_ref_idx on (upstream_owner, upstream_repo, branch). Auto-applies on next host-service start; existing workspaces get null upstream and self-heal within one 30s sync cycle.

Full design in plans/20260421-pr-detection-matcher-fix.md.

Test plan

  • Restart dev desktop (host-service child process needs to reload). Confirm v1 sidebar no longer shows PR Port desktop build and CI for Windows with release artifacts #3261 on main.
  • Same for v2 workspace detail Review tab.
  • Contributor-from-fork workflow: workspace tracking a fork remote still resolves its own PR correctly.
  • Workspace with no upstream (fresh branch, never pushed): no PR attached (expected).
  • Two workspaces on the same branch name but different tracking remotes: each resolves its own PR.

Summary by cubic

Stops cross‑fork PRs from attaching to unrelated workspaces. We now match on upstream owner/repo + tracked branch, and the v1 sidebar ignores cross‑repo PRs when the local branch has no owner prefix.

  • Bug Fixes

    • apps/desktop v1 sidebar: prMatchesLocalBranch rejects isCrossRepository when the local branch lacks a fork‑owner prefix.
    • packages/host-service: match on ${owner}/${repo}#${branch} from the tracked upstream; resolve via @{push} first, then require branch.<name>.merge and fall back to branch.<name>.pushRemoteremote.pushDefaultbranch.<name>.remote. Store upstreamOwner, upstreamRepo, upstreamBranch; lowercase owner/repo; GitHub query adds isCrossRepository, headRepositoryOwner.login, headRepository.name.
  • Migration

    • Adds upstream_owner, upstream_repo, upstream_branch and replaces the branch index with composite (upstream_owner, upstream_repo, upstream_branch) via 0003_workspace_upstream_ref (auto‑applies on host‑service start). Existing workspaces backfill on next sync; restart desktop in dev to reload the host‑service.

Written for commit 14587af. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented incorrect PR-to-workspace matches when branch names collide across forks, improving cross-repository PR attribution.
  • New Features

    • Workspaces now persist upstream owner/repo/branch so syncs and PR lookups use owner/repo#branch keys.
    • PR queries include cross-repository metadata for more accurate matching.
  • Documentation

    • Added plan documenting the PR-to-workspace matching fix and verification steps.
  • Tests

    • Updated tests to account for nullable upstream fields during branch sync.
  • Chores

    • Added a database migration and schema snapshot to support upstream fields.

Related

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds upstream owner/repo/branch tracking to workspaces, updates host-service PR query/types to include cross-repo and head repo owner/name, changes host-service sync and PR matching to use owner/repo#branch keys, and adjusts desktop PR-resolution signature/logic to account for cross-repository PRs.

Changes

Cohort / File(s) Summary
Database Schema & Migrations
packages/host-service/drizzle/0003_workspace_upstream_ref.sql, packages/host-service/drizzle/meta/0003_snapshot.json, packages/host-service/drizzle/meta/_journal.json, packages/host-service/src/db/schema.ts
Add nullable upstream_owner/upstream_repo/upstream_branch to workspaces; remove branch-only index; add composite workspaces_upstream_ref_idx; include migration SQL, Drizzle snapshot, and journal entry.
Host-Service: PR Matching & Upstream Resolution
packages/host-service/src/runtime/pull-requests/pull-requests.ts, packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts, packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts
Resolve tracked upstream (push/tracking remote) into upstreamOwner/upstreamRepo/upstreamBranch and persist to workspaces; treat workspace unchanged only if branch, headSha, and upstream fields match; compute wantedKeys as owner/repo#branch; update fetchRepoPullRequests to accept wantedKeys, filter & dedupe PRs, and return map keyed by owner/repo#branch; extend GraphQL query/types with isCrossRepository, headRepositoryOwner.login, headRepository.name.
Desktop PR Resolution
apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts
Update prMatchesLocalBranch signature to require isCrossRepository; when fork-owner prefix cannot be derived (getForkOwnerPrefix(...) returns null) do not match cross-repository PRs (return false), preserve branch-name equality fallback for non-cross-repo PRs.
Tests & Documentation
packages/host-service/test/pull-requests.test.ts, plans/20260421-pr-detection-matcher-fix.md
Update test expectation to include upstreamOwner/upstreamRepo/upstreamBranch nulls for unborn branches; add plan doc describing matcher fix, upstream resolution, verification scenarios, and v1-only note.

Sequence Diagram

sequenceDiagram
    participant Desktop as Desktop
    participant HostService as HostService
    participant Git as Git
    participant GitHub as GitHub
    participant DB as DB

    Desktop->>HostService: syncWorkspaceBranches(localBranch)
    HostService->>Git: resolveBranchUpstream(localBranch)\n(use @{push} + fallbacks -> remote/merge)
    Git-->>HostService: upstreamOwner/upstreamRepo/upstreamBranch
    HostService->>DB: UPDATE workspaces SET upstreamOwner, upstreamRepo, upstreamBranch, headSha, branch

    HostService->>HostService: build wantedKeys = Set{owner/repo#branch}
    HostService->>GitHub: PULL_REQUESTS_QUERY(wantedKeys)\n(include isCrossRepository, headRepositoryOwner, headRepository.name)
    GitHub-->>HostService: PR nodes with head metadata

    HostService->>HostService: fetchRepoPullRequests(wantedKeys)\nfilter & dedupe → map by owner/repo#branch
    HostService->>DB: match workspaces by upstream ref and persist PR links
    HostService-->>Desktop: return matched PRs keyed by owner/repo#branch
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I sniffed the remotes, found owners and names,

Tied branches to repos, avoided forked shames.
Now PRs find their homes, no more cross-fork crime,
I hopped, I matched, and saved branch-matching time.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main fix: preventing cross-fork PRs from being misattributed to local workspaces, which is the core objective of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description is comprehensive and well-structured, covering the bug, fixes across both v1 and v2, migration details, and a detailed test plan.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr-3261-detection-in-v1-sidebar

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 21, 2026

Greptile encountered an error while reviewing this PR. Please reach out to support@greptile.com for assistance.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/host-service/src/runtime/pull-requests/pull-requests.ts (1)

164-176: ⚠️ Potential issue | 🟡 Minor

Startup race clears PR associations for pre-existing workspaces until next sync.

start() fires syncWorkspaceBranches() and refreshEligibleProjects(true) concurrently without awaiting. After this migration, existing rows have upstreamOwner/upstreamRepo = null, so if refreshEligibleProjects runs first, performProjectRefresh produces an empty wantedKeys and unconditionally sets pullRequestId = null for every workspace at Line 391‑395. PRs then re-attach on the next 30s sync cycle, but users will see PR badges briefly disappear on every host-service restart until the backfill is complete.

Consider awaiting the first syncWorkspaceBranches() before kicking off the initial refresh, or in performProjectRefresh skip the set({ pullRequestId: null }) write when the workspace has no upstream key yet and already has a non-null pullRequestId (preserve last-known until we have data to dispute it).

🛠️ Suggested startup ordering
-		void this.syncWorkspaceBranches();
-		void this.refreshEligibleProjects(true);
+		void (async () => {
+			await this.syncWorkspaceBranches();
+			await this.refreshEligibleProjects(true);
+		})();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/host-service/src/runtime/pull-requests/pull-requests.ts` around
lines 164 - 176, start() races initial sync and refresh causing
performProjectRefresh to clear pullRequestId for workspaces that haven't yet
been backfilled; fix by awaiting the initial syncWorkspaceBranches() before
calling refreshEligibleProjects(true) (i.e., call await
this.syncWorkspaceBranches() then kick off this.refreshEligibleProjects(true)),
or alternatively modify performProjectRefresh so that when a workspace has no
upstream key (wantedKeys empty) it does not call set({ pullRequestId: null }) if
the existing workspace.pullRequestId is non-null (preserve last-known PR until
upstreamOwner/upstreamRepo are available).
apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts (1)

107-121: ⚠️ Potential issue | 🔴 Critical

Missing isCrossRepository in shouldAcceptPRMatch's pr Pick — reintroduces cross-repository misattribution bug.

prMatchesLocalBranch requires isCrossRepository in its pr parameter (line 85), but shouldAcceptPRMatch types its pr argument as Pick<GHPRResponse, "headRefName" | "headRefOid" | "headRepositoryOwner" | "state"> without it. At line 119, this narrower object is passed to prMatchesLocalBranch. Since isCrossRepository is optional in the schema, TypeScript won't error, but at runtime when the field is missing, it becomes undefined. The guard at line 96 (if (pr.isCrossRepository) return false;) then fails silently, and the exact misattribution defect warned about in lines 94–95 leaks back in for any cross-repository PR.

🔧 Proposed fix
 	pr: Pick<
 		GHPRResponse,
-		"headRefName" | "headRefOid" | "headRepositoryOwner" | "state"
+		"headRefName" | "headRefOid" | "headRepositoryOwner" | "state" | "isCrossRepository"
 	>;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts`
around lines 107 - 121, The PR object passed into shouldAcceptPRMatch is missing
the isCrossRepository field, causing prMatchesLocalBranch's guard (the
pr.isCrossRepository check inside prMatchesLocalBranch) to receive undefined and
allow cross-repo PRs to be misattributed; update the pr parameter type in
shouldAcceptPRMatch (the Pick<GHPRResponse, ...>) to include "isCrossRepository"
so the runtime value is present, and ensure any callers that construct the pr
argument populate that field before calling
shouldAcceptPRMatch/prMatchesLocalBranch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts`:
- Around line 107-121: The PR object passed into shouldAcceptPRMatch is missing
the isCrossRepository field, causing prMatchesLocalBranch's guard (the
pr.isCrossRepository check inside prMatchesLocalBranch) to receive undefined and
allow cross-repo PRs to be misattributed; update the pr parameter type in
shouldAcceptPRMatch (the Pick<GHPRResponse, ...>) to include "isCrossRepository"
so the runtime value is present, and ensure any callers that construct the pr
argument populate that field before calling
shouldAcceptPRMatch/prMatchesLocalBranch.

In `@packages/host-service/src/runtime/pull-requests/pull-requests.ts`:
- Around line 164-176: start() races initial sync and refresh causing
performProjectRefresh to clear pullRequestId for workspaces that haven't yet
been backfilled; fix by awaiting the initial syncWorkspaceBranches() before
calling refreshEligibleProjects(true) (i.e., call await
this.syncWorkspaceBranches() then kick off this.refreshEligibleProjects(true)),
or alternatively modify performProjectRefresh so that when a workspace has no
upstream key (wantedKeys empty) it does not call set({ pullRequestId: null }) if
the existing workspace.pullRequestId is non-null (preserve last-known PR until
upstreamOwner/upstreamRepo are available).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e3abb71-3fc4-4836-8ff6-d846f9e3c5e8

📥 Commits

Reviewing files that changed from the base of the PR and between 0358690 and 2048a1c.

📒 Files selected for processing (10)
  • apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts
  • packages/host-service/drizzle/0003_workspace_upstream_ref.sql
  • packages/host-service/drizzle/meta/0003_snapshot.json
  • packages/host-service/drizzle/meta/_journal.json
  • packages/host-service/src/db/schema.ts
  • packages/host-service/src/runtime/pull-requests/pull-requests.ts
  • packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts
  • packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts
  • packages/host-service/test/pull-requests.test.ts
  • plans/20260421-pr-detection-matcher-fix.md

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/host-service/src/runtime/pull-requests/pull-requests.ts">

<violation number="1" location="packages/host-service/src/runtime/pull-requests/pull-requests.ts:476">
P2: PR matching uses case-sensitive owner/repo key comparison, which can miss valid matches when remote URL casing differs from GitHub API casing.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread packages/host-service/src/runtime/pull-requests/pull-requests.ts Outdated
…aces

Two match sites keyed on branch name alone, so any cross-fork PR whose
`headRefName` collided with a local branch got attached — e.g. PR #3261
(`quueli/superset-windows:main` → `superset-sh/superset:main`) latched
onto every local `main` workspace in the sidebar.

- `pr-resolution.ts` (v1 `usePRStatus` via `workspaces.getGitHubStatus`):
  reject `isCrossRepository` when the local branch has no fork-owner
  prefix. Added a v1-sunset marker — don't evolve this module.
- `pull-requests.ts` (`_dashboard` sidebar + v2 review tab via
  `pullRequests.getByWorkspaces` / `git.getPullRequest`): key the match
  on a `(upstreamOwner, upstreamRepo, upstreamBranch)` tuple. Adds
  those three columns to the host-service `workspaces` table,
  populated in `syncWorkspaceBranches` by resolving `@{push}` first
  and falling back to the same config chain `gh` uses. Tuple key
  lowercases owner/repo (GitHub is case-insensitive there) but
  preserves branch casing. `upstreamBranch` is separate from local
  `branch` so `gh pr checkout`-style renames (`main` → `quueli-main`)
  still match the PR's `headRefName`.

Query extended with `isCrossRepository`, `headRepositoryOwner`,
`headRepository`. Local SQLite migration `0003_workspace_upstream_ref`
auto-applies on next host-service start; workspaces self-heal within
one 30s sync cycle.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/host-service/src/runtime/pull-requests/pull-requests.ts`:
- Around line 84-126: In resolveWorkspaceUpstream, ensure a tracked remote
branch exists before returning an upstream: after computing mergeRef via
tryConfig(`branch.${localBranch}.merge`), if mergeRef is falsy then return null
(instead of falling back to localBranch); only compute branch =
mergeRef.replace(/^refs\/heads\//, "") and return the { owner, name, branch }
when mergeRef exists so fresh local branches with no upstream won't be
associated with an upstream PR.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e14bc0c-ea59-4e07-80f9-5cf7a4a05b2d

📥 Commits

Reviewing files that changed from the base of the PR and between 2048a1c and aff1763.

📒 Files selected for processing (10)
  • apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts
  • packages/host-service/drizzle/0003_workspace_upstream_ref.sql
  • packages/host-service/drizzle/meta/0003_snapshot.json
  • packages/host-service/drizzle/meta/_journal.json
  • packages/host-service/src/db/schema.ts
  • packages/host-service/src/runtime/pull-requests/pull-requests.ts
  • packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts
  • packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts
  • packages/host-service/test/pull-requests.test.ts
  • plans/20260421-pr-detection-matcher-fix.md
✅ Files skipped from review due to trivial changes (5)
  • packages/host-service/drizzle/0003_workspace_upstream_ref.sql
  • packages/host-service/drizzle/meta/_journal.json
  • packages/host-service/src/runtime/pull-requests/utils/github-query/query.ts
  • packages/host-service/src/runtime/pull-requests/utils/github-query/types.ts
  • plans/20260421-pr-detection-matcher-fix.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/host-service/test/pull-requests.test.ts
  • packages/host-service/src/db/schema.ts
  • packages/host-service/drizzle/meta/0003_snapshot.json
  • apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts

Comment thread packages/host-service/src/runtime/pull-requests/pull-requests.ts Outdated
Kitenite added a commit that referenced this pull request Apr 22, 2026
Without an explicit merge ref, a repo-wide `remote.pushDefault` would
let an untracked local branch attach to any PR on that remote whose
headRefName happens to match. That's the same branch-name-collision
bug this PR was introduced to prevent — just via a different route.

Reported by coderabbitai on #3625.
Without an explicit merge ref, a repo-wide `remote.pushDefault` would
let an untracked local branch attach to any PR on that remote whose
headRefName happens to match. That's the same branch-name-collision
bug this PR was introduced to prevent — just via a different route.

Reported by coderabbitai on #3625.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/host-service/src/runtime/pull-requests/pull-requests.ts (1)

415-437: Extract the upstream key builder; drop the dead ?? workspace.branch fallback.

The (upstreamOwner, upstreamRepo, upstreamBranch ?? branch) construction is duplicated between the wantedKeys build (Lines 417-421) and the per-workspace match (Lines 432-436). Additionally, resolveWorkspaceUpstream always returns all three fields or null, so by construction upstreamBranch is non-null whenever upstreamOwner/upstreamRepo are set — meaning the ?? workspace.branch fallback is dead today and, if a future code path ever persisted a partial upstream tuple, it would silently misattribute PRs to the local branch name (re-opening the very collision this PR fixes). Safer to key strictly on the persisted upstreamBranch.

♻️ Proposed refactor
+	private workspaceUpstreamKey(workspace: {
+		upstreamOwner: string | null;
+		upstreamRepo: string | null;
+		upstreamBranch: string | null;
+	}): string | null {
+		if (!workspace.upstreamBranch) return null;
+		return upstreamKey(
+			workspace.upstreamOwner,
+			workspace.upstreamRepo,
+			workspace.upstreamBranch,
+		);
+	}
+
 	private async performProjectRefresh(projectId: string): Promise<void> {
@@
 		const wantedKeys = new Set<string>();
 		for (const workspace of projectWorkspaces) {
-			const key = upstreamKey(
-				workspace.upstreamOwner,
-				workspace.upstreamRepo,
-				workspace.upstreamBranch ?? workspace.branch,
-			);
+			const key = this.workspaceUpstreamKey(workspace);
 			if (key) wantedKeys.add(key);
 		}
@@
 		for (const workspace of projectWorkspaces) {
-			const key = upstreamKey(
-				workspace.upstreamOwner,
-				workspace.upstreamRepo,
-				workspace.upstreamBranch ?? workspace.branch,
-			);
+			const key = this.workspaceUpstreamKey(workspace);
 			const match = key ? keyToPullRequest.get(key) : undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/host-service/src/runtime/pull-requests/pull-requests.ts` around
lines 415 - 437, Extract and centralize the upstream key construction into a
single helper call (use the existing upstreamKey function) and remove the dead
fallback "?? workspace.branch" so the key is built strictly from
workspace.upstreamOwner, workspace.upstreamRepo, and workspace.upstreamBranch;
update both the wantedKeys population and the per-workspace matching to call the
same helper (referencing projectWorkspaces and upstreamKey) so the logic is not
duplicated and no longer falls back to workspace.branch before calling
fetchRepoPullRequests and when resolving the match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/host-service/src/runtime/pull-requests/pull-requests.ts`:
- Around line 415-437: Extract and centralize the upstream key construction into
a single helper call (use the existing upstreamKey function) and remove the dead
fallback "?? workspace.branch" so the key is built strictly from
workspace.upstreamOwner, workspace.upstreamRepo, and workspace.upstreamBranch;
update both the wantedKeys population and the per-workspace matching to call the
same helper (referencing projectWorkspaces and upstreamKey) so the logic is not
duplicated and no longer falls back to workspace.branch before calling
fetchRepoPullRequests and when resolving the match.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bd59753e-2bfd-4ff5-88fb-7716b66d9b8f

📥 Commits

Reviewing files that changed from the base of the PR and between 8c82d26 and 6811f74.

📒 Files selected for processing (1)
  • packages/host-service/src/runtime/pull-requests/pull-requests.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plans/20260421-pr-detection-matcher-fix.md (1)

34-34: Replace internal “memory” reference with a durable source.

Line 34’s project_v1_sunset memory reference is hard to validate later. Prefer a concrete doc/issue/ADR link for traceability.

✏️ Proposed wording
-- **Consolidate v1 and v2 into one path** — deferred. v1 dies with the v1 UI sunset (see `project_v1_sunset` memory). No port needed.
+- **Consolidate v1 and v2 into one path** — deferred. v1 is planned to be removed with the v1 UI sunset (link the tracking issue/ADR here). No port needed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/20260421-pr-detection-matcher-fix.md` at line 34, The note referencing
the ephemeral internal memory key project_v1_sunset should be replaced with a
durable, verifiable reference: update the sentence that reads "see
`project_v1_sunset` memory" to point to a concrete artifact (a design doc, ADR,
or issue/PR URL or ID) that records the v1 UI sunset decision and timeline;
ensure the replacement uses the full link or canonical identifier and, if
appropriate, add a brief parenthetical summary (one line) so readers know what
the linked artifact contains while keeping traceability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plans/20260421-pr-detection-matcher-fix.md`:
- Line 3: Replace the inaccurate phrase "Shipped in PR `#3625`." with wording that
reflects the PR is still open (e.g., "Proposed/implemented in PR `#3625`") so the
document does not imply the change is released; update the exact sentence in the
plans file that currently reads "Shipped in PR `#3625`." to "Proposed/implemented
in PR `#3625`" (or similar) to accurately convey status.

---

Nitpick comments:
In `@plans/20260421-pr-detection-matcher-fix.md`:
- Line 34: The note referencing the ephemeral internal memory key
project_v1_sunset should be replaced with a durable, verifiable reference:
update the sentence that reads "see `project_v1_sunset` memory" to point to a
concrete artifact (a design doc, ADR, or issue/PR URL or ID) that records the v1
UI sunset decision and timeline; ensure the replacement uses the full link or
canonical identifier and, if appropriate, add a brief parenthetical summary (one
line) so readers know what the linked artifact contains while keeping
traceability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8866855c-5524-4c65-ad6e-2f5411f1028a

📥 Commits

Reviewing files that changed from the base of the PR and between 6811f74 and 14587af.

📒 Files selected for processing (1)
  • plans/20260421-pr-detection-matcher-fix.md

@@ -0,0 +1,52 @@
# Fix PR → workspace matcher (cross-fork collision)

Shipped in PR #3625.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use “proposed/implemented in PR #3625” instead of “shipped.”

Line 3 is currently inaccurate while PR #3625 is still open, and this can confuse future readers about release state.

✏️ Proposed wording
-Shipped in PR `#3625`.
+Proposed in PR `#3625` (implemented, pending merge).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Shipped in PR #3625.
Proposed in PR `#3625` (implemented, pending merge).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plans/20260421-pr-detection-matcher-fix.md` at line 3, Replace the inaccurate
phrase "Shipped in PR `#3625`." with wording that reflects the PR is still open
(e.g., "Proposed/implemented in PR `#3625`") so the document does not imply the
change is released; update the exact sentence in the plans file that currently
reads "Shipped in PR `#3625`." to "Proposed/implemented in PR `#3625`" (or similar)
to accurately convey status.

@Kitenite Kitenite merged commit 6ae8ea9 into main Apr 22, 2026
13 checks passed
@Kitenite Kitenite deleted the pr-3261-detection-in-v1-sidebar branch May 6, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant