diff --git a/.opencode/skills/github-triage/SKILL.md b/.opencode/skills/github-triage/SKILL.md index cb2910fad..7e2cefec0 100644 --- a/.opencode/skills/github-triage/SKILL.md +++ b/.opencode/skills/github-triage/SKILL.md @@ -1,105 +1,181 @@ --- 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 -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. ---- +## Architecture -## ARCHITECTURE - -``` -1 issue or PR = 1 TaskCreate = 1 task(category="free", run_in_background=true) -``` +**1 ISSUE/PR = 1 TASKCREATE = 1 `quick` SUBAGENT (background). NO EXCEPTIONS.** | Rule | Value | |------|-------| -| Category for ALL subagents | `free` | -| Execution mode | `run_in_background=true` | -| Parallelism | ALL items launched simultaneously | -| Result tracking | Each subagent calls `TaskCreate` with its findings | -| Result collection | `background_output()` polling loop | +| Category | `quick` | +| Execution | `run_in_background=true` | +| Parallelism | ALL items simultaneously | +| Tracking | `TaskCreate` per item | +| Output | `/tmp/{YYYYMMDD-HHmmss}/issue-{N}.md` or `pr-{N}.md` | --- -## PHASE 1: FETCH ALL OPEN ITEMS +## Zero-Action Policy (ABSOLUTE) - -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.** + + +--- + +## Evidence Rule (MANDATORY) + + +**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. + + +--- + +## Phase 0: Setup ```bash REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) - -# Issues: all open -gh issue list --repo $REPO --state open --limit 500 \ - --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 +REPORT_DIR="/tmp/$(date +%Y%m%d-%H%M%S)" +mkdir -p "$REPORT_DIR" +COMMIT_SHA=$(git rev-parse HEAD) ``` -If either returns exactly 500 results, paginate using `--search "created: +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 +``` --- -## PHASE 2: CLASSIFY EACH ITEM +## Phase 2: Classify -For each item, determine its type based on title, labels, and body content: - - - -### Issues - -| Type | Detection | Action Path | -|------|-----------|-------------| -| `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 | - - +| Type | Detection | +|------|-----------| +| `ISSUE_QUESTION` | `[Question]`, `[Discussion]`, `?`, "how to" / "why does" / "is it possible" | +| `ISSUE_BUG` | `[Bug]`, `Bug:`, error messages, stack traces, unexpected behavior | +| `ISSUE_FEATURE` | `[Feature]`, `[RFE]`, `[Enhancement]`, `Feature Request`, `Proposal` | +| `ISSUE_OTHER` | Anything else | +| `PR_BUGFIX` | Title starts with `fix`, branch contains `fix/`/`bugfix/`, label `bug` | +| `PR_OTHER` | Everything else | --- -## PHASE 3: SPAWN 1 BACKGROUND TASK PER ITEM - -For EVERY item, create a TaskCreate entry first, then spawn a background task. +## Phase 3: Spawn Subagents ``` For each item: 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 } ``` --- -## 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 ``` -You are a GitHub issue responder for the repository {REPO}. +You are analyzing issue #{number} for {REPO}. ITEM: - Issue #{number}: {title} @@ -107,52 +183,43 @@ ITEM: - Body: {body} - Comments: {comments_summary} -YOUR JOB: -1. Read the issue carefully. Understand what the user is asking. -2. Search the codebase to find the answer. Use Grep and Read tools. - - Search for relevant file names, function names, config keys mentioned in the issue. - - Read the files you find to understand how the feature works. -3. Decide: Can you answer this clearly and accurately from the codebase? +TASK: +1. Understand the question. +2. Search the codebase (Grep, Read) for the answer. +3. For every finding, construct a permalink: https://github.com/{REPO}/blob/{COMMIT_SHA}/{path}#L{N} +4. Write report to {REPORT_DIR}/issue-{number}.md -IF YES (you found a clear, accurate answer): - 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] +REPORT FORMAT (write this as the file content): -IF NO (not enough info in codebase, or answer is uncertain): - Report back with: - ACTION: NEEDS_MANUAL_ATTENTION - REASON: [why you couldn't answer — be specific] - PARTIAL_FINDINGS: [what you DID find, if anything] +# Issue #{number}: {title} +**Type:** Question | **Author:** {author} | **Created:** {createdAt} -RULES: -- NEVER guess. Only answer if the codebase clearly supports your answer. -- NEVER make up file paths or function names. -- The [sisyphus-bot] prefix is MANDATORY on every comment you post. -- Be genuinely helpful — imagine you're a senior maintainer who cares about the community. +## Question +[1-2 sentence summary] + +## Findings +[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. ``` - - --- -### SUBAGENT_ISSUE_BUG - - +### ISSUE_BUG ``` -You are a GitHub bug analyzer for the repository {REPO}. +You are analyzing bug report #{number} for {REPO}. ITEM: - Issue #{number}: {title} @@ -160,74 +227,75 @@ ITEM: - Body: {body} - Comments: {comments_summary} -YOUR JOB: -1. Read the issue carefully. Understand the reported bug: - - What behavior does the user expect? - - What behavior do they actually see? - - What steps reproduce it? -2. Search the codebase for the relevant code. Use Grep and Read tools. - - Find the files/functions mentioned or related to the bug. - - Read them carefully and trace the logic. -3. Determine one of three outcomes: +TASK: +1. Understand: expected behavior, actual behavior, reproduction steps. +2. Search the codebase for relevant code. Trace the logic. +3. Determine verdict: CONFIRMED_BUG, NOT_A_BUG, ALREADY_FIXED, or UNCLEAR. +4. For ALREADY_FIXED: find the fixing commit using git log/git blame. Include the commit SHA and what changed. +5. For every finding, construct a permalink. +6. Write report to {REPORT_DIR}/issue-{number}.md -OUTCOME A — CONFIRMED BUG (you found the problematic code): - Step 1: Post a comment on the issue. The comment MUST: - - Start with exactly: [sisyphus-bot] - - Apologize sincerely for the inconvenience ("We're sorry you ran into this issue.") - - Briefly acknowledge what the bug is - - Say "We've identified the root cause and will work on a fix." - - 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] +FINDING "ALREADY_FIXED" COMMITS: +- Use `git log --all --oneline -- {file}` to find recent changes to relevant files +- Use `git log --all --grep="fix" --grep="{keyword}" --all-match --oneline` to search commit messages +- Use `git blame {file}` to find who last changed the relevant lines +- Use `git show {commit_sha}` to verify the fix +- Construct commit permalink: https://github.com/{REPO}/commit/{fix_commit_sha} -OUTCOME B — NOT A BUG (user misunderstanding, provably correct behavior): - 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] +REPORT FORMAT (write this as the file content): -OUTCOME C — UNCLEAR (can't determine from codebase alone): - Report back with: - 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] +# Issue #{number}: {title} +**Type:** Bug Report | **Author:** {author} | **Created:** {createdAt} -RULES: -- NEVER guess at root causes. Only report CONFIRMED_BUG if you found the exact problematic code. -- NEVER close bug issues yourself. Only comment. -- For OUTCOME B (not a bug): you MUST have rigorous proof. If there's ANY doubt, choose OUTCOME C instead. -- The [sisyphus-bot] prefix is MANDATORY on every comment. -- When apologizing, be genuine. The user took time to report this. +## Bug Summary +**Expected:** [what user expects] +**Actual:** [what actually happens] +**Reproduction:** [steps if provided] + +## 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. ``` - - --- -### SUBAGENT_ISSUE_FEATURE - - +### ISSUE_FEATURE ``` -You are a GitHub feature request analyzer for the repository {REPO}. +You are analyzing feature request #{number} for {REPO}. ITEM: - Issue #{number}: {title} @@ -235,38 +303,41 @@ ITEM: - Body: {body} - Comments: {comments_summary} -YOUR JOB: -1. Read the feature request. -2. Search the codebase to check if this feature already exists (partially or fully). -3. Assess feasibility and alignment with the project. +TASK: +1. Understand the request. +2. Search codebase for existing (partial/full) implementations. +3. Assess feasibility. +4. Write report to {REPORT_DIR}/issue-{number}.md -Report back with: - 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] +REPORT FORMAT (write this as the file content): -If the feature already fully exists: - Post a comment (prefix: [sisyphus-bot]) explaining how to use the existing feature with examples. - gh issue comment {number} --repo {REPO} --body "YOUR_COMMENT" +# Issue #{number}: {title} +**Type:** Feature Request | **Author:** {author} | **Created:** {createdAt} -RULES: -- Do NOT close feature requests. -- The [sisyphus-bot] prefix is MANDATORY on any comment. +## Request Summary +[What the user wants] + +## 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] ``` - - --- -### SUBAGENT_ISSUE_OTHER - - +### ISSUE_OTHER ``` -You are a GitHub issue analyzer for the repository {REPO}. +You are analyzing issue #{number} for {REPO}. ITEM: - Issue #{number}: {title} @@ -274,209 +345,195 @@ ITEM: - Body: {body} - Comments: {comments_summary} -YOUR JOB: -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] +TASK: Assess and write report to {REPORT_DIR}/issue-{number}.md -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] ``` - - --- -### SUBAGENT_PR_BUGFIX - - +### PR_BUGFIX ``` -You are a GitHub PR reviewer for the repository {REPO}. +You are reviewing PR #{number} for {REPO}. ITEM: - PR #{number}: {title} - Author: {author} -- Base: {baseRefName} -- Head: {headRefName} -- Draft: {isDraft} -- Mergeable: {mergeable} -- Review Decision: {reviewDecision} -- CI Status: {statusCheckRollup_summary} +- Base: {baseRefName} <- Head: {headRefName} +- Draft: {isDraft} | Mergeable: {mergeable} +- Review: {reviewDecision} | CI: {statusCheckRollup_summary} - Body: {body} -YOUR JOB: -1. Fetch PR details (DO NOT checkout the branch — read-only analysis): - gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision -2. Read the changed files list. For each changed file, use `gh api repos/{REPO}/pulls/{number}/files` to see the diff. -3. Search the codebase to understand what the PR is fixing and whether the fix is correct. -4. Evaluate merge safety: +TASK: +1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision +2. Read diff: gh api repos/{REPO}/pulls/{number}/files +3. Search codebase to verify fix correctness. +4. Write report to {REPORT_DIR}/pr-{number}.md -MERGE CONDITIONS (ALL must be true for auto-merge): - 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) +REPORT FORMAT (write this as the file content): -IF ALL MERGE CONDITIONS MET: - Step 1: Merge the PR: - gh pr merge {number} --repo {REPO} --squash --auto - Step 2: Report back with: - ACTION: MERGED - FIX_SUMMARY: [what bug was fixed and how] - FILES_CHANGED: [list of files] - RISK: NONE +# PR #{number}: {title} +**Type:** Bugfix | **Author:** {author} +**Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft} -IF ANY CONDITION NOT MET: - Report back with: - 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] +## Fix Summary +[What bug, how fixed - with permalinks to changed code] -ABSOLUTE RULES: -- 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. -- Only merge if you are 100% certain ALL conditions are met. When in doubt, report instead. -- The [sisyphus-bot] prefix is MANDATORY on any comment you post. +## Code Review + +### Correctness +[Is fix correct? Root cause addressed? Evidence with permalinks] + +### 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. ``` - - --- -### SUBAGENT_PR_OTHER - - +### PR_OTHER ``` -You are a GitHub PR reviewer for the repository {REPO}. +You are reviewing PR #{number} for {REPO}. ITEM: - PR #{number}: {title} - Author: {author} -- Base: {baseRefName} -- Head: {headRefName} -- Draft: {isDraft} -- Mergeable: {mergeable} -- Review Decision: {reviewDecision} -- CI Status: {statusCheckRollup_summary} +- Base: {baseRefName} <- Head: {headRefName} +- Draft: {isDraft} | Mergeable: {mergeable} +- Review: {reviewDecision} | CI: {statusCheckRollup_summary} - Body: {body} -YOUR JOB: -1. Fetch PR details (READ-ONLY — no checkout): - gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision -2. Read the changed files via `gh api repos/{REPO}/pulls/{number}/files`. -3. Assess the PR and report: +TASK: +1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision +2. Read diff: gh api repos/{REPO}/pulls/{number}/files +3. Write report to {REPORT_DIR}/pr-{number}.md - ACTION: PR_ASSESSED - 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] +REPORT FORMAT (write this as the file content): -ABSOLUTE RULES: -- NEVER run `git checkout`, `git fetch`, `git pull`, or `git switch`. READ-ONLY. -- NEVER checkout the PR branch. Use `gh api` and `gh pr view` only. -- Do NOT merge non-bugfix PRs automatically. Report only. +# PR #{number}: {title} +**Type:** [FEATURE | REFACTOR | DOCS | CHORE | TEST | OTHER] +**Author:** {author} +**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. ``` - +--- + +## 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 - -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 - - ---- - -## PHASE 5: FINAL SUMMARY - -After all background tasks complete, produce a summary: +Write to `{REPORT_DIR}/SUMMARY.md` AND display to user: ```markdown -# GitHub Triage Report — {REPO} +# GitHub Triage Report - {REPO} -**Date:** {date} +**Date:** {date} | **Commit:** {COMMIT_SHA} **Items Processed:** {total} +**Report Directory:** {REPORT_DIR} ## Issues ({issue_count}) -| Action | Count | -|--------|-------| -| Answered & Closed | {issues_answered} | -| Bug Confirmed | {bugs_confirmed} | -| Not A Bug (explained) | {bugs_not_a_bug} | -| Feature Assessed | {features_assessed} | -| Needs Manual Attention | {needs_manual} | +| Category | Count | +|----------|-------| +| Bug Confirmed | {n} | +| Bug Already Fixed | {n} | +| Not A Bug | {n} | +| Needs Investigation | {n} | +| Question Analyzed | {n} | +| Feature Assessed | {n} | +| Other | {n} | ## PRs ({pr_count}) -| Action | Count | -|--------|-------| -| Auto-Merged (safe bugfix) | {prs_merged} | -| Needs Human Decision | {prs_needs_decision} | -| Assessed (non-bugfix) | {prs_assessed} | +| Category | Count | +|----------|-------| +| Bugfix Reviewed | {n} | +| Other PR Reviewed | {n} | -## Items Requiring Your Attention -[List each item that needs human decision with its report summary] +## Items Requiring Attention +[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 | |-----------|----------| -| 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 | -| Using `run_in_background=false` | CRITICAL | -| Subagent running `git checkout` on a PR branch | CRITICAL | -| Posting comment without `[sisyphus-bot]` prefix | CRITICAL | -| Merging a PR that doesn't meet ALL 6 conditions | CRITICAL | -| Closing a bug issue (only comment, never close bugs) | 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 +| `run_in_background=false` | CRITICAL | +| `git checkout` on PR branch | CRITICAL | +| Guessing without codebase evidence | HIGH | +| Not writing report to `{REPORT_DIR}` | HIGH | +| Using branch name instead of commit SHA in permalink | HIGH |