关于 github-triage
只读的 GitHub 问题与 PR 分诊编排器,面向需要分析大量待处理事项的团队。它为每个事项分配独立的后台子代理,要求报告中的事实附带固定提交的 GitHub 永久链接,并禁止修改 GitHub 状态。
主要功能
- 01获取开放的 issue 和 PR
- 02按规则分类问题与 PR
- 03每个事项启动独立后台子代理
- 04将分析报告写入 /tmp
- 05要求事实声明附带提交固定的永久链接
- 06禁止执行 GitHub 状态修改
适用场景
- 01只读分析开放 issue 与 PR
- 02并行分诊大型待处理队列
- 03为代码问题分析整理可追溯证据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ code-yeongyu/ oh-my-openagent --skill github-triage安装后在 Claude Code 中输入/github-triage确认已加载。
附带文件scripts/gh_fetch.py
详细介绍
GitHub 分诊 - 只读分析器
只读 GitHub 分诊协调器。获取未关闭的问题/PR,进行分类,并为每个条目启动 1 个后台 `quick` 子 Agent。每个子 Agent 都会进行分析并写入报告文件。绝不修改 GitHub。架构
1 个问题/PR = 1 个 task_create = 1 个 quick 子 Agent(后台)。绝无例外。
| 规则 | 值 |
|---|---|
| 类别 | quick |
| 执行方式 | run_in_background=true |
| 并行度 | 同时处理所有条目 |
| 跟踪 | 每个条目创建 1 个 task_create |
| 输出 | /tmp/{YYYYMMDD-HHmmss}/issue-{N}.md 或 pr-{N}.md |
零操作策略(绝对要求)
<zero_action> 子 Agent 绝不能运行任何会写入或修改 GitHub 状态的命令。
禁止(包括但不限于):
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
允许:
gh issue view、gh pr view、gh api(仅限 GET)——读取 GitHub 数据Grep、Read、Glob——读取代码库Write——仅将报告文件写入/tmp/git log、git show、git blame——读取 Git 历史(用于查找修复提交)
任何 GitHub 修改都属于严重违规。 </zero_action>
证据规则(强制要求)
**报告中的每项事实陈述都必须附有 GitHub 永久链接作为证明。**永久链接是指向特定提交中特定行或范围的 URL,例如:
https://github.com/{owner}/{repo}/blob/{commit_sha}/{path}#L{start}-L{end}
如何生成永久链接
- 使用 Grep/Read 查找相关文件和行。
- 获取当前提交 SHA:
git rev-parse HEAD - 构造链接:
https://github.com/{REPO}/blob/{SHA}/{filepath}#L{line}(范围使用#L{start}-L{end})
规则
- 没有永久链接 = 不得提出该项声明。 如果无法用永久链接支持某项陈述,请改为写明“未找到证据”。
- 没有永久链接的陈述必须明确标记为
[UNVERIFIED],且不具备任何权重。 - 指向
main/master/dev分支的永久链接不可接受——只能使用提交 SHA。 - 分析 Bug 时:链接到存在问题的代码。验证修复时:链接到修复提交的差异。
阶段 0:设置
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
REPORT_DIR="/tmp/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$REPORT_DIR"
COMMIT_SHA=$(git rev-parse HEAD)
将 REPO、REPORT_DIR 和 COMMIT_SHA 传递给每个子 Agent。
阶段 1:获取所有未关闭条目(已修正)
重要: body 和 comments 字段可能包含会导致 jq 解析失败的控制字符。请先获取基本元数据,然后由子 Agent 逐条获取完整详情。
# Step 1: Fetch basic metadata (without body/comments to avoid JSON parsing issues)
ISSUES_LIST=$(gh issue list --repo $REPO --state open --limit 500 \
--json number,title,labels,author,createdAt)
ISSUE_COUNT=$(echo "$ISSUES_LIST" | jq length)
# Paginate if needed
if [ "$ISSUE_COUNT" -eq 500 ]; then
LAST_DATE=$(echo "$ISSUES_LIST" | jq -r '.[-1].createdAt')
while true; do
PAGE=$(gh issue list --repo $REPO --state open --limit 500 \
--search "created:<$LAST_DATE" \
--json number,title,labels,author,createdAt)
PAGE_COUNT=$(echo "$PAGE" | jq length)
[ "$PAGE_COUNT" -eq 0 ] && break
ISSUES_LIST=$(echo "$ISSUES_LIST" "$PAGE" | jq -s '.[0] + .[1] | unique_by(.number)')
ISSUE_COUNT=$(echo "$ISSUES_LIST" | jq length)
[ "$PAGE_COUNT" -lt 500 ] && break
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
done
fi
# Same for PRs
PRS_LIST=$(gh pr list --repo $REPO --state open --limit 500 \
--json number,title,labels,author,headRefName,baseRefName,isDraft,createdAt)
PR_COUNT=$(echo "$PRS_LIST" | jq length)
if [ "$PR_COUNT" -eq 500 ]; then
LAST_DATE=$(echo "$PRS_LIST" | jq -r '.[-1].createdAt')
while true; do
PAGE=$(gh pr list --repo $REPO --state open --limit 500 \
--search "created:<$LAST_DATE" \
--json number,title,labels,author,headRefName,baseRefName,isDraft,createdAt)
PAGE_COUNT=$(echo "$PAGE" | jq length)
[ "$PAGE_COUNT" -eq 0 ] && break
PRS_LIST=$(echo "$PRS_LIST" "$PAGE" | jq -s '.[0] + .[1] | unique_by(.number)')
PR_COUNT=$(echo "$PRS_LIST" | jq length)
[ "$PAGE_COUNT" -lt 500 ] && break
LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
done
fi
echo "Total issues: $ISSUE_COUNT, Total PRs: $PR_COUNT"
大型代码库处理: 如果条目总数超过 50,必须处理所有条目。使用上面的分页代码获取每一个未关闭的问题和 PR。 不要抽样或将条目限制为 50 个——必须处理整个积压列表。
示例:如果有 500 个未关闭问题,就启动 500 个子 Agent。如果有 1000 个未关闭 PR,就启动 1000 个子 Agent。
注意: 后台任务系统会自动排队处理超出的任务。
阶段 2:分类
| 类型 | 判定方式 |
|---|---|
ISSUE_QUESTION | [Question]、[Discussion]、?、"how to" / "why does" / "is it possible" |
ISSUE_BUG | [Bug]、Bug:、错误消息、堆栈跟踪、异常行为 |
ISSUE_FEATURE | [Feature]、[RFE]、[Enhancement]、Feature Request、Proposal |
ISSUE_OTHER | 其他所有情况 |
PR_BUGFIX | 标题以 fix 开头,分支包含 fix//bugfix/,或标签为 bug |
PR_OTHER | 其他所有情况 |
阶段 3:启动子 Agent(单独调用工具)
重要:必须通过单独的 task_create 工具调用,逐个创建任务。绝不能批量创建或编写脚本。
对每个条目,按顺序执行以下步骤:
步骤 3.1:创建任务记录
task_create(
subject="Triage: #{number} {title}",
description="GitHub {issue|PR} triage analysis - {type}",
metadata={"type": "{ISSUE_QUESTION|ISSUE_BUG|ISSUE_FEATURE|ISSUE_OTHER|PR_BUGFIX|PR_OTHER}", "number": {number}}
)
第 3.2 步:启动分析子 Agent(后台)
task(
category="quick",
run_in_background=true,
load_skills=[],
prompt=SUBAGENT_PROMPT
)
对子 Agent 的绝对要求:
- 仅进行分析——绝不在 GitHub 上执行操作(不发表评论、不合并、不关闭)
- 只读——仅使用工具读取代码和 GitHub 数据
- 仅撰写报告——通过 Write 工具将输出写入
{REPORT_DIR}/{issue|pr}-{number}.md - 必须提供证据——每项声明都必须附有 GitHub 永久链接作为证明
For each item:
1. task_create(subject="Triage: #{number} {title}")
2. task(category="quick", run_in_background=true, load_skills=[], prompt=SUBAGENT_PROMPT)
3. Store mapping: item_number -> { task_id, background_task_id }
子 Agent 提示词
通用前言(包含在所有子 Agent 提示词中)
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
ISSUE_QUESTION
You are analyzing issue #{number} for {REPO}.
ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}
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
REPORT FORMAT (write this as the file content):
# Issue #{number}: {title}
**Type:** Question | **Author:** {author} | **Created:** {createdAt}
## 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.
ISSUE_BUG
You are analyzing bug report #{number} for {REPO}.
ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}
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
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}
REPORT FORMAT (write this as the file content):
# Issue #{number}: {title}
**Type:** Bug Report | **Author:** {author} | **Created:** {createdAt}
## 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.
ISSUE_FEATURE
You are analyzing feature request #{number} for {REPO}.
ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}
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 FORMAT (write this as the file content):
# Issue #{number}: {title}
**Type:** Feature Request | **Author:** {author} | **Created:** {createdAt}
## 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]
ISSUE_OTHER
You are analyzing issue #{number} for {REPO}.
ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}
TASK: Assess and write report to {REPORT_DIR}/issue-{number}.md
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]
PR_BUGFIX
You are reviewing PR #{number} for {REPO}.
ITEM:
- PR #{number}: {title}
- Author: {author}
- Base: {baseRefName} <- Head: {headRefName}
- Draft: {isDraft} | Mergeable: {mergeable}
- Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Body: {body}
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
REPORT FORMAT (write this as the file content):
# PR #{number}: {title}
**Type:** Bugfix | **Author:** {author}
**Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft}
## Fix Summary
[What bug, how fixed - with permalinks to changed code]
## 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.
PR_OTHER
You are reviewing PR #{number} for {REPO}.
ITEM:
- PR #{number}: {title}
- Author: {author}
- Base: {baseRefName} <- Head: {headRefName}
- Draft: {isDraft} | Mergeable: {mergeable}
- Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Body: {body}
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
REPORT FORMAT (write this as the file content):
# 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.
第 4 阶段:收集并更新
按任务轮询 background_output()。每项任务完成后:
- 解析报告。
task_update(id=task_id, status="completed", description=REPORT_SUMMARY)- 立即向用户输出。
第 5 阶段:最终摘要
写入 {REPORT_DIR}/SUMMARY.md 并向用户展示:
# GitHub Triage Report - {REPO}
**Date:** {date} | **Commit:** {COMMIT_SHA}
**Items Processed:** {total}
**Report Directory:** {REPORT_DIR}
## Issues ({issue_count})
| 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})
| Category | Count |
|----------|-------|
| Bugfix Reviewed | {n} |
| Other PR Reviewed | {n} |
## Items Requiring Attention
[Each item: number, title, verdict, 1-line summary, link to report file]
## Report Files
[All generated files with paths]
反模式
| 违规行为 | 严重程度 |
|---|---|
| 进行任何 GitHub 修改(评论/关闭/合并/审核/添加标签/编辑) | 严重 |
| 声明没有永久链接作为依据 | 严重 |
使用 quick 以外的类别 | 严重 |
| 将多个项目批量合并到一个任务中 | 严重 |
run_in_background=false | 严重 |
对 PR 分支执行 git checkout | 严重 |
| 在没有代码库证据的情况下猜测 | 高 |
未将报告写入 {REPORT_DIR} | 高 |
| 在永久链接中使用分支名称而非提交 SHA | 高 |