Files
orca/src/main/ipc/github-work-item-args.ts
T
JinjingandOrca 33bd676644 fix(github): align PR source and review head origin (#10677)
* fix(github): align PR source and review head origin

* fix(github): pin number-based work item open to the repo source preference

Open-by-number and details still ran the upstream-first multi-candidate PR
probe, so a fork and its upstream sharing a PR number opened different PRs
than the list and start-point paths did once #10677 pinned those to origin.

Thread repo.issueSourcePreference through dispatchWorkItem, getWorkItemDetails,
getRepoWorkItem, and getRepoWorkItemDetails. getWorkItemByOwnerRepo is left
alone: explicit owner/repo already pins identity. auto/upstream/undefined keep
the multi-candidate probe.

Co-authored-by: Orca <help@stably.ai>

* test(github): enforce origin preference in review head origin resolution

The explicit origin preference must short-circuit before any identity probe, so no remote queries should occur. Add validation to reject unexpected remotes and tighten the test assertion to verify no remote get-url calls happen at all.

* fix(github): enforce origin preference in issue open-by-number lookup

listWorkItems and getWorkItem must share preference so origin/upstream
toggles cannot disagree. Explicit origin preference now fail-closes when
origin identity is unresolved (no bare-lookup fallback), matching the
PR candidate resolution rule.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-25 22:48:53 -07:00

55 lines
1.6 KiB
TypeScript

import type { TaskSourceContext } from '../../shared/task-source-context'
import type { IssueSourcePreference } from '../../shared/types'
export type WorkItemArgs = {
repoPath: string
repoId?: string | null
sourceContext?: TaskSourceContext | null
number: number
type?: 'issue' | 'pr'
}
type RegisteredRepoContext = {
path: string
connectionId?: string | null
issueSourcePreference?: IssueSourcePreference
}
type LocalGitExecOptions = {
wslDistro?: string
}
// Why: renderer input crosses the IPC boundary and is untrusted. Reject
// non-integer or < 1 numbers, and coerce unrecognised `type` values to
// undefined so getWorkItem falls through to its issue-then-PR probe rather
// than silently dispatching to the wrong branch.
export function dispatchWorkItem<T>(
args: WorkItemArgs,
repo: RegisteredRepoContext,
fn: (
path: string,
n: number,
t?: 'issue' | 'pr',
connectionId?: string | null,
localGitOptions?: LocalGitExecOptions,
preference?: IssueSourcePreference
) => Promise<T | null>,
localGitOptions?: LocalGitExecOptions
): Promise<T | null> | null {
const { number, type } = args
if (typeof number !== 'number' || !Number.isInteger(number) || number < 1) {
return null
}
const safeType = type === 'issue' || type === 'pr' ? type : undefined
// Why: open-by-number must pin the same source the list and start-point use,
// else a fork and its upstream sharing a PR number resolve to different PRs.
return fn(
repo.path,
number,
safeType,
repo.connectionId ?? null,
localGitOptions,
repo.issueSourcePreference
)
}