github-triage について
オープンな issue と PR を分析する、読み取り専用の GitHub トリアージオーケストレーターです。各項目にバックグラウンドのサブエージェントを割り当て、事実の主張にはコミット固定の GitHub パーマリンクを求め、GitHub の状態変更を禁止します。
主な機能
- 01オープンな issue と PR の取得
- 02規則に基づく issue と PR の分類
- 03項目ごとの個別バックグラウンドサブエージェント
- 04/tmp への分析レポート出力
- 05事実の主張にコミット固定パーマリンクを要求
- 06GitHub の状態変更を禁止
活用シーン
- 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 トリアージオーケストレーターです。オープン中の Issue/PR を取得して分類し、項目ごとにバックグラウンドで `quick` サブエージェントを 1 つ起動します。各サブエージェントは分析を行い、レポートファイルを書き込みます。GitHub の変更は一切行いません。アーキテクチャ
1 ISSUE/PR = 1 task_create = 1 quick サブエージェント(バックグラウンド)。例外なし。
| ルール | 値 |
|---|---|
| カテゴリー | quick |
| 実行 | run_in_background=true |
| 並列処理 | すべての項目を同時に処理 |
| 追跡 | 項目ごとに task_create |
| 出力 | /tmp/{YYYYMMDD-HHmmss}/issue-{N}.md または pr-{N}.md |
アクション禁止ポリシー(絶対)
<zero_action> サブエージェントは、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 のみを使用してください。- バグの分析では問題のあるコードへのパーマリンクを、修正の検証では修正コミットの差分へのパーマリンクを記載してください。
フェーズ 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 を渡します。
フェーズ 1:オープン中の項目をすべて取得(修正版)
重要: body と comments の各フィールドには、jq の解析を妨げる制御文字が含まれている場合があります。最初に基本メタデータを取得し、その後サブエージェントで項目ごとの詳細を取得してください。
# 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 を超える場合、すべての項目を処理する必要があります。上記のページネーション用コードを使って、オープン中の Issue と PR をすべて取得してください。 項目を 50 件にサンプリングしたり制限したりしないでください。未処理の項目をすべて処理してください。
例:オープン中の Issue が 500 件ある場合は、サブエージェントを 500 個起動します。オープン中の PR が 1000 件ある場合は、サブエージェントを 1000 個起動します。
注: バックグラウンドタスクシステムが、上限を超えるタスクを自動的にキューに追加します。
フェーズ 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:サブエージェントの起動(ツールを個別に呼び出す)
重要:task_create ツールを個別に呼び出して、タスクを 1 つずつ作成してください。まとめて実行したり、スクリプトを使ったりしてはいけません。
各項目について、以下の手順を順番に実行します。
ステップ 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:分析サブエージェントを起動(バックグラウンド)
task(
category="quick",
run_in_background=true,
load_skills=[],
prompt=SUBAGENT_PROMPT
)
サブエージェントの絶対ルール:
- 分析のみ - 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 }
サブエージェントのプロンプト
共通の前文(すべてのサブエージェントのプロンプトに含める)
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 以外のカテゴリの使用 | 致命的 |
| 複数の項目を 1 つのタスクにまとめること | 致命的 |
run_in_background=false | 致命的 |
PR ブランチでの git checkout | 致命的 |
| コードベースの証拠なしの推測 | 高 |
{REPORT_DIR} にレポートを書き込まないこと | 高 |
| パーマリンクにコミット SHA ではなくブランチ名を使用すること | 高 |