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 本文
thinkingBudgetGemini Pro の thinking budget tokens (-1=dynamic MAX / 0=OFF / 正数=固定上限)。デフォルト -1
reviewEfforto3 の 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-o3reviewGpt4実装難易度 / コスト試算 / 完了条件検証可能性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.parsesafeParseLlmJson() で吸収し、個別失敗を 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-12Phase 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. 関連リンク

実装更新 (2026-05-28)

  • 部分成功許容 (ADR-0081 / PR #1087): Promise.allPromise.allSettled に変更。3 ベンダー (Gemini Pro / Claude Opus / GPT-o3) のうち 1 つが落ちても残り 2 つの結果で通過する。最低 1 成功が必要 (全失敗時はエラー)
  • 各ベンダー結果の JSON.parsesafeParseLlmJson() に置換 (個別失敗を structured error log に記録)
  • ChatOpenAI インスタンスに maxRetries=3 (exponential backoff) を付与
  • KV 化未対応: 3 ベンダーごとに評価観点を切替える動的テンプレートのため loadPrompt 対象外。今後の課題 (ADR-0085 §残課題)