review-fix: マルチエージェント調査&修正
レビュー指摘 — multi-review、PRコメント、その他ソース — を受け取り、各指摘を3つの観点から調査した上で、修正対象をユーザーに選ばせる。コード変更前に全体像を把握できるため、安全で納得感のある修正が可能。
動作概要
レビュー入力 → 指摘のパース → 各指摘を調査(3エージェント並列)
→ 調査結果を提示 → ユーザーが選択 → 選択分を修正 → サマリー
ステップ1 — レビュー入力のパース
$ARGUMENTS に基づいて、対象となるレビュー指摘を特定する:
| 入力 | アクション |
|---|---|
last review または空 |
会話履歴から直近のmulti-review出力を検索 |
| ファイルパス | ファイルをレビューレポートとして読み込み、指摘を抽出 |
PR番号(#123) |
gh pr view <number> --comments でレビューコメントを取得 |
| テキスト貼り付け | テキストを直接レビュー指摘としてパース |
| 自然言語 | ユーザーの参照先を特定し、指摘を抽出 |
multi-review出力のパース
入力がmulti-review由来の場合(最も一般的なケース)、レポートは重要度ヘッダー(Critical、Important、Suggestions、Positive)で構造化されたMarkdown形式。各指摘を以下の内部構造にパースする:
{
"id": 1,
"severity": "critical",
"title": "文字列補間によるSQLインジェクション",
"location": "auth.ts:42",
"expert": "セキュリティ",
"detail": "レビューからの元の詳細",
"recommendation": "元の推奨事項"
}
その他のレビュー形式のパース
PRコメント、フリーテキスト、その他ツールの出力の場合、構造化された指摘の抽出をベストエフォートで行う。各指摘にはタイトルと調査に十分なコンテキストが最低限必要。入力が曖昧な場合は推測せずユーザーに確認する。
「Positive」な指摘は除外する — それらは維持すべき良い点であり、修正対象ではない。
パース後、番号付きサマリーを表示:
レビューからN件の指摘を検出しました:
1. [Critical] 文字列補間によるSQLインジェクション — auth.ts:42
2. [Important] ユーザー一覧でのN+1クエリパターン — api.ts:55
3. [Suggestion] 入力バリデーション不足 — handler.ts:12
ステップ2 — 全指摘の調査
ここがこのスキルの核心的な価値:コードに触れる前に各指摘を複数の観点から調査する。このステップを省略してはいけない。自分でインライン調査せず、Agent ツールで専用のサブエージェントをスポーンすること。
別エージェントを使う理由は、それぞれが独立したコンテキストで動作するため:
- コードエクスプローラーはメインコンテキストを汚さずにコールチェーンを深く追跡できる
- テストアナリストは会話を散らかさずにテストファイルを広く検索できる
- ベストプラクティスリサーチャーは他の作業をブロックせずに複数のWeb検索を実行できる
- 3つ全てが並列実行されるため、合計時間は約1倍(3倍ではなく)
エージェントのスポーン方法
Agent ツール(subagent_type: general-purpose)を使い、全調査エージェントを1つのメッセージでスポーンする。N件の指摘に対して、1レスポンスで最大 3×N 個の Agent ツールコールを行う。
指摘が多い場合(4件超)はバッチ処理:1ラウンドにつき3〜4件の指摘を調査し、システムの過負荷を避ける。
各指摘に対して、以下の3つのエージェントをスポーンする:
エージェント1:コードエクスプローラー
根本原因をコードベース全体で追跡し、影響範囲を特定する。以下のプロンプトテンプレートを使用:
あなたはコードエクスプローラーとしてレビュー指摘を調査します。
根本原因の追跡と影響範囲の特定が任務です — 修正は行わず、調査のみ行ってください。
作業ディレクトリ: {working_directory}
指摘内容:
タイトル: {title}
場所: {location}
詳細: {detail}
推奨事項: {recommendation}
手順:
1. 報告された場所のコードとその周辺コンテキストを読む
2. データフローを追跡 — 問題のある入力はどこから来るか?出力はどこに行くか?
3. 関連コードを全て発見:呼び出し元、呼び出し先、コードベース内の類似パターン
4. 根本原因を特定(表面的な症状ではなく)
5. 影響範囲を特定 — 修正によって他のどのコードが影響を受けるか?
JSONコードブロックで結果を返してください:
{
"root_cause": "根本的な問題の明確な説明",
"affected_files": ["file:line", ...],
"related_patterns": ["他の場所で見つかった類似パターンの説明"],
"blast_radius": "変更によって影響を受ける範囲",
"confidence": "high | medium | low"
}
エージェント2:テストアナリスト
指摘箇所周辺のテスト状況を確認する。以下のプロンプトテンプレートを使用:
あなたはテストアナリストとしてレビュー指摘周辺のテストカバレッジを調査します。
テスト状況の評価が任務です — 修正は行わず、調査のみ行ってください。
作業ディレクトリ: {working_directory}
指摘内容:
タイトル: {title}
場所: {location}
詳細: {detail}
手順:
1. 報告された場所に関連するテストファイルをコードベースから検索
2. 具体的な問題がテストされているか確認(例:このエンドポイントのSQLインジェクションテストはあるか?)
3. テストギャップを特定 — 存在すべきなのに欠けているテストは?
4. この問題を修正する場合、どんな新テストが必要か?
5. 修正によって既存テストが壊れないか確認
JSONコードブロックで結果を返してください:
{
"existing_tests": ["test_file:test_name — カバー内容"],
"covers_issue": true/false,
"test_gaps": ["不足しているテストカバレッジの説明"],
"tests_needed_for_fix": ["追加すべきテストの説明"],
"tests_at_risk": ["修正で壊れる可能性のあるテスト"]
}
エージェント3:ベストプラクティスリサーチャー
Webを検索して現在の推奨事項や既知の問題を調査する。以下のプロンプトテンプレートを使用:
あなたはベストプラクティスリサーチャーとしてレビュー指摘に関連する
現在の推奨事項を調査します。調査が任務です — 修正は行いません。
指摘内容:
タイトル: {title}
詳細: {detail}
推奨事項: {recommendation}
言語/フレームワーク: {コードベースから検出}
手順:
1. WebSearchを使い、この種の問題に対する現在のベストプラクティスを検索
2. セキュリティ関連の指摘であれば、既知のCVEやセキュリティアドバイザリーを検索
3. 非推奨APIに関する指摘であれば、公式ドキュメントや移行ガイドを検索
4. 推奨される修正アプローチについてのコミュニティのコンセンサスを確認
5. 推奨される修正に既知の落とし穴がないか確認
JSONコードブロックで結果を返してください:
{
"best_practice": "現在推奨されるアプローチ",
"sources": ["URL — 簡潔な説明"],
"caveats": ["推奨修正の既知の落とし穴やエッジケース"],
"alternative_approaches": ["主要アプローチが合わない場合の他の有効なアプローチ"]
}
例:2件の指摘に対するエージェントスポーン
2件の指摘に対して、1つのメッセージで6つのAgentツールコールをスポーンする:
- Agent(description="指摘1: コードエクスプローラー", prompt="あなたはコードエクスプローラー...", subagent_type="general-purpose")
- Agent(description="指摘1: テストアナリスト", prompt="あなたはテストアナリスト...", subagent_type="general-purpose")
- Agent(description="指摘1: ベストプラクティス", prompt="あなたはベストプラクティスリサーチャー...", subagent_type="general-purpose")
- Agent(description="指摘2: コードエクスプローラー", prompt="あなたはコードエクスプローラー...", subagent_type="general-purpose")
- Agent(description="指摘2: テストアナリスト", prompt="あなたはテストアナリスト...", subagent_type="general-purpose")
- Agent(description="指摘2: ベストプラクティス", prompt="あなたはベストプラクティスリサーチャー...", subagent_type="general-purpose")
6つ全てを1メッセージで送信し、並列実行する。
ステップ3 — 調査結果の提示
全エージェント完了後、各指摘ごとの調査結果を明確なレポートにまとめる。ユーザーが情報に基づいた判断ができる形式で提示する:
# 調査結果
## 指摘1: [Critical] 文字列補間によるSQLインジェクション — auth.ts:42
### 根本原因
`buildQuery()` 関数がユーザー入力をSQL文字列に直接連結している。
同じパターンが `search.ts:78` と `report.ts:33` にも存在。
### テスト状況
- 既存テスト: `auth.test.ts:testLogin` — ハッピーパスのみカバー
- 悪意のある入力のテストなし
- 修正に必要なテスト: パラメータ化クエリテスト、インジェクション試行テスト
### ベストプラクティス
パラメータ化クエリ(プリペアドステートメント)を使用する。公式ドキュメント: [リンク]
- 注意点: パラメータ化クエリへの切り替えにはクエリビルダーインターフェースの更新が必要。
### 影響: 3ファイル | 確信度: 高
---
## 指摘2: [Important] N+1クエリパターン — api.ts:55
...
レポート後、ユーザーに修正対象の選択を求める:
どの指摘を修正しますか?(番号を入力: "1,3" または "all")
指摘が4件以下の場合は AskUserQuestion ツールの multiSelect を使用する。5件以上の場合は番号付きリストを表示し、カンマ区切りの番号を自由入力で受け付ける。
ステップ4 — 選択した指摘の修正
選択された各指摘に対し、調査結果に基づいた修正を適用する:
- 修正を計画 — 表面的な症状ではなく根本原因の分析に基づく
- コード変更を適用 — コードエクスプローラーが特定した全ての影響ファイルに対して
- テストを追加・更新 — テストアナリストのギャップ分析に基づく
- ベストプラクティスに従う — リサーチャーが特定した推奨事項(注意点への対処を含む)
依存関係順に修正する — 指摘Aの修正が指摘Bに関連するコードに影響する場合、Aを先に修正。順序が関係ない場合は重要度順(criticalから)。
各修正後:
- ビルド/リントが通ることを確認(プロジェクトにビルドコマンドがあれば実行)
- 既存テストを実行してリグレッションを確認
修正が想定以上に複雑な場合(アーキテクチャ変更が必要等)、大規模な変更を静かに行うのではなく、ユーザーに状況を説明して判断を仰ぐ。
ステップ5 — サマリー
全修正適用後、サマリーを作成:
# 修正サマリー
## 適用した修正
| # | 指摘 | 変更ファイル数 | 追加テスト数 |
|---|------|-------------|------------|
| 1 | SQLインジェクション — auth.ts:42 | 3 | 2 |
| 3 | バリデーション不足 — handler.ts:12 | 1 | 1 |
## スキップした指摘
| # | 指摘 | 理由 |
|---|------|------|
| 2 | N+1クエリパターン | ユーザーが未選択 |
## 検証結果
- ビルド: PASS
- テスト: 24件成功、0件失敗(新規3件)
## 備考
- SQLインジェクション修正時に、search.tsとreport.tsの同じパターンも
同時に修正しました(調査中に発見)。
- マージ前にフルテストスイートの実行を推奨します。
ヒント
- 指摘が多い場合(6件以上)、並列エージェントスポーンが重くなる。3〜4件ずつバッチ処理してコンテキストの過負荷を避けることを検討する。
- レビュー入力が曖昧で場所情報が不足している場合、コードエクスプローラーエージェントが問題の所在を特定する上で特に重要になる。
- セキュリティ関連の指摘では、必ずWeb検索でベストプラクティスを確認する — セキュリティの推奨事項は急速に変化する。
- 調査結果を相互参照する:コードエクスプローラーが5ファイルで同じパターンを発見したがレビューでは1ファイルしか言及されていない場合、修正前にユーザーに広範な影響範囲を報告する。