From 562defc6c8bb3660e7567dbd8b2990713d55c271 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:03:12 -0400 Subject: [PATCH 01/32] feat(examples): add automated issue cleanup workflow Adds a new GitHub Action workflow and Gemini CLI command configuration to automatically process open issues with specific labels. The workflow identifies the 10 issues with the oldest last update time, checks their validity against the codebase, searches for duplicates, and provides a triage summary (Maintainer-only vs Help-wanted) for further review. --- examples/workflows/issue-cleanup/README.md | 23 +++++ .../issue-cleanup/gemini-issue-cleanup.toml | 35 +++++++ .../issue-cleanup/gemini-issue-cleanup.yml | 95 +++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 examples/workflows/issue-cleanup/README.md create mode 100644 examples/workflows/issue-cleanup/gemini-issue-cleanup.toml create mode 100644 examples/workflows/issue-cleanup/gemini-issue-cleanup.yml diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md new file mode 100644 index 000000000..8b117bb47 --- /dev/null +++ b/examples/workflows/issue-cleanup/README.md @@ -0,0 +1,23 @@ +# Issue Cleanup Workflow + +This document describes a workflow to batch-process and clean up older open issues using Gemini CLI. + +## Overview + +The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: + +1. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. +2. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. +3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment categorizing it as either `Maintainer-only` (epic, sensitive, internal) or `Help-wanted` (community-friendly). + +## Usage + +This example is tailored to process issues in a specific repository (`google-gemini/gemini-cli`) matching specific labels (`area/core`, `area/extensions`, `area/site`, `area/non-interactive`), selecting the 10 issues with the oldest last update time. + +To adapt this to your own repository: + +1. Copy `gemini-issue-cleanup.yml` to your repository's `.github/workflows/` directory. +2. Update the repository name and search string in the `Find old issues for cleanup` step in `gemini-issue-cleanup.yml`. +3. Update the repository name in the `Checkout Target Repository Code` step in `gemini-issue-cleanup.yml`. +4. Copy `gemini-issue-cleanup.toml` to your `.github/commands/` directory. +5. Update the prompt instructions in `gemini-issue-cleanup.toml` replacing `google-gemini/gemini-cli` with your repository name. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml new file mode 100644 index 000000000..b8d9f302f --- /dev/null +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -0,0 +1,35 @@ +description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." +prompt = """ +## Role +You are an expert AI triage assistant and repository maintainer for the `google-gemini/gemini-cli` repository. + +## Task +Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `google-gemini/gemini-cli` and sequentially perform three specific checks. +You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command(gh)`) to investigate the codebase and issue tracker. Do NOT guess or hallucinate. + +### Step 1: Check Code Validity +- Use `gh issue view !{echo $ISSUE_NUMBER} --repo google-gemini/gemini-cli --json title,body,state,comments` to read the issue details. +- Search the local workspace (which contains the latest `google-gemini/gemini-cli` code) to determine if the issue is still valid. + - For example, if it's a bug, does the buggy code still exist? If it's a feature request, has it already been implemented? +- If you definitively determine the issue is NO LONGER VALID: + - Close the issue and leave a brief comment explaining why (e.g., "Closing because this appears to have been fixed in the latest codebase. "). + - Use `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase. " --repo google-gemini/gemini-cli` + - STOP execution. You are done with this issue. + +### Step 2: Check for Duplicates +- If the issue is still valid, check if it's a duplicate of another issue that is already being tracked or worked on. +- Use `gh issue list --search "" --repo google-gemini/gemini-cli --state all` with relevant keywords to find potential duplicates. +- If you find a clear duplicate that someone is working on or has already resolved: + - Close the issue as not planned, pointing to the duplicate. + - Use `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo google-gemini/gemini-cli` + - STOP execution. You are done with this issue. + +### Step 3: Provide Triage Summary +- If the issue is still valid and NOT a duplicate, add a brief summary comment for further triaging. +- State whether the issue should be categorized as: + - **Maintainer-only**: (e.g., epic, core architecture, sensitive fixes, internal tasks) + - **Help-wanted**: (e.g., good for community, general bugs, features, or tasks ready for external help) +- Your comment should be brief and clearly explain *why* it fits that category. +- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n**Category:** \n\n**Reasoning:** " --repo google-gemini/gemini-cli` +- STOP execution. You are done with this issue. +""" diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml new file mode 100644 index 000000000..16c7c2717 --- /dev/null +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -0,0 +1,95 @@ +name: '๐Ÿงน Gemini Issue Cleanup' + +on: + schedule: + - cron: '0 0 * * 0' # Runs weekly at midnight on Sunday + workflow_dispatch: + +concurrency: + group: '${{ github.workflow }}' + cancel-in-progress: true + +defaults: + run: + shell: 'bash' + +jobs: + find-issues: + runs-on: 'ubuntu-latest' + outputs: + issue_numbers: '${{ steps.find_issues.outputs.issue_numbers }}' + steps: + - name: 'Find old issues for cleanup' + id: 'find_issues' + env: + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' + run: |- + echo '๐Ÿ” Finding old issues for cleanup...' + # Query matches target: google-gemini/gemini-cli, open issues, sorted by oldest last update time + # with labels area/core, area/extensions, area/site, area/non-interactive + ISSUES="$(gh issue list \ + --repo google-gemini/gemini-cli \ + --state 'open' \ + --search "label:area/core,area/extensions,area/site,area/non-interactive sort:updated-asc" \ + --json number \ + --limit 10 \ + )" + + # Convert to JSON array of integers + ISSUE_NUMBERS="$(echo "${ISSUES}" | jq -c '[.[].number | tostring]')" + + if [ "${ISSUE_NUMBERS}" = "[]" ] || [ -z "${ISSUE_NUMBERS}" ]; then + echo "issue_numbers=[]" >> "${GITHUB_OUTPUT}" + echo "โœ… No issues found to clean up." + else + echo "issue_numbers=${ISSUE_NUMBERS}" >> "${GITHUB_OUTPUT}" + echo "โœ… Found $(echo "${ISSUES}" | jq 'length') issue(s) to process." + fi + + process-issue: + needs: find-issues + if: needs.find-issues.outputs.issue_numbers != '[]' && needs.find-issues.outputs.issue_numbers != '' + runs-on: 'ubuntu-latest' + strategy: + matrix: + issue_number: ${{ fromJSON(needs.find-issues.outputs.issue_numbers) }} + max-parallel: 3 + fail-fast: false + permissions: + contents: 'read' + id-token: 'write' + issues: 'write' + steps: + - name: 'Checkout Target Repository Code' + uses: 'actions/checkout@v4' + with: + repository: 'google-gemini/gemini-cli' + + - name: 'Run Gemini Issue Cleanup' + uses: 'google-github-actions/run-gemini-cli@v0' # Replace with actual version when deploying + env: + ISSUE_NUMBER: '${{ matrix.issue_number }}' + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' + with: + # Modify the auth settings depending on your environment + gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}' + gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}' + gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}' + gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}' + gemini_api_key: '${{ secrets.GEMINI_API_KEY }}' + workflow_name: 'gemini-issue-cleanup' + # Passing issue number to let the agent retrieve it + settings: |- + { + "model": { + "maxSessionTurns": 50 + }, + "tools": { + "core": [ + "grep_search", + "read_file", + "run_shell_command(gh)" + ] + } + } + prompt: '/gemini-issue-cleanup' From 69bd8f0b5d87588121853fb04cf0e09ad9a78838 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:05:04 -0400 Subject: [PATCH 02/32] fix(lint): YAML quoting in issue cleanup workflow --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 16c7c2717..ab205b0d9 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -47,12 +47,13 @@ jobs: fi process-issue: - needs: find-issues - if: needs.find-issues.outputs.issue_numbers != '[]' && needs.find-issues.outputs.issue_numbers != '' + needs: 'find-issues' + if: |- + needs.find-issues.outputs.issue_numbers != '[]' && needs.find-issues.outputs.issue_numbers != '' runs-on: 'ubuntu-latest' strategy: matrix: - issue_number: ${{ fromJSON(needs.find-issues.outputs.issue_numbers) }} + issue_number: '${{ fromJSON(needs.find-issues.outputs.issue_numbers) }}' max-parallel: 3 fail-fast: false permissions: From a416cf5f8888d9b71da7392b68b653ea99ee4724 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:21:56 -0400 Subject: [PATCH 03/32] feat(examples): optimize issue cleanup prompt for efficiency --- .../workflows/issue-cleanup/gemini-issue-cleanup.toml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index b8d9f302f..52883ad28 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -3,13 +3,18 @@ prompt = """ ## Role You are an expert AI triage assistant and repository maintainer for the `google-gemini/gemini-cli` repository. +## Critical Constraints +1. **Focus on the Target Issue**: DO NOT investigate the workflow files, `.github/commands/`, or how this tool is configured. Proceed immediately to Step 1. +2. **Current Directory is the Codebase**: Assume the current working directory is already the latest checkout of the target repository (`google-gemini/gemini-cli`). DO NOT attempt to clone the repository or check your remote. +3. **Efficiency**: Use your search tools (`grep_search`, `read_file`) quickly. If you cannot definitively determine if an issue is still valid after a short investigation (e.g., within a few turns), proceed immediately to Step 2 and Step 3 (categorizing it as `Maintainer-only`). DO NOT spend excessive turns exploring the codebase. + ## Task Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `google-gemini/gemini-cli` and sequentially perform three specific checks. You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command(gh)`) to investigate the codebase and issue tracker. Do NOT guess or hallucinate. ### Step 1: Check Code Validity - Use `gh issue view !{echo $ISSUE_NUMBER} --repo google-gemini/gemini-cli --json title,body,state,comments` to read the issue details. -- Search the local workspace (which contains the latest `google-gemini/gemini-cli` code) to determine if the issue is still valid. +- Search the local workspace to determine if the issue is still valid. - For example, if it's a bug, does the buggy code still exist? If it's a feature request, has it already been implemented? - If you definitively determine the issue is NO LONGER VALID: - Close the issue and leave a brief comment explaining why (e.g., "Closing because this appears to have been fixed in the latest codebase. "). @@ -27,7 +32,7 @@ You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command ### Step 3: Provide Triage Summary - If the issue is still valid and NOT a duplicate, add a brief summary comment for further triaging. - State whether the issue should be categorized as: - - **Maintainer-only**: (e.g., epic, core architecture, sensitive fixes, internal tasks) + - **Maintainer-only**: (e.g., epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) - **Help-wanted**: (e.g., good for community, general bugs, features, or tasks ready for external help) - Your comment should be brief and clearly explain *why* it fits that category. - Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n**Category:** \n\n**Reasoning:** " --repo google-gemini/gemini-cli` From 0d94b4bb9b82d2bdd98fb19108711c67442c80b9 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:23:52 -0400 Subject: [PATCH 04/32] feat(examples): instruct agent to explicitly clone the target repository --- examples/workflows/issue-cleanup/gemini-issue-cleanup.toml | 6 +++--- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 52883ad28..c39644c2b 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -4,9 +4,9 @@ prompt = """ You are an expert AI triage assistant and repository maintainer for the `google-gemini/gemini-cli` repository. ## Critical Constraints -1. **Focus on the Target Issue**: DO NOT investigate the workflow files, `.github/commands/`, or how this tool is configured. Proceed immediately to Step 1. -2. **Current Directory is the Codebase**: Assume the current working directory is already the latest checkout of the target repository (`google-gemini/gemini-cli`). DO NOT attempt to clone the repository or check your remote. -3. **Efficiency**: Use your search tools (`grep_search`, `read_file`) quickly. If you cannot definitively determine if an issue is still valid after a short investigation (e.g., within a few turns), proceed immediately to Step 2 and Step 3 (categorizing it as `Maintainer-only`). DO NOT spend excessive turns exploring the codebase. +1. **Focus on the Target Issue**: DO NOT investigate the workflow files, `.github/commands/`, or how this tool is configured. +2. **Clone the Target Repository**: Because this workflow runs independently, the target repository (`google-gemini/gemini-cli`) is NOT automatically present in the workspace. You MUST explicitly clone it (e.g., `git clone https://github.com/google-gemini/gemini-cli.git target-repo`) before beginning your investigation in Step 1. +3. **Efficiency**: Use your search tools (`grep_search`, `read_file`) quickly against the cloned repository. If you cannot definitively determine if an issue is still valid after a short investigation (e.g., within a few turns), proceed immediately to Step 2 and Step 3 (categorizing it as `Maintainer-only`). DO NOT spend excessive turns exploring the codebase. ## Task Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `google-gemini/gemini-cli` and sequentially perform three specific checks. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index ab205b0d9..3e459a3fc 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -61,10 +61,8 @@ jobs: id-token: 'write' issues: 'write' steps: - - name: 'Checkout Target Repository Code' + - name: 'Checkout Current Repository' uses: 'actions/checkout@v4' - with: - repository: 'google-gemini/gemini-cli' - name: 'Run Gemini Issue Cleanup' uses: 'google-github-actions/run-gemini-cli@v0' # Replace with actual version when deploying @@ -89,7 +87,8 @@ jobs: "core": [ "grep_search", "read_file", - "run_shell_command(gh)" + "run_shell_command(gh)", + "run_shell_command(git)" ] } } From 0eedc99208ea5d8dd6b06c1826280ff2d64b4c5e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:25:37 -0400 Subject: [PATCH 05/32] fix(examples): apply PR review suggestions for issue cleanup workflow --- examples/workflows/issue-cleanup/README.md | 8 +++----- .../issue-cleanup/gemini-issue-cleanup.toml | 16 ++++++++-------- .../issue-cleanup/gemini-issue-cleanup.yml | 9 +++++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 8b117bb47..22d9ebcb0 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -12,12 +12,10 @@ The Issue Cleanup workflow is designed to automate the triage of stale issues by ## Usage -This example is tailored to process issues in a specific repository (`google-gemini/gemini-cli`) matching specific labels (`area/core`, `area/extensions`, `area/site`, `area/non-interactive`), selecting the 10 issues with the oldest last update time. +This example is tailored to process issues in your repository matching specific labels (`area/core`, `area/extensions`, `area/site`, `area/non-interactive`), selecting the 10 issues with the oldest last update time. To adapt this to your own repository: 1. Copy `gemini-issue-cleanup.yml` to your repository's `.github/workflows/` directory. -2. Update the repository name and search string in the `Find old issues for cleanup` step in `gemini-issue-cleanup.yml`. -3. Update the repository name in the `Checkout Target Repository Code` step in `gemini-issue-cleanup.yml`. -4. Copy `gemini-issue-cleanup.toml` to your `.github/commands/` directory. -5. Update the prompt instructions in `gemini-issue-cleanup.toml` replacing `google-gemini/gemini-cli` with your repository name. +2. Update the search string in the `Find old issues for cleanup` step in `gemini-issue-cleanup.yml` to match your repository's labels. +3. Copy `gemini-issue-cleanup.toml` to your `.github/commands/` directory. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index c39644c2b..5fa25ac42 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,32 +1,32 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ ## Role -You are an expert AI triage assistant and repository maintainer for the `google-gemini/gemini-cli` repository. +You are an expert AI triage assistant and repository maintainer for the `!{echo $REPOSITORY}` repository. ## Critical Constraints 1. **Focus on the Target Issue**: DO NOT investigate the workflow files, `.github/commands/`, or how this tool is configured. -2. **Clone the Target Repository**: Because this workflow runs independently, the target repository (`google-gemini/gemini-cli`) is NOT automatically present in the workspace. You MUST explicitly clone it (e.g., `git clone https://github.com/google-gemini/gemini-cli.git target-repo`) before beginning your investigation in Step 1. +2. **Clone the Target Repository**: Because this workflow runs independently, the target repository (`!{echo $REPOSITORY}`) is NOT automatically present in the workspace. You MUST explicitly clone it (e.g., `git clone https://github.com/!{echo $REPOSITORY}.git target-repo`) before beginning your investigation in Step 1. 3. **Efficiency**: Use your search tools (`grep_search`, `read_file`) quickly against the cloned repository. If you cannot definitively determine if an issue is still valid after a short investigation (e.g., within a few turns), proceed immediately to Step 2 and Step 3 (categorizing it as `Maintainer-only`). DO NOT spend excessive turns exploring the codebase. ## Task -Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `google-gemini/gemini-cli` and sequentially perform three specific checks. +Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `!{echo $REPOSITORY}` and sequentially perform three specific checks. You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command(gh)`) to investigate the codebase and issue tracker. Do NOT guess or hallucinate. ### Step 1: Check Code Validity -- Use `gh issue view !{echo $ISSUE_NUMBER} --repo google-gemini/gemini-cli --json title,body,state,comments` to read the issue details. +- Use `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,state,comments` to read the issue details. - Search the local workspace to determine if the issue is still valid. - For example, if it's a bug, does the buggy code still exist? If it's a feature request, has it already been implemented? - If you definitively determine the issue is NO LONGER VALID: - Close the issue and leave a brief comment explaining why (e.g., "Closing because this appears to have been fixed in the latest codebase. "). - - Use `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase. " --repo google-gemini/gemini-cli` + - Use `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase. " --repo !{echo $REPOSITORY}` - STOP execution. You are done with this issue. ### Step 2: Check for Duplicates - If the issue is still valid, check if it's a duplicate of another issue that is already being tracked or worked on. -- Use `gh issue list --search "" --repo google-gemini/gemini-cli --state all` with relevant keywords to find potential duplicates. +- Use `gh issue list --search "" --repo !{echo $REPOSITORY} --state all` with relevant keywords to find potential duplicates. - If you find a clear duplicate that someone is working on or has already resolved: - Close the issue as not planned, pointing to the duplicate. - - Use `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo google-gemini/gemini-cli` + - Use `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` - STOP execution. You are done with this issue. ### Step 3: Provide Triage Summary @@ -35,6 +35,6 @@ You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command - **Maintainer-only**: (e.g., epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) - **Help-wanted**: (e.g., good for community, general bugs, features, or tasks ready for external help) - Your comment should be brief and clearly explain *why* it fits that category. -- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n**Category:** \n\n**Reasoning:** " --repo google-gemini/gemini-cli` +- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n**Category:** \n\n**Reasoning:** " --repo !{echo $REPOSITORY}` - STOP execution. You are done with this issue. """ diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 3e459a3fc..5520ddfdb 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -25,18 +25,18 @@ jobs: GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' run: |- echo '๐Ÿ” Finding old issues for cleanup...' - # Query matches target: google-gemini/gemini-cli, open issues, sorted by oldest last update time + # Query matches target repository, open issues, sorted by oldest last update time # with labels area/core, area/extensions, area/site, area/non-interactive ISSUES="$(gh issue list \ - --repo google-gemini/gemini-cli \ + --repo ${{ github.repository }} \ --state 'open' \ --search "label:area/core,area/extensions,area/site,area/non-interactive sort:updated-asc" \ --json number \ --limit 10 \ )" - # Convert to JSON array of integers - ISSUE_NUMBERS="$(echo "${ISSUES}" | jq -c '[.[].number | tostring]')" + # Convert to JSON array + ISSUE_NUMBERS="$(echo "${ISSUES}" | jq -c '[.[].number]')" if [ "${ISSUE_NUMBERS}" = "[]" ] || [ -z "${ISSUE_NUMBERS}" ]; then echo "issue_numbers=[]" >> "${GITHUB_OUTPUT}" @@ -68,6 +68,7 @@ jobs: uses: 'google-github-actions/run-gemini-cli@v0' # Replace with actual version when deploying env: ISSUE_NUMBER: '${{ matrix.issue_number }}' + REPOSITORY: '${{ github.repository }}' GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' with: # Modify the auth settings depending on your environment From 298d9d65b02c38243c45343535a8fdcf17c65b8e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:27:20 -0400 Subject: [PATCH 06/32] feat(examples): allow custom instructions for issue cleanup triage summary --- examples/workflows/issue-cleanup/README.md | 2 +- .../workflows/issue-cleanup/gemini-issue-cleanup.toml | 10 +++++----- .../workflows/issue-cleanup/gemini-issue-cleanup.yml | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 22d9ebcb0..6775d7172 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -8,7 +8,7 @@ The Issue Cleanup workflow is designed to automate the triage of stale issues by 1. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. 2. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. -3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment categorizing it as either `Maintainer-only` (epic, sensitive, internal) or `Help-wanted` (community-friendly). +3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). ## Usage diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 5fa25ac42..401ae5e4a 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -31,10 +31,10 @@ You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command ### Step 3: Provide Triage Summary - If the issue is still valid and NOT a duplicate, add a brief summary comment for further triaging. -- State whether the issue should be categorized as: - - **Maintainer-only**: (e.g., epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) - - **Help-wanted**: (e.g., good for community, general bugs, features, or tasks ready for external help) -- Your comment should be brief and clearly explain *why* it fits that category. -- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n**Category:** \n\n**Reasoning:** " --repo !{echo $REPOSITORY}` +- To formulate your summary, follow these custom instructions: +``` +!{echo $CUSTOM_INSTRUCTIONS} +``` +- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` - STOP execution. You are done with this issue. """ diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 5520ddfdb..837cb77ec 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -70,6 +70,7 @@ jobs: ISSUE_NUMBER: '${{ matrix.issue_number }}' REPOSITORY: '${{ github.repository }}' GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' + CUSTOM_INSTRUCTIONS: 'State whether the issue should be categorized as **Maintainer-only** (epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) or **Help-wanted** (good for community, general bugs, features, or tasks ready for external help). Your comment should be brief and clearly explain *why* it fits that category.' with: # Modify the auth settings depending on your environment gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}' From cf62bef248e943d6b5eabdc951efae695e9a3036 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 15:28:38 -0400 Subject: [PATCH 07/32] feat(examples): support fallback to standard triage summary if custom instructions are omitted --- examples/workflows/issue-cleanup/README.md | 2 +- examples/workflows/issue-cleanup/gemini-issue-cleanup.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 6775d7172..36476e286 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -8,7 +8,7 @@ The Issue Cleanup workflow is designed to automate the triage of stale issues by 1. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. 2. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. -3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). +3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary (identifying the core problem, impact, and next steps). ## Usage diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 401ae5e4a..da9a5f769 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -31,10 +31,10 @@ You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command ### Step 3: Provide Triage Summary - If the issue is still valid and NOT a duplicate, add a brief summary comment for further triaging. -- To formulate your summary, follow these custom instructions: +- If custom instructions are provided below, use them to formulate your summary. Otherwise, formulate a standard triage summary (e.g., identifying the core problem, potential impact, and recommended next steps for a maintainer). ``` !{echo $CUSTOM_INSTRUCTIONS} ``` -- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` +- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` - STOP execution. You are done with this issue. """ From 1cdeb18f996d7592b7b124cf710389f2c9964670 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 16:03:12 -0400 Subject: [PATCH 08/32] feat(examples): add staleness check and optimize cleanup bot --- examples/workflows/issue-cleanup/README.md | 7 +-- .../issue-cleanup/gemini-issue-cleanup.toml | 53 +++++++++---------- .../issue-cleanup/gemini-issue-cleanup.yml | 4 +- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 36476e286..6c5b6f4d4 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,9 +6,10 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. -2. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. -3. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary (identifying the core problem, impact, and next steps). +1. **Check for Staleness and Vagueness**: Identifies issues with insufficient information. If a request for more information has gone unanswered for over a week, it closes the issue. If it's a new vague issue, it asks the reporter for specific details. +2. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. +3. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. +4. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary (identifying the core problem, impact, and next steps). ## Usage diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index da9a5f769..e090f70cc 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,40 +1,39 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ ## Role -You are an expert AI triage assistant and repository maintainer for the `!{echo $REPOSITORY}` repository. +You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your job is to process Issue #!{echo $ISSUE_NUMBER} as efficiently as possible. ## Critical Constraints -1. **Focus on the Target Issue**: DO NOT investigate the workflow files, `.github/commands/`, or how this tool is configured. -2. **Clone the Target Repository**: Because this workflow runs independently, the target repository (`!{echo $REPOSITORY}`) is NOT automatically present in the workspace. You MUST explicitly clone it (e.g., `git clone https://github.com/!{echo $REPOSITORY}.git target-repo`) before beginning your investigation in Step 1. -3. **Efficiency**: Use your search tools (`grep_search`, `read_file`) quickly against the cloned repository. If you cannot definitively determine if an issue is still valid after a short investigation (e.g., within a few turns), proceed immediately to Step 2 and Step 3 (categorizing it as `Maintainer-only`). DO NOT spend excessive turns exploring the codebase. +1. **NO META-ANALYSIS**: DO NOT read local files in the repository you are running in (like `package.json`, `README.md`, or `.github/`). Only read files within the `target-repo/` folder you clone in Step 1. +2. **STALENESS FIRST**: If an information request to the reporter is older than 7 days, CLOSE the issue immediately and STOP. Do not investigate the code. +3. **MANDATORY SERIAL START**: In your very first turn, you MUST execute exactly these three tools: + - `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` + - `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json author,comments,updatedAt` + - `date` -## Task -Your task is to analyze GitHub Issue #!{echo $ISSUE_NUMBER} in `!{echo $REPOSITORY}` and sequentially perform three specific checks. -You MUST use your tools (like `grep_search`, `read_file`, and `run_shell_command(gh)`) to investigate the codebase and issue tracker. Do NOT guess or hallucinate. +## Task Lifecycle -### Step 1: Check Code Validity -- Use `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,state,comments` to read the issue details. -- Search the local workspace to determine if the issue is still valid. - - For example, if it's a bug, does the buggy code still exist? If it's a feature request, has it already been implemented? -- If you definitively determine the issue is NO LONGER VALID: - - Close the issue and leave a brief comment explaining why (e.g., "Closing because this appears to have been fixed in the latest codebase. "). - - Use `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase. " --repo !{echo $REPOSITORY}` - - STOP execution. You are done with this issue. +### Step 1: Staleness & Vagueness Check +- Examine the `gh issue view` output. +- **Vagueness**: If the issue is too vague (no logs, no repro steps), @mention the reporter asking for specific details. STOP. +- **Staleness**: If a maintainer or bot previously asked for information and it has been more than 7 days (check against `date`) and the reporter has NOT replied: + - `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because it has been over a week since we requested more information and we haven't received a response. Feel free to reopen if you can provide the requested details." --repo !{echo $REPOSITORY}` + - STOP execution. +- If not stale or vague, proceed to Step 2. -### Step 2: Check for Duplicates -- If the issue is still valid, check if it's a duplicate of another issue that is already being tracked or worked on. -- Use `gh issue list --search "" --repo !{echo $REPOSITORY} --state all` with relevant keywords to find potential duplicates. -- If you find a clear duplicate that someone is working on or has already resolved: - - Close the issue as not planned, pointing to the duplicate. - - Use `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` - - STOP execution. You are done with this issue. +### Step 2: Code Validity Check +- Search `target-repo/` to see if the bug still exists or the feature is already implemented. +- If fixed: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase." --repo !{echo $REPOSITORY}`. STOP. -### Step 3: Provide Triage Summary -- If the issue is still valid and NOT a duplicate, add a brief summary comment for further triaging. -- If custom instructions are provided below, use them to formulate your summary. Otherwise, formulate a standard triage summary (e.g., identifying the core problem, potential impact, and recommended next steps for a maintainer). +### Step 3: Duplicate Check +- Search for duplicates using `gh issue list`. +- If found: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}`. STOP. + +### Step 4: Triage Summary +- If unique and valid, provide a summary comment using these instructions: ``` !{echo $CUSTOM_INSTRUCTIONS} ``` -- Use `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` -- STOP execution. You are done with this issue. +- Action: `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` +- STOP. """ diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 837cb77ec..c6363f9af 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -89,8 +89,10 @@ jobs: "core": [ "grep_search", "read_file", + "list_directory", "run_shell_command(gh)", - "run_shell_command(git)" + "run_shell_command(git)", + "run_shell_command(date)" ] } } From 225eca7a90acc0df343f045876624706c839f3b6 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 18:42:16 -0400 Subject: [PATCH 09/32] feat(examples): separate staleness check from agent via github-script --- examples/workflows/issue-cleanup/README.md | 9 +-- .../issue-cleanup/gemini-issue-cleanup.toml | 33 ++++++----- .../issue-cleanup/gemini-issue-cleanup.yml | 57 +++++++++++++++++++ 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 6c5b6f4d4..89ddf5f66 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,10 +6,11 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness and Vagueness**: Identifies issues with insufficient information. If a request for more information has gone unanswered for over a week, it closes the issue. If it's a new vague issue, it asks the reporter for specific details. -2. **Check Code Validity**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. -3. **Find Duplicates**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. -4. **Summarize for Triage**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary (identifying the core problem, impact, and next steps). +1. **Check for Staleness (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days. If so, it closes the issue directly via a GitHub Action script to save AI resources. +2. **Check for Vagueness (AI)**: If an issue is not stale but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. +3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. +4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. +5. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. ## Usage diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index e090f70cc..d3b3f0623 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,33 +1,32 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ -## Role You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your job is to process Issue #!{echo $ISSUE_NUMBER} as efficiently as possible. ## Critical Constraints 1. **NO META-ANALYSIS**: DO NOT read local files in the repository you are running in (like `package.json`, `README.md`, or `.github/`). Only read files within the `target-repo/` folder you clone in Step 1. -2. **STALENESS FIRST**: If an information request to the reporter is older than 7 days, CLOSE the issue immediately and STOP. Do not investigate the code. -3. **MANDATORY SERIAL START**: In your very first turn, you MUST execute exactly these three tools: - - `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` - - `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json author,comments,updatedAt` - - `date` +2. **EFFICIENCY**: If the issue is too vague, close it immediately and stop. Do not investigate code for vague issues. ## Task Lifecycle -### Step 1: Staleness & Vagueness Check -- Examine the `gh issue view` output. -- **Vagueness**: If the issue is too vague (no logs, no repro steps), @mention the reporter asking for specific details. STOP. -- **Staleness**: If a maintainer or bot previously asked for information and it has been more than 7 days (check against `date`) and the reporter has NOT replied: - - `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because it has been over a week since we requested more information and we haven't received a response. Feel free to reopen if you can provide the requested details." --repo !{echo $REPOSITORY}` - - STOP execution. -- If not stale or vague, proceed to Step 2. +### Step 1: Setup & Vagueness Check +- Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` +- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments` +- **Vagueness Check**: If the issue description is fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet: + - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` + - **STOP EXECUTION IMMEDIATELY**. +- If the issue is clear or the reporter has provided info, proceed to Step 2. ### Step 2: Code Validity Check - Search `target-repo/` to see if the bug still exists or the feature is already implemented. -- If fixed: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase." --repo !{echo $REPOSITORY}`. STOP. +- If definitively NO LONGER VALID: + - Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase." --repo !{echo $REPOSITORY}` + - **STOP EXECUTION IMMEDIATELY**. ### Step 3: Duplicate Check -- Search for duplicates using `gh issue list`. -- If found: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}`. STOP. +- Search for duplicates using `gh issue list --search "" --repo !{echo $REPOSITORY} --state all` +- If a clear duplicate is found: + - Close it: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` + - **STOP EXECUTION IMMEDIATELY**. ### Step 4: Triage Summary - If unique and valid, provide a summary comment using these instructions: @@ -35,5 +34,5 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j !{echo $CUSTOM_INSTRUCTIONS} ``` - Action: `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` -- STOP. +- **STOP EXECUTION**. """ diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index c6363f9af..7420fb93e 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -61,10 +61,67 @@ jobs: id-token: 'write' issues: 'write' steps: + - name: 'Check for Staleness' + id: 'staleness' + uses: 'actions/github-script@v7' + env: + ISSUE_NUMBER: '${{ matrix.issue_number }}' + with: + script: |- + const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10); + console.log(`Checking staleness for issue #${issueNumber}`); + + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + }); + const reporter = issue.user.login; + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + }); + + // Find last maintainer comment + const maintainerComments = comments.filter(c => c.user.login !== reporter && !c.user.login.includes('github-actions') && c.user.type !== 'Bot'); + + if (maintainerComments.length > 0) { + const lastMaintainerComment = maintainerComments[maintainerComments.length - 1]; + const reporterReplied = comments.some(c => c.user.login === reporter && new Date(c.created_at) > new Date(lastMaintainerComment.created_at)); + + if (!reporterReplied) { + const daysAgo = (new Date() - new Date(lastMaintainerComment.created_at)) / (1000 * 60 * 60 * 24); + console.log(`Last maintainer comment was ${daysAgo.toFixed(1)} days ago.`); + + if (daysAgo > 7) { + console.log(`Issue is stale. Closing.`); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: "Closing because it has been over a week since we requested more information and we haven't received a response. Feel free to reopen if you can provide the requested details." + }); + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + state: 'closed' + }); + core.setOutput('is_stale', 'true'); + return; + } + } + } + core.setOutput('is_stale', 'false'); + - name: 'Checkout Current Repository' + if: steps.staleness.outputs.is_stale != 'true' uses: 'actions/checkout@v4' - name: 'Run Gemini Issue Cleanup' + if: steps.staleness.outputs.is_stale != 'true' uses: 'google-github-actions/run-gemini-cli@v0' # Replace with actual version when deploying env: ISSUE_NUMBER: '${{ matrix.issue_number }}' From 6cee6e808e325425760225aec64f302b65261372 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 18:43:40 -0400 Subject: [PATCH 10/32] feat(examples): support explicit maintainers input for staleness check --- examples/workflows/issue-cleanup/README.md | 3 ++- .../issue-cleanup/gemini-issue-cleanup.yml | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 89ddf5f66..d8ad0edc8 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -20,4 +20,5 @@ To adapt this to your own repository: 1. Copy `gemini-issue-cleanup.yml` to your repository's `.github/workflows/` directory. 2. Update the search string in the `Find old issues for cleanup` step in `gemini-issue-cleanup.yml` to match your repository's labels. -3. Copy `gemini-issue-cleanup.toml` to your `.github/commands/` directory. +3. Configure the `maintainers` input in `gemini-issue-cleanup.yml` (either via the workflow dispatch inputs or by setting the `MAINTAINERS` repository variable) to explicitly list which users count as maintainers for the staleness check. +4. Copy `gemini-issue-cleanup.toml` to your `.github/commands/` directory. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 7420fb93e..4d6f63824 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -4,6 +4,11 @@ on: schedule: - cron: '0 0 * * 0' # Runs weekly at midnight on Sunday workflow_dispatch: + inputs: + maintainers: + description: 'Comma-separated list of maintainer usernames (e.g., gemini-cli)' + required: false + default: 'gemini-cli' concurrency: group: '${{ github.workflow }}' @@ -66,11 +71,14 @@ jobs: uses: 'actions/github-script@v7' env: ISSUE_NUMBER: '${{ matrix.issue_number }}' + MAINTAINERS: "${{ inputs.maintainers || vars.MAINTAINERS || ' }}" with: script: |- const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10); console.log(`Checking staleness for issue #${issueNumber}`); + const maintainers = process.env.MAINTAINERS ? process.env.MAINTAINERS.split(',').map(m => m.trim()) : []; + const { data: issue } = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, @@ -85,8 +93,11 @@ jobs: }); // Find last maintainer comment - const maintainerComments = comments.filter(c => c.user.login !== reporter && !c.user.login.includes('github-actions') && c.user.type !== 'Bot'); - + const maintainerComments = comments.filter(c => { + if (c.user.login === reporter) return false; + if (maintainers.length > 0) return maintainers.includes(c.user.login); + return !c.user.login.includes('github-actions') && c.user.type !== 'Bot'; + }); if (maintainerComments.length > 0) { const lastMaintainerComment = maintainerComments[maintainerComments.length - 1]; const reporterReplied = comments.some(c => c.user.login === reporter && new Date(c.created_at) > new Date(lastMaintainerComment.created_at)); From 3652158cfe85b24c9419eeb3cfb5f3e7a0b4faeb Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 18:45:11 -0400 Subject: [PATCH 11/32] fix(examples): fix YAML syntax error for MAINTAINERS environment variable fallback --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 4d6f63824..807d857e4 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -71,7 +71,7 @@ jobs: uses: 'actions/github-script@v7' env: ISSUE_NUMBER: '${{ matrix.issue_number }}' - MAINTAINERS: "${{ inputs.maintainers || vars.MAINTAINERS || ' }}" + MAINTAINERS: '${{ inputs.maintainers || vars.MAINTAINERS }}' with: script: |- const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10); From d5722736e5d63730804f1cd57ff783accb6fc1e9 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:02:39 -0400 Subject: [PATCH 12/32] feat(examples): enable AI to write and execute reproduction scripts to verify bug fixes --- examples/workflows/issue-cleanup/README.md | 2 +- .../workflows/issue-cleanup/gemini-issue-cleanup.toml | 9 +++++---- .../workflows/issue-cleanup/gemini-issue-cleanup.yml | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index d8ad0edc8..9d81c17a4 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -8,7 +8,7 @@ The Issue Cleanup workflow is designed to automate the triage of stale issues by 1. **Check for Staleness (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days. If so, it closes the issue directly via a GitHub Action script to save AI resources. 2. **Check for Vagueness (AI)**: If an issue is not stale but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. -3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. If the issue has already been resolved implicitly, it will close the issue with an explanation. +3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. 5. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index d3b3f0623..999ad0d73 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -16,10 +16,11 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j - **STOP EXECUTION IMMEDIATELY**. - If the issue is clear or the reporter has provided info, proceed to Step 2. -### Step 2: Code Validity Check -- Search `target-repo/` to see if the bug still exists or the feature is already implemented. -- If definitively NO LONGER VALID: - - Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because this appears to have been fixed in the latest codebase." --repo !{echo $REPOSITORY}` +### Step 2: Reproduction & Code Validity Check +- If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. +- Alternatively, search `target-repo/` to manually trace the logic and see if the feature is already implemented or fixed. +- If you can prove the issue is definitively NO LONGER VALID (e.g., your reproduction script works correctly without the bug, or the code has clearly been fixed): + - Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because I have verified this works correctly in the latest codebase. " --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. ### Step 3: Duplicate Check diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 807d857e4..5b16379a0 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -160,7 +160,8 @@ jobs: "list_directory", "run_shell_command(gh)", "run_shell_command(git)", - "run_shell_command(date)" + "run_shell_command(date)", + "run_shell_command(node)" ] } } From d0904f59f991a81f2e65a2d93be4e9c35789eb40 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:05:01 -0400 Subject: [PATCH 13/32] feat(examples): add 1-month age check for issue cleanup --- examples/workflows/issue-cleanup/README.md | 2 +- .../workflows/issue-cleanup/gemini-issue-cleanup.toml | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 9d81c17a4..8416fe2c6 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -7,7 +7,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: 1. **Check for Staleness (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days. If so, it closes the issue directly via a GitHub Action script to save AI resources. -2. **Check for Vagueness (AI)**: If an issue is not stale but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. +2. **Check for Age and Vagueness (AI)**: If an issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce the issue with the latest build. If the issue lacks sufficient information (e.g., reproduction steps), it asks the reporter for specific details and stops. 3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. 5. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 999ad0d73..7277a7438 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -8,13 +8,16 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j ## Task Lifecycle -### Step 1: Setup & Vagueness Check +### Step 1: Setup, Age & Vagueness Check - Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` -- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments` +- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,updatedAt` +- **Age Check**: If the issue was last updated over 1 month ago (compare `updatedAt` to the current `date`): + - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs?" --repo !{echo $REPOSITORY}` + - **STOP EXECUTION IMMEDIATELY**. - **Vagueness Check**: If the issue description is fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet: - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -- If the issue is clear or the reporter has provided info, proceed to Step 2. +- If the issue is clear, recent, or the reporter has provided info, proceed to Step 2. ### Step 2: Reproduction & Code Validity Check - If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. From 2b10d1f53ca1e6da64791a119e9ced69078541a4 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:05:27 -0400 Subject: [PATCH 14/32] feat(examples): ask for detailed reproduction steps in 1-month age check --- examples/workflows/issue-cleanup/gemini-issue-cleanup.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 7277a7438..655b6d7dd 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -12,7 +12,7 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j - Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` - Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,updatedAt` - **Age Check**: If the issue was last updated over 1 month ago (compare `updatedAt` to the current `date`): - - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs?" --repo !{echo $REPOSITORY}` + - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs? If so, please provide detailed reproduction steps." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. - **Vagueness Check**: If the issue description is fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet: - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` From 55bf172ecc31427601617d03a4b8054a7aaf594e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:12:22 -0400 Subject: [PATCH 15/32] feat(examples): move 1-month age check to native github-script step --- examples/workflows/issue-cleanup/README.md | 4 ++-- .../issue-cleanup/gemini-issue-cleanup.toml | 9 +++------ .../issue-cleanup/gemini-issue-cleanup.yml | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 8416fe2c6..79ea84a08 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,8 +6,8 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days. If so, it closes the issue directly via a GitHub Action script to save AI resources. -2. **Check for Age and Vagueness (AI)**: If an issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce the issue with the latest build. If the issue lacks sufficient information (e.g., reproduction steps), it asks the reporter for specific details and stops. +1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce the issue with the latest build. This is handled via a native GitHub Action script to save AI resources. +2. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. 5. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 655b6d7dd..999ad0d73 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -8,16 +8,13 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j ## Task Lifecycle -### Step 1: Setup, Age & Vagueness Check +### Step 1: Setup & Vagueness Check - Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` -- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,updatedAt` -- **Age Check**: If the issue was last updated over 1 month ago (compare `updatedAt` to the current `date`): - - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs? If so, please provide detailed reproduction steps." --repo !{echo $REPOSITORY}` - - **STOP EXECUTION IMMEDIATELY**. +- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments` - **Vagueness Check**: If the issue description is fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet: - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -- If the issue is clear, recent, or the reporter has provided info, proceed to Step 2. +- If the issue is clear or the reporter has provided info, proceed to Step 2. ### Step 2: Reproduction & Code Validity Check - If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 5b16379a0..de9bdd5b8 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -125,6 +125,23 @@ jobs: } } } + + // Check overall issue age / inactivity + const lastUpdateDaysAgo = (new Date() - new Date(issue.updated_at)) / (1000 * 60 * 60 * 24); + console.log(`Issue was last updated ${lastUpdateDaysAgo.toFixed(1)} days ago.`); + + if (lastUpdateDaysAgo > 30) { + console.log(`Issue has been inactive for over a month. Asking for repro.`); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs? If so, please provide detailed reproduction steps.` + }); + core.setOutput('is_stale', 'true'); + return; + } + core.setOutput('is_stale', 'false'); - name: 'Checkout Current Repository' From 67c955466683b56af4e53aa7fcbf500455c93d99 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:16:28 -0400 Subject: [PATCH 16/32] fix(examples): expand staleness maintainer check to include repository members --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index de9bdd5b8..254f644dd 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -95,7 +95,8 @@ jobs: // Find last maintainer comment const maintainerComments = comments.filter(c => { if (c.user.login === reporter) return false; - if (maintainers.length > 0) return maintainers.includes(c.user.login); + const isMaintainer = maintainers.includes(c.user.login) || ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(c.author_association); + if (maintainers.length > 0) return isMaintainer; return !c.user.login.includes('github-actions') && c.user.type !== 'Bot'; }); if (maintainerComments.length > 0) { From 7892be4040ed92555d23d1ab1b6fecc10fb6aa2f Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:23:14 -0400 Subject: [PATCH 17/32] feat(examples): update issue labels during staleness and inactivity checks --- .../issue-cleanup/gemini-issue-cleanup.yml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 254f644dd..009f66967 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -109,6 +109,29 @@ jobs: if (daysAgo > 7) { console.log(`Issue is stale. Closing.`); + + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + name: 'status/need-triage' + }); + } catch (e) { + // Ignore + } + + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + labels: ['status/needs-info'] + }); + } catch (e) { + console.log('Failed to add needs-info label:', e.message); + } + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, @@ -133,6 +156,29 @@ jobs: if (lastUpdateDaysAgo > 30) { console.log(`Issue has been inactive for over a month. Asking for repro.`); + + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + name: 'status/need-triage' + }); + } catch (e) { + // Ignore if label doesn't exist + } + + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + labels: ['status/needs-info'] + }); + } catch (e) { + console.log('Failed to add needs-info label:', e.message); + } + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, From fa2f69922c96b3cf7d49cf351802e3815ba81b89 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:27:42 -0400 Subject: [PATCH 18/32] fix(examples): only update labels when asking for repro, not when closing --- .../issue-cleanup/gemini-issue-cleanup.yml | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 009f66967..5796fb2bf 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -110,28 +110,6 @@ jobs: if (daysAgo > 7) { console.log(`Issue is stale. Closing.`); - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - name: 'status/need-triage' - }); - } catch (e) { - // Ignore - } - - try { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - labels: ['status/needs-info'] - }); - } catch (e) { - console.log('Failed to add needs-info label:', e.message); - } - await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, From 7817cb2651c36ed4fadefae4f84a4eaba57e38d8 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:36:41 -0400 Subject: [PATCH 19/32] feat(examples): close issue when asking for repro after 1 month inactivity --- examples/workflows/issue-cleanup/README.md | 2 +- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 79ea84a08..7cde78c45 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,7 +6,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce the issue with the latest build. This is handled via a native GitHub Action script to save AI resources. +1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it closes the issue while asking the reporter to try reproducing it with the latest build. This is handled via a native GitHub Action script to save AI resources. 2. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 5796fb2bf..438c126fb 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -163,6 +163,12 @@ jobs: issue_number: issueNumber, body: `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs? If so, please provide detailed reproduction steps.` }); + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + state: 'closed' + }); core.setOutput('is_stale', 'true'); return; } From 0345f0781fd7a4db685046d35851f83e663862e9 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:37:28 -0400 Subject: [PATCH 20/32] feat(examples): instruct reporter to reopen issue if reproducible in latest build --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 438c126fb..e663b9e21 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -161,7 +161,7 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - body: `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build and let us know if it still occurs? If so, please provide detailed reproduction steps.` + body: `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps and feel free to reopen this issue.` }); await github.rest.issues.update({ owner: context.repo.owner, From d966b7f00c3dec281ac2b8982a2eb0902f94c80d Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:39:44 -0400 Subject: [PATCH 21/32] feat(examples): close stale and inactive issues as 'not planned' --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index e663b9e21..1d3d76418 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -120,7 +120,8 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - state: 'closed' + state: 'closed', + state_reason: 'not_planned' }); core.setOutput('is_stale', 'true'); return; @@ -167,7 +168,8 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - state: 'closed' + state: 'closed', + state_reason: 'not_planned' }); core.setOutput('is_stale', 'true'); return; From fc993bb42de7300852db434f383c6a01a6640c5e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:42:12 -0400 Subject: [PATCH 22/32] fix(examples): quote 'on' in workflow yaml to satisfy yamllint truthy rule --- examples/workflows/issue-cleanup/gemini-issue-cleanup.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 1d3d76418..65c931e0e 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -1,6 +1,6 @@ name: '๐Ÿงน Gemini Issue Cleanup' -on: +'on': schedule: - cron: '0 0 * * 0' # Runs weekly at midnight on Sunday workflow_dispatch: From a5f1f4e425dfe1c50bca173ee0f5990ba07caf56 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:50:22 -0400 Subject: [PATCH 23/32] feat(examples): exempt P0/P1 issues from auto-closing and tag assignees --- examples/workflows/issue-cleanup/README.md | 2 +- .../issue-cleanup/gemini-issue-cleanup.yml | 44 +++++++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 7cde78c45..8e0aa3dee 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,7 +6,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it closes the issue while asking the reporter to try reproducing it with the latest build. This is handled via a native GitHub Action script to save AI resources. +1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. 2. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 65c931e0e..0eec637fa 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -158,19 +158,47 @@ jobs: console.log('Failed to add needs-info label:', e.message); } - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps and feel free to reopen this issue.` + const assignees = issue.assignees.map(a => a.login); + const hasAssignees = assignees.length > 0; + const assigneeMentions = hasAssignees ? assignees.map(a => `@${a}`).join(' ') : ''; + + const isHighPriority = issue.labels.some(l => { + const name = typeof l === 'string' ? l : l.name; + const lowerName = name.toLowerCase(); + return lowerName === 'priority/p0' || lowerName === 'priority/p1' || lowerName === 'p0' || lowerName === 'p1'; }); - await github.rest.issues.update({ + + let commentBody = `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps.`; + + if (!isHighPriority) { + if (hasAssignees) { + commentBody += `\n\n${assigneeMentions}, please reopen if you are actively working on this.`; + } else { + commentBody += ` Feel free to reopen this issue.`; + } + } else { + if (hasAssignees) { + commentBody += `\n\n${assigneeMentions}, checking in on this high priority issue.`; + } + } + + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - state: 'closed', - state_reason: 'not_planned' + body: commentBody }); + + if (!isHighPriority) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + state: 'closed', + state_reason: 'not_planned' + }); + } + core.setOutput('is_stale', 'true'); return; } From d1c7784feca58d55ceb89008171b79d2a45e20a2 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:52:05 -0400 Subject: [PATCH 24/32] feat(examples): customize 30-day inactivity comment for feature requests --- examples/workflows/issue-cleanup/README.md | 2 +- .../issue-cleanup/gemini-issue-cleanup.yml | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 8e0aa3dee..8f2873b4e 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,7 +6,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. +1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. 2. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 0eec637fa..2e80e20b7 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -168,12 +168,23 @@ jobs: return lowerName === 'priority/p0' || lowerName === 'priority/p1' || lowerName === 'p0' || lowerName === 'p1'; }); - let commentBody = `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps.`; + const isFeatureRequest = issue.labels.some(l => { + const name = typeof l === 'string' ? l : l.name; + const lowerName = name.toLowerCase(); + return lowerName.includes('feature') || lowerName.includes('enhancement'); + }); + + let commentBody = ''; + if (isFeatureRequest) { + commentBody = `@${reporter}, this feature request hasn't been updated in over a month. Please reopen if this is still needed.`; + } else { + commentBody = `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps.`; + } if (!isHighPriority) { if (hasAssignees) { commentBody += `\n\n${assigneeMentions}, please reopen if you are actively working on this.`; - } else { + } else if (!isFeatureRequest) { commentBody += ` Feel free to reopen this issue.`; } } else { From 8867a8c7c87d5f0524a280459d22e4fe95fff6b9 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 19:57:52 -0400 Subject: [PATCH 25/32] feat(examples): skip triage for issues tracked by epics or projects --- examples/workflows/issue-cleanup/README.md | 11 ++--- .../issue-cleanup/gemini-issue-cleanup.yml | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 8f2873b4e..86886457b 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,11 +6,12 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. -2. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. -3. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. -4. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. -5. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. +1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. +2. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. +3. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. +4. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. +5. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. +6. **Summarize for Triage (AI)**: If an issue is still valid and unique, it provides a summary comment based on customizable instructions (e.g., categorizing it as `Maintainer-only` or `Help-wanted`). If no custom instructions are provided, it falls back to a standard triage summary. ## Usage diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 2e80e20b7..a73320160 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -79,6 +79,49 @@ jobs: const maintainers = process.env.MAINTAINERS ? process.env.MAINTAINERS.split(',').map(m => m.trim()) : []; + // First, check if it's tracked by a parent issue or part of a project + const query = ` + query($owner: String!, $repo: String!, $issueNumber: Int!) { + repository(owner: $owner, name: $repo) { + issue(number: $issueNumber) { + trackedInIssues(first: 1) { + totalCount + } + projectItems(first: 1) { + totalCount + } + } + } + } + `; + try { + const result = await github.graphql(query, { + owner: context.repo.owner, + repo: context.repo.repo, + issueNumber: issueNumber + }); + const isTracked = result.repository.issue.trackedInIssues.totalCount > 0; + const inProject = result.repository.issue.projectItems.totalCount > 0; + + if (isTracked || inProject) { + console.log(`Issue #${issueNumber} is tracked by a parent issue or project. Removing 'status/need-triage' and stopping.`); + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + name: 'status/need-triage' + }); + } catch (e) { + // Ignore if label doesn't exist + } + core.setOutput('is_stale', 'true'); + return; + } + } catch (err) { + console.log('Failed to fetch GraphQL data for parent issues/projects:', err.message); + } + const { data: issue } = await github.rest.issues.get({ owner: context.repo.owner, repo: context.repo.repo, From afec57e8980be3d5a3d01765bfeca4097b97e27a Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:03:10 -0400 Subject: [PATCH 26/32] feat(examples): ask reporter for clarification on unassigned feature requests tracked by projects --- examples/workflows/issue-cleanup/README.md | 2 +- .../issue-cleanup/gemini-issue-cleanup.yml | 33 +++++++++++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index 86886457b..a741a7c5d 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,7 +6,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. +1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. If it is a feature request and currently has no assignees, it additionally asks the reporter if it is still needed. 2. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. 3. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 4. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index a73320160..3d556662b 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -79,6 +79,13 @@ jobs: const maintainers = process.env.MAINTAINERS ? process.env.MAINTAINERS.split(',').map(m => m.trim()) : []; + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + }); + const reporter = issue.user.login; + // First, check if it's tracked by a parent issue or part of a project const query = ` query($owner: String!, $repo: String!, $issueNumber: Int!) { @@ -115,6 +122,25 @@ jobs: } catch (e) { // Ignore if label doesn't exist } + + const assignees = issue.assignees.map(a => a.login); + const hasAssignees = assignees.length > 0; + + const isFeatureRequest = issue.labels.some(l => { + const name = typeof l === 'string' ? l : l.name; + const lowerName = name.toLowerCase(); + return lowerName.includes('feature') || lowerName.includes('enhancement'); + }); + + if (isFeatureRequest && !hasAssignees) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `@${reporter}, this feature request is currently tracked by an epic or project but has no assignees. Could you please let us know if this is still needed?` + }); + } + core.setOutput('is_stale', 'true'); return; } @@ -122,13 +148,6 @@ jobs: console.log('Failed to fetch GraphQL data for parent issues/projects:', err.message); } - const { data: issue } = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - }); - const reporter = issue.user.login; - const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, From 017c0776234c219933f4e679d7ab39e2f407e1fc Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:08:58 -0400 Subject: [PATCH 27/32] feat(examples): ask for repro on tracked non-feature issues with no assignees --- examples/workflows/issue-cleanup/README.md | 2 +- .../workflows/issue-cleanup/gemini-issue-cleanup.yml | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index a741a7c5d..e202ada46 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,7 +6,7 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. If it is a feature request and currently has no assignees, it additionally asks the reporter if it is still needed. +1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. If it has no assignees, it additionally asks the reporter if it is still needed (for feature requests) or asks them to try reproducing it with the latest build (for other issues). 2. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. 3. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 4. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 3d556662b..a9d90452a 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -132,12 +132,18 @@ jobs: return lowerName.includes('feature') || lowerName.includes('enhancement'); }); - if (isFeatureRequest && !hasAssignees) { + if (!hasAssignees) { + let commentBody = ''; + if (isFeatureRequest) { + commentBody = `@${reporter}, this feature request is currently tracked by an epic or project but has no assignees. Could you please let us know if this is still needed?`; + } else { + commentBody = `@${reporter}, this issue is currently tracked by an epic or project but has no assignees. Could you please try reproducing it with the latest build and let us know if it still occurs?`; + } await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, - body: `@${reporter}, this feature request is currently tracked by an epic or project but has no assignees. Could you please let us know if this is still needed?` + body: commentBody }); } From 3d7b3cd0075bcbbd0333436c1e4bdef1c18272ff Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:12:58 -0400 Subject: [PATCH 28/32] feat(examples): check for resolved comments before asking for repro, and remove project tracking skip --- examples/workflows/issue-cleanup/README.md | 4 +- .../issue-cleanup/gemini-issue-cleanup.yml | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/examples/workflows/issue-cleanup/README.md b/examples/workflows/issue-cleanup/README.md index e202ada46..f7c141dcd 100644 --- a/examples/workflows/issue-cleanup/README.md +++ b/examples/workflows/issue-cleanup/README.md @@ -6,8 +6,8 @@ This document describes a workflow to batch-process and clean up older open issu The Issue Cleanup workflow is designed to automate the triage of stale issues by using the Gemini CLI to: -1. **Check for Projects and Parent Issues (Native)**: Identifies if an issue is already part of a GitHub Project or tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. If it has no assignees, it additionally asks the reporter if it is still needed (for feature requests) or asks them to try reproducing it with the latest build (for other issues). -2. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. +1. **Check for Parent Issues (Native)**: Identifies if an issue is tracked by a parent issue (task list). If so, it removes the triage label and stops, assuming the issue is already being managed as part of a larger epic. If it has no assignees, it additionally asks the reporter if it is still needed (for feature requests) or asks them to try reproducing it with the latest build (for other issues). +2. **Check for Staleness and Age (Native)**: Identifies if an issue has been waiting for reporter feedback for over 7 days, closing it if so. If the issue is not stale but hasn't been updated in over a month, it first checks if the last comment indicates the issue is resolved (e.g., "functioning properly"); if so, it closes it as completed. Otherwise, it asks the reporter to reproduce it with the latest build. For feature requests, it asks to reopen if still needed. By default, it closes the inactive issue as "not planned" and tags any assignees to reopen it. However, if the issue is a high-priority (`p0` or `p1`), it leaves the issue open. This logic runs natively to save AI resources. 3. **Check for Vagueness (AI)**: If an issue is not stale or old but lacks sufficient information (e.g., reproduction steps), the agent asks the reporter for specific details and stops. 4. **Check Code Validity (AI)**: Determines if an issue is still relevant against the current codebase. The agent may attempt to write and execute a minimal reproduction script to verify if a bug has been resolved, or manually inspect the code. If verified as fixed, it will close the issue with an explanation. 5. **Find Duplicates (AI)**: Checks if the issue has a more recent duplicate. If a duplicate exists, it closes the issue and links to the duplicate. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index a9d90452a..9a0e56019 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -86,7 +86,7 @@ jobs: }); const reporter = issue.user.login; - // First, check if it's tracked by a parent issue or part of a project + // First, check if it's tracked by a parent issue const query = ` query($owner: String!, $repo: String!, $issueNumber: Int!) { repository(owner: $owner, name: $repo) { @@ -94,9 +94,6 @@ jobs: trackedInIssues(first: 1) { totalCount } - projectItems(first: 1) { - totalCount - } } } } @@ -108,10 +105,9 @@ jobs: issueNumber: issueNumber }); const isTracked = result.repository.issue.trackedInIssues.totalCount > 0; - const inProject = result.repository.issue.projectItems.totalCount > 0; - if (isTracked || inProject) { - console.log(`Issue #${issueNumber} is tracked by a parent issue or project. Removing 'status/need-triage' and stopping.`); + if (isTracked) { + console.log(`Issue #${issueNumber} is tracked by a parent issue. Removing 'status/need-triage' and stopping.`); try { await github.rest.issues.removeLabel({ owner: context.repo.owner, @@ -135,9 +131,9 @@ jobs: if (!hasAssignees) { let commentBody = ''; if (isFeatureRequest) { - commentBody = `@${reporter}, this feature request is currently tracked by an epic or project but has no assignees. Could you please let us know if this is still needed?`; + commentBody = `@${reporter}, this feature request is currently tracked by an epic but has no assignees. Could you please let us know if this is still needed?`; } else { - commentBody = `@${reporter}, this issue is currently tracked by an epic or project but has no assignees. Could you please try reproducing it with the latest build and let us know if it still occurs?`; + commentBody = `@${reporter}, this issue is currently tracked by an epic but has no assignees. Could you please try reproducing it with the latest build and let us know if it still occurs?`; } await github.rest.issues.createComment({ owner: context.repo.owner, @@ -151,7 +147,7 @@ jobs: return; } } catch (err) { - console.log('Failed to fetch GraphQL data for parent issues/projects:', err.message); + console.log('Failed to fetch GraphQL data for parent issues:', err.message); } const { data: comments } = await github.rest.issues.listComments({ @@ -202,6 +198,30 @@ jobs: console.log(`Issue was last updated ${lastUpdateDaysAgo.toFixed(1)} days ago.`); if (lastUpdateDaysAgo > 30) { + // Check if the last comment says it's fixed + if (comments.length > 0) { + const lastCommentBody = comments[comments.length - 1].body.toLowerCase(); + const resolvedKeywords = ['functioning properly', 'works now', 'is fixed', 'resolved now']; + if (resolvedKeywords.some(kw => lastCommentBody.includes(kw))) { + console.log(`Issue appears resolved in the last comment. Closing.`); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." + }); + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + state: 'closed', + state_reason: 'completed' + }); + core.setOutput('is_stale', 'true'); + return; + } + } + console.log(`Issue has been inactive for over a month. Asking for repro.`); try { From 7b58e43e4c29b514723d1bcfa7c2689580d5a77e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:15:59 -0400 Subject: [PATCH 29/32] feat(examples): let AI agent analyze comments to identify resolved issues before handling 30-day inactivity --- .../issue-cleanup/gemini-issue-cleanup.toml | 58 +++++++++- .../issue-cleanup/gemini-issue-cleanup.yml | 105 +----------------- 2 files changed, 57 insertions(+), 106 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index 999ad0d73..e2b137ed1 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -4,17 +4,65 @@ You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your j ## Critical Constraints 1. **NO META-ANALYSIS**: DO NOT read local files in the repository you are running in (like `package.json`, `README.md`, or `.github/`). Only read files within the `target-repo/` folder you clone in Step 1. -2. **EFFICIENCY**: If the issue is too vague, close it immediately and stop. Do not investigate code for vague issues. +2. **EFFICIENCY**: If the issue is too vague or inactive, close/comment immediately and stop. Do not investigate code. ## Task Lifecycle -### Step 1: Setup & Vagueness Check +### Step 1: Setup & Comment Analysis - Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` -- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments` -- **Vagueness Check**: If the issue description is fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet: +- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,labels,assignees` + +**Resolution Check (Priority 1):** +- Read the comments. Does the latest comment indicate that the issue has been fixed, resolved, or is functioning properly? + - If YES: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." --reason "completed" --repo !{echo $REPOSITORY}` + - **STOP EXECUTION IMMEDIATELY**. + +**Inactivity Check (Priority 2):** +- Is `!{echo $INACTIVE_OVER_30_DAYS}` equal to `true`? + - If YES (and it was not resolved above): Execute the following bash script exactly as written to handle the inactivity. +```bash +ISSUE_JSON=$(gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json author,labels,assignees) +REPORTER=$(echo "$ISSUE_JSON" | jq -r '.author.login') +HAS_ASSIGNEES=$(echo "$ISSUE_JSON" | jq '.assignees | length > 0') +ASSIGNEE_MENTIONS=$(echo "$ISSUE_JSON" | jq -r '.assignees | map("@" + .login) | join(" ")') +IS_HIGH_PRIORITY=$(echo "$ISSUE_JSON" | jq '.labels | map(.name | ascii_downcase) | any(. == "priority/p0" or . == "priority/p1" or . == "p0" or . == "p1")') +IS_FEATURE=$(echo "$ISSUE_JSON" | jq '.labels | map(.name | ascii_downcase) | any(contains("feature") or contains("enhancement"))') + +gh issue edit !{echo $ISSUE_NUMBER} --remove-label "status/need-triage" --repo !{echo $REPOSITORY} 2>/dev/null || true +gh issue edit !{echo $ISSUE_NUMBER} --add-label "status/needs-info" --repo !{echo $REPOSITORY} 2>/dev/null || true + +COMMENT="" +if [ "$IS_FEATURE" = "true" ]; then + COMMENT="@${REPORTER}, this feature request hasn't been updated in over a month. Please reopen if this is still needed." +else + COMMENT="@${REPORTER}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps." +fi + +if [ "$IS_HIGH_PRIORITY" = "false" ]; then + if [ "$HAS_ASSIGNEES" = "true" ]; then + COMMENT="${COMMENT}\n\n${ASSIGNEE_MENTIONS}, please reopen if you are actively working on this." + elif [ "$IS_FEATURE" = "false" ]; then + COMMENT="${COMMENT} Feel free to reopen this issue." + fi +else + if [ "$HAS_ASSIGNEES" = "true" ]; then + COMMENT="${COMMENT}\n\n${ASSIGNEE_MENTIONS}, checking in on this high priority issue." + fi +fi + +gh issue comment !{echo $ISSUE_NUMBER} --body "$COMMENT" --repo !{echo $REPOSITORY} + +if [ "$IS_HIGH_PRIORITY" = "false" ]; then + gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --repo !{echo $REPOSITORY} +fi +``` + - **STOP EXECUTION IMMEDIATELY**. + +**Vagueness Check (Priority 3):** +- If the issue is NOT inactive over 30 days: Is the issue description fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet? - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -- If the issue is clear or the reporter has provided info, proceed to Step 2. +- If the issue is clear, proceed to Step 2. ### Step 2: Reproduction & Code Validity Check - If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index 9a0e56019..f863a61c5 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -198,110 +198,12 @@ jobs: console.log(`Issue was last updated ${lastUpdateDaysAgo.toFixed(1)} days ago.`); if (lastUpdateDaysAgo > 30) { - // Check if the last comment says it's fixed - if (comments.length > 0) { - const lastCommentBody = comments[comments.length - 1].body.toLowerCase(); - const resolvedKeywords = ['functioning properly', 'works now', 'is fixed', 'resolved now']; - if (resolvedKeywords.some(kw => lastCommentBody.includes(kw))) { - console.log(`Issue appears resolved in the last comment. Closing.`); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." - }); - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - state: 'closed', - state_reason: 'completed' - }); - core.setOutput('is_stale', 'true'); - return; - } - } - - console.log(`Issue has been inactive for over a month. Asking for repro.`); - - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - name: 'status/need-triage' - }); - } catch (e) { - // Ignore if label doesn't exist - } - - try { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - labels: ['status/needs-info'] - }); - } catch (e) { - console.log('Failed to add needs-info label:', e.message); - } - - const assignees = issue.assignees.map(a => a.login); - const hasAssignees = assignees.length > 0; - const assigneeMentions = hasAssignees ? assignees.map(a => `@${a}`).join(' ') : ''; - - const isHighPriority = issue.labels.some(l => { - const name = typeof l === 'string' ? l : l.name; - const lowerName = name.toLowerCase(); - return lowerName === 'priority/p0' || lowerName === 'priority/p1' || lowerName === 'p0' || lowerName === 'p1'; - }); - - const isFeatureRequest = issue.labels.some(l => { - const name = typeof l === 'string' ? l : l.name; - const lowerName = name.toLowerCase(); - return lowerName.includes('feature') || lowerName.includes('enhancement'); - }); - - let commentBody = ''; - if (isFeatureRequest) { - commentBody = `@${reporter}, this feature request hasn't been updated in over a month. Please reopen if this is still needed.`; - } else { - commentBody = `@${reporter}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps.`; - } - - if (!isHighPriority) { - if (hasAssignees) { - commentBody += `\n\n${assigneeMentions}, please reopen if you are actively working on this.`; - } else if (!isFeatureRequest) { - commentBody += ` Feel free to reopen this issue.`; - } - } else { - if (hasAssignees) { - commentBody += `\n\n${assigneeMentions}, checking in on this high priority issue.`; - } - } - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - body: commentBody - }); - - if (!isHighPriority) { - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNumber, - state: 'closed', - state_reason: 'not_planned' - }); - } - - core.setOutput('is_stale', 'true'); + core.setOutput('inactive_over_30_days', 'true'); + core.setOutput('is_stale', 'false'); // Let AI handle it return; } + core.setOutput('inactive_over_30_days', 'false'); core.setOutput('is_stale', 'false'); - name: 'Checkout Current Repository' @@ -314,6 +216,7 @@ jobs: env: ISSUE_NUMBER: '${{ matrix.issue_number }}' REPOSITORY: '${{ github.repository }}' + INACTIVE_OVER_30_DAYS: '${{ steps.staleness.outputs.inactive_over_30_days }}' GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' CUSTOM_INSTRUCTIONS: 'State whether the issue should be categorized as **Maintainer-only** (epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) or **Help-wanted** (good for community, general bugs, features, or tasks ready for external help). Your comment should be brief and clearly explain *why* it fits that category.' with: From b5e9a4f4aaf18d9bd48bc1754b68bf020029591e Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:22:32 -0400 Subject: [PATCH 30/32] feat(examples): refactor triage prompt to action-first syntax to stop self-investigation --- .../issue-cleanup/gemini-issue-cleanup.toml | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index e2b137ed1..be61fe44e 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,23 +1,17 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ -You are an automated triage bot for the `!{echo $REPOSITORY}` repository. Your job is to process Issue #!{echo $ISSUE_NUMBER} as efficiently as possible. +Execute the following triage process for Issue #!{echo $ISSUE_NUMBER} in the `!{echo $REPOSITORY}` repository. You must perform these exact steps in order. Do not investigate your own configuration. -## Critical Constraints -1. **NO META-ANALYSIS**: DO NOT read local files in the repository you are running in (like `package.json`, `README.md`, or `.github/`). Only read files within the `target-repo/` folder you clone in Step 1. -2. **EFFICIENCY**: If the issue is too vague or inactive, close/comment immediately and stop. Do not investigate code. - -## Task Lifecycle - -### Step 1: Setup & Comment Analysis +### Step 1: Fetch Context (DO THIS IMMEDIATELY) - Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` - Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,labels,assignees` -**Resolution Check (Priority 1):** +### Step 2: Resolution Check - Read the comments. Does the latest comment indicate that the issue has been fixed, resolved, or is functioning properly? - If YES: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." --reason "completed" --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -**Inactivity Check (Priority 2):** +### Step 3: Inactivity Check - Is `!{echo $INACTIVE_OVER_30_DAYS}` equal to `true`? - If YES (and it was not resolved above): Execute the following bash script exactly as written to handle the inactivity. ```bash @@ -58,26 +52,26 @@ fi ``` - **STOP EXECUTION IMMEDIATELY**. -**Vagueness Check (Priority 3):** +### Step 4: Vagueness Check - If the issue is NOT inactive over 30 days: Is the issue description fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet? - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -- If the issue is clear, proceed to Step 2. +- If the issue is clear, proceed to Step 5. -### Step 2: Reproduction & Code Validity Check +### Step 5: Reproduction & Code Validity Check - If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. - Alternatively, search `target-repo/` to manually trace the logic and see if the feature is already implemented or fixed. - If you can prove the issue is definitively NO LONGER VALID (e.g., your reproduction script works correctly without the bug, or the code has clearly been fixed): - Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because I have verified this works correctly in the latest codebase. " --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -### Step 3: Duplicate Check +### Step 6: Duplicate Check - Search for duplicates using `gh issue list --search "" --repo !{echo $REPOSITORY} --state all` - If a clear duplicate is found: - Close it: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` - **STOP EXECUTION IMMEDIATELY**. -### Step 4: Triage Summary +### Step 7: Triage Summary - If unique and valid, provide a summary comment using these instructions: ``` !{echo $CUSTOM_INSTRUCTIONS} From 399fae84be67e078f7f4f9c9c8018952b552dae2 Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Mon, 6 Apr 2026 20:25:48 -0400 Subject: [PATCH 31/32] fix(examples): force triage bot to serialize setup operations and block pre-research --- .../issue-cleanup/gemini-issue-cleanup.toml | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index be61fe44e..e51c1d067 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,19 +1,24 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ -Execute the following triage process for Issue #!{echo $ISSUE_NUMBER} in the `!{echo $REPOSITORY}` repository. You must perform these exact steps in order. Do not investigate your own configuration. +Execute the following triage process for Issue #!{echo $ISSUE_NUMBER} in the `!{echo $REPOSITORY}` repository. +You are a script executor. You MUST execute these steps in exact sequential order. Do not skip steps. Do not parallelize steps. Do not investigate your own configuration. -### Step 1: Fetch Context (DO THIS IMMEDIATELY) -- Run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` -- Run `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,labels,assignees` +### STEP 1: FETCH DATA (MANDATORY FIRST TURN) +You MUST execute ONLY these two commands in your very first turn. Do NOT execute any other tools. +1. `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` +2. `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,labels,assignees` -### Step 2: Resolution Check -- Read the comments. Does the latest comment indicate that the issue has been fixed, resolved, or is functioning properly? - - If YES: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." --reason "completed" --repo !{echo $REPOSITORY}` - - **STOP EXECUTION IMMEDIATELY**. +WAIT for the output of Step 1 before proceeding to Step 2. -### Step 3: Inactivity Check -- Is `!{echo $INACTIVE_OVER_30_DAYS}` equal to `true`? - - If YES (and it was not resolved above): Execute the following bash script exactly as written to handle the inactivity. +### STEP 2: RESOLUTION CHECK +Read the comments from the `gh issue view` output. +Does the latest comment indicate that the issue has been fixed, resolved, or is functioning properly? +- If YES: Execute `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." --reason "completed" --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. +- If NO: Proceed to Step 3. + +### STEP 3: INACTIVITY CHECK +Check the environment variable `!{echo $INACTIVE_OVER_30_DAYS}`. Is it exactly equal to the string `true`? +- If YES: Execute the following bash script exactly as written. ```bash ISSUE_JSON=$(gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json author,labels,assignees) REPORTER=$(echo "$ISSUE_JSON" | jq -r '.author.login') @@ -50,29 +55,26 @@ if [ "$IS_HIGH_PRIORITY" = "false" ]; then gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --repo !{echo $REPOSITORY} fi ``` - - **STOP EXECUTION IMMEDIATELY**. + - After executing this script, **STOP EXECUTION IMMEDIATELY**. Do not proceed to Step 4. +- If NO: Proceed to Step 4. -### Step 4: Vagueness Check -- If the issue is NOT inactive over 30 days: Is the issue description fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet? - - Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` - - **STOP EXECUTION IMMEDIATELY**. -- If the issue is clear, proceed to Step 5. +### STEP 4: VAGUENESS CHECK +Is the issue description fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet? +- If YES: Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. +- If NO: Proceed to Step 5. -### Step 5: Reproduction & Code Validity Check -- If the issue describes a reproducible bug (e.g., a runtime error, unexpected output, or terminal behavior), you should write and execute a minimal test script using `node` to verify if the bug still occurs in the `target-repo/` codebase. -- Alternatively, search `target-repo/` to manually trace the logic and see if the feature is already implemented or fixed. -- If you can prove the issue is definitively NO LONGER VALID (e.g., your reproduction script works correctly without the bug, or the code has clearly been fixed): - - Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because I have verified this works correctly in the latest codebase. " --repo !{echo $REPOSITORY}` - - **STOP EXECUTION IMMEDIATELY**. +### STEP 5: REPRODUCTION & CODE VALIDITY +Search the `target-repo/` codebase to see if the bug still occurs or if the feature is already implemented. +- If definitively NO LONGER VALID: Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because I have verified this works correctly in the latest codebase. " --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. +- If still valid: Proceed to Step 6. -### Step 6: Duplicate Check -- Search for duplicates using `gh issue list --search "" --repo !{echo $REPOSITORY} --state all` -- If a clear duplicate is found: - - Close it: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` - - **STOP EXECUTION IMMEDIATELY**. +### STEP 6: DUPLICATES +Search for duplicates using `gh issue list --search "" --repo !{echo $REPOSITORY} --state all`. +- If found: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. +- If no duplicates: Proceed to Step 7. -### Step 7: Triage Summary -- If unique and valid, provide a summary comment using these instructions: +### STEP 7: TRIAGE SUMMARY +Provide a summary comment using these instructions: ``` !{echo $CUSTOM_INSTRUCTIONS} ``` From ced7de355d0292fd08ecc834888fda759ed7b78c Mon Sep 17 00:00:00 2001 From: Coco Sheng Date: Tue, 7 Apr 2026 17:26:46 -0400 Subject: [PATCH 32/32] feat(workflows): refactor issue cleanup to use single source of truth and advanced triage logic --- .github/commands/gemini-issue-cleanup.toml | 1 + .../issue-cleanup/gemini-issue-cleanup.toml | 136 +++++++++--------- .../issue-cleanup/gemini-issue-cleanup.yml | 95 +++++++----- 3 files changed, 132 insertions(+), 100 deletions(-) create mode 120000 .github/commands/gemini-issue-cleanup.toml diff --git a/.github/commands/gemini-issue-cleanup.toml b/.github/commands/gemini-issue-cleanup.toml new file mode 120000 index 000000000..c3e922553 --- /dev/null +++ b/.github/commands/gemini-issue-cleanup.toml @@ -0,0 +1 @@ +../../examples/workflows/issue-cleanup/gemini-issue-cleanup.toml \ No newline at end of file diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml index e51c1d067..3ecb4a3fa 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.toml @@ -1,83 +1,85 @@ description = "Analyzes and cleans up older issues by checking code validity, duplicates, and providing a triage summary." prompt = """ -Execute the following triage process for Issue #!{echo $ISSUE_NUMBER} in the `!{echo $REPOSITORY}` repository. -You are a script executor. You MUST execute these steps in exact sequential order. Do not skip steps. Do not parallelize steps. Do not investigate your own configuration. +Execute the following triage process for `!{echo $ISSUE_LINK}`. +You are a script executor. You MUST execute these steps in exact sequential order. Do not skip steps. Do not parallelize steps. Do not investigate your own configuration. DO NOT clone the repository until you reach Step 5. -### STEP 1: FETCH DATA (MANDATORY FIRST TURN) -You MUST execute ONLY these two commands in your very first turn. Do NOT execute any other tools. -1. `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` -2. `gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json title,body,author,comments,labels,assignees` - -WAIT for the output of Step 1 before proceeding to Step 2. - -### STEP 2: RESOLUTION CHECK -Read the comments from the `gh issue view` output. -Does the latest comment indicate that the issue has been fixed, resolved, or is functioning properly? -- If YES: Execute `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because the latest comments indicate this issue has been resolved. Feel free to reopen if the problem persists." --reason "completed" --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. -- If NO: Proceed to Step 3. + +!{echo $CUSTOM_INSTRUCTIONS} + -### STEP 3: INACTIVITY CHECK -Check the environment variable `!{echo $INACTIVE_OVER_30_DAYS}`. Is it exactly equal to the string `true`? -- If YES: Execute the following bash script exactly as written. -```bash -ISSUE_JSON=$(gh issue view !{echo $ISSUE_NUMBER} --repo !{echo $REPOSITORY} --json author,labels,assignees) -REPORTER=$(echo "$ISSUE_JSON" | jq -r '.author.login') -HAS_ASSIGNEES=$(echo "$ISSUE_JSON" | jq '.assignees | length > 0') -ASSIGNEE_MENTIONS=$(echo "$ISSUE_JSON" | jq -r '.assignees | map("@" + .login) | join(" ")') -IS_HIGH_PRIORITY=$(echo "$ISSUE_JSON" | jq '.labels | map(.name | ascii_downcase) | any(. == "priority/p0" or . == "priority/p1" or . == "p0" or . == "p1")') -IS_FEATURE=$(echo "$ISSUE_JSON" | jq '.labels | map(.name | ascii_downcase) | any(contains("feature") or contains("enhancement"))') +### STEP 1: FETCH DATA (MANDATORY FIRST TURN) +You MUST execute ONLY these commands in your very first turn. Do NOT execute any other tools. +1. `gh issue view !{echo $ISSUE_LINK} --json title,body,author,comments,labels,assignees` +2. `gh api repos/!{echo $REPOSITORY}/issues/$(echo !{echo $ISSUE_LINK} | awk -F/ '{print $NF}')/timeline --jq '[.[] | select(.event == "cross-referenced" and .source.issue)] | map({issue: .source.issue.number, state: .source.issue.state, state_reason: .source.issue.state_reason, is_pr: (.source.issue.pull_request != null)})'` +3. `gh api graphql -F owner=$(echo !{echo $REPOSITORY} | cut -d/ -f1) -F repo=$(echo !{echo $REPOSITORY} | cut -d/ -f2) -F number=$(echo !{echo $ISSUE_LINK} | awk -F/ '{print $NF}') -f query='query($owner: String!, $repo: String!, $number: Int!) { repository(owner: $owner, name: $repo) { issue(number: $number) { parent { number } } } }' --jq '.data.repository.issue.parent'` +4. `gh api repos/!{echo $REPOSITORY}/issues/$(echo !{echo $ISSUE_LINK} | awk -F/ '{print $NF}') --jq '{is_epic: (.sub_issues_summary.total > 0)}'` -gh issue edit !{echo $ISSUE_NUMBER} --remove-label "status/need-triage" --repo !{echo $REPOSITORY} 2>/dev/null || true -gh issue edit !{echo $ISSUE_NUMBER} --add-label "status/needs-info" --repo !{echo $REPOSITORY} 2>/dev/null || true +WAIT for the outputs of Step 1 before proceeding to Step 2. -COMMENT="" -if [ "$IS_FEATURE" = "true" ]; then - COMMENT="@${REPORTER}, this feature request hasn't been updated in over a month. Please reopen if this is still needed." -else - COMMENT="@${REPORTER}, this issue hasn't been updated in over a month. Could you please try reproducing it with the latest build? If it still occurs, please provide detailed reproduction steps." -fi +### STEP 2: PRE-TRIAGE OVERRIDES +Review the provided at the beginning of this prompt. Do they contain any conditions that dictate stopping execution early based on the data fetched in Step 1 (e.g., specific labels)? +- If YES and the condition is met: Execute the actions specified in the custom instructions and **STOP EXECUTION IMMEDIATELY**. Do not proceed to Step 3. +- If NO or the condition is not met: Proceed to Step 3. -if [ "$IS_HIGH_PRIORITY" = "false" ]; then - if [ "$HAS_ASSIGNEES" = "true" ]; then - COMMENT="${COMMENT}\n\n${ASSIGNEE_MENTIONS}, please reopen if you are actively working on this." - elif [ "$IS_FEATURE" = "false" ]; then - COMMENT="${COMMENT} Feel free to reopen this issue." - fi -else - if [ "$HAS_ASSIGNEES" = "true" ]; then - COMMENT="${COMMENT}\n\n${ASSIGNEE_MENTIONS}, checking in on this high priority issue." - fi -fi +### STEP 3: RESOLUTION CHECK +Read ALL the comments from the `gh issue view` output carefully. +Check if ANY of the following conditions are met in the comments (especially the latest ones): +1. Is it fixed, resolved, no longer reproducible, or functioning properly? (e.g., someone mentions it `might be fixed`, `should be fixed`, or `no longer an issue`) AND the reporter has not replied afterward to contradict this? +2. Is there a workaround provided? +3. Does someone state the issue is actually unrelated to this repository/project, or is an external problem (like a terminal emulator bug)? -gh issue comment !{echo $ISSUE_NUMBER} --body "$COMMENT" --repo !{echo $REPOSITORY} +- If condition 1 or 2 is met: Execute `gh issue close !{echo $ISSUE_LINK} --comment "Closing because the comments indicate this issue might be fixed, has a workaround, is no longer an issue, or is resolved. Feel free to reopen if the problem persists." --reason "completed"` and **STOP EXECUTION IMMEDIATELY**. +- If condition 3 is met: Execute `gh issue close !{echo $ISSUE_LINK} --comment "Closing because the comments indicate this issue is unrelated to the Gemini CLI or is an external problem." --reason "not planned"` and **STOP EXECUTION IMMEDIATELY**. +- If NONE of these conditions are met: Proceed to Step 4. -if [ "$IS_HIGH_PRIORITY" = "false" ]; then - gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --repo !{echo $REPOSITORY} -fi -``` - - After executing this script, **STOP EXECUTION IMMEDIATELY**. Do not proceed to Step 4. -- If NO: Proceed to Step 4. +### STEP 4: ASSIGNEE AND INACTIVITY CHECK +1. ASSIGNEE CHECK: Look at the assignees and comments from Step 1. If an assignee is a contributor and hasn't made any updates on the issue for over 2 weeks, you MUST execute `gh issue edit !{echo $ISSUE_LINK} --remove-assignee ` to remove them. (Do this before proceeding further). +2. INACTIVITY CHECK: Check the environment variable `!{echo $INACTIVE_OVER_60_DAYS}`. Is it exactly equal to the string `true`? +- If YES: + a. Formulate a comment to the reporter (@). Evaluate the issue description and whether it is an Epic (from Step 1.4): + - Always mention that the issue is being closed or pinged because it has been inactive for over 60 days. + - IF IT IS AN EPIC (has sub-issues): Ask the reporter if it is still in progress or complete, and if it is complete, ask them to close it. + - IF IT IS NOT AN EPIC: + - If it's a feature/enhancement request and the description is relatively vague, ask: 1) if it is still needed and 2) if they can provide more details on the feature request. + - If the issue was mentioned by another issue that is closed as completed or by a pull request that is merged/closed (based on the cross-referenced timeline events), mention this cross-reference (e.g., "I see this issue was mentioned by #123 which is closed as completed...") and ask if this means it is resolved. Do NOT mention cross-references that are still open or closed as "not planned". + - If it's a feature/enhancement request but well-described, just ask if it's still needed. + - If it's a bug, ask if they can reproduce it with the latest build and provide detailed reproduction steps. + - If the issue has assignees, append a ping to the assignees to check in. + - If it is NOT an Epic AND the issue is NOT high priority (`priority/p0` or `priority/p1`) AND does NOT have a parent issue (from Step 1.3), append "Feel free to reopen this issue." to the comment. + b. Execute `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage"` (ignore errors if the label doesn't exist). If it is NOT an Epic, also append `--add-label "status/needs-info"`. + c. Execute `gh issue comment !{echo $ISSUE_LINK} --body ""` + d. If it is NOT an Epic AND the issue is NOT high priority AND does NOT have a parent issue (from Step 1.3), execute `gh issue close !{echo $ISSUE_LINK} --reason "not planned"`. + - After executing these actions, **STOP EXECUTION IMMEDIATELY**. Do not proceed to Step 5. +- If NO: Check the environment variable `!{echo $INACTIVE_OVER_30_DAYS}`. Is it exactly equal to the string `true`? + - If YES AND the issue is a bug report (not a feature/enhancement request) AND it is NOT an Epic: + a. Execute `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage" --add-label "status/needs-info"` (ignore errors if labels don't exist). + b. Execute `gh issue comment !{echo $ISSUE_LINK} --body "@, this issue has been inactive for over a month. Could you please try reproducing it with the latest nightly build and let us know if it still occurs?"` + - After executing these actions, **STOP EXECUTION IMMEDIATELY**. Do not proceed to Step 5. + - If NO (or it is not a bug, or it is an Epic): Proceed to Step 5. -### STEP 4: VAGUENESS CHECK -Is the issue description fundamentally missing context (no logs, no repro steps, just "it's broken") AND no one has asked for more information yet? -- If YES: Ask the reporter: `gh issue comment !{echo $ISSUE_NUMBER} --body "@, thank you for the report! Could you please provide more specific details (e.g., reproduction steps, expected behavior, and environment)? Closing this as vague if no response is received in a week." --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. -- If NO: Proceed to Step 5. +### STEP 5: VAGUENESS CHECK +Is the issue fundamentally missing context AND no one has asked for more information yet? +- For bugs: Explicit reproduction steps are **REQUIRED**. Even if the user provides logs, error traces, or screenshots, if they do not provide clear, step-by-step instructions on how to reproduce the bug, it MUST be considered vague. +- For feature requests: If it is just a vague statement without clear use cases or details, it is considered vague. +- If YES (it is vague): Execute `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage" --add-label "status/needs-info"` (ignore errors if labels don't exist). Ask the reporter: `gh issue comment !{echo $ISSUE_LINK} --body "@, thank you for the report! Could you please provide more specific details (e.g., detailed reproduction steps, expected behavior, logs, and environment details)? Closing this as vague if no response is received in a week."` and **STOP EXECUTION IMMEDIATELY**. +- If NO: Proceed to Step 6. -### STEP 5: REPRODUCTION & CODE VALIDITY -Search the `target-repo/` codebase to see if the bug still occurs or if the feature is already implemented. -- If definitively NO LONGER VALID: Close it: `gh issue close !{echo $ISSUE_NUMBER} --comment "Closing because I have verified this works correctly in the latest codebase. " --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. -- If still valid: Proceed to Step 6. +### STEP 6: REPRODUCTION & CODE VALIDITY +1. Review the issue comments. If a community member has already clearly identified the root cause of the bug, DO NOT clone the repo, DO NOT write tests, and DO NOT execute any code. You may only perform a quick `grep_search` or `read_file` if the repo is already cloned to determine if the fix is simple. +- If your quick code check reveals that the problematic code has already been significantly changed or appears fixed in the current `target-repo`, DO NOT investigate git history or releases. Simply execute `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage" --add-label "status/needs-info"` and `gh issue comment !{echo $ISSUE_LINK} --body "@, the code related to this issue appears to have been updated recently. Could you please try reproducing it with the latest nightly build and let us know if it still occurs?"` and **STOP EXECUTION IMMEDIATELY**. +- Otherwise, immediately proceed to Step 7. +2. If no root cause is identified, run `git clone https://github.com/!{echo $REPOSITORY}.git target-repo` and search the `target-repo/` codebase using `grep_search` and `read_file` ONLY. You are explicitly FORBIDDEN from writing new files, running `npm test`, attempting to fix the code, OR attempting to reproduce the bug by executing code or shell commands (e.g., creating named pipes, running scripts, etc.). Your ONLY goal is to perform STATIC code analysis to determine if the logic for the bug still exists, if the feature is already implemented, or if the reported behavior is actually intentional by design. +- If definitively NO LONGER VALID: Close it: `gh issue close !{echo $ISSUE_LINK} --comment "Closing because I have verified this works correctly in the latest codebase. "` and **STOP EXECUTION IMMEDIATELY**. +- If INTENTIONAL BY DESIGN: Close it: `gh issue close !{echo $ISSUE_LINK} --reason "not planned" --comment "Closing this issue as the reported behavior is intentional by design. "` and **STOP EXECUTION IMMEDIATELY**. +- If still valid: Proceed to Step 7. -### STEP 6: DUPLICATES +### STEP 7: DUPLICATES Search for duplicates using `gh issue list --search "" --repo !{echo $REPOSITORY} --state all`. -- If found: `gh issue close !{echo $ISSUE_NUMBER} --reason "not planned" --comment "Closing as duplicate of #." --repo !{echo $REPOSITORY}` and **STOP EXECUTION IMMEDIATELY**. -- If no duplicates: Proceed to Step 7. +- If found: `gh issue close !{echo $ISSUE_LINK} --reason "not planned" --comment "Closing as duplicate of #."` and **STOP EXECUTION IMMEDIATELY**. +- If no duplicates: Proceed to Step 8. -### STEP 7: TRIAGE SUMMARY -Provide a summary comment using these instructions: -``` -!{echo $CUSTOM_INSTRUCTIONS} -``` -- Action: `gh issue comment !{echo $ISSUE_NUMBER} --body "### Triage Summary\n\n" --repo !{echo $REPOSITORY}` +### STEP 8: TRIAGE SUMMARY +Provide a summary comment using the provided at the beginning of this prompt. +- Action: `gh issue comment !{echo $ISSUE_LINK} --body "### Triage Summary\\n\\n"` - **STOP EXECUTION**. """ diff --git a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml index f863a61c5..0b9b8f664 100644 --- a/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml +++ b/examples/workflows/issue-cleanup/gemini-issue-cleanup.yml @@ -5,6 +5,10 @@ name: '๐Ÿงน Gemini Issue Cleanup' - cron: '0 0 * * 0' # Runs weekly at midnight on Sunday workflow_dispatch: inputs: + issue_link: + description: 'Link to the GitHub issue to process (e.g., https://github.com/owner/repo/issues/123). If provided, only this issue will be processed.' + required: false + type: string maintainers: description: 'Comma-separated list of maintainer usernames (e.g., gemini-cli)' required: false @@ -22,43 +26,47 @@ jobs: find-issues: runs-on: 'ubuntu-latest' outputs: - issue_numbers: '${{ steps.find_issues.outputs.issue_numbers }}' + issue_links: '${{ steps.find_issues.outputs.issue_links }}' steps: - name: 'Find old issues for cleanup' id: 'find_issues' env: GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' + ISSUE_LINK_INPUT: '${{ inputs.issue_link }}' run: |- + if [ -n "${ISSUE_LINK_INPUT}" ]; then + echo '๐Ÿ” Using provided issue link...' + echo "issue_links=[\"${ISSUE_LINK_INPUT}\"]" >> "${GITHUB_OUTPUT}" + exit 0 + fi + echo '๐Ÿ” Finding old issues for cleanup...' - # Query matches target repository, open issues, sorted by oldest last update time - # with labels area/core, area/extensions, area/site, area/non-interactive ISSUES="$(gh issue list \ --repo ${{ github.repository }} \ --state 'open' \ --search "label:area/core,area/extensions,area/site,area/non-interactive sort:updated-asc" \ - --json number \ + --json url \ --limit 10 \ )" - # Convert to JSON array - ISSUE_NUMBERS="$(echo "${ISSUES}" | jq -c '[.[].number]')" + ISSUE_LINKS="$(echo "${ISSUES}" | jq -c '[.[].url]')" - if [ "${ISSUE_NUMBERS}" = "[]" ] || [ -z "${ISSUE_NUMBERS}" ]; then - echo "issue_numbers=[]" >> "${GITHUB_OUTPUT}" + if [ "${ISSUE_LINKS}" = "[]" ] || [ -z "${ISSUE_LINKS}" ]; then + echo "issue_links=[]" >> "${GITHUB_OUTPUT}" echo "โœ… No issues found to clean up." else - echo "issue_numbers=${ISSUE_NUMBERS}" >> "${GITHUB_OUTPUT}" + echo "issue_links=${ISSUE_LINKS}" >> "${GITHUB_OUTPUT}" echo "โœ… Found $(echo "${ISSUES}" | jq 'length') issue(s) to process." fi process-issue: needs: 'find-issues' if: |- - needs.find-issues.outputs.issue_numbers != '[]' && needs.find-issues.outputs.issue_numbers != '' + needs.find-issues.outputs.issue_links != '[]' && needs.find-issues.outputs.issue_links != '' runs-on: 'ubuntu-latest' strategy: matrix: - issue_number: '${{ fromJSON(needs.find-issues.outputs.issue_numbers) }}' + issue_link: '${{ fromJSON(needs.find-issues.outputs.issue_links) }}' max-parallel: 3 fail-fast: false permissions: @@ -70,18 +78,22 @@ jobs: id: 'staleness' uses: 'actions/github-script@v7' env: - ISSUE_NUMBER: '${{ matrix.issue_number }}' + ISSUE_LINK: '${{ matrix.issue_link }}' MAINTAINERS: '${{ inputs.maintainers || vars.MAINTAINERS }}' with: script: |- - const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10); - console.log(`Checking staleness for issue #${issueNumber}`); + const issueLink = process.env.ISSUE_LINK; + const parts = issueLink.split('/'); + const issueNumber = parseInt(parts[parts.length - 1], 10); + const repoOwner = parts[parts.length - 4]; + const repoName = parts[parts.length - 3]; + console.log(`Checking staleness for issue #${issueNumber} from ${issueLink}`); const maintainers = process.env.MAINTAINERS ? process.env.MAINTAINERS.split(',').map(m => m.trim()) : []; const { data: issue } = await github.rest.issues.get({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, }); const reporter = issue.user.login; @@ -100,8 +112,8 @@ jobs: `; try { const result = await github.graphql(query, { - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issueNumber: issueNumber }); const isTracked = result.repository.issue.trackedInIssues.totalCount > 0; @@ -110,8 +122,8 @@ jobs: console.log(`Issue #${issueNumber} is tracked by a parent issue. Removing 'status/need-triage' and stopping.`); try { await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, name: 'status/need-triage' }); @@ -136,8 +148,8 @@ jobs: commentBody = `@${reporter}, this issue is currently tracked by an epic but has no assignees. Could you please try reproducing it with the latest build and let us know if it still occurs?`; } await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, body: commentBody }); @@ -151,8 +163,8 @@ jobs: } const { data: comments } = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, }); @@ -175,14 +187,14 @@ jobs: console.log(`Issue is stale. Closing.`); await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, body: "Closing because it has been over a week since we requested more information and we haven't received a response. Feel free to reopen if you can provide the requested details." }); await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: repoOwner, + repo: repoName, issue_number: issueNumber, state: 'closed', state_reason: 'not_planned' @@ -197,12 +209,21 @@ jobs: const lastUpdateDaysAgo = (new Date() - new Date(issue.updated_at)) / (1000 * 60 * 60 * 24); console.log(`Issue was last updated ${lastUpdateDaysAgo.toFixed(1)} days ago.`); - if (lastUpdateDaysAgo > 30) { + if (lastUpdateDaysAgo > 60) { + core.setOutput('inactive_over_60_days', 'true'); core.setOutput('inactive_over_30_days', 'true'); core.setOutput('is_stale', 'false'); // Let AI handle it return; } + if (lastUpdateDaysAgo > 30) { + core.setOutput('inactive_over_60_days', 'false'); + core.setOutput('inactive_over_30_days', 'true'); + core.setOutput('is_stale', 'false'); + return; + } + + core.setOutput('inactive_over_60_days', 'false'); core.setOutput('inactive_over_30_days', 'false'); core.setOutput('is_stale', 'false'); @@ -210,15 +231,22 @@ jobs: if: steps.staleness.outputs.is_stale != 'true' uses: 'actions/checkout@v4' + - name: 'Set Repository' + if: steps.staleness.outputs.is_stale != 'true' + run: | + REPOSITORY=$(echo "${{ matrix.issue_link }}" | awk -F'/' '{print $4"/"$5}') + echo "REPOSITORY=$REPOSITORY" >> $GITHUB_ENV + - name: 'Run Gemini Issue Cleanup' if: steps.staleness.outputs.is_stale != 'true' uses: 'google-github-actions/run-gemini-cli@v0' # Replace with actual version when deploying env: - ISSUE_NUMBER: '${{ matrix.issue_number }}' - REPOSITORY: '${{ github.repository }}' + ISSUE_LINK: '${{ matrix.issue_link }}' + REPOSITORY: '${{ env.REPOSITORY }}' + INACTIVE_OVER_60_DAYS: '${{ steps.staleness.outputs.inactive_over_60_days }}' INACTIVE_OVER_30_DAYS: '${{ steps.staleness.outputs.inactive_over_30_days }}' GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN || github.token }}' - CUSTOM_INSTRUCTIONS: 'State whether the issue should be categorized as **Maintainer-only** (epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) or **Help-wanted** (good for community, general bugs, features, or tasks ready for external help). Your comment should be brief and clearly explain *why* it fits that category.' + CUSTOM_INSTRUCTIONS: 'If the issue already has a maintainer-only label, just run `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage"` and **STOP EXECUTION IMMEDIATELY** without providing a triage summary. Otherwise, review the issue comments to see if a community member has already identified the root cause. If a root cause is identified: determine if it is a very simple fix. If it is a simple fix, post guidance for the fix, categorize the issue as **Maintainer-only**, and explain why. If it is not a simple fix, determine whether it should be **Maintainer-only** or **Help-wanted** and explain why. If no root cause is identified: State whether the issue should be categorized as **Maintainer-only** (epic, core architecture, sensitive fixes, internal tasks, or issues requiring deep investigation) or **Help-wanted** (good for community, general bugs, features, or tasks ready for external help). Your comment should be brief and clearly explain *why* it fits that category. If you categorized the issue as **Help-wanted**, also run `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage" --add-label "help wanted"`. If you categorized the issue as **Maintainer-only**, also run `gh issue edit !{echo $ISSUE_LINK} --remove-label "status/need-triage" --add-label "๐Ÿ”’ maintainer only"`.' with: # Modify the auth settings depending on your environment gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}' @@ -241,7 +269,8 @@ jobs: "run_shell_command(gh)", "run_shell_command(git)", "run_shell_command(date)", - "run_shell_command(node)" + "run_shell_command(node)", + "run_shell_command(echo)" ] } }