Phase 3 設計メモ — Gate 3 並列レビュー (Gemini Flash / Claude Sonnet / GPT-4o)
TL;DR(このページは何か・専門語ゼロ): 一定の水準を満たした判断のたたき台に対し、3 種類の AI が同時にそれぞれ違う視点(事業・論理・技術)から意見を付ける仕組みの設計メモです。この段では起案を差し戻さず、意見を変更提案の本文にそのまま並べて添え、最終的にどうするかは人が決めます。なぜ差し戻さないのか、なぜ 3 つ同時に走らせるのか、1 つの AI が応答に失敗しても全体を止めない理由、テストを最小限にした判断を記録しています。
位置付け: PR #596 で実装した Phase 3 (Gate 3 並列レビュー) の 設計判断と運用ポリシー を残すドキュメント。
- 実装コード:
drp/src/nodes/parallel_review.ts- プロンプト原本:
prompts/05_parallel_review.mdv1.0- 全体像:
README.mdの「アーキテクチャ」「フェーズ計画 §Phase 3」セクション役割分担: README = 現状の SSoT / changelog = 履歴 / 本ファイル = Phase 3 固有の設計判断 (採用しなかった代替案・運用上の注意)
1. Phase 3 の位置付け (なぜ「差戻しなし」なのか)
Phase 1〜2c で構築したゲート〔Gate=審査の関門。各段で起案を通すか差し戻すかを判定する〕は すべて差戻し型:
| Gate | 差戻しトリガ |
|---|---|
| Gate 0 Triage〔トリアージ=そもそも記録に残す価値があるかの選別〕 | ADR 対象外と判定 → END |
| Gate 1 Socratic〔ソクラティック=前提・代替案を問い直して盲点を洗い出す段〕 | 情報不足 → 質問返却 + END |
| Gate 4 Scoring | 40 点未満 → END |
| Gate 2 Consistency〔コンシステンシー=過去 ADR との整合チェックの段〕 | CONFLICT 検出 + supersede 宣言なし → END |
これらを通過した起案ドラフトは 「ADR〔Architecture Decision Record=技術判断の記録〕として PR 化する水準を満たした」 と見なされる。Phase 3 がさらに差戻し判定を加えると:
- レビューモデル 3 つの意見不一致の解決ロジックが必要 (どれを採用するか / 多数決か / 厳しい方を採るか)
- レビュー LLM のハルシネーションでブロックされる事故が起きやすい (4 段ゲート目で意味不明な指摘で差し戻される)
- レビュー品質を確かめるためのテストケースが少なくとも 9 通り (3 モデル × pass/fail/borderline) 必要になる
これらのコストに対し、Phase 1〜2c の 4 段ゲートで品質はすでに担保されている。よって Phase 3 は情報提供型 (差戻しなし) とした。レビュー結果は PR 本文に転記 され、最終承認者 (代表取締役) が見て判断する。
⚠️ 「差戻しなし」を将来 ⇒ 「条件付き差戻し」に変える際の前提: レビューモデルのハルシネーション率 (誤った指摘の頻度) を計測した上で、
indicator == "CRITICAL"等の厳格指標のみに限定する設計が必要。盲目的な多数決差戻しは禁忌。
2. なぜ Promise.all (ノード内並列) を選んだか
採用案: parallel_review.ts 内で Promise.all([gemini, claude, gpt])
const [geminiResult, claudeResult, gptResult] = await Promise.all([
callGemini(prompt).catch(err => ({ error: err.message })),
callClaude(prompt).catch(err => ({ error: err.message })),
callGpt(prompt).catch(err => ({ error: err.message })),
]);
検討した代替案
| 案 | 採用しなかった理由 |
|---|---|
A. LangGraph 並列分岐 (graph.addBranch(...)) | 3 ノードに分割するとグラフ可視化が煩雑、State チャネルが 3 倍化、合流ノードが追加で必要 |
| B. 直列実行 (Gemini → Claude → GPT) | レイテンシ 3 倍 (各 5-10 秒 → 計 15-30 秒)。Cloudflare Workers の CPU 制約 (30 秒) を超過リスク |
| C. Cloudflare Queues 経由の非同期 | 起案者の Web UI レスポンスから外れる。「PR が出てから 30 秒以内にレビューも揃う」UX が崩れる |
Promise.all 採用の根拠
- レイテンシ: 3 モデルの中で最も遅い 1 つの応答時間 = 全体応答時間
- コード単純さ: グラフ定義はノード 1 つで済む。エラー処理も各
catchで完結 - Cloudflare Workers 適合: Workers Paid plan の 30 秒 CPU 上限内に余裕で収まる (Gemini Flash ~ 3 秒 / Claude Sonnet ~ 8 秒 / GPT-4o ~ 6 秒)
3. なぜ 3 モデル + その役割分担なのか
モデル選定の根拠
| モデル | 特化視点 | 選定理由 |
|---|---|---|
| Gemini Flash | ビジネスインパクト / アーキテクチャ整合性 / 長期負債リスク | Google ecosystem 文脈 (Workspace / GCP) への理解度が高い + 高速・安価で網羅レビューに向く |
| Claude Sonnet | 論理的一貫性 / 問題定義と決定のつながり / 撤退条件の現実性 | 長文の論理矛盾検出に強い (RQ-038 で確認済)。撤退条件の現実性判定は ADR-0019 の Reject 条件設計でも有用と判明 |
| GPT-4o | 技術的実現可能性 / コスト試算の妥当性 / 完了条件の検証可能性 | 数値計算・コスト試算の整合性確認に強い。完了条件 (Definition of Done) の検証可能性チェックも得意領域 |
なぜ 3 つで、4 つや 2 つではないのか
- 3 つの根拠: ビジネス / 論理 / 技術 の意思決定 3 視点に対応 — どれが欠けても重大な見落としが残る
- 4 つ以上にしない理由: コスト・レイテンシが膨らむ + プロバイダ依存性が増える + レビュー結果の PR 本文転記で冗長化
- 2 つにしない理由: 多数決が成立せず、ハルシネーション検知の参照点が不足
📝 将来の変更余地: モデルが進化すれば役割を再配置する (Gemini 2.5 が論理に強くなれば Claude と入れ替え等)。役割と LLM の固定的な紐付けは避け、
prompts/05_parallel_review.mdで役割視点だけを SSoT〔Single Source of Truth=唯一の正となる出どころ〕化 している。
4. エラー処理ポリシー — 「3 モデル中 1 つ失敗してもパイプライン継続」
設計
// 各モデル呼出を個別 catch で吸収
const results = await Promise.all([
callGemini(prompt).catch(err => ({ role: "business", error: err.message })),
callClaude(prompt).catch(err => ({ role: "logic", error: err.message })),
callGpt(prompt).catch(err => ({ role: "tech", error: err.message })),
]);
// PR 本文には成功したレビューのみ転記、失敗したものは「(レビュー取得失敗)」と注記
なぜ全失敗時もパイプラインを止めないか
- Phase 3 は 情報提供型: レビューが 1 つも取れなくても、Phase 1〜2c で ADR の起案品質は既に担保されている
- 1 モデル障害で起案フロー全体が止まると、代表取締役 (1 人開発) のADR 起案サイクルが LLM プロバイダ可用性に依存してしまう
- 起案件数 (推定週 3-5 件) に対し、レビュー取得失敗率の許容ライン (3 モデル全失敗 = ほぼ起きない) を考えると、止めるコストの方が大きい
モニタリング項目 (Phase 3 運用後に整備)
- 各モデルの呼出成功率 (LiteLLM Gateway のログから集計可能)
- レビュー文面の有用性 (代表取締役が PR 本文を読んでレビュー指摘で実際に判断を変えた件数)
- ハルシネーション率 (誤った技術的指摘・存在しない過去 ADR への言及など)
5. PR 本文への転記フォーマット
src/nodes/webhook.ts で 3 モデルのレビュー結果を指定セクションとして PR 本文に転記。フォーマット例:
## Gate 3: 並列レビュー (Phase 3)
> Scoring + Consistency 通過後の 3 モデル並列レビュー (情報提供型・差戻しなし)
### ビジネスインパクト視点 (Gemini Flash)
<gemini_review_text>
### 論理的一貫性視点 (Claude Sonnet)
<claude_review_text>
### 技術的実現可能性視点 (GPT-4o)
<gpt_review_text>
---
💡 設計意図: 3 視点が並列に並ぶことで、代表取締役が PR レビュー時に「ビジネス → 論理 → 技術」の順で頭を切り替えられる。同じ指摘を重複読みする苦痛を避ける。
6. テスト戦略 (Phase 3 固有の事情)
単体テストを最小限にした理由
Phase 1〜2c では test-tc.mjs / test-tc-socratic.mjs / test-tc-consistency.mjs で差戻し判定が正しく出るかを検証していた。Phase 3 は差戻しを持たないため、テスト対象は:
- 3 モデル呼出が並列に走るか → コード上の
Promise.allで自明 - 1 モデル失敗時に残り 2 つで PR 生成できるか →
catchブロックで自明 - レビュー文面の品質 → これは実起案でしか測れない
→ よって自動テストでカバーすべき差分が薄いため、test-tc-parallel-review.mjs を敢えて作らず、運用後にプロンプト改訂の必要性が見えた段階で TC を追加する方針 (YAGNI)。
運用後の TC 整備指針
- TC-P01: 高品質起案 (TC-07 派生) で 3 モデル全合格 → 全レビュー文が PR 本文に転記されることのみ確認
- TC-P02: Claude のみ意図的に失敗させて 2 モデルで PR 生成 (モック差し替え)
- TC-P03: 3 モデル全失敗のとき「(レビュー取得失敗)」セクションが出ること
7. 関連ドキュメント
- 全体像:
README.md - プロンプト原本:
prompts/05_parallel_review.mdv1.0 - フェーズ計画 (全完了):
README.md§フェーズ計画 - ADR-0019 (LangGraph 移行):
docs/adr/0019-drp-migration.md - ADR-0020 (Triage 学術根拠):
docs/adr/0020-adr-triage-criteria-rationale.md - 失敗パターン集:
../failure_patterns.md
8. 次の投資領域 (Phase 3 完了後)
設計時に想定した全ゲートが本番稼働。全フェーズ完了を受け、次の投資領域は以下:
- ADR 事後評価ループ (ADR-0021 候補) — ADR-0020 §決定 #4 で予告した DORA 指標 / インシデント相関分析。実装した ADR が本当に良い決定だったかを 3-6 ヶ月後に評価
- Phase 3 レビュー品質モニタリング — 3 モデルのうちどのレビューが PR 本文で実際にレビュアーの判断を変えたかを記録 → モデル選定 / プロンプト改訂のフィードバック
- 02_scoring.md の根拠注記 — ADR-0020 §決定 #2 で予告した「数値閾値は外部根拠なし」明記 (未実施)
- MAS 案件起票フローへの応用 (RQ-040 起案中) — Decision Pipeline のゲート設計思想を MAS 案件起票にも展開する案。RQ-040 の調査結果次第