TL;DR(このノードは何をする・専門語ゼロ): 出来上がった判断記録の原稿を受け取り、10 個の観点を各 5 点・合計 50 点満点で採点する品質の関所。判断の重みに応じた合格ラインに届かなければ「ここを足してください」と具体的な助言を添えて差し戻す。点数はあくまで材料で、最後に進めると決める責任は起案者と代表取締役が持つ。

実装: drp/src/nodes/scoring.ts プロンプト設計ドキュメント: prompts/02_scoring.md プロンプト SSoT: drp/prompts/production/gate4-scoring/prompt.md テスト: drp/test-tc.mjs (TC-06 / TC-07) 基盤 ADR: ADR-0020 (閾値根拠) / ADR-0033 (モデル選定)


1. 役割と位置づけ

生成された ADR〔Architecture Decision Record=技術判断の記録〕本文を 10 項目 × 5 点 = 50 点満点 で採点し、mode〔モード=判断の重みを軽い・普通・重大の 3 段階に仕分けする区分〕別閾値 (Light 35 / Standard 40 / Critical 45) 未満なら差戻す 品質の関所。Pipeline 全体で「40 点未満は PR 化させない」原則の実体。

  • 解決する課題: 起案者が「とりあえず形だけ」の ADR を提出すると、レビュアー (代表取締役) のレビュー負荷が膨大になる。低品質を機械的に弾くことでレビュー対象を高品質に絞り込む。
  • 設計思想: 差戻し型ゲートpass=falserejected=true を立て END へ。feedback_for_user には「何を追加すべきか」を 150 字以内で具体的に書かせる。
  • 「AI に責任逃れさせない」原則: スコアは判断材料であり、最終的に起案者が「私はこの決定で進めたい」と PR 概要欄に書く義務を負う (operator_guide 参照)。

2. フロー図

flowchart LR
    B[body_generation] --> SC[scoring]
    SC -->|rejected=false| CV[cross_validation]
    SC -->|rejected=true
feedback_for_user を返却| END([END])

3. トリガー条件

条件挙動
body_generation から adrBody を受け取り必ず実行 (無条件 edge)

4. 入力 (State)

State フィールド用途
adrBody採点対象の Markdown 本文
triageMode閾値判定 (Light 35 / Standard 40 / Critical 45)。null なら Standard
scoringEffortclaude-opus の reasoning_effort (high / xhigh / max)。デフォルト max

5. 処理ロジック

1. createLlmWithEffort(env, MODELS.scoring='claude-opus', state.scoringEffort='max')
   - temperature=1 (Claude 4.x thinking 必須値)
   - reasoning_effort=max (Adaptive Thinking 最大)
2. user msg: "mode: {Light|Standard|Critical}\nadr_draft:\n{adrBody}"
3. invoke → JSON 抽出
4. total を 3 段階で集計:
   a. result.scores オブジェクトから (各項目の {score, comment}.score を加算)
   b. (a) が 0 なら result.score_summary_md の Markdown テーブル 2 列目を加算
   c. それでも 0 なら result.total を使う
5. pass = (total >= threshold)
6. pass=false → score / scoringDetail / rejected=true / rejectionMsg=feedback_for_user
7. pass=true  → score / scoringDetail / rejected=false / rejectionMsg=feedback_for_user (警告として継続)

Self-Consistency サンプリング (N>1): LLM パラメータは loadLlmParams(env, 'gate4-scoring', { temperature: 1.0, sampling_n: 1 })KV から取得する。KV の sampling_n が 2 以上のとき、同一入力を Promise.allSettled で N 回並列採点し多数決で判定する (ADR-0056 温度サンプリング戦略):

  • 各サンプルの total から mean / stdDev を算出
  • majorityPass = (合格サンプル数 > N/2)rejected = !majorityPass
  • 代表スコア = Math.round(mean)、出力に scoringSamples / scoringMean / scoringStdDev を付与 (§8)
  • 全 N サンプル失敗時のみ All N scoring samples failed で停止
  • sampling_n <= 1 (既定) のときは上記の単発採点パス

採点 10 項目 (各 0〜5 点):

キー観点
1_problem_definition問題定義の明確さ (現状の痛みの具体性・数値)
2_alternatives代替案の網羅性 (最低 2 案 + 却下理由)
3_decision_criteria判断基準の明示 (評価軸)
4_past_adr_consistency過去決定との整合性 (参照 / Supersede / Conflict)
5_impact_scope影響範囲の特定 (ファイル / モジュール / データ / ステークホルダー)
6_operational_pitfalls運用上の罠の検証
7_rollback_strategy失敗時のロールバック性
8_cost_estimateコスト試算 (時間 / 金銭、粗くても数値)
9_completion_criteria検証可能な完了条件 (観測可能な指標)
10_long_term_impact長期的影響 (半年後の負債化リスク・Review After)

閾値の根拠: 学術的・業界標準的な絶対値はなく、Phase 1 検証 (TC-06=3/50・TC-07=45/50) で弁別力を実証した組織内ヒューリスティクス (ADR-0020 §4 / Basili GQM 1994)。


6. LLM 設定

項目根拠
モデルclaude-opus (claude-opus-4-7)ADR-0033 で gpt-4.1 から upgrade。10 項目を critical に評価する判断力
temperature1Claude 4.x の thinking 有効化必須値 (createLlmWithEffort が固定)
reasoning_effortmax (デフォルト)Adaptive Thinking 最大。state.scoringEffort で上書き可
コスト目安0.30〜0.80 USD / 起案opus + thinking max。Pipeline 最大
レイテンシ30〜90 秒thinking でモデル内推論時間が長い

createLlmWithEffortLiteLLM_map_reasoning_effort 経由で claude-opus 向け thinking + output_config を自動生成する (gateway.ts:42-47)。


7. 副作用

なし。LLM 呼出のみ。


8. 出力 (State)

通過

{
  score: number,                  // 例: 47 (N>1 時は Math.round(mean))
  scoringDetail: string,          // Markdown 表 (PR 本文転記用)
  rejected: false,
  rejectionMsg: '合格点ですが、〇〇は改善余地あり...',
  // --- Self-Consistency (N>1) 時のみ実値。単発採点 (sampling_n<=1) では null/[] ---
  scoringSamples: Array<{ total: number, pass: boolean }>,  // 各サンプルの結果
  scoringMean: number | null,     // 平均点 (小数1桁)
  scoringStdDev: number | null,   // 標準偏差 (小数1桁、ばらつき監視用)
}

weakest_items (最低点項目キーの配列) は LLM 出力 ScoringResult に含まれ、rejectionMsg / feedback_for_user の生成に使われる (scoring.ts プロンプト rule 6)。

差戻し

{
  score: number,                  // 例: 32
  scoringDetail: string,
  rejected: true,
  rejectionMsg: '〇〇を追加してください。〇〇の数値が無い...',  // 150 字以内
}

scoringDetail の形式 (system prompt で強制):

| 採点項目 | 点数 | コメント |
|---------|------|---------|
| 問題定義 | 4 | ... |
| 代替案 | 3 | ... |
...

9. 分岐 (次ノード)

.addConditionalEdges('scoring', (s) => s.rejected ? END : 'cross_validation')
rejected次ノード
falsecross_validation (Gate 4 通過 → 盲点×Must 軸の交差検証へ)
trueEND (feedback_for_user を起案者に返却)

N>1 サンプリング時は rejected = !majorityPass (下記 §5 参照)。


10. エラー時の挙動

  • LLM 失敗 / JSON parse 失敗: catch なし → 例外スロー → グラフ全体失敗
  • total 集計のフォールバック: 3 段階 (scores → score_summary_md → result.total) で吸収。0 のまま落ちることは少ないが、全て失敗すれば total=0 で必ず差戻し (実用上は防御層)
  • モデル別の出力形式ブレ: scoring プロンプトは scores object 形式を期待するが、claude が score_summary_md だけ返す場合に備え Markdown テーブルからも集計可

11. 既知の弱点・運用注意

  • モデル upgrade のコスト影響: gpt-4.1 → claude-opus + thinking max でコストが 3〜5 倍。Pipeline 全体コストの 60%+ を scoring が占める。
  • 「Critical=45 点」の運用負担: 月次決算 Critical ADR が 45 点に届かず差戻され続けるケースあり → 起案者が Standard に格下げして再起案する経路が必要 (現状は手動)。
  • Markdown テーブル列順依存: cols[1] (2 列目) を点数列として読む。LLM が「| コメント | 項目 | 点数 |」順で出力すると誤集計 → プロンプトで列順を明示。
  • scoringEffort の活用: 通常は max で十分。コスト削減目的で個別起案だけ high に下げる UI は未実装。
  • 「合格でも feedback を返す」設計: pass=true でも feedback_for_user は捨てず PR 本文に転記される (改善余地として起案者に共有)。

12. テストケース

ID内容期待
TC-06情報希薄な ADR (一般論のみ)3〜10 / 50 で差戻し
TC-07情報豊富な ADR (数値・代替案・撤退条件あり)45〜50 / 50 で通過

実行: node drp/test-tc.mjs --scoring-only 注意: テストは OpenAI 直接呼出 (gpt-4o) で本番 (claude-opus) とは厳密一致しないが、線形性 (低情報 → 低スコア / 高情報 → 高スコア) は確認可能。


13. 過去の設計判断ログ

日時変更経緯
2026-05-04v0.1 初版 (Phase 1)10 項目・mode 別閾値の設計確定
2026-05-11LangGraph TS 移行Dify 退役、プロンプト本文は踏襲
ADR-0033 採択gpt-4.1 → claude-opus + thinking max採点の論理深度向上
(実装途中)total 集計フォールバック 3 段階導入LLM が scores object 形式を返さないケースに対処

14. 関連リンク

実装更新 (2026-05-28)

  • 閾値 KV 外部化 (ADR-0084 / PR #1088): loadThresholds(env)llm/prompt_loader.ts に追加。KV キー bizlp:prompts:gate4-scoring:thresholds から {Light, Standard, Critical} を取得し、未設定時は {35, 40, 45} にフォールバック。閾値変更手順は operator_guide_langgraph.md §7.4 参照
  • SYSTEM_PROMPTFALLBACK_PROMPT にリネーム + loadPrompt(env, 'gate4-scoring', FALLBACK_PROMPT) に切替 (PR #1090)
  • ChatOpenAI インスタンスに maxRetries=3 (exponential backoff) を付与