refactor(github-triage): rewrite as read-only report-based analyzer

This commit is contained in:
YeonGyu-Kim
2026-03-12 17:30:42 +09:00
parent ca7c0e391e
commit 2bbbdc4ca9
+385 -328
View File
@@ -1,105 +1,181 @@
--- ---
name: github-triage name: github-triage
description: "Unified GitHub triage for issues AND PRs. 1 item = 1 background task (category: free). Issues: answer questions from codebase, analyze bugs. PRs: review bugfixes, merge safe ones. All parallel, all background. Triggers: 'triage', 'triage issues', 'triage PRs', 'github triage'." description: "Read-only GitHub triage for issues AND PRs. 1 item = 1 background task (category: quick). Analyzes all open items and writes evidence-backed reports to /tmp/{datetime}/. Every claim requires a GitHub permalink as proof. NEVER takes any action on GitHub - no comments, no merges, no closes, no labels. Reports only. Triggers: 'triage', 'triage issues', 'triage PRs', 'github triage'."
--- ---
# GitHub Triage — Unified Issue & PR Processor # GitHub Triage - Read-Only Analyzer
<role> <role>
You are a GitHub triage orchestrator. You fetch all open issues and PRs, classify each one, then spawn exactly 1 background subagent per item using `category="free"`. Each subagent analyzes its item, takes action (comment/close/merge/report), and records results via TaskCreate. Read-only GitHub triage orchestrator. Fetch open issues/PRs, classify, spawn 1 background `quick` subagent per item. Each subagent analyzes and writes a report file. ZERO GitHub mutations.
</role> </role>
--- ## Architecture
## ARCHITECTURE **1 ISSUE/PR = 1 TASKCREATE = 1 `quick` SUBAGENT (background). NO EXCEPTIONS.**
```
1 issue or PR = 1 TaskCreate = 1 task(category="free", run_in_background=true)
```
| Rule | Value | | Rule | Value |
|------|-------| |------|-------|
| Category for ALL subagents | `free` | | Category | `quick` |
| Execution mode | `run_in_background=true` | | Execution | `run_in_background=true` |
| Parallelism | ALL items launched simultaneously | | Parallelism | ALL items simultaneously |
| Result tracking | Each subagent calls `TaskCreate` with its findings | | Tracking | `TaskCreate` per item |
| Result collection | `background_output()` polling loop | | Output | `/tmp/{YYYYMMDD-HHmmss}/issue-{N}.md` or `pr-{N}.md` |
--- ---
## PHASE 1: FETCH ALL OPEN ITEMS ## Zero-Action Policy (ABSOLUTE)
<fetch> <zero_action>
Run these commands to collect data. Use the bundled script if available, otherwise fall back to gh CLI. Subagents MUST NEVER run ANY command that writes or mutates GitHub state.
**FORBIDDEN** (non-exhaustive):
`gh issue comment`, `gh issue close`, `gh issue edit`, `gh pr comment`, `gh pr merge`, `gh pr review`, `gh pr edit`, `gh api -X POST`, `gh api -X PUT`, `gh api -X PATCH`, `gh api -X DELETE`
**ALLOWED**:
- `gh issue view`, `gh pr view`, `gh api` (GET only) - read GitHub data
- `Grep`, `Read`, `Glob` - read codebase
- `Write` - write report files to `/tmp/` ONLY
- `git log`, `git show`, `git blame` - read git history (for finding fix commits)
**ANY GitHub mutation = CRITICAL violation.**
</zero_action>
---
## Evidence Rule (MANDATORY)
<evidence>
**Every factual claim in a report MUST include a GitHub permalink as proof.**
A permalink is a URL pointing to a specific line/range in a specific commit, e.g.:
`https://github.com/{owner}/{repo}/blob/{commit_sha}/{path}#L{start}-L{end}`
### How to generate permalinks
1. Find the relevant file and line(s) via Grep/Read.
2. Get the current commit SHA: `git rev-parse HEAD`
3. Construct: `https://github.com/{REPO}/blob/{SHA}/{filepath}#L{line}` (or `#L{start}-L{end}` for ranges)
### Rules
- **No permalink = no claim.** If you cannot back a statement with a permalink, state "No evidence found" instead.
- Claims without permalinks are explicitly marked `[UNVERIFIED]` and carry zero weight.
- Permalinks to `main`/`master`/`dev` branches are NOT acceptable - use commit SHAs only.
- For bug analysis: permalink to the problematic code. For fix verification: permalink to the fixing commit diff.
</evidence>
---
## Phase 0: Setup
```bash ```bash
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
REPORT_DIR="/tmp/$(date +%Y%m%d-%H%M%S)"
# Issues: all open mkdir -p "$REPORT_DIR"
gh issue list --repo $REPO --state open --limit 500 \ COMMIT_SHA=$(git rev-parse HEAD)
--json number,title,state,createdAt,updatedAt,labels,author,body,comments
# PRs: all open
gh pr list --repo $REPO --state open --limit 500 \
--json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup
``` ```
If either returns exactly 500 results, paginate using `--search "created:<LAST_CREATED_AT"` until exhausted. Pass `REPO`, `REPORT_DIR`, and `COMMIT_SHA` to every subagent.
---
## Phase 1: Fetch All Open Items
<fetch>
Paginate if 500 results returned.
```bash
ISSUES=$(gh issue list --repo $REPO --state open --limit 500 \
--json number,title,state,createdAt,updatedAt,labels,author,body,comments)
ISSUE_LEN=$(echo "$ISSUES" | jq length)
if [ "$ISSUE_LEN" -eq 500 ]; then
LAST_DATE=$(echo "$ISSUES" | jq -r '.[-1].createdAt')
while true; do
PAGE=$(gh issue list --repo $REPO --state open --limit 500 \
--search "created:<$LAST_DATE" \
--json number,title,state,createdAt,updatedAt,labels,author,body,comments)
PAGE_LEN=$(echo "$PAGE" | jq length)
[ "$PAGE_LEN" -eq 0 ] && break
ISSUES=$(echo "[$ISSUES, $PAGE]" | jq -s 'add | unique_by(.number)')
[ "$PAGE_LEN" -lt 500 ] && break
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
done
fi
PRS=$(gh pr list --repo $REPO --state open --limit 500 \
--json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
PR_LEN=$(echo "$PRS" | jq length)
if [ "$PR_LEN" -eq 500 ]; then
LAST_DATE=$(echo "$PRS" | jq -r '.[-1].createdAt')
while true; do
PAGE=$(gh pr list --repo $REPO --state open --limit 500 \
--search "created:<$LAST_DATE" \
--json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
PAGE_LEN=$(echo "$PAGE" | jq length)
[ "$PAGE_LEN" -eq 0 ] && break
PRS=$(echo "[$PRS, $PAGE]" | jq -s 'add | unique_by(.number)')
[ "$PAGE_LEN" -lt 500 ] && break
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
done
fi
```
</fetch> </fetch>
--- ---
## PHASE 2: CLASSIFY EACH ITEM ## Phase 2: Classify
For each item, determine its type based on title, labels, and body content: | Type | Detection |
|------|-----------|
<classification> | `ISSUE_QUESTION` | `[Question]`, `[Discussion]`, `?`, "how to" / "why does" / "is it possible" |
| `ISSUE_BUG` | `[Bug]`, `Bug:`, error messages, stack traces, unexpected behavior |
### Issues | `ISSUE_FEATURE` | `[Feature]`, `[RFE]`, `[Enhancement]`, `Feature Request`, `Proposal` |
| `ISSUE_OTHER` | Anything else |
| Type | Detection | Action Path | | `PR_BUGFIX` | Title starts with `fix`, branch contains `fix/`/`bugfix/`, label `bug` |
|------|-----------|-------------| | `PR_OTHER` | Everything else |
| `ISSUE_QUESTION` | Title contains `[Question]`, `[Discussion]`, `?`, or body is asking "how to" / "why does" / "is it possible" | SUBAGENT_ISSUE_QUESTION |
| `ISSUE_BUG` | Title contains `[Bug]`, `Bug:`, body describes unexpected behavior, error messages, stack traces | SUBAGENT_ISSUE_BUG |
| `ISSUE_FEATURE` | Title contains `[Feature]`, `[RFE]`, `[Enhancement]`, `Feature Request`, `Proposal` | SUBAGENT_ISSUE_FEATURE |
| `ISSUE_OTHER` | Anything else | SUBAGENT_ISSUE_OTHER |
### PRs
| Type | Detection | Action Path |
|------|-----------|-------------|
| `PR_BUGFIX` | Title starts with `fix`, `fix:`, `fix(`, branch contains `fix/`, `bugfix/`, or labels include `bug` | SUBAGENT_PR_BUGFIX |
| `PR_OTHER` | Everything else (feat, refactor, docs, chore, etc.) | SUBAGENT_PR_OTHER |
</classification>
--- ---
## PHASE 3: SPAWN 1 BACKGROUND TASK PER ITEM ## Phase 3: Spawn Subagents
For EVERY item, create a TaskCreate entry first, then spawn a background task.
``` ```
For each item: For each item:
1. TaskCreate(subject="Triage: #{number} {title}") 1. TaskCreate(subject="Triage: #{number} {title}")
2. task(category="free", run_in_background=true, load_skills=[], prompt=SUBAGENT_PROMPT) 2. task(category="quick", run_in_background=true, load_skills=[], prompt=SUBAGENT_PROMPT)
3. Store mapping: item_number -> { task_id, background_task_id } 3. Store mapping: item_number -> { task_id, background_task_id }
``` ```
--- ---
## SUBAGENT PROMPT TEMPLATES ## Subagent Prompts
Each subagent gets an explicit, step-by-step prompt. Free models are limited — leave NOTHING implicit. ### Common Preamble (include in ALL subagent prompts)
```
CONTEXT:
- Repository: {REPO}
- Report directory: {REPORT_DIR}
- Current commit SHA: {COMMIT_SHA}
PERMALINK FORMAT:
Every factual claim MUST include a permalink: https://github.com/{REPO}/blob/{COMMIT_SHA}/{filepath}#L{start}-L{end}
No permalink = no claim. Mark unverifiable claims as [UNVERIFIED].
To get current SHA if needed: git rev-parse HEAD
ABSOLUTE RULES (violating ANY = critical failure):
- NEVER run gh issue comment, gh issue close, gh issue edit
- NEVER run gh pr comment, gh pr merge, gh pr review, gh pr edit
- NEVER run any gh command with -X POST, -X PUT, -X PATCH, -X DELETE
- NEVER run git checkout, git fetch, git pull, git switch, git worktree
- Your ONLY writable output: {REPORT_DIR}/{issue|pr}-{number}.md via the Write tool
```
--- ---
### SUBAGENT_ISSUE_QUESTION ### ISSUE_QUESTION
<issue_question_prompt>
``` ```
You are a GitHub issue responder for the repository {REPO}. You are analyzing issue #{number} for {REPO}.
ITEM: ITEM:
- Issue #{number}: {title} - Issue #{number}: {title}
@@ -107,52 +183,43 @@ ITEM:
- Body: {body} - Body: {body}
- Comments: {comments_summary} - Comments: {comments_summary}
YOUR JOB: TASK:
1. Read the issue carefully. Understand what the user is asking. 1. Understand the question.
2. Search the codebase to find the answer. Use Grep and Read tools. 2. Search the codebase (Grep, Read) for the answer.
- Search for relevant file names, function names, config keys mentioned in the issue. 3. For every finding, construct a permalink: https://github.com/{REPO}/blob/{COMMIT_SHA}/{path}#L{N}
- Read the files you find to understand how the feature works. 4. Write report to {REPORT_DIR}/issue-{number}.md
3. Decide: Can you answer this clearly and accurately from the codebase?
IF YES (you found a clear, accurate answer): REPORT FORMAT (write this as the file content):
Step A: Write a helpful comment. The comment MUST:
- Start with exactly: [sisyphus-bot]
- Be warm, friendly, and thorough
- Include specific file paths and code references
- Include code snippets or config examples if helpful
- End with "Feel free to reopen if this doesn't resolve your question!"
Step B: Post the comment:
gh issue comment {number} --repo {REPO} --body "YOUR_COMMENT"
Step C: Close the issue:
gh issue close {number} --repo {REPO}
Step D: Report back with this EXACT format:
ACTION: ANSWERED_AND_CLOSED
COMMENT_POSTED: yes
SUMMARY: [1-2 sentence summary of your answer]
IF NO (not enough info in codebase, or answer is uncertain): # Issue #{number}: {title}
Report back with: **Type:** Question | **Author:** {author} | **Created:** {createdAt}
ACTION: NEEDS_MANUAL_ATTENTION
REASON: [why you couldn't answer — be specific]
PARTIAL_FINDINGS: [what you DID find, if anything]
RULES: ## Question
- NEVER guess. Only answer if the codebase clearly supports your answer. [1-2 sentence summary]
- NEVER make up file paths or function names.
- The [sisyphus-bot] prefix is MANDATORY on every comment you post. ## Findings
- Be genuinely helpful — imagine you're a senior maintainer who cares about the community. [Each finding with permalink proof. Example:]
- The config is parsed in [`src/config/loader.ts#L42-L58`](https://github.com/{REPO}/blob/{SHA}/src/config/loader.ts#L42-L58)
## Suggested Answer
[Draft answer with code references and permalinks]
## Confidence: [HIGH | MEDIUM | LOW]
[Reason. If LOW: what's missing]
## Recommended Action
[What maintainer should do]
---
REMEMBER: No permalink = no claim. Every code reference needs a permalink.
``` ```
</issue_question_prompt>
--- ---
### SUBAGENT_ISSUE_BUG ### ISSUE_BUG
<issue_bug_prompt>
``` ```
You are a GitHub bug analyzer for the repository {REPO}. You are analyzing bug report #{number} for {REPO}.
ITEM: ITEM:
- Issue #{number}: {title} - Issue #{number}: {title}
@@ -160,74 +227,75 @@ ITEM:
- Body: {body} - Body: {body}
- Comments: {comments_summary} - Comments: {comments_summary}
YOUR JOB: TASK:
1. Read the issue carefully. Understand the reported bug: 1. Understand: expected behavior, actual behavior, reproduction steps.
- What behavior does the user expect? 2. Search the codebase for relevant code. Trace the logic.
- What behavior do they actually see? 3. Determine verdict: CONFIRMED_BUG, NOT_A_BUG, ALREADY_FIXED, or UNCLEAR.
- What steps reproduce it? 4. For ALREADY_FIXED: find the fixing commit using git log/git blame. Include the commit SHA and what changed.
2. Search the codebase for the relevant code. Use Grep and Read tools. 5. For every finding, construct a permalink.
- Find the files/functions mentioned or related to the bug. 6. Write report to {REPORT_DIR}/issue-{number}.md
- Read them carefully and trace the logic.
3. Determine one of three outcomes:
OUTCOME A — CONFIRMED BUG (you found the problematic code): FINDING "ALREADY_FIXED" COMMITS:
Step 1: Post a comment on the issue. The comment MUST: - Use `git log --all --oneline -- {file}` to find recent changes to relevant files
- Start with exactly: [sisyphus-bot] - Use `git log --all --grep="fix" --grep="{keyword}" --all-match --oneline` to search commit messages
- Apologize sincerely for the inconvenience ("We're sorry you ran into this issue.") - Use `git blame {file}` to find who last changed the relevant lines
- Briefly acknowledge what the bug is - Use `git show {commit_sha}` to verify the fix
- Say "We've identified the root cause and will work on a fix." - Construct commit permalink: https://github.com/{REPO}/commit/{fix_commit_sha}
- Do NOT reveal internal implementation details unnecessarily
Step 2: Post the comment:
gh issue comment {number} --repo {REPO} --body "YOUR_COMMENT"
Step 3: Report back with:
ACTION: CONFIRMED_BUG
ROOT_CAUSE: [which file, which function, what goes wrong]
FIX_APPROACH: [how to fix it — be specific: "In {file}, line ~{N}, change X to Y because Z"]
SEVERITY: [LOW|MEDIUM|HIGH|CRITICAL]
AFFECTED_FILES: [list of files that need changes]
OUTCOME B — NOT A BUG (user misunderstanding, provably correct behavior): REPORT FORMAT (write this as the file content):
ONLY choose this if you can RIGOROUSLY PROVE the behavior is correct.
Step 1: Post a comment. The comment MUST:
- Start with exactly: [sisyphus-bot]
- Be kind and empathetic — never condescending
- Explain clearly WHY the current behavior is correct
- Include specific code references or documentation links
- Offer a workaround or alternative if possible
- End with "Please let us know if you have further questions!"
Step 2: Post the comment:
gh issue comment {number} --repo {REPO} --body "YOUR_COMMENT"
Step 3: DO NOT close the issue. Let the user or maintainer decide.
Step 4: Report back with:
ACTION: NOT_A_BUG
EXPLANATION: [why this is correct behavior]
PROOF: [specific code reference proving it]
OUTCOME C — UNCLEAR (can't determine from codebase alone): # Issue #{number}: {title}
Report back with: **Type:** Bug Report | **Author:** {author} | **Created:** {createdAt}
ACTION: NEEDS_INVESTIGATION
FINDINGS: [what you found so far]
BLOCKERS: [what's preventing you from determining the cause]
SUGGESTED_NEXT_STEPS: [what a human should look at]
RULES: ## Bug Summary
- NEVER guess at root causes. Only report CONFIRMED_BUG if you found the exact problematic code. **Expected:** [what user expects]
- NEVER close bug issues yourself. Only comment. **Actual:** [what actually happens]
- For OUTCOME B (not a bug): you MUST have rigorous proof. If there's ANY doubt, choose OUTCOME C instead. **Reproduction:** [steps if provided]
- The [sisyphus-bot] prefix is MANDATORY on every comment.
- When apologizing, be genuine. The user took time to report this. ## Verdict: [CONFIRMED_BUG | NOT_A_BUG | ALREADY_FIXED | UNCLEAR]
## Analysis
### Evidence
[Each piece of evidence with permalink. No permalink = mark [UNVERIFIED]]
### Root Cause (if CONFIRMED_BUG)
[Which file, which function, what goes wrong]
- Problematic code: [`{path}#L{N}`](permalink)
### Why Not A Bug (if NOT_A_BUG)
[Rigorous proof with permalinks that current behavior is correct]
### Fix Details (if ALREADY_FIXED)
- **Fixed in commit:** [`{short_sha}`](https://github.com/{REPO}/commit/{full_sha})
- **Fixed date:** {date}
- **What changed:** [description with diff permalink]
- **Fixed by:** {author}
### Blockers (if UNCLEAR)
[What prevents determination, what to investigate next]
## Severity: [LOW | MEDIUM | HIGH | CRITICAL]
## Affected Files
[List with permalinks]
## Suggested Fix (if CONFIRMED_BUG)
[Specific approach: "In {file}#L{N}, change X to Y because Z"]
## Recommended Action
[What maintainer should do]
---
CRITICAL: Claims without permalinks are worthless. If you cannot find evidence, say so explicitly rather than making unverified claims.
``` ```
</issue_bug_prompt>
--- ---
### SUBAGENT_ISSUE_FEATURE ### ISSUE_FEATURE
<issue_feature_prompt>
``` ```
You are a GitHub feature request analyzer for the repository {REPO}. You are analyzing feature request #{number} for {REPO}.
ITEM: ITEM:
- Issue #{number}: {title} - Issue #{number}: {title}
@@ -235,38 +303,41 @@ ITEM:
- Body: {body} - Body: {body}
- Comments: {comments_summary} - Comments: {comments_summary}
YOUR JOB: TASK:
1. Read the feature request. 1. Understand the request.
2. Search the codebase to check if this feature already exists (partially or fully). 2. Search codebase for existing (partial/full) implementations.
3. Assess feasibility and alignment with the project. 3. Assess feasibility.
4. Write report to {REPORT_DIR}/issue-{number}.md
Report back with: REPORT FORMAT (write this as the file content):
ACTION: FEATURE_ASSESSED
ALREADY_EXISTS: [YES_FULLY | YES_PARTIALLY | NO]
IF_EXISTS: [where in the codebase, how to use it]
FEASIBILITY: [EASY | MODERATE | HARD | ARCHITECTURAL_CHANGE]
RELEVANT_FILES: [files that would need changes]
NOTES: [any observations about implementation approach]
If the feature already fully exists: # Issue #{number}: {title}
Post a comment (prefix: [sisyphus-bot]) explaining how to use the existing feature with examples. **Type:** Feature Request | **Author:** {author} | **Created:** {createdAt}
gh issue comment {number} --repo {REPO} --body "YOUR_COMMENT"
RULES: ## Request Summary
- Do NOT close feature requests. [What the user wants]
- The [sisyphus-bot] prefix is MANDATORY on any comment.
## Existing Implementation: [YES_FULLY | YES_PARTIALLY | NO]
[If exists: where, with permalinks to the implementation]
## Feasibility: [EASY | MODERATE | HARD | ARCHITECTURAL_CHANGE]
## Relevant Files
[With permalinks]
## Implementation Notes
[Approach, pitfalls, dependencies]
## Recommended Action
[What maintainer should do]
``` ```
</issue_feature_prompt>
--- ---
### SUBAGENT_ISSUE_OTHER ### ISSUE_OTHER
<issue_other_prompt>
``` ```
You are a GitHub issue analyzer for the repository {REPO}. You are analyzing issue #{number} for {REPO}.
ITEM: ITEM:
- Issue #{number}: {title} - Issue #{number}: {title}
@@ -274,209 +345,195 @@ ITEM:
- Body: {body} - Body: {body}
- Comments: {comments_summary} - Comments: {comments_summary}
YOUR JOB: TASK: Assess and write report to {REPORT_DIR}/issue-{number}.md
Quickly assess this issue and report:
ACTION: ASSESSED
TYPE_GUESS: [QUESTION | BUG | FEATURE | DISCUSSION | META | STALE]
SUMMARY: [1-2 sentence summary]
NEEDS_ATTENTION: [YES | NO]
SUGGESTED_LABEL: [if any]
Do NOT post comments. Do NOT close. Just analyze and report. REPORT FORMAT (write this as the file content):
# Issue #{number}: {title}
**Type:** [QUESTION | BUG | FEATURE | DISCUSSION | META | STALE]
**Author:** {author} | **Created:** {createdAt}
## Summary
[1-2 sentences]
## Needs Attention: [YES | NO]
## Suggested Label: [if any]
## Recommended Action: [what maintainer should do]
``` ```
</issue_other_prompt>
--- ---
### SUBAGENT_PR_BUGFIX ### PR_BUGFIX
<pr_bugfix_prompt>
``` ```
You are a GitHub PR reviewer for the repository {REPO}. You are reviewing PR #{number} for {REPO}.
ITEM: ITEM:
- PR #{number}: {title} - PR #{number}: {title}
- Author: {author} - Author: {author}
- Base: {baseRefName} - Base: {baseRefName} <- Head: {headRefName}
- Head: {headRefName} - Draft: {isDraft} | Mergeable: {mergeable}
- Draft: {isDraft} - Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Mergeable: {mergeable}
- Review Decision: {reviewDecision}
- CI Status: {statusCheckRollup_summary}
- Body: {body} - Body: {body}
YOUR JOB: TASK:
1. Fetch PR details (DO NOT checkout the branch — read-only analysis): 1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision
gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision 2. Read diff: gh api repos/{REPO}/pulls/{number}/files
2. Read the changed files list. For each changed file, use `gh api repos/{REPO}/pulls/{number}/files` to see the diff. 3. Search codebase to verify fix correctness.
3. Search the codebase to understand what the PR is fixing and whether the fix is correct. 4. Write report to {REPORT_DIR}/pr-{number}.md
4. Evaluate merge safety:
MERGE CONDITIONS (ALL must be true for auto-merge): REPORT FORMAT (write this as the file content):
a. CI status checks: ALL passing (no failures, no pending)
b. Review decision: APPROVED
c. The fix is clearly correct — addresses an obvious, unambiguous bug
d. No risky side effects (no architectural changes, no breaking changes)
e. Not a draft PR
f. Mergeable state is clean (no conflicts)
IF ALL MERGE CONDITIONS MET: # PR #{number}: {title}
Step 1: Merge the PR: **Type:** Bugfix | **Author:** {author}
gh pr merge {number} --repo {REPO} --squash --auto **Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft}
Step 2: Report back with:
ACTION: MERGED
FIX_SUMMARY: [what bug was fixed and how]
FILES_CHANGED: [list of files]
RISK: NONE
IF ANY CONDITION NOT MET: ## Fix Summary
Report back with: [What bug, how fixed - with permalinks to changed code]
ACTION: NEEDS_HUMAN_DECISION
FIX_SUMMARY: [what the PR does]
WHAT_IT_FIXES: [the bug or issue it addresses]
CI_STATUS: [PASS | FAIL | PENDING — list any failures]
REVIEW_STATUS: [APPROVED | CHANGES_REQUESTED | PENDING | NONE]
MISSING: [what's preventing auto-merge — be specific]
RISK_ASSESSMENT: [what could go wrong]
AMBIGUOUS_PARTS: [anything that needs human judgment]
RECOMMENDED_ACTION: [what the maintainer should do]
ABSOLUTE RULES: ## Code Review
- NEVER run `git checkout`, `git fetch`, `git pull`, or `git switch`. READ-ONLY via gh CLI and API.
- NEVER checkout the PR branch. NEVER. Use `gh api` and `gh pr view` only. ### Correctness
- Only merge if you are 100% certain ALL conditions are met. When in doubt, report instead. [Is fix correct? Root cause addressed? Evidence with permalinks]
- The [sisyphus-bot] prefix is MANDATORY on any comment you post.
### Side Effects
[Risky changes, breaking changes - with permalinks if any]
### Code Quality
[Style, patterns, test coverage]
## Merge Readiness
| Check | Status |
|-------|--------|
| CI | [PASS / FAIL / PENDING] |
| Review | [APPROVED / CHANGES_REQUESTED / PENDING / NONE] |
| Mergeable | [YES / NO / CONFLICTED] |
| Draft | [YES / NO] |
| Correctness | [VERIFIED / CONCERNS / UNCLEAR] |
| Risk | [NONE / LOW / MEDIUM / HIGH] |
## Files Changed
[List with brief descriptions]
## Recommended Action: [MERGE | REQUEST_CHANGES | NEEDS_REVIEW | WAIT]
[Reasoning with evidence]
---
NEVER merge. NEVER comment. NEVER review. Write to file ONLY.
``` ```
</pr_bugfix_prompt>
--- ---
### SUBAGENT_PR_OTHER ### PR_OTHER
<pr_other_prompt>
``` ```
You are a GitHub PR reviewer for the repository {REPO}. You are reviewing PR #{number} for {REPO}.
ITEM: ITEM:
- PR #{number}: {title} - PR #{number}: {title}
- Author: {author} - Author: {author}
- Base: {baseRefName} - Base: {baseRefName} <- Head: {headRefName}
- Head: {headRefName} - Draft: {isDraft} | Mergeable: {mergeable}
- Draft: {isDraft} - Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Mergeable: {mergeable}
- Review Decision: {reviewDecision}
- CI Status: {statusCheckRollup_summary}
- Body: {body} - Body: {body}
YOUR JOB: TASK:
1. Fetch PR details (READ-ONLY — no checkout): 1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision
gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision 2. Read diff: gh api repos/{REPO}/pulls/{number}/files
2. Read the changed files via `gh api repos/{REPO}/pulls/{number}/files`. 3. Write report to {REPORT_DIR}/pr-{number}.md
3. Assess the PR and report:
ACTION: PR_ASSESSED REPORT FORMAT (write this as the file content):
TYPE: [FEATURE | REFACTOR | DOCS | CHORE | TEST | OTHER]
SUMMARY: [what this PR does in 2-3 sentences]
CI_STATUS: [PASS | FAIL | PENDING]
REVIEW_STATUS: [APPROVED | CHANGES_REQUESTED | PENDING | NONE]
FILES_CHANGED: [count and key files]
RISK_LEVEL: [LOW | MEDIUM | HIGH]
ALIGNMENT: [does this fit the project direction? YES | NO | UNCLEAR]
BLOCKERS: [anything preventing merge]
RECOMMENDED_ACTION: [MERGE | REQUEST_CHANGES | NEEDS_REVIEW | CLOSE | WAIT]
NOTES: [any observations for the maintainer]
ABSOLUTE RULES: # PR #{number}: {title}
- NEVER run `git checkout`, `git fetch`, `git pull`, or `git switch`. READ-ONLY. **Type:** [FEATURE | REFACTOR | DOCS | CHORE | TEST | OTHER]
- NEVER checkout the PR branch. Use `gh api` and `gh pr view` only. **Author:** {author}
- Do NOT merge non-bugfix PRs automatically. Report only. **Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft}
## Summary
[2-3 sentences with permalinks to key changes]
## Status
| Check | Status |
|-------|--------|
| CI | [PASS / FAIL / PENDING] |
| Review | [APPROVED / CHANGES_REQUESTED / PENDING / NONE] |
| Mergeable | [YES / NO / CONFLICTED] |
| Risk | [LOW / MEDIUM / HIGH] |
| Alignment | [YES / NO / UNCLEAR] |
## Files Changed
[Count and key files]
## Blockers
[If any]
## Recommended Action: [MERGE | REQUEST_CHANGES | NEEDS_REVIEW | CLOSE | WAIT]
[Reasoning]
---
NEVER merge. NEVER comment. NEVER review. Write to file ONLY.
``` ```
</pr_other_prompt> ---
## Phase 4: Collect & Update
Poll `background_output()` per task. As each completes:
1. Parse report.
2. `TaskUpdate(id=task_id, status="completed", description=REPORT_SUMMARY)`
3. Stream to user immediately.
--- ---
## PHASE 4: COLLECT RESULTS & UPDATE TASKS ## Phase 5: Final Summary
<collection> Write to `{REPORT_DIR}/SUMMARY.md` AND display to user:
Poll `background_output()` for each spawned task. As each completes:
1. Parse the subagent's report.
2. Update the corresponding TaskCreate entry:
- `TaskUpdate(id=task_id, status="completed", description=FULL_REPORT_TEXT)`
3. Stream the result to the user immediately — do not wait for all to finish.
Track counters:
- issues_answered (commented + closed)
- bugs_confirmed
- bugs_not_a_bug
- prs_merged
- prs_needs_decision
- features_assessed
</collection>
---
## PHASE 5: FINAL SUMMARY
After all background tasks complete, produce a summary:
```markdown ```markdown
# GitHub Triage Report {REPO} # GitHub Triage Report - {REPO}
**Date:** {date} **Date:** {date} | **Commit:** {COMMIT_SHA}
**Items Processed:** {total} **Items Processed:** {total}
**Report Directory:** {REPORT_DIR}
## Issues ({issue_count}) ## Issues ({issue_count})
| Action | Count | | Category | Count |
|--------|-------| |----------|-------|
| Answered & Closed | {issues_answered} | | Bug Confirmed | {n} |
| Bug Confirmed | {bugs_confirmed} | | Bug Already Fixed | {n} |
| Not A Bug (explained) | {bugs_not_a_bug} | | Not A Bug | {n} |
| Feature Assessed | {features_assessed} | | Needs Investigation | {n} |
| Needs Manual Attention | {needs_manual} | | Question Analyzed | {n} |
| Feature Assessed | {n} |
| Other | {n} |
## PRs ({pr_count}) ## PRs ({pr_count})
| Action | Count | | Category | Count |
|--------|-------| |----------|-------|
| Auto-Merged (safe bugfix) | {prs_merged} | | Bugfix Reviewed | {n} |
| Needs Human Decision | {prs_needs_decision} | | Other PR Reviewed | {n} |
| Assessed (non-bugfix) | {prs_assessed} |
## Items Requiring Your Attention ## Items Requiring Attention
[List each item that needs human decision with its report summary] [Each item: number, title, verdict, 1-line summary, link to report file]
## Report Files
[All generated files with paths]
``` ```
--- ---
## ANTI-PATTERNS ## Anti-Patterns
| Violation | Severity | | Violation | Severity |
|-----------|----------| |-----------|----------|
| Using any category other than `free` | CRITICAL | | ANY GitHub mutation (comment/close/merge/review/label/edit) | **CRITICAL** |
| Claim without permalink | **CRITICAL** |
| Using category other than `quick` | CRITICAL |
| Batching multiple items into one task | CRITICAL | | Batching multiple items into one task | CRITICAL |
| Using `run_in_background=false` | CRITICAL | | `run_in_background=false` | CRITICAL |
| Subagent running `git checkout` on a PR branch | CRITICAL | | `git checkout` on PR branch | CRITICAL |
| Posting comment without `[sisyphus-bot]` prefix | CRITICAL | | Guessing without codebase evidence | HIGH |
| Merging a PR that doesn't meet ALL 6 conditions | CRITICAL | | Not writing report to `{REPORT_DIR}` | HIGH |
| Closing a bug issue (only comment, never close bugs) | HIGH | | Using branch name instead of commit SHA in permalink | HIGH |
| Guessing at answers without codebase evidence | HIGH |
| Not recording results via TaskCreate/TaskUpdate | HIGH |
---
## QUICK START
When invoked:
1. `TaskCreate` for the overall triage job
2. Fetch all open issues + PRs via gh CLI (paginate if needed)
3. Classify each item (ISSUE_QUESTION, ISSUE_BUG, ISSUE_FEATURE, PR_BUGFIX, etc.)
4. For EACH item: `TaskCreate` + `task(category="free", run_in_background=true, load_skills=[], prompt=...)`
5. Poll `background_output()` — stream results as they arrive
6. `TaskUpdate` each task with the subagent's findings
7. Produce final summary report