| name | triage-pr |
| description | Triage a single GitHub PR by PR number. Check out the PR's branch, detect conflicts with the target branch via `gh pr status` (and label the PR with `cc-resolve-conflict` if any are found), collect unresolved review comments and CI status and judge only whether each item must be fixed, then take action (add cc-fix-onetime label if fixes are needed; if release-ready, add cc-release-ready label for an Epic PR marked `cc-epic-issue` instead of merging, otherwise merge the PR). |
| argument-hint | [pr-number] |
| hooks | {"Stop":[{"matcher":"","hooks":[{"type":"command","command":"node \"${CLAUDE_PLUGIN_ROOT}/scripts/stop-servers.mjs\""}]}]} |
Triage PR
指定されたPR番号のPRに対して、コンフリクト検知から修正要否の判定、最終アクション(ラベル付与またはマージ)までを一貫して実行するスキルです。Instructionsに従って、PRの状態を確認し、適切なアクションを実行してください。
このスキルがやること・やらないこと
やること:
- ステップ1のコンフリクト検知(
gh pr statusで確認し、コンフリクトがあればcc-resolve-conflictラベル付与のみで終了)
- ステップ2の未解決レビューコメント・CIステータスの収集と、各項目が「修正すべきか」の二分判定のみ
- ステップ3のアクション: 修正が必要なら
cc-fix-onetimeラベル付与 / マージ可能な場合は、Epic PR(cc-epic-issue付き)ならcc-release-readyラベル付与(マージはしない)、通常PRならマージ
絶対にやらないこと:
- PRのコード修正・実装: 「対応すべき」と判定された項目があっても、このスキル内では一切コードを変更しない。修正の実行は
cc-fix-onetimeラベル付与後に別スキル(fix-review-pointなど)の責務
- コンフリクト解消の直接実行: rebase・コンフリクトファイルの編集・force-pushは行わない。検知したら
cc-resolve-conflictラベルを付けて終了し、実際の解消は同ラベルをトリガーに別スキル(resolve-pr-conflict等)が担当する
- 修正プランの作成:
create-review-fix-plan スキルを呼び出してはならない。修正方針・タスク分解・影響範囲の見積もりは cc-fix-onetime を拾う fix-review-point 側の責務であり、ここで作ると同じ分析をPRごとに二重に行いトークンを無駄に消費する。本スキルは「修正すべきコメントが1件でもあるか」だけを判定する
- 新規コミットの作成: コミット・push・commit amendを行わない
- テスト追加・Lint修正・リファクタリング: 評価対象であっても、実行せずラベル付与にとどめる
ファイル編集ツール(Edit / Write / MultiEdit / NotebookEdit)はこのスキルの本文では一切呼び出さない。コードを触る作業はすべて「ラベル付与 → 別スキルが拾って実行」の流れに委ねる(ステップ1のcc-resolve-conflict、ステップ3パターンAのcc-fix-onetime)。
Instructions
!git fetch -p >/dev/null 2>&1 || true
プリアンブル(! インライン実行)に失敗しうるコマンドを置かないこと: プリアンブルのコマンドが失敗すると、セッションはモデル未起動のまま何も出力せず exit 0 で終了し、ワーカーが空振り実行を延々と繰り返す。プリアンブルには || true で非致命化したコマンドだけを置き、gh pr checkout のような失敗しうるコマンドは本文のステップ0で実行する。
実行モードの制約
本スキル固有のリスク: 本スキルは claude-task-worker の triage-pr ワーカー(cc-triage-scope ラベル)から自動起動され、ワーカーはスキルプロセスの同期完了を根拠に cc-fix-onetime の付与やマージ、cc-triage-scope の除去を進める。処理が未確定のままターンを終えると、判定未確定のまま cc-fix-onetime が付かず fix-review-point ワーカーへの引き継ぎが空振りしたり、マージ判定前にラベルが外れてPRが放置される状態壊れが起きる。
実行内容
ステップ0: PRブランチのcheckout
以下を実行してPRブランチをcheckoutする。
gh pr checkout $ARGUMENTS
このコマンドが失敗した場合(典型例: fatal: '<branch>' is already used by worktree at ... — PRブランチが別のworktreeでcheckout中)は、後続のステップに進まず、エラー出力をそのまま含めて「判定: エラー」で結果報告を行い終了する。ラベル操作・自前のリトライは行わない(ブロッカー解消後のポーリングで自動的に再実行される)。
ステップ1: コンフリクト検知とラベル付与
gh pr status でPRのstatus(mergeable / コンフリクト有無)を取得する。
gh pr status
出力から #$ARGUMENTS の行を特定し、コンフリクト表示("Conflict" / 衝突マーク等)があるかを判定する。gh pr status は現在のユーザーに関連するPR(作成者・レビュアー・assignee)のみ表示するため、対象PRが出力に含まれない場合はフォールバックとして以下で同じ情報を取得する。
gh pr view $ARGUMENTS --json mergeable -q .mergeable
返却値 MERGEABLE / CONFLICTING / UNKNOWN のうち CONFLICTING のときコンフリクトありと判定する。UNKNOWN の場合はGitHub側で判定中のため、数秒のスリープ後に1回だけリトライする。
判定に応じて分岐する。
-
マージ可能(MERGEABLE): ステップ2に進む
-
コンフリクトあり(CONFLICTING): cc-resolve-conflict ラベルを付与してこのスキルを終了する。ステップ2・ステップ3には進まない(コンフリクト解消前に修正要否の判定やマージを行っても意味がないため)
gh pr edit $ARGUMENTS --add-label "cc-resolve-conflict"
-
判定不能(UNKNOWN のままリトライ後も継続する場合): マージ可能性が未確定のまま修正要否判定・マージへ進むのは危険なため、後続のステップに進まず、ラベル操作は一切行わずに「判定: エラー」で結果報告を行い終了する(ステップ0のgh pr checkout失敗時と同様の扱い)。自前のリトライはこの1回のみとし、それ以上は繰り返さない(ブロッカー解消後のポーリングで自動的に再実行される)
ステップ2: 修正要否の判定(判定のみ・実行禁止)
修正プラン(create-review-fix-plan)は生成しない。 本スキルが必要とするのは「修正すべき項目が1件でもあるか」という真偽値だけであり、修正方針・タスク分解・依存関係・影響範囲の見積もりは cc-fix-onetime を拾った fix-review-point が改めて行う。ここでプランを作ると同じ分析(サブエージェントのfan-out探索とタスク定義の生成)をPRごとに二重に走らせることになるため、判定に必要な最小限の情報だけを集める。
重要: 判定は内部的な思考にとどめ、ファイルの編集・コミット・pushは行わない。対応すべき項目があると判断したら コードに手を加えず ステップ3のパターンA(ラベル付与)へ進むこと。裏取りのためのRead/Grep/codegraph参照は許容するが、判定が変わらない範囲では省略する。
2-1. 判定材料の収集
以下を 同一メッセージ内で並列に実行 する。
bash "${CLAUDE_SKILL_DIR}/../create-review-fix-plan/scripts/fetch-unresolved-comments.sh"
CHECKS_JSON=$(gh pr checks $ARGUMENTS --json state,name,link,workflow 2>&1)
CHECKS_EXIT=$?
gh pr view $ARGUMENTS --json title,body,labels
-
1つ目のスクリプトは未解決のインラインレビューコメント(unresolved_threads[])とConversationタブの一般コメント(conversation_comments[])を返す。インラインだけを見ると行外の指摘を取りこぼすため両方を対象にする。カレントブランチのPRを対象とするため、ステップ0の gh pr checkout 済みであることが前提
-
gh pr checks は失敗チェックがあると終了コードが非0になるが、これは「失敗チェックが存在する」という正常系の結果であり、認証失敗・通信障害・不正なPR番号等の実行時エラーと区別する必要がある。区別は終了コードではなく 出力がJSONとしてパース可能かどうか で行う。
echo "$CHECKS_JSON" | jq -e . >/dev/null 2>&1
パースに成功した場合のみ、その内容を「失敗チェックの有無」の判定材料として使う(CHECKS_EXIT が非0でもJSONとしてパースできていれば、それは失敗チェックの存在を表す正常系として扱う)。パースに失敗した場合(=実行時エラーで gh pr checks 自体が意味のある出力を返せなかった場合)は、後続のステップに進まず、ラベル操作は一切行わずに出力内容をそのまま含めて「判定: エラー」で結果報告を行い終了する(「CI失敗なし」には倒さない。ステップ0のgh pr checkout失敗時と同様の扱い)
state が FAILURE / STARTUP_FAILURE のチェックについてのみ、link から run-id を抽出して gh run view <run-id> --log-failed で失敗内容を確認する。全Passなら追加のログ取得は行わない
-
gh pr view の結果は「デザインPRか(cc-ui-design)」「Epic PRか(cc-epic-issue)」「Refs #<N> の有無」の確認に使う。ステップ3で同じ情報を再取得しないよう、ここで取得したラベル一覧を使い回す
-
デザインPR(cc-ui-design)と判定した場合のみ、差分ファイル一覧を追加で取得する(実装コードの混入・スナップショットの有無の確認用)
gh pr diff $ARGUMENTS --name-only
2-2. ノイズの除外
会話コメントには対応不要なノイズが混ざるため、次を判定対象から除外する。
is_minimized: true のコメント(折りたたみ済み=outdated/resolved/spam等として処理済み)
/gemini review のようなボット起動コマンドや、CIステータスの自動投稿
- PR作成者自身の単なる進捗報告・補足など、対応を求めていないチャット
判断に迷う場合は「このコメントは未対応の修正要求か?」を基準にする。
2-3. 各項目の二分判定
残った各コメント・各CI失敗を、下記の評価基準に照らして 「対応すべき」/「対応不要」の二値 に振り分ける。修正方針・修正手順・対象ファイルの列挙は書かない(fix-review-point が行う)。
判定の基準線: 「重要か」「軽微か」といった主観的な軽重で切らない。不正な動作・テスト失敗・誤解を招く結果・将来の障害につながる設計上の穴を引き起こしうる指摘はすべて「対応すべき」とし、「対応不要」に落とすのは下記「対応不要の可能性あり」に具体的に該当するもの(純粋なスタイル/命名の好み、PR範囲外の提案、既存規約と矛盾する提案)だけに限る。どちらにも当てはまらない指摘は「対応すべき」に倒す(このスキルはマージのゲートであり、取りこぼした指摘は誰も直さないまま PR がマージされる)。
「対応すべき」が1件見つかった時点で残りの項目の精査を打ち切り、ステップ3のパターンAへ進んでよい(以降の項目をいくら精査しても付与するラベルは変わらないため)。ただしデザインPRでCI失敗の切り分けが必要な場合(パターンC判定)は、その切り分けを終えてから分岐する。
ステップ3のパターンB(マージ可能)へ進めるのは、2-1で取得した全チェックが SUCCESS 等の明示的な成功状態であることを確認できた場合に限る。 PENDING や実行中など未完了のチェックが1件でも残っている場合は、CIが失敗しているわけではなくても「対応不要」の暗黙扱いにせず、パターンBへは進まない。
未完了チェックが残っている場合の分岐は「対応すべき」項目の有無で決まる。
- 「対応すべき」が1件以上ある場合: CIの完了を待たずステップ3のパターンA(またはデザインPRならパターンC)へ進む。CI結果に関わらず修正は必要であり、待っても付与するラベルは変わらないため
- 「対応すべき」が1件もない場合: 判定を確定させず、ステップ3に進まずに「判定: 保留(CI未完了)」として結果報告のみ行い終了する(次回ポーリングで再評価させる。ラベル操作は行わない)
デザインPR(cc-ui-design ラベル付き)の場合の評価基準
2-1で取得したラベル一覧に cc-ui-design が含まれる場合、そのPRは .pen(Pencilデザインファイル)とスナップショットPNGのみを変更するデザインPRであり、コードレビューの観点(型安全性・テスト・Lint等)をそのまま適用しても意味がない。以下の観点に差し替えて評価する。
- 差分が
.pen とスナップショットPNGに限定されているか(実装コードが混入していないか)。混入していれば「対応すべき」
- スナップショットが差分に含まれ、デザイン意図がPR bodyから読み取れるか。スナップショットが無くレビューできない場合は「対応すべき」
- 対象Issueに一致する
Refs #<N> がPR bodyに存在するか。Refs #<N> の記述が欠落している、または記載されているIssue番号が対象Issueと一致しない場合は要件突き合わせ自体が不可能なため「対応すべき」とする(Closes/Fixes等のclosing keywordはこの参照としては扱わない。下記の通り別途拒否対象)
- Issueの要件(対象画面・要素・状態バリエーション)を満たしているか。
Refs #<N> で参照されているIssueの内容と突き合わせる。要件の取りこぼしがあれば「対応すべき」
Closes / Fixes などの closing keyword がPR bodyに含まれていないか。含まれているとマージ時に実装Issueが閉じてしまうため「対応すべき」
.pen は暗号化バイナリのため Read / Grep で開かない。デザイン内容の確認はスナップショットPNGとPR bodyの記述で行う(必要なら inspect-pencil-node スキルを使う)。
上記以外の観点(テストカバレッジ・Lint・型安全性など)はデザインPRには適用しない。CIが失敗している場合、失敗が .pen/スナップショットPNGの変更で解消可能な種類(デザインレビュー系のチェック等)であれば通常PRと同様に「対応すべき」とする。一方、ベースブランチ側の障害や実装コードに対する必須チェック(型チェック・ユニットテスト等、デザインPRの変更差分では触れられない失敗)が原因であれば、.pen変更のみで直せる見込みがなくcc-fix-onetimeへ乗せても解消しないため「対応すべき」とはせず、ステップ3のパターンCへ進めて cc-need-human-check を付与する。
対応すべき
- バグ・正確性の問題: ロジックエラー、不正な動作、欠落したエッジケース
- セキュリティ脆弱性: SQLインジェクション、XSS、認証バイパス、データ漏洩
- 破壊的変更: APIコントラクト違反、マイグレーションなしの後方互換性の破壊
- 型安全性の違反: TypeScript型エラー、ランタイム障害を引き起こす可能性のある安全でないキャスト
- テスト失敗: 壊れたテスト、新しいロジックに対する重要なテストカバレッジの欠如
- Lintエラー: パイプラインをブロックする違反
- データ整合性リスク: レースコンディション、重要なデータに対するバリデーションの欠如
- CIがオールグリーンになっていない: CIが失敗している
対応不要の可能性あり(この6項目に具体的に該当する場合のみ)
- 純粋なスタイル好み: コードベースパターンと一貫性のあるフォーマット選択
- 主観的な命名提案: 既存の名前が明確で規約に従っている場合
- 過剰設計の提案: まだ必要のないコードに対する抽象化の追加
- スコープクリープ: PR範囲外の無関係なコードのリファクタリングや機能追加の提案
- 既存パターンとの冗長: 確立されたコードベース規約と矛盾する提案
- 既に解消済み: 指摘後のコミットで修正されており、現在のコードに問題が残っていないことを確認できた(
is_outdated: true でも中身が未解消なら「対応すべき」)
「軽微そう」「クリティカルパスではなさそう」という理由だけで「対応不要」に落とさない。上のどれにも具体的に当てはめられない場合は「対応すべき」とする。
ステップ3: 判定に基づくアクション
評価結果に基づき、以下のパターン(通常はA/Bのいずれか、デザインPRでCI失敗が解消不能な場合はC)で判定し、必ずいずれかのアクションを実行する。判定のみで終了せず、コマンドの実行まで確実に行う。
パターンA: 修正が必要な場合
「対応すべき」と判定された項目が1つでもある場合、以下を実行してcc-fix-onetimeラベルを追加する。ラベル付与のみで終了し、コード修正は行わない。たとえ修正項目が明確で実装が容易に見えても、コード変更・コミット・pushを行ってはならない(実際の修正はcc-fix-onetimeラベルをトリガーに別スキルが担当する)。
gh pr edit $ARGUMENTS --add-label "cc-fix-onetime"
パターンC: デザインPRでCI失敗が.pen変更では解消不能な場合
cc-ui-design ラベル付きPRで、CI失敗の原因がベースブランチ側の障害や実装コードに対する必須チェック(.pen/スナップショットPNGの変更では直接修正できないもの)である場合、以下を実行してcc-need-human-checkラベルを追加し終了する。cc-fix-onetimeは付与しない(コード修正でしか直らない失敗を.pen変更で解消しようとするtriage-pr⇔fix-review-pointの無限ループを避けるため)。
gh pr edit $ARGUMENTS --add-label "cc-need-human-check"
パターンB: マージ可能な場合
すべての項目が「対応不要」、または対象となるコメント・CI失敗が1件もない場合、マージ可能(リリース問題なし)と判定する。
まず対象PRが Epic PR(cc-epic-issue ラベル付き)かどうかを、2-1で取得したラベル一覧で確認する(再取得はしない)。
-
Epic PR の場合(ラベル一覧に cc-epic-issue を含む): このPRをマージするとデフォルトブランチへの集約反映(=リリース)になるため、このスキルではマージせず cc-release-ready ラベルのみを付与して終了する。実際のリリース(マージ)は人間の判断に委ねるゲートとして扱う。以降のマージ手順・関連Issueクローズには進まない。
gh pr edit $ARGUMENTS --add-label "cc-release-ready"
-
通常のPRの場合(cc-epic-issue を含まない): 以下の手順でマージし、必要に応じて関連Issueを明示的にクローズする。判定だけで終了しないこと。
- マージ前に、PRのbaseブランチとデフォルトブランチ名を取得する。
BASE_BRANCH=$(gh pr view $ARGUMENTS --json baseRefName -q .baseRefName)
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name)
- 必ず以下のコマンドを実行してマージする。
gh pr merge $ARGUMENTS --merge --delete-branch
マージコマンドが失敗した場合は、エラー内容を記録して報告し、以降の手順に進まない。
-
マージ成功後、BASE_BRANCH が DEFAULT_BRANCH と 一致しない(cc-epic-<N> のような非デフォルトブランチへのマージ)場合のみ、関連Issueを明示的にクローズする。GitHubのCloses #<issue番号>記法によるIssue自動クローズはPRがデフォルトブランチへマージされた場合にのみ発動し、非デフォルトブランチへのマージでは発動しないため、EpicフローでサブIssueが閉じられずEpic PR作成が止まるのを防ぐ必要がある。BASE_BRANCH が DEFAULT_BRANCH と一致する場合はGitHubが自動でクローズするため、この手順はスキップする。
3-1. PR本文から関連Issueの番号を抽出する(「PRクローズ時のIssue連動Close」と同じ抽出コマンドを流用)。
gh pr view $ARGUMENTS --json body --jq '.body' | grep -ioE '(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]]+#[0-9]+' | grep -oE '[0-9]+'
3-2. 抽出したIssue番号それぞれに対して、完了クローズを実行する(複数ある場合は全て)。実装がEpicブランチに取り込まれた完了クローズのため、マージせずクローズする場合の--reason "not planned"とは異なり--reason completedを用いる。
gh issue close <issue番号> --reason completed
関連Issueが抽出できない場合は、その旨を報告に含めること。
意思決定の原則
- 正確性はスタイルに優先: 機能的な正確性を常に優先する
- レビュアーの意図を尊重: 具体的な提案を却下する場合でも、レビュアーが達成しようとしていることを理解する
- コードベースの一貫性: プロジェクトで確立されたパターンを優先する
- 実用主義: 各変更のコスト対効果を考慮する
- 判断に迷う場合は対応すべきに寄せる
PRクローズ時のIssue連動Close
何かしらの理由でgh pr closeによりPRをクローズする場合、必ず関連するIssueも併せてCloseすること。GitHubはPRがマージされずにCloseされた場合、Closes #<issue番号>記法で紐づいたIssueを自動Closeしないため、明示的にCloseする必要がある。
手順:
- PRのdescriptionから関連Issueの番号を取得する。
gh pr view $ARGUMENTS --json body --jq '.body' | grep -ioE '(close[sd]?|fix(e[sd])?|resolve[sd]?)[[:space:]]+#[0-9]+' | grep -oE '[0-9]+'
- PRをCloseする。
gh pr close $ARGUMENTS --delete-branch
- 取得したIssue番号それぞれに対してCloseを実行する(複数ある場合は全て)。
gh issue close <issue番号> --reason "not planned"
関連Issueが取得できない場合は、その旨を報告に含めること。
注意事項
- 作業は全てworktree上で行い、デフォルトブランチで作業は絶対に行わないこと
- ファイル編集などの作業を行う際は、pwdコマンドでworktree内部であることを確認してから行うこと
cc-triage-scopeラベルがPRに付与されている場合、いかなる操作においても絶対に削除しないこと。gh pr editで--remove-labelを使用する際もcc-triage-scopeを対象に含めない
- このスキル本文では一切コードを変更しない(「やること・やらないこと」参照)。コンフリクト解消も修正実行もラベル経由で別スキルに委譲する
出力
処理結果として以下を報告する:
- 判定: コンフリクト検知(
cc-resolve-conflictラベル付与) / パターンA(修正が必要・cc-fix-onetimeラベル付与) / パターンB-Epic(Epic PRのリリースゲート・cc-release-readyラベル付与、マージせず終了) / パターンB-通常(マージ済み。非デフォルトブランチへのマージ時は連動Closeした関連Issue番号も明記) / パターンC(デザインPRのCI失敗が解消不能・cc-need-human-checkラベル付与) / 保留(CI未完了・ラベル操作なし) / PRクローズ(関連IssueもClose) / エラー
- 理由: 判定の根拠(コンフリクト検知時はターゲットブランチ名、対応すべき項目の要約、マージ可能と判断した理由、Epic PRで
cc-release-readyを付与した旨、非デフォルトブランチへのマージで--reason completedにより連動Closeした関連Issue番号、CI未完了で保留した場合は未完了チェック名、エラー時はgh pr viewのmergeable判定不能またはgh pr checks出力のパース失敗など発生箇所、またはクローズ理由と連動Closeした関連Issue番号)