07. Parallel Review Node (Gate 3)
TL;DR(このノードは何をする・専門語ゼロ): 採点と過去決定の照合を通った良い下書きに対し、3 種類の AI を同時に走らせて多角的な意見をもらう関門。それぞれビジネス視点・論理視点・技術視点を担当し、良い点・気がかりな点・改善案を付箋のように書き出す。ここは合否を決めず差し戻しもしない。集めた意見は変更提案の本文に貼り付けられ、最終判断はあくまで人間のレビュー担当に委ねられる。
実装:
drp/src/nodes/parallel_review.tsプロンプト設計ドキュメント:prompts/05_parallel_review.md/ 設計メモ:phase3_parallel_review_design.mdプロンプト SSoT:drp/prompts/production/gate3-parallel-review/prompt.mdテスト: なし (情報提供型のため差戻し判定なし、実起案でモニタリング) 基盤 ADR: ADR-0033 (モデル選定)
1. 役割と位置づけ
Scoring + Consistency を通過した 高品質 ADR ドラフトに対する付加価値レビュー。3 モデル並列実行 (Gemini Pro / Claude Opus / o3) で、それぞれの専門視点から strength / concern / suggestion をアノテーション〔annotation=本文の該当箇所に紐づけた注釈〕形式で生成する。
- 解決する課題: レビュアー (代表取締役) が単一視点でレビューする手間を「先回りで複眼化」する。1 人レビューの盲点を補う。
- 設計思想: 情報提供型ゲート (差戻しなし)。Pipeline の最終門番ではなく、PR 本文に追記される補助情報。差戻し権限を持たないことでレイテンシ・コストを抑え、判定責任を最終レビュアーに残す。
- エラー耐性: 各モデルのエラーは個別 catch → 残り 2 モデルの結果で PR を生成しパイプライン継続。単独プロバイダ障害で ADR 起案が止まらない。
2. フロー図
flowchart LR
C[consistency] -->|rejected=false| P[parallel_review]
P -->|Promise.all| G[Gemini Pro
thinking budget]
P --> CL[Claude Opus]
P --> O[o3
reasoning_effort]
G --> PA[policy_alignment]
CL --> PA
O --> PA
3. トリガー条件
| 条件 | 挙動 |
|---|---|
consistency から rejected=false | 実行 |
consistency から rejected=true | スキップ |
buildPreGraph では実行されない。
4. 入力 (State)
| State フィールド | 用途 |
|---|---|
adrBody | レビュー対象 ADR 本文 |
thinkingBudget | Gemini Pro の thinking budget tokens (-1=dynamic MAX / 0=OFF / 正数=固定上限)。デフォルト -1 |
reviewEffort | o3 の reasoning_effort (low / medium / high)。デフォルト high |
5. 処理ロジック
1. REVIEWER_CONFIGS から 3 設定を読む:
- { modelKey: 'reviewGemini', role: 'ビジネス・アーキテクチャ reviewer', focus: ビジネスインパクト... }
- { modelKey: 'reviewClaude', role: '論理・詳細 reviewer', focus: 論理的一貫性... }
- { modelKey: 'reviewGpt4', role: '技術・体系的 reviewer', focus: 技術的実現可能性..., useOSeries: true }
2. Promise.all で 3 並列実行:
- Gemini: createLlm(env, 'gemini-pro', 0.2, budgetTokens=state.thinkingBudget)
- Claude: createLlm(env, 'claude-opus', 0.2)
- o3: createOSeriesLlm(env, 'gpt-o3', state.reviewEffort)
3. 各モデルの response.content を text 結合 → JSON parse → annotations 配列
4. 全結果を JSON.stringify でまとめて parallelReviewDetail に格納
アノテーション形式 (各レビュアーが生成):
{
"annotations": [
{ "quote": "ADR 本文からの引用文字列 or #overall", "type": "strength" | "concern" | "suggestion", "comment": "1〜2文" }
]
}
配分目安: strength 1〜3 件、concern 2〜5 件、suggestion 2〜4 件。
quote は ADR 本文に実在する文字列 (見出し行も可)。特定箇所に紐付かないコメントは #overall。
6. LLM 設定
| モデル | キー | 視点 | 設定 |
|---|---|---|---|
gemini-pro (3.1-preview deep think) | reviewGemini | ビジネスインパクト / アーキ整合 / 長期負債リスク | temperature=0.2 + thinkingBudget=-1 (dynamic MAX) |
claude-opus (4-7) | reviewClaude | 論理一貫性 / 代替案公平性 / 撤退条件現実性 | temperature=0.2 |
gpt-o3 | reviewGpt4 | 実装難易度 / コスト試算 / 完了条件検証可能性 | reasoning_effort=high (temperature 非対応) |
コスト目安: 3 モデル合計で 0.40〜1.00 USD / 起案 (Pipeline 全体コストの 30〜40%)。
レイテンシ: Promise.allSettled〔Promise.allSettled=全並列処理の成否を待ち、一部失敗でも残りの結果を取れる仕組み〕 で並列 → 最遅モデル (通常 gemini-pro deep think) 待ち = 30〜90 秒。
7. 副作用
なし。3 並列 LLM 呼出のみ。GitHub API には触れない。
8. 出力 (State)
{
parallelReviewDetail: string, // JSON.stringify([{label:'Gemini', annotations:[...]}, {label:'Claude', ...}, {label:'o3', ...}])
}
webhook ノードが PR 本文に ## Gate 3: 並列レビュー(3 モデル) セクションとして転記する (webhook.ts 内の parallelReviewSection)。
形式例 (PR 本文):
## Gate 3: 並列レビュー(3 モデル)
### Gemini — ビジネス・アーキテクチャ視点
**強み**
- ...
**懸念点**
- ...
**改善提案**
- ...
### Claude — 論理・詳細視点
...
9. 分岐 (次ノード)
.addEdge('parallel_review', 'policy_alignment')
無条件で policy_alignment へ。差戻しなし。
10. エラー時の挙動
- モデル個別失敗 (部分成功許容):
Promise.allSettledで実行するため、3 ベンダーのうち 1〜2 が失敗しても残りの結果で通過する (ADR-0081 / PR #1087)。全 3 ベンダー失敗時のみエラーで停止。各ChatOpenAIにはmaxRetries=3(exponential backoff) を付与。 - JSON parse 失敗: 各ベンダー結果の
JSON.parseはsafeParseLlmJson()で吸収し、個別失敗を structured error log に記録 → 該当ベンダーのみスキップして全体は継続 - annotations 欠落:
result.annotationsが配列でなければ空配列で補正 (parallel_review.ts:104)
11. 既知の弱点・運用注意
- 部分成功で継続: 3 ベンダーのうち 1〜2 失敗は
Promise.allSettledで吸収し残り結果で継続 (ADR-0081 / PR #1087 で対応済)。全 3 失敗時のみエラー。 - テスト未整備: 情報提供型のため pass/fail 判定がなく、テストケースを整備しづらい。プロンプト品質は実起案で目視モニタリング。Phase 3 運用後の改善項目 (
prompts/05_parallel_review.md末尾参照)。 - コスト最適化: scoring + consistency 通過後のみ実行 (低品質起案には呼ばない)。3 モデル並列の意義は「コストはかかるが PR 1 件ごとの判断材料の質を最大化」。
reviewGpt4のモデル名: gateway.ts ではgpt-o3(MODELS.reviewGpt4)。実体は OpenAI o3 /temperatureは渡さない (o-series 非対応)。- Gemini thinking budget:
-1= dynamic MAX (Gemini 3.1 Pro 推奨)。コスト削減目的なら正数で固定上限を指定可。 - アノテーション引用の正確性: LLM が
quoteを引用形式で返すが、稀に存在しない文字列を生成する (hallucination〔hallucination=幻覚。AI がもっともらしい嘘を作る現象〕)。レビュアーが PR 本文で違和感を持った場合のスポットチェック必要。
12. テストケース
なし。Phase 3 完了時 (PR #596) に運用後改善項目として保留。
代替モニタリング: 実起案の PR 本文に転記された 3 モデルレビューをレビュアーが目視し、「単一モデルの低品質指摘」が再発したらプロンプト改修。
13. 過去の設計判断ログ
| 日時 | 変更 | 経緯 |
|---|---|---|
| 2026-05-12 | Phase 3 実装 (PR #596) | 情報提供型として導入。差戻し型は scoring/consistency で十分と判断 |
| (設計時) | LangGraph 分岐ではなく Promise.all ノード内並列 | レイテンシ削減 + Cloudflare Workers CPU 制約適合 |
| (設計時) | 3 モデルの役割分担を明確化 | ビジネス / 論理 / 技術 の 3 視点 (重複を意図的に避ける) |
| ADR-0033 採択 | gpt-4o → gpt-o3 (reasoning_effort=high) に upgrade | 技術視点の深度向上 |
| ADR-0033 採択 | Gemini Flash → Gemini Pro (deep think) に upgrade | ビジネス視点の長文推論力強化 |
14. 関連リンク
- 前ノード: 06_consistency.md
- 次ノード: 08_policy_alignment.md
- プロンプト設計: prompts/05_parallel_review.md
- 設計メモ: phase3_parallel_review_design.md
- 関連 ADR: ADR-0033 / ADR-0081
実装更新 (2026-05-28)
- 部分成功許容 (ADR-0081 / PR #1087):
Promise.all→Promise.allSettledに変更。3 ベンダー (Gemini Pro / Claude Opus / GPT-o3) のうち 1 つが落ちても残り 2 つの結果で通過する。最低 1 成功が必要 (全失敗時はエラー) - 各ベンダー結果の
JSON.parseをsafeParseLlmJson()に置換 (個別失敗を structured error log に記録) ChatOpenAIインスタンスにmaxRetries=3(exponential backoff) を付与- KV 化未対応: 3 ベンダーごとに評価観点を切替える動的テンプレートのため
loadPrompt対象外。今後の課題 (ADR-0085 §残課題)