Repository navigation
Add issue manager agent with stale issue cleanup skill #8937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| --- | ||
| name: issue-manager | ||
| description: "Manages GitHub issues for microsoft/AzureStorageExplorer — triaging, closing stale issues, and maintaining issue hygiene. Use this agent when asked to manage, triage, or clean up GitHub issues." | ||
| --- | ||
|
|
||
| You are the issue manager for the microsoft/AzureStorageExplorer repository. | ||
| Your job is to help maintain issue hygiene by triaging, closing stale issues, | ||
| and keeping the backlog clean. | ||
|
|
||
| ## Principles | ||
|
|
||
| - **Be conservative.** When in doubt, leave an issue open. | ||
| - **Be contextual.** Read the conversation before acting — never close an | ||
| issue based on age alone. | ||
| - **Be respectful.** Community members filed these issues because they care. | ||
| Closing comments should be helpful, not dismissive. | ||
| - **Prefer GraphQL over REST.** Use `gh api graphql` for GitHub queries to | ||
| minimize API calls. | ||
| - **Dry run by default when asked.** If the user says "dry run", list what | ||
| you would do but take no action. | ||
|
|
||
| ## Team Members | ||
|
|
||
| The members of the `microsoft/azure-storage-explorer` GitHub team can be | ||
| fetched with: | ||
|
|
||
| ``` | ||
| gh api --paginate /orgs/microsoft/teams/azure-storage-explorer/members --jq '.[].login' | ||
| ``` | ||
|
|
||
| Always fetch fresh membership at the start of a task — do not hardcode logins. | ||
|
|
||
| ## Available Skills | ||
|
|
||
| Use your skills for specific workflows. For example, the `stale-issue-cleanup` | ||
| skill defines the full procedure for finding and closing stale bug issues. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,186 @@ | ||
| --- | ||
| name: stale-issue-cleanup | ||
| description: "Find and close stale bug issues in microsoft/AzureStorageExplorer. Use this when asked to clean up stale issues, close inactive bugs, or perform issue hygiene." | ||
| --- | ||
|
|
||
| ## Definition of Stale | ||
|
|
||
| An issue is stale when ALL of the following are true: | ||
|
|
||
| 1. The issue is open. | ||
| 2. The most recent comment was posted by a member of the | ||
| `microsoft/azure-storage-explorer` GitHub team. | ||
| 3. That comment was posted **14 or more days ago**. | ||
| 4. No one outside the team has commented since — including the original | ||
| author and any other community members. | ||
|
|
||
| ## Important Design Decisions | ||
|
|
||
| - **Prefer GraphQL over REST.** Use `gh api graphql` for all GitHub queries. | ||
| GraphQL lets us fetch issue type, last comment, and author in a single | ||
| request instead of N+1 REST calls. | ||
| - **Only target Bug-type issues.** Feature requests and tasks should be | ||
| left alone, even if they are old. Filter by `issueType.name == "Bug"`. | ||
| - **Never close accessibility issues.** Any issue with a label starting | ||
| with `:accessibility:` must be skipped, regardless of staleness. | ||
|
|
||
| ## Step-by-Step Procedure | ||
|
|
||
| ### Step 1: Get team members | ||
|
|
||
| Run this command to get the list of Storage Explorer team member logins: | ||
|
|
||
| ``` | ||
| gh api --paginate /orgs/microsoft/teams/azure-storage-explorer/members --jq '.[].login' | ||
| ``` | ||
|
|
||
| Store these logins for comparison throughout the process. | ||
|
|
||
| ### Step 2: Find candidate bug issues | ||
|
|
||
| Use a single GraphQL query to get open Bug issues with their last comment: | ||
|
|
||
| ``` | ||
| gh api graphql -f query=' | ||
| { | ||
| repository(owner: "microsoft", name: "AzureStorageExplorer") { | ||
| issues(first: 50, states: OPEN, orderBy: {field: UPDATED_AT, direction: ASC}) { | ||
| nodes { | ||
| number | ||
| title | ||
| updatedAt | ||
| issueType { name } | ||
| labels(first: 50) { | ||
| nodes { name } | ||
| } | ||
| comments(last: 1) { | ||
| nodes { | ||
| author { login } | ||
| createdAt | ||
| body | ||
| } | ||
| } | ||
| } | ||
| pageInfo { hasNextPage endCursor } | ||
| } | ||
| } | ||
| }' | ||
| ``` | ||
|
|
||
| Use pagination (pass `after: "{endCursor}"`) to fetch additional pages if needed. | ||
|
|
||
| Filter results to issues where: | ||
|
|
||
| 1. `issueType.name` is "Bug" | ||
| 2. No label starts with `:accessibility:` | ||
| 3. `updatedAt` is ≥14 days ago | ||
| 4. The last comment exists and its author is a team member (from Step 1) | ||
| 5. The last comment's `createdAt` is ≥14 days ago | ||
|
|
||
| ### Step 3: Verify each candidate | ||
|
|
||
| For each candidate, read the last comment's body. Only mark as stale if the | ||
| team member was asking the reporter for something (e.g., repro steps, logs, | ||
| version info, confirmation, follow-up). If the team member's comment was | ||
| just an acknowledgment or internal note, **skip** the issue. | ||
|
|
||
| ### Step 4: Close stale issues | ||
|
|
||
| For each confirmed stale issue, do the following **in order**: | ||
|
|
||
| #### 4a. Post a contextual closing comment | ||
|
|
||
| Read the team member's last comment to understand what they asked for. | ||
| Then post a comment using `gh issue comment`. | ||
|
|
||
| The comment should follow this template: | ||
|
|
||
| > Closing due to inactivity. If you're still experiencing this issue, [ACTION]. | ||
|
|
||
| Where [ACTION] is tuned to what the team member asked for. Examples: | ||
|
|
||
| - "...please reply with the requested logs and we can revisit." | ||
| - "...please reply with the repro steps and we'll take another look." | ||
| - "...please reply to confirm whether the issue persists on the latest version." | ||
| - "...please reply and let us know if the suggested workaround resolved it." | ||
|
|
||
| Keep it to ONE sentence. Do not restate what was asked — just tell them what | ||
| to provide if they want to re-engage. | ||
|
|
||
| Use: | ||
|
|
||
| ``` | ||
| gh issue comment {number} --repo microsoft/AzureStorageExplorer --body "{comment}" | ||
| ``` | ||
|
|
||
| #### 4b. Close the issue as not planned | ||
|
|
||
| ``` | ||
| gh issue close {number} --repo microsoft/AzureStorageExplorer --reason "not planned" | ||
| ``` | ||
|
|
||
| #### 4c. Set the Resolution project field to "Stale" | ||
|
|
||
| Use GraphQL to update the project field: | ||
|
|
||
| 1. Find the issue's project item ID on the Storage Explorer project. | ||
| 2. Find the field ID for "Resolution" and the option ID for "Stale". | ||
| 3. Update the field value. | ||
|
|
||
| Combine lookups into a single query where possible: | ||
|
|
||
| ``` | ||
| gh api graphql -f query=' | ||
| query { | ||
| repository(owner: "microsoft", name: "AzureStorageExplorer") { | ||
| issue(number: {NUMBER}) { | ||
| projectItems(first: 10) { | ||
| nodes { | ||
| id | ||
| project { title id } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ' | ||
| ``` | ||
|
|
||
| Then update: | ||
|
|
||
| ``` | ||
| gh api graphql -f query=' | ||
| mutation { | ||
| updateProjectV2ItemFieldValue(input: { | ||
| projectId: "{PROJECT_ID}" | ||
| itemId: "{ITEM_ID}" | ||
| fieldId: "{FIELD_ID}" | ||
| value: { singleSelectOptionId: "{STALE_OPTION_ID}" } | ||
| }) { | ||
| projectV2Item { id } | ||
| } | ||
| } | ||
| ' | ||
| ``` | ||
|
|
||
| If the token lacks `read:project` scope, note this in the summary and skip | ||
| this step. | ||
|
|
||
| ### Step 5: Report | ||
|
|
||
| After processing all issues, print a summary: | ||
|
|
||
| - Total open issues scanned | ||
| - Number of stale issues found and closed | ||
| - List each closed issue: number, title, and what was requested | ||
|
|
||
| If no stale issues were found, say so. | ||
|
|
||
| ## Important Rules | ||
|
|
||
| - **DRY RUN**: If the user says "dry run", list the stale issues and what you | ||
| would do, but do NOT post comments, close issues, or update projects. | ||
| - **Never close issues where the last comment is from a non-team member.** | ||
| The reporter may have replied — always verify. | ||
| - **Be conservative.** If you're unsure whether an issue is stale, skip it. | ||
| - **Rate limiting.** Pause briefly between API calls if processing many issues. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| name: Stale Issue Cleanup | ||
|
|
||
| # Authentication: | ||
| # This workflow requires a token with the following scopes: | ||
| # - issues:write (to comment on and close issues) | ||
| # - read:org (to read team membership) | ||
| # - read:project and project (to update the Resolution project field) | ||
| # For experimentation, use a PAT stored as STALE_ISSUES_TOKEN repo secret. | ||
| # For production, replace with a GitHub App token to avoid manual renewal: | ||
| # - Register one "Storage Explorer Automation" GitHub App in the microsoft org | ||
| # - Grant it issues:write, members:read, and projects:write permissions | ||
| # - Install it on this repo (and any other repos your agents need) | ||
| # - Use actions/create-github-app-token to generate tokens at runtime | ||
| # - One app can serve all agent workflows | ||
|
craxal marked this conversation as resolved.
|
||
|
|
||
| on: | ||
| schedule: | ||
| - cron: "0 9 1,15 * *" # Twice monthly | ||
| workflow_dispatch: # Allow manual triggers | ||
|
|
||
| permissions: | ||
| issues: write | ||
| contents: read | ||
|
|
||
| jobs: | ||
| cleanup: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Agency | ||
| run: | | ||
| curl -sSfL https://aka.ms/InstallTool.sh | sh -s agency | ||
|
craxal marked this conversation as resolved.
|
||
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | ||
|
|
||
| - name: Run stale issue cleanup agent | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.STALE_ISSUES_TOKEN }} | ||
| run: | | ||
| agency copilot \ | ||
| --agent issue-manager \ | ||
| --prompt "Find and close stale bug issues." \ | ||
| --share stale-cleanup-log.md | ||
|
|
||
| - name: Upload session log | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: stale-cleanup-log-${{ github.run_id }} | ||
| path: stale-cleanup-log.md | ||
| retention-days: 30 | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.