From e67ddde7c8f7c8ad82a1e38068784e654275c7bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:25:04 +0000 Subject: [PATCH 1/6] Initial plan From 80bf8c789db452c184280e6a2a9335217b09863c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:33:04 +0000 Subject: [PATCH 2/6] Prioritize exact PR number matches Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/commands.ts | 7 ++----- src/github/pullRequestQuickPick.ts | 15 +++++++++++++++ src/test/github/quickPicks.test.ts | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 src/github/pullRequestQuickPick.ts create mode 100644 src/test/github/quickPicks.test.ts diff --git a/src/commands.ts b/src/commands.ts index 79f4303e59..c620cd6115 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -30,6 +30,7 @@ import { IssueOverviewPanel } from './github/issueOverview'; import { GHPRComment, GHPRCommentThread, TemporaryComment } from './github/prComment'; import { PullRequestModel } from './github/pullRequestModel'; import { PullRequestOverviewPanel } from './github/pullRequestOverview'; +import { getPullRequestQuickPickItem } from './github/pullRequestQuickPick'; import { chooseItem } from './github/quickPicks'; import { RepositoriesManager } from './github/repositoriesManager'; import { codespacesPrLink, getIssuesUrl, getPullsUrl, isInCodespaces, ISSUE_OR_URL_EXPRESSION, parseIssueExpressionOutput, vscodeDevPrLink } from './github/utils'; @@ -1994,11 +1995,7 @@ ${contents} } // Sort PRs by number in descending order (most recent first) const sortedPRs = prs.sort((a, b) => b.number - a.number); - const prItems: (vscode.QuickPickItem & { prNumber: number })[] = sortedPRs.map(pr => ({ - label: `#${pr.number} ${pr.title}`, - description: `by @${pr.author.login}`, - prNumber: pr.number - })); + const prItems = sortedPRs.map(getPullRequestQuickPickItem); quickPick.items = prItems; const selected = await selectedPromise; diff --git a/src/github/pullRequestQuickPick.ts b/src/github/pullRequestQuickPick.ts new file mode 100644 index 0000000000..2966d5b1ff --- /dev/null +++ b/src/github/pullRequestQuickPick.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type * as vscode from 'vscode'; +import type { PullRequestNumberData } from './graphql'; + +export function getPullRequestQuickPickItem(pr: PullRequestNumberData): vscode.QuickPickItem & { prNumber: number } { + return { + label: `#${pr.number}`, + description: `${pr.title} by @${pr.author.login}`, + prNumber: pr.number, + }; +} diff --git a/src/test/github/quickPicks.test.ts b/src/test/github/quickPicks.test.ts new file mode 100644 index 0000000000..beb491e41a --- /dev/null +++ b/src/test/github/quickPicks.test.ts @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { default as assert } from 'assert'; +import { getPullRequestQuickPickItem } from '../../github/pullRequestQuickPick'; + +describe('QuickPicks', () => { + it('separates pull request numbers from titles to prioritize exact number matches', () => { + const item = getPullRequestQuickPickItem({ + number: 10063, + title: 'upgrade library to v5', + author: { login: 'octocat' }, + }); + + assert.deepStrictEqual(item, { + label: '#10063', + description: 'upgrade library to v5 by @octocat', + prNumber: 10063, + }); + }); +}); From 29f800ead419f2b164a63c81858d498fb9cc3b1a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:03:22 +0000 Subject: [PATCH 3/6] Keep checkout picker changes in existing files Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/commands.ts | 10 +++++++++- src/github/pullRequestQuickPick.ts | 15 --------------- src/test/extension.test.ts | 22 ++++++++++++++++++++++ src/test/github/quickPicks.test.ts | 23 ----------------------- 4 files changed, 31 insertions(+), 39 deletions(-) delete mode 100644 src/github/pullRequestQuickPick.ts delete mode 100644 src/test/github/quickPicks.test.ts diff --git a/src/commands.ts b/src/commands.ts index c620cd6115..bf86bd49c6 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -24,13 +24,13 @@ import { CopilotRemoteAgentManager, SessionIdForPr } from './github/copilotRemot import { guessExtensionFromMime, pickFilesForUpload, placeholdersForNames, runFileUploads, runPendingUploads } from './github/fileUpload'; import { FolderRepositoryManager } from './github/folderRepositoryManager'; import { GitHubRepository } from './github/githubRepository'; +import type { PullRequestNumberData } from './github/graphql'; import { Issue } from './github/interface'; import { IssueModel } from './github/issueModel'; import { IssueOverviewPanel } from './github/issueOverview'; import { GHPRComment, GHPRCommentThread, TemporaryComment } from './github/prComment'; import { PullRequestModel } from './github/pullRequestModel'; import { PullRequestOverviewPanel } from './github/pullRequestOverview'; -import { getPullRequestQuickPickItem } from './github/pullRequestQuickPick'; import { chooseItem } from './github/quickPicks'; import { RepositoriesManager } from './github/repositoriesManager'; import { codespacesPrLink, getIssuesUrl, getPullsUrl, isInCodespaces, ISSUE_OR_URL_EXPRESSION, parseIssueExpressionOutput, vscodeDevPrLink } from './github/utils'; @@ -130,6 +130,14 @@ export async function closeAllPrAndReviewEditors() { } } +export function getPullRequestQuickPickItem(pr: PullRequestNumberData): vscode.QuickPickItem & { prNumber: number } { + return { + label: `#${pr.number}`, + description: `${pr.title} by @${pr.author.login}`, + prNumber: pr.number, + }; +} + function isCrossChatSessionWithPR(value: any): value is CrossChatSessionWithPR { const asCrossChatSessionWithPR = value as Partial; return !!asCrossChatSessionWithPR.pullRequestDetails; diff --git a/src/github/pullRequestQuickPick.ts b/src/github/pullRequestQuickPick.ts deleted file mode 100644 index 2966d5b1ff..0000000000 --- a/src/github/pullRequestQuickPick.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import type * as vscode from 'vscode'; -import type { PullRequestNumberData } from './graphql'; - -export function getPullRequestQuickPickItem(pr: PullRequestNumberData): vscode.QuickPickItem & { prNumber: number } { - return { - label: `#${pr.number}`, - description: `${pr.title} by @${pr.author.login}`, - prNumber: pr.number, - }; -} diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 3038c33295..5545bd89b1 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,7 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + import { default as assert } from 'assert'; import { parseDiffHunk } from '../common/diffHunk'; +import { getPullRequestQuickPickItem } from '../commands'; describe('Extension Tests', function () { + describe('getPullRequestQuickPickItem', () => { + it('separates pull request numbers from titles to prioritize exact number matches', () => { + const item = getPullRequestQuickPickItem({ + number: 10063, + title: 'upgrade library to v5', + author: { login: 'octocat' }, + }); + + assert.deepStrictEqual(item, { + label: '#10063', + description: 'upgrade library to v5 by @octocat', + prNumber: 10063, + }); + }); + }); + describe('parseDiffHunk', () => { it('should handle empty string', () => { const diffHunk = parseDiffHunk(''); diff --git a/src/test/github/quickPicks.test.ts b/src/test/github/quickPicks.test.ts deleted file mode 100644 index beb491e41a..0000000000 --- a/src/test/github/quickPicks.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { default as assert } from 'assert'; -import { getPullRequestQuickPickItem } from '../../github/pullRequestQuickPick'; - -describe('QuickPicks', () => { - it('separates pull request numbers from titles to prioritize exact number matches', () => { - const item = getPullRequestQuickPickItem({ - number: 10063, - title: 'upgrade library to v5', - author: { login: 'octocat' }, - }); - - assert.deepStrictEqual(item, { - label: '#10063', - description: 'upgrade library to v5 by @octocat', - prNumber: 10063, - }); - }); -}); From 25bc92238008087e44f83f5b7644cdc8b4bd7b34 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 11 Aug 2026 14:49:31 +0000 Subject: [PATCH 4/6] Preserve checkout picker labels Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/commands.ts | 33 +++++++++++++++++++++++++-------- src/test/extension.test.ts | 30 +++++++++++++++++------------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index bf86bd49c6..b6ceb913bd 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -24,7 +24,6 @@ import { CopilotRemoteAgentManager, SessionIdForPr } from './github/copilotRemot import { guessExtensionFromMime, pickFilesForUpload, placeholdersForNames, runFileUploads, runPendingUploads } from './github/fileUpload'; import { FolderRepositoryManager } from './github/folderRepositoryManager'; import { GitHubRepository } from './github/githubRepository'; -import type { PullRequestNumberData } from './github/graphql'; import { Issue } from './github/interface'; import { IssueModel } from './github/issueModel'; import { IssueOverviewPanel } from './github/issueOverview'; @@ -130,12 +129,16 @@ export async function closeAllPrAndReviewEditors() { } } -export function getPullRequestQuickPickItem(pr: PullRequestNumberData): vscode.QuickPickItem & { prNumber: number } { - return { - label: `#${pr.number}`, - description: `${pr.title} by @${pr.author.login}`, - prNumber: pr.number, - }; +type PullRequestQuickPickItem = vscode.QuickPickItem & { prNumber: number }; + +export function findExactPullRequestNumberMatch(value: string, items: readonly PullRequestQuickPickItem[]): PullRequestQuickPickItem | undefined { + const numberMatch = /^#?(\d+)$/.exec(value); + if (!numberMatch) { + return undefined; + } + + const prNumber = Number(numberMatch[1]); + return items.find(item => item.prNumber === prNumber); } function isCrossChatSessionWithPR(value: any): value is CrossChatSessionWithPR { @@ -1977,6 +1980,7 @@ ${contents} let acceptDisposable: vscode.Disposable | undefined; let hideDisposable: vscode.Disposable | undefined; + let valueChangeDisposable: vscode.Disposable | undefined; try { const selectedPromise = new Promise<{ selectedItem: (vscode.QuickPickItem & { prNumber?: number }) | undefined, selectedString: string | undefined }>((resolve) => { @@ -2003,9 +2007,21 @@ ${contents} } // Sort PRs by number in descending order (most recent first) const sortedPRs = prs.sort((a, b) => b.number - a.number); - const prItems = sortedPRs.map(getPullRequestQuickPickItem); + const prItems: PullRequestQuickPickItem[] = sortedPRs.map(pr => ({ + label: `#${pr.number} ${pr.title}`, + description: `by @${pr.author.login}`, + prNumber: pr.number + })); quickPick.items = prItems; + const prioritizeExactNumberMatch = (value: string) => { + const exactNumberMatch = findExactPullRequestNumberMatch(value, prItems); + if (exactNumberMatch) { + quickPick.activeItems = [exactNumberMatch]; + } + }; + valueChangeDisposable = quickPick.onDidChangeValue(prioritizeExactNumberMatch); + prioritizeExactNumberMatch(quickPick.value); const selected = await selectedPromise; quickPick.busy = true; @@ -2049,6 +2065,7 @@ ${contents} // Clean up event listeners and QuickPick acceptDisposable?.dispose(); hideDisposable?.dispose(); + valueChangeDisposable?.dispose(); quickPick.hide(); quickPick.dispose(); } diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 5545bd89b1..480a9bb5cd 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -5,22 +5,26 @@ import { default as assert } from 'assert'; import { parseDiffHunk } from '../common/diffHunk'; -import { getPullRequestQuickPickItem } from '../commands'; +import { findExactPullRequestNumberMatch } from '../commands'; describe('Extension Tests', function () { - describe('getPullRequestQuickPickItem', () => { - it('separates pull request numbers from titles to prioritize exact number matches', () => { - const item = getPullRequestQuickPickItem({ - number: 10063, - title: 'upgrade library to v5', - author: { login: 'octocat' }, - }); + describe('findExactPullRequestNumberMatch', () => { + it('prioritizes an exact number over a title match without changing the label', () => { + const items = [ + { + label: '#10064 Follow up on #10063', + description: 'by @octocat', + prNumber: 10064, + }, + { + label: '#10063 Upgrade library to v5', + description: 'by @hubot', + prNumber: 10063, + }, + ]; - assert.deepStrictEqual(item, { - label: '#10063', - description: 'upgrade library to v5 by @octocat', - prNumber: 10063, - }); + assert.strictEqual(findExactPullRequestNumberMatch('10063', items), items[1]); + assert.strictEqual(items[1].label, '#10063 Upgrade library to v5'); }); }); From 60a69629269b717200003d3a7f1256cc2a767ffc Mon Sep 17 00:00:00 2001 From: Alex Ross <38270282+alexr00@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:29:30 +0200 Subject: [PATCH 5/6] Attestation commit From 5e80317a7434eb76652f4632ca0a7e2460a4a029 Mon Sep 17 00:00:00 2001 From: Alex Ross <38270282+alexr00@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:56:11 +0200 Subject: [PATCH 6/6] CCR feedback --- src/commands.ts | 4 +--- src/test/extension.test.ts | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index b6ceb913bd..923d61832e 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -2016,9 +2016,7 @@ ${contents} quickPick.items = prItems; const prioritizeExactNumberMatch = (value: string) => { const exactNumberMatch = findExactPullRequestNumberMatch(value, prItems); - if (exactNumberMatch) { - quickPick.activeItems = [exactNumberMatch]; - } + quickPick.activeItems = exactNumberMatch ? [exactNumberMatch] : []; }; valueChangeDisposable = quickPick.onDidChangeValue(prioritizeExactNumberMatch); prioritizeExactNumberMatch(quickPick.value); diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 480a9bb5cd..4be8763c4e 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -24,6 +24,9 @@ describe('Extension Tests', function () { ]; assert.strictEqual(findExactPullRequestNumberMatch('10063', items), items[1]); + assert.strictEqual(findExactPullRequestNumberMatch('#10063', items), items[1]); + assert.strictEqual(findExactPullRequestNumberMatch('1006', items), undefined); + assert.strictEqual(findExactPullRequestNumberMatch('10063 title', items), undefined); assert.strictEqual(items[1].label, '#10063 Upgrade library to v5'); }); });