From daa417a09767138412aea2d8d79f083b53f1e746 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:35:50 -0400 Subject: [PATCH 01/22] ci: add dedicated evaluation step for missing priority labels --- .github/workflows/gemini-scheduled-issue-triage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 6c8f10dcb78..225a34740d7 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -81,7 +81,7 @@ jobs: echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 50 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ @@ -179,6 +179,7 @@ jobs: 5. Label Policy: - If the issue already has a kind/ label, do not change it. - If the issue already has a priority/ label, do not change it. + - If the issue is missing a priority/ label, you must evaluate the issue's impact to determine the priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. - If the issue already has an area/ label, do not change it. - If the issue already has an effort/ label, do not change it. - If the issue is missing an effort/ label AND its area is area/core, area/extensions, area/site, or area/non-interactive, you must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. Do NOT evaluate or assign an effort/ label to issues in any other areas (such as area/agent). From 2d09d9d6e60e9469932ff440ba3e4962465b2f15 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:37:16 -0400 Subject: [PATCH 02/22] fix(ci): ensure status/bot-triaged and status/manual-triage are mutually exclusive --- .github/scripts/apply-issue-labels.cjs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/scripts/apply-issue-labels.cjs b/.github/scripts/apply-issue-labels.cjs index 03c11403fed..4616b071dbc 100644 --- a/.github/scripts/apply-issue-labels.cjs +++ b/.github/scripts/apply-issue-labels.cjs @@ -85,12 +85,23 @@ module.exports = async ({ github, context, core }) => { continue; } - const labelsToAdd = entry.labels_to_add || []; - labelsToAdd.push('status/bot-triaged'); - + let labelsToAdd = entry.labels_to_add || []; let labelsToRemove = entry.labels_to_remove || []; + labelsToRemove.push('status/need-triage'); - // Deduplicate array + + if (labelsToAdd.includes('status/manual-triage')) { + // If the AI flagged it for manual triage, remove bot-triaged if it exists + labelsToRemove.push('status/bot-triaged'); + // Ensure we don't accidentally try to add bot-triaged if the AI returned it + labelsToAdd = labelsToAdd.filter((l) => l !== 'status/bot-triaged'); + } else { + // Standard successful bot triage + labelsToAdd.push('status/bot-triaged'); + } + + // Deduplicate arrays + labelsToAdd = [...new Set(labelsToAdd)]; labelsToRemove = [...new Set(labelsToRemove)]; if (labelsToAdd.length > 0) { From de7d4bade42d66633d8e309c738583fc0c3be6c1 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:39:13 -0400 Subject: [PATCH 03/22] fix(ci): strictly enforce single area label in prompt and script --- .github/scripts/apply-issue-labels.cjs | 12 ++++++++++++ .github/workflows/gemini-scheduled-issue-triage.yml | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/scripts/apply-issue-labels.cjs b/.github/scripts/apply-issue-labels.cjs index 4616b071dbc..4775b5e00a8 100644 --- a/.github/scripts/apply-issue-labels.cjs +++ b/.github/scripts/apply-issue-labels.cjs @@ -104,6 +104,18 @@ module.exports = async ({ github, context, core }) => { labelsToAdd = [...new Set(labelsToAdd)]; labelsToRemove = [...new Set(labelsToRemove)]; + // Enforce mutually exclusive area labels + const areaLabelsToAdd = labelsToAdd.filter((l) => l.startsWith('area/')); + if (areaLabelsToAdd.length > 1) { + core.warning( + `Issue #${issueNumber} has multiple area labels to add: ${areaLabelsToAdd.join(', ')}. Keeping only the first one.`, + ); + const firstArea = areaLabelsToAdd[0]; + labelsToAdd = labelsToAdd.filter( + (l) => !l.startsWith('area/') || l === firstArea, + ); + } + if (labelsToAdd.length > 0) { await github.rest.issues.addLabels({ owner: context.repo.owner, diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 225a34740d7..58df81eb581 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -181,6 +181,7 @@ jobs: - If the issue already has a priority/ label, do not change it. - If the issue is missing a priority/ label, you must evaluate the issue's impact to determine the priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. - If the issue already has an area/ label, do not change it. + - If the issue is missing an area/ label, select exactly ONE area/ label that best fits the issue. Issues MUST NOT have multiple area/ labels. - If the issue already has an effort/ label, do not change it. - If the issue is missing an effort/ label AND its area is area/core, area/extensions, area/site, or area/non-interactive, you must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. Do NOT evaluate or assign an effort/ label to issues in any other areas (such as area/agent). - If any of these are missing, select exactly ONE appropriate label for the missing category. @@ -214,7 +215,7 @@ jobs: - Do not add comments or modify the issue content. - Do not remove the following labels maintainer, help wanted or good first issue. - Triage only the current issue. - - Identify only one area/ label. + - Identify exactly ONE area/ label. Do NOT assign multiple area/ labels to a single issue. - Identify only one kind/ label (Do not apply kind/duplicate or kind/parent-issue) - Identify only one priority/ label. - Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario. From 109ff9ffce428a093113f7579a26ac28d7bf7e92 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:45:59 -0400 Subject: [PATCH 04/22] ci: add cleanup step for multiple area labels --- .github/scripts/cleanup-multiple-areas.cjs | 56 +++++++++++++++++++ .../gemini-scheduled-issue-triage.yml | 10 ++++ 2 files changed, 66 insertions(+) create mode 100644 .github/scripts/cleanup-multiple-areas.cjs diff --git a/.github/scripts/cleanup-multiple-areas.cjs b/.github/scripts/cleanup-multiple-areas.cjs new file mode 100644 index 00000000000..4649ef1c9bf --- /dev/null +++ b/.github/scripts/cleanup-multiple-areas.cjs @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +module.exports = async ({ github, context, core }) => { + core.info('Fetching open issues to check for multiple area labels...'); + + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }); + + let cleanedCount = 0; + + for (const issue of issues) { + // Skip pull requests + if (issue.pull_request) continue; + + const areaLabels = issue.labels + .filter((l) => l.name && l.name.startsWith('area/')) + .map((l) => l.name); + + if (areaLabels.length > 1) { + core.info( + `Issue #${issue.number} has multiple area labels: ${areaLabels.join(', ')}`, + ); + + // Keep the first one, remove the rest + for (let i = 1; i < areaLabels.length; i++) { + const labelToRemove = areaLabels[i]; + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + name: labelToRemove, + }); + core.info( + `Successfully removed ${labelToRemove} from #${issue.number}`, + ); + } catch (error) { + core.warning( + `Failed to remove ${labelToRemove} from #${issue.number}: ${error.message}`, + ); + } + } + cleanedCount++; + } + } + + core.info(`Cleaned up multiple area labels from ${cleanedCount} issues.`); +}; diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 58df81eb581..a6f00a4f87b 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -319,3 +319,13 @@ jobs: script: |- const cleanupLabels = require('./.github/scripts/cleanup-triage-labels.cjs'); await cleanupLabels({ github, context, core }); + + - name: 'Clean Up Multiple Area Labels' + if: |- + always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') + uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' + with: + github-token: '${{ steps.generate_token.outputs.token }}' + script: |- + const cleanupMultipleAreas = require('./.github/scripts/cleanup-multiple-areas.cjs'); + await cleanupMultipleAreas({ github, context, core }); From c3c5d14cd8e450db7185e778e40fa8e18615cbf6 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:48:13 -0400 Subject: [PATCH 05/22] ci: use ai to resolve multiple area labels intelligently --- .github/scripts/cleanup-multiple-areas.cjs | 56 ------------------- .github/scripts/find-multiple-areas.cjs | 51 +++++++++++++++++ .../gemini-scheduled-issue-triage.yml | 17 +++++- 3 files changed, 65 insertions(+), 59 deletions(-) delete mode 100644 .github/scripts/cleanup-multiple-areas.cjs create mode 100644 .github/scripts/find-multiple-areas.cjs diff --git a/.github/scripts/cleanup-multiple-areas.cjs b/.github/scripts/cleanup-multiple-areas.cjs deleted file mode 100644 index 4649ef1c9bf..00000000000 --- a/.github/scripts/cleanup-multiple-areas.cjs +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2026 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = async ({ github, context, core }) => { - core.info('Fetching open issues to check for multiple area labels...'); - - const issues = await github.paginate(github.rest.issues.listForRepo, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - per_page: 100, - }); - - let cleanedCount = 0; - - for (const issue of issues) { - // Skip pull requests - if (issue.pull_request) continue; - - const areaLabels = issue.labels - .filter((l) => l.name && l.name.startsWith('area/')) - .map((l) => l.name); - - if (areaLabels.length > 1) { - core.info( - `Issue #${issue.number} has multiple area labels: ${areaLabels.join(', ')}`, - ); - - // Keep the first one, remove the rest - for (let i = 1; i < areaLabels.length; i++) { - const labelToRemove = areaLabels[i]; - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issue.number, - name: labelToRemove, - }); - core.info( - `Successfully removed ${labelToRemove} from #${issue.number}`, - ); - } catch (error) { - core.warning( - `Failed to remove ${labelToRemove} from #${issue.number}: ${error.message}`, - ); - } - } - cleanedCount++; - } - } - - core.info(`Cleaned up multiple area labels from ${cleanedCount} issues.`); -}; diff --git a/.github/scripts/find-multiple-areas.cjs b/.github/scripts/find-multiple-areas.cjs new file mode 100644 index 00000000000..3e576861706 --- /dev/null +++ b/.github/scripts/find-multiple-areas.cjs @@ -0,0 +1,51 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +const fs = require('node:fs'); + +module.exports = async ({ github, context, core }) => { + core.info('Fetching open issues to check for multiple area labels...'); + + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }); + + const multipleAreaIssues = []; + + for (const issue of issues) { + if (issue.pull_request) continue; + + const areaLabels = issue.labels + .filter((l) => l.name && l.name.startsWith('area/')) + .map((l) => l.name); + + if (areaLabels.length > 1) { + core.info( + `Issue #${issue.number} has multiple area labels: ${areaLabels.join(', ')}`, + ); + multipleAreaIssues.push({ + number: issue.number, + title: issue.title, + body: issue.body || '', + }); + } + } + + // Limit to 20 to avoid overwhelming the AI in a single run + const issuesToProcess = multipleAreaIssues.slice(0, 20); + + fs.writeFileSync( + 'multiple_area_issues.json', + JSON.stringify(issuesToProcess, null, 2), + ); + + core.info( + `Found ${multipleAreaIssues.length} issues with multiple area labels. Wrote ${issuesToProcess.length} to multiple_area_issues.json`, + ); +}; diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index a6f00a4f87b..0824c9d451f 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -61,6 +61,16 @@ jobs: const syncIssueTypes = require('./.github/scripts/sync-issue-types.cjs'); await syncIssueTypes({ github, context, core }); + - name: 'Find Issues with Multiple Area Labels' + if: |- + ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} + uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' + with: + github-token: '${{ steps.generate_token.outputs.token }}' + script: |- + const findMultipleAreas = require('./.github/scripts/find-multiple-areas.cjs'); + await findMultipleAreas({ github, context, core }); + - name: 'Find untriaged issues' if: |- ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} @@ -88,7 +98,8 @@ jobs: --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' - jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json no_type_issues.json > issues_to_triage.json + if [ ! -f multiple_area_issues.json ]; then echo "[]" > multiple_area_issues.json; fi + jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json multiple_area_issues.json > issues_to_triage.json ISSUE_COUNT="$(jq 'length' issues_to_triage.json)" if [ "$ISSUE_COUNT" -gt 0 ]; then @@ -180,8 +191,8 @@ jobs: - If the issue already has a kind/ label, do not change it. - If the issue already has a priority/ label, do not change it. - If the issue is missing a priority/ label, you must evaluate the issue's impact to determine the priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. - - If the issue already has an area/ label, do not change it. - - If the issue is missing an area/ label, select exactly ONE area/ label that best fits the issue. Issues MUST NOT have multiple area/ labels. + - If the issue has exactly ONE area/ label, do not change it. + - If the issue is missing an area/ label, OR if the issue currently has MULTIPLE area/ labels, select exactly ONE area/ label that best fits the issue. Issues MUST NOT have multiple area/ labels. If you are fixing an issue with multiple area/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. - If the issue already has an effort/ label, do not change it. - If the issue is missing an effort/ label AND its area is area/core, area/extensions, area/site, or area/non-interactive, you must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. Do NOT evaluate or assign an effort/ label to issues in any other areas (such as area/agent). - If any of these are missing, select exactly ONE appropriate label for the missing category. From f28027d5832165d8e2c8e595f2c32aac11b48f8d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:50:17 -0400 Subject: [PATCH 06/22] ci: enforce mutually exclusive priority labels and clean up conflicts --- .github/scripts/apply-issue-labels.cjs | 14 +++++ .github/scripts/find-multiple-areas.cjs | 51 ------------------- .../gemini-scheduled-issue-triage.yml | 16 +++--- 3 files changed, 22 insertions(+), 59 deletions(-) delete mode 100644 .github/scripts/find-multiple-areas.cjs diff --git a/.github/scripts/apply-issue-labels.cjs b/.github/scripts/apply-issue-labels.cjs index 4775b5e00a8..f875a7ed389 100644 --- a/.github/scripts/apply-issue-labels.cjs +++ b/.github/scripts/apply-issue-labels.cjs @@ -116,6 +116,20 @@ module.exports = async ({ github, context, core }) => { ); } + // Enforce mutually exclusive priority labels + const priorityLabelsToAdd = labelsToAdd.filter((l) => + l.startsWith('priority/'), + ); + if (priorityLabelsToAdd.length > 1) { + core.warning( + `Issue #${issueNumber} has multiple priority labels to add: ${priorityLabelsToAdd.join(', ')}. Keeping only the first one.`, + ); + const firstPriority = priorityLabelsToAdd[0]; + labelsToAdd = labelsToAdd.filter( + (l) => !l.startsWith('priority/') || l === firstPriority, + ); + } + if (labelsToAdd.length > 0) { await github.rest.issues.addLabels({ owner: context.repo.owner, diff --git a/.github/scripts/find-multiple-areas.cjs b/.github/scripts/find-multiple-areas.cjs deleted file mode 100644 index 3e576861706..00000000000 --- a/.github/scripts/find-multiple-areas.cjs +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2026 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -const fs = require('node:fs'); - -module.exports = async ({ github, context, core }) => { - core.info('Fetching open issues to check for multiple area labels...'); - - const issues = await github.paginate(github.rest.issues.listForRepo, { - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - per_page: 100, - }); - - const multipleAreaIssues = []; - - for (const issue of issues) { - if (issue.pull_request) continue; - - const areaLabels = issue.labels - .filter((l) => l.name && l.name.startsWith('area/')) - .map((l) => l.name); - - if (areaLabels.length > 1) { - core.info( - `Issue #${issue.number} has multiple area labels: ${areaLabels.join(', ')}`, - ); - multipleAreaIssues.push({ - number: issue.number, - title: issue.title, - body: issue.body || '', - }); - } - } - - // Limit to 20 to avoid overwhelming the AI in a single run - const issuesToProcess = multipleAreaIssues.slice(0, 20); - - fs.writeFileSync( - 'multiple_area_issues.json', - JSON.stringify(issuesToProcess, null, 2), - ); - - core.info( - `Found ${multipleAreaIssues.length} issues with multiple area labels. Wrote ${issuesToProcess.length} to multiple_area_issues.json`, - ); -}; diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 0824c9d451f..1d81a886a63 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -61,15 +61,15 @@ jobs: const syncIssueTypes = require('./.github/scripts/sync-issue-types.cjs'); await syncIssueTypes({ github, context, core }); - - name: 'Find Issues with Multiple Area Labels' + - name: 'Find Issues with Conflicting Labels' if: |- ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' with: github-token: '${{ steps.generate_token.outputs.token }}' script: |- - const findMultipleAreas = require('./.github/scripts/find-multiple-areas.cjs'); - await findMultipleAreas({ github, context, core }); + const findConflictingLabels = require('./.github/scripts/find-conflicting-labels.cjs'); + await findConflictingLabels({ github, context, core }); - name: 'Find untriaged issues' if: |- @@ -98,8 +98,8 @@ jobs: --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' - if [ ! -f multiple_area_issues.json ]; then echo "[]" > multiple_area_issues.json; fi - jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json multiple_area_issues.json > issues_to_triage.json + if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi + jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json conflicting_labels_issues.json > issues_to_triage.json ISSUE_COUNT="$(jq 'length' issues_to_triage.json)" if [ "$ISSUE_COUNT" -gt 0 ]; then @@ -189,8 +189,8 @@ jobs: 4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/*, priority/*, and effort/*. 5. Label Policy: - If the issue already has a kind/ label, do not change it. - - If the issue already has a priority/ label, do not change it. - - If the issue is missing a priority/ label, you must evaluate the issue's impact to determine the priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. + - If the issue has exactly ONE priority/ label, do not change it. + - If the issue is missing a priority/ label, OR if the issue currently has MULTIPLE priority/ labels, you must evaluate the issue's impact to determine exactly ONE priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. If you are fixing an issue with multiple priority/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. - If the issue has exactly ONE area/ label, do not change it. - If the issue is missing an area/ label, OR if the issue currently has MULTIPLE area/ labels, select exactly ONE area/ label that best fits the issue. Issues MUST NOT have multiple area/ labels. If you are fixing an issue with multiple area/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. - If the issue already has an effort/ label, do not change it. @@ -228,7 +228,7 @@ jobs: - Triage only the current issue. - Identify exactly ONE area/ label. Do NOT assign multiple area/ labels to a single issue. - Identify only one kind/ label (Do not apply kind/duplicate or kind/parent-issue) - - Identify only one priority/ label. + - Identify exactly ONE priority/ label. Do NOT assign multiple priority/ labels to a single issue. - Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario. Categorization Guidelines (Effort): From 004db1403e61e3d0184d00ed1165efab18ff786d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:52:50 -0400 Subject: [PATCH 07/22] test: temporarily limit triage to 5 issues --- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 1d81a886a63..32a34b23e6e 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 5 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 5 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 5 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 5 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 94ec3213bd986b776372cb1ed0303b4c5c579da2 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 10:54:00 -0400 Subject: [PATCH 08/22] fix(ci): track new conflict script and remove old multiple area cleanup step --- .github/scripts/find-conflicting-labels.cjs | 60 +++++++++++++++++++ .../gemini-scheduled-issue-triage.yml | 10 ---- 2 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 .github/scripts/find-conflicting-labels.cjs diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs new file mode 100644 index 00000000000..d2e6413710d --- /dev/null +++ b/.github/scripts/find-conflicting-labels.cjs @@ -0,0 +1,60 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +const fs = require('node:fs'); + +module.exports = async ({ github, context, core }) => { + core.info('Fetching open issues to check for conflicting labels...'); + + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + }); + + const conflictingLabelIssues = []; + + for (const issue of issues) { + if (issue.pull_request) continue; + + const areaLabels = issue.labels + .filter((l) => l.name && l.name.startsWith('area/')) + .map((l) => l.name); + + const priorityLabels = issue.labels + .filter((l) => l.name && l.name.startsWith('priority/')) + .map((l) => l.name); + + if (areaLabels.length > 1 || priorityLabels.length > 1) { + let message = `Issue #${issue.number} has conflicting labels:`; + if (areaLabels.length > 1) + message += ` multiple areas (${areaLabels.join(', ')}).`; + if (priorityLabels.length > 1) + message += ` multiple priorities (${priorityLabels.join(', ')}).`; + + core.info(message); + + conflictingLabelIssues.push({ + number: issue.number, + title: issue.title, + body: issue.body || '', + }); + } + } + + // Limit to 5 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 5); + + fs.writeFileSync( + 'conflicting_labels_issues.json', + JSON.stringify(issuesToProcess, null, 2), + ); + + core.info( + `Found ${conflictingLabelIssues.length} issues with conflicting labels. Wrote ${issuesToProcess.length} to conflicting_labels_issues.json`, + ); +}; diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 32a34b23e6e..c60fe0cd2bb 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -330,13 +330,3 @@ jobs: script: |- const cleanupLabels = require('./.github/scripts/cleanup-triage-labels.cjs'); await cleanupLabels({ github, context, core }); - - - name: 'Clean Up Multiple Area Labels' - if: |- - always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') - uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' - with: - github-token: '${{ steps.generate_token.outputs.token }}' - script: |- - const cleanupMultipleAreas = require('./.github/scripts/cleanup-multiple-areas.cjs'); - await cleanupMultipleAreas({ github, context, core }); From c664b6e0a5d7e29d8d232d4f311ccc5928441d64 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 11:07:09 -0400 Subject: [PATCH 09/22] chore: revert temporary triage limits back to production defaults --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index d2e6413710d..1d671be8c51 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 5 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 5); + // Limit to 20 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 20); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index c60fe0cd2bb..0d963860dc9 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 5 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 5 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 5 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 5 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From a7281e168ce5747b3473ab8caf844577bd87b45d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 11:59:56 -0400 Subject: [PATCH 10/22] test: temporarily limit triage to 2 issues --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 1d671be8c51..6cbc7ed754f 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 20 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 20); + // Limit to 2 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 2); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 0d963860dc9..802dd2cdfe8 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 2 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 2 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 2 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 2 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From e0df9f28c03dc854d185e390420b7d5c800873c6 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 12:06:40 -0400 Subject: [PATCH 11/22] chore: revert temporary triage limits back to production defaults again --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 6cbc7ed754f..1d671be8c51 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 2 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 2); + // Limit to 20 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 20); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 802dd2cdfe8..0d963860dc9 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 2 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 2 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 2 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 2 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 228fd680ea22e297e1ef865d12ed3c99e351327d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 13:20:09 -0400 Subject: [PATCH 12/22] test: temporarily limit triage to 1 issue --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 1d671be8c51..6bdfa2d971e 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 20 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 20); + // Limit to 1 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 1); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 0d963860dc9..e67cf1992e4 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 1 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 1 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 1 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 1 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 42b22dc9b4a9f77faaf490b8a4ab6fe4974a1a2e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:21:12 -0400 Subject: [PATCH 13/22] refactor(ci): decouple standard and effort triage steps to reduce token load --- .../gemini-scheduled-issue-triage.yml | 153 +++++++++++++++--- 1 file changed, 130 insertions(+), 23 deletions(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index e67cf1992e4..117d0f62c12 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -97,17 +97,25 @@ jobs: gh issue list --repo "${GITHUB_REPOSITORY}" \ --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 1 --json number,title,body > no_effort_issues.json - echo '🔄 Merging and deduplicating issues...' + echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi - jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json conflicting_labels_issues.json > issues_to_triage.json + jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json conflicting_labels_issues.json > standard_issues_to_triage.json - ISSUE_COUNT="$(jq 'length' issues_to_triage.json)" - if [ "$ISSUE_COUNT" -gt 0 ]; then + echo '📏 Deduplicating effort issues...' + jq -c -s 'add | unique_by(.number)' no_effort_issues.json > effort_issues_to_triage.json + + STANDARD_COUNT="$(jq 'length' standard_issues_to_triage.json)" + EFFORT_COUNT="$(jq 'length' effort_issues_to_triage.json)" + if [ "$STANDARD_COUNT" -gt 0 ] || [ "$EFFORT_COUNT" -gt 0 ]; then echo "has_issues=true" >> "${GITHUB_OUTPUT}" + echo "has_standard_issues=$([ "$STANDARD_COUNT" -gt 0 ] && echo 'true' || echo 'false')" >> "${GITHUB_OUTPUT}" + echo "has_effort_issues=$([ "$EFFORT_COUNT" -gt 0 ] && echo 'true' || echo 'false')" >> "${GITHUB_OUTPUT}" else echo "has_issues=false" >> "${GITHUB_OUTPUT}" + echo "has_standard_issues=false" >> "${GITHUB_OUTPUT}" + echo "has_effort_issues=false" >> "${GITHUB_OUTPUT}" fi - echo "✅ Found ${ISSUE_COUNT} unique issues to triage! 🎯" + echo "✅ Found ${STANDARD_COUNT} standard issues and ${EFFORT_COUNT} effort issues to triage! 🎯" - name: 'Create Gemini CLI Experiments Override' if: |- @@ -140,11 +148,11 @@ jobs: core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`); return labelNames; - - name: 'Run Gemini Issue Analysis' + - name: 'Run Standard Triage Analysis' if: |- - steps.get_issue_from_event.outputs.has_issues == 'true' || steps.find_issues.outputs.has_issues == 'true' + steps.get_issue_from_event.outputs.has_issues == 'true' || steps.find_issues.outputs.has_standard_issues == 'true' uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0 - id: 'gemini_issue_analysis' + id: 'gemini_standard_issue_analysis' env: GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs REPOSITORY: '${{ github.repository }}' @@ -165,8 +173,6 @@ jobs: "maxSessionTurns": 25, "coreTools": [ "run_shell_command(echo)", - "grep_search", - "glob", "read_file" ], "telemetry": { @@ -184,30 +190,27 @@ jobs: ## Steps 1. You are only able to use the echo and read_file commands. Review the available labels in the environment variable: "${AVAILABLE_LABELS}". - 2. Use the read_file tool to read the file "issues_to_triage.json" which contains the JSON array of issues to triage. + 2. Use the read_file tool to read the file "standard_issues_to_triage.json" which contains the JSON array of issues to triage. 3. Review the issue title, body and any comments provided in the JSON file. - 4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/*, priority/*, and effort/*. + 4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/*, and priority/*. 5. Label Policy: - If the issue already has a kind/ label, do not change it. - If the issue has exactly ONE priority/ label, do not change it. - - If the issue is missing a priority/ label, OR if the issue currently has MULTIPLE priority/ labels, you must evaluate the issue's impact to determine exactly ONE priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based on the categorization guidelines. If you are fixing an issue with multiple priority/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. + - If the issue is missing a priority/ label, OR if the issue currently has MULTIPLE priority/ labels, you must evaluate the issue's impact to determine exactly ONE priority level (priority/p0, priority/p1, priority/p2, priority/p3, or priority/unknown) based the guidelines. If you are fixing an issue with multiple priority/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. - If the issue has exactly ONE area/ label, do not change it. - If the issue is missing an area/ label, OR if the issue currently has MULTIPLE area/ labels, select exactly ONE area/ label that best fits the issue. Issues MUST NOT have multiple area/ labels. If you are fixing an issue with multiple area/ labels, put the correct one in `labels_to_add` and put all the incorrect ones in `labels_to_remove`. - - If the issue already has an effort/ label, do not change it. - - If the issue is missing an effort/ label AND its area is area/core, area/extensions, area/site, or area/non-interactive, you must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. Do NOT evaluate or assign an effort/ label to issues in any other areas (such as area/agent). - If any of these are missing, select exactly ONE appropriate label for the missing category. 6. Identify other applicable labels based on the issue content, such as status/*, help wanted, good first issue, etc. 7. Give me a single short explanation about why you are selecting each label in the process. 8. Output a JSON array of objects, each containing the issue number - and the labels to add and remove, along with an explanation. If you assigned an effort/ label, you MUST also include an effort_analysis field. This effort_analysis must be highly detailed, technical, and empirical. It MUST NOT contain vague guesses (e.g., avoid words like "likely points to" or "possibly"). You must explicitly cite the specific file paths and architectural mechanisms you discovered using your search tools, explain the root cause, and then explicitly state how that complexity maps to the chosen effort level guidelines. For example: + and the labels to add and remove, along with an explanation. For example: ``` [ { "issue_number": 123, - "labels_to_add": ["area/core", "kind/bug", "priority/p2", "effort/small"], + "labels_to_add": ["area/core", "kind/bug", "priority/p2"], "labels_to_remove": ["status/need-triage"], - "explanation": "This issue is a UI bug that needs to be addressed with medium priority.", - "effort_analysis": "The `vscode-ide-companion` extension indiscriminately tracks active text editors via `vscode.window.onDidChangeActiveTextEditor` in `open-files-manager.ts`. When a user opens `.vscode/settings.json`, its content is sent to the CLI's context. The fix is highly localized to the VS Code companion extension's event listener. It involves adding a simple conditional check to exclude specific configuration files from the active editor tracking logic, which is a trivial logic adjustment with a clear root cause." + "explanation": "This issue is a UI bug that needs to be addressed with medium priority." } ] ``` @@ -231,6 +234,94 @@ jobs: - Identify exactly ONE priority/ label. Do NOT assign multiple priority/ labels to a single issue. - Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario. + Categorization Guidelines (Priority): + P0 - Urgent Blocking Issues: + - Definition: Critical failures breaking core functionality for a large portion of users. Examples: CLI fails to launch globally, core commands (gemini run) crash on valid input, unhandled promise rejections on boot, critical security vulnerability. + - Note: You must apply status/manual-triage instead of priority/p0. + P1 - Critical but Workable: + - Definition: Severe issues without a reasonable workaround, significantly degrading the developer experience but not globally blocking. Examples: Specific tools failing consistently (e.g., `web_search` returns 500s), persistent PTY streaming hangs, memory leaks leading to OOM after short use. + P2 - Significant Issues: + - Definition: Affect some workflows but a clear workaround exists, or non-critical bugs. Examples: Theme flickering, confusing error messages, minor UI misalignment, failing to read deeply nested config files correctly. + P3 - Minor/Enhancements: + - Definition: Trivial bugs, typos, documentation requests, or feature requests. + + Categorization Guidelines (Kind): + kind/bug: The issue is describing an unexpected behavior or failure in the application. + kind/enhancement: The issue is describing a feature request or an improvement to an existing feature. + kind/question: The issue is asking a question about how to use the CLI or about a specific feature. + + Categorization Guidelines (Area): + area/agent: The "brain" of the CLI. Core agent logic, model quality, tool/function calling, memory, web search, generated code quality, sub-agents. + area/core: The fundamental CLI app. UI/UX, installation, OS compatibility, performance, command parsing, theming, flickering. + area/documentation: Website docs, READMEs, inline help text. + area/enterprise: Telemetry, Policy, Quota / Licensing + area/extensions: Gemini CLI extensions capability + area/non-interactive: GitHub Actions, SDK, 3P Integrations, Shell Scripting, Command line automation + area/platform: Platform specific behavior + area/security: Authentication, authorization, privacy, data leaks, credential storage. + + - name: 'Run Effort Triage Analysis' + if: |- + steps.find_issues.outputs.has_effort_issues == 'true' + uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0 + id: 'gemini_effort_issue_analysis' + env: + GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs + REPOSITORY: '${{ github.repository }}' + AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}' + GEMINI_CLI_TRUST_WORKSPACE: 'true' + GEMINI_EXP: 'gemini_exp.json' + GEMINI_STRICT_TELEMETRY_LIMITS: 'true' + with: + gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}' + gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}' + gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}' + gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' + gemini_api_key: '${{ secrets.GEMINI_API_KEY }}' + use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}' + use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}' + settings: |- + { + "maxSessionTurns": 25, + "coreTools": [ + "run_shell_command(echo)", + "grep_search", + "glob", + "read_file" + ], + "telemetry": { + "enabled": true, + "target": "gcp" + } + } + prompt: |- + ## Role + + You are an expert software architect. Analyze the provided GitHub issues and assign the correct `effort/*` label based on the codebase complexity. + + ## Steps + + 1. Use the read_file tool to read "effort_issues_to_triage.json". + 2. For each issue in the array: + - You must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. + 3. Output a JSON array of objects, each containing the issue number and the effort label to add, along with an explanation and an effort_analysis field. This effort_analysis must be highly detailed, technical, and empirical. It MUST NOT contain vague guesses (e.g., avoid words like "likely points to" or "possibly"). You must explicitly cite the specific file paths and architectural mechanisms you discovered using your search tools, explain the root cause, and then explicitly state how that complexity maps to the chosen effort level guidelines. For example: + ``` + [ + { + "issue_number": 123, + "labels_to_add": ["effort/small"], + "explanation": "This is a simple logic fix.", + "effort_analysis": "The `vscode-ide-companion` extension indiscriminately tracks active text editors via `vscode.window.onDidChangeActiveTextEditor` in `open-files-manager.ts`. When a user opens `.vscode/settings.json`, its content is sent to the CLI's context. The fix is highly localized to the VS Code companion extension's event listener. It involves adding a simple conditional check to exclude specific configuration files from the active editor tracking logic, which is a trivial logic adjustment with a clear root cause." + } + ] + ``` + + ## Guidelines + + - Output only valid JSON format + - Do not include any explanation or additional text, just the JSON + - Triage only the current issue. + Categorization Guidelines (Effort): effort/small (1 day or less): - Trivial Logic & Config: Schema updates (Zod), feature flag toggles, adding missing fields to package.json or settings.json. @@ -285,13 +376,29 @@ jobs: - This product is designed to use different models eg.. using pro, downgrading to flash etc. - When users report that they dont expect the model to change those would be categorized as feature requests. - - name: 'Apply Labels to Issues' + - name: 'Apply Standard Labels to Issues' + if: |- + ${{ steps.gemini_standard_issue_analysis.outcome == 'success' && + steps.gemini_standard_issue_analysis.outputs.summary != '[]' && + steps.gemini_standard_issue_analysis.outputs.summary != '' }} + env: + REPOSITORY: '${{ github.repository }}' + LABELS_OUTPUT: '${{ steps.gemini_standard_issue_analysis.outputs.summary }}' + uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' + with: + github-token: '${{ steps.generate_token.outputs.token }}' + script: |- + const applyLabels = require('./.github/scripts/apply-issue-labels.cjs'); + await applyLabels({ github, context, core }); + + - name: 'Apply Effort Labels to Issues' if: |- - ${{ steps.gemini_issue_analysis.outcome == 'success' && - steps.gemini_issue_analysis.outputs.summary != '[]' }} + ${{ steps.gemini_effort_issue_analysis.outcome == 'success' && + steps.gemini_effort_issue_analysis.outputs.summary != '[]' && + steps.gemini_effort_issue_analysis.outputs.summary != '' }} env: REPOSITORY: '${{ github.repository }}' - LABELS_OUTPUT: '${{ steps.gemini_issue_analysis.outputs.summary }}' + LABELS_OUTPUT: '${{ steps.gemini_effort_issue_analysis.outputs.summary }}' uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' with: github-token: '${{ steps.generate_token.outputs.token }}' From 154455a52bfda3322fa224c3bcdd661659fe9f03 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:34:05 -0400 Subject: [PATCH 14/22] chore: revert temporary triage limits back to production defaults --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 6bdfa2d971e..1d671be8c51 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 1 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 1); + // Limit to 20 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 20); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 117d0f62c12..6789f869058 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 1 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 1 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 1 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 1 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 0839a6d043482545e3bb00aa37a262cf4d641b0d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:35:21 -0400 Subject: [PATCH 15/22] fix(ci): remove bot-triaged exclusion from effort query to unblock backlog --- .github/workflows/gemini-scheduled-issue-triage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 6789f869058..2a1a4a4ed95 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -95,7 +95,7 @@ jobs: echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From dec6be3ba12c609232cc5b5f30d3272e147438fc Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:37:41 -0400 Subject: [PATCH 16/22] test: temporarily limit triage to 5 issues --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 1d671be8c51..d2e6413710d 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 20 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 20); + // Limit to 5 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 5); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 2a1a4a4ed95..bf0a43d9583 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 5 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 5 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 5 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 5 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 09e33a98d885bb896fac19c490dc69ff2817032d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:43:09 -0400 Subject: [PATCH 17/22] fix(ci): disable telemetry in effort triage step to prevent docker container conflict --- .github/workflows/gemini-scheduled-issue-triage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index bf0a43d9583..27b5b233a62 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -290,7 +290,7 @@ jobs: "read_file" ], "telemetry": { - "enabled": true, + "enabled": false, "target": "gcp" } } From 405a0c6413bc6b9829f605e7f350e1e3bec99f23 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 15:50:38 -0400 Subject: [PATCH 18/22] fix(ci): re-enable telemetry for effort triage by manually stopping docker container between steps --- .github/workflows/gemini-scheduled-issue-triage.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 27b5b233a62..e7d876451a7 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -260,6 +260,11 @@ jobs: area/platform: Platform specific behavior area/security: Authentication, authorization, privacy, data leaks, credential storage. + - name: 'Stop Telemetry Collector' + if: |- + steps.find_issues.outputs.has_effort_issues == 'true' + run: docker stop gemini-telemetry-collector || true + - name: 'Run Effort Triage Analysis' if: |- steps.find_issues.outputs.has_effort_issues == 'true' @@ -290,7 +295,7 @@ jobs: "read_file" ], "telemetry": { - "enabled": false, + "enabled": true, "target": "gcp" } } From 54ec40010432e5c45889194487fa840404055ed0 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 16:00:04 -0400 Subject: [PATCH 19/22] fix(ci): use docker rm -f to forcefully clear container name conflict --- .github/workflows/gemini-scheduled-issue-triage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index e7d876451a7..1f4b432e91c 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -263,7 +263,7 @@ jobs: - name: 'Stop Telemetry Collector' if: |- steps.find_issues.outputs.has_effort_issues == 'true' - run: docker stop gemini-telemetry-collector || true + run: docker rm -f gemini-telemetry-collector || true - name: 'Run Effort Triage Analysis' if: |- From ba97409db91dbbddcad63ce1124c4e502498ace4 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 17:11:05 -0400 Subject: [PATCH 20/22] chore: revert temporary triage limits back to production defaults --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index d2e6413710d..1d671be8c51 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 5 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 5); + // Limit to 20 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 20); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index 1f4b432e91c..be3efa9c046 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -83,19 +83,19 @@ jobs: echo '🔍 Finding issues missing area labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 5 --json number,title,body > no_area_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 50 --json number,title,body > no_area_issues.json echo '🔍 Finding issues missing kind labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 5 --json number,title,body > no_kind_issues.json + --search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 5 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 5 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From 0b0bdd468765cd59061ab93479173b4aeaaacb8e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 17:24:55 -0400 Subject: [PATCH 21/22] ci: permanently set standard triage limits to 50 and effort to 5 --- .github/scripts/find-conflicting-labels.cjs | 4 ++-- .github/workflows/gemini-scheduled-issue-triage.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/scripts/find-conflicting-labels.cjs b/.github/scripts/find-conflicting-labels.cjs index 1d671be8c51..35b5e64e5ac 100644 --- a/.github/scripts/find-conflicting-labels.cjs +++ b/.github/scripts/find-conflicting-labels.cjs @@ -46,8 +46,8 @@ module.exports = async ({ github, context, core }) => { } } - // Limit to 20 to avoid overwhelming the AI in a single run - const issuesToProcess = conflictingLabelIssues.slice(0, 20); + // Limit to 50 to avoid overwhelming the AI in a single run + const issuesToProcess = conflictingLabelIssues.slice(0, 50); fs.writeFileSync( 'conflicting_labels_issues.json', diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index be3efa9c046..d452368fee7 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -91,11 +91,11 @@ jobs: echo '🏷️ Finding issues missing priority labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 20 --json number,title,body > no_priority_issues.json + --search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 50 --json number,title,body > no_priority_issues.json echo '📏 Finding issues missing effort labels...' gh issue list --repo "${GITHUB_REPOSITORY}" \ - --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json + --search 'is:open is:issue -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 5 --json number,title,body > no_effort_issues.json echo '🔄 Merging and deduplicating standard triage issues...' if [ ! -f conflicting_labels_issues.json ]; then echo "[]" > conflicting_labels_issues.json; fi From fc349e82f353a2e750fed3f450b6ef3ac5edc1c9 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 11 May 2026 17:39:57 -0400 Subject: [PATCH 22/22] chore: fix unquoted string in triage workflow --- .github/workflows/gemini-scheduled-issue-triage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gemini-scheduled-issue-triage.yml b/.github/workflows/gemini-scheduled-issue-triage.yml index d452368fee7..6413f7c157e 100644 --- a/.github/workflows/gemini-scheduled-issue-triage.yml +++ b/.github/workflows/gemini-scheduled-issue-triage.yml @@ -263,7 +263,7 @@ jobs: - name: 'Stop Telemetry Collector' if: |- steps.find_issues.outputs.has_effort_issues == 'true' - run: docker rm -f gemini-telemetry-collector || true + run: 'docker rm -f gemini-telemetry-collector || true' - name: 'Run Effort Triage Analysis' if: |-