TL;DR(このノードは何をする・専門語ゼロ): 起案を読んで「この問題はどんな実害を引き起こすか」を A / B / C の 3 つに分けて、後段の審査の重みを決める。A は後から取り返せない実害なので審査を厚くする。B は放置すると複利的に悪化するので実測データを要求する。C は軽微なので人間に「今は着手しない」と伝える。どれを引いても差し戻しはしない。判定は LLM ではなくコードが下し、根拠は本文からの逐語引用と機械照合する。

実装: drp/src/nodes/abc_screen.ts 判定コード (pure module): drp/src/nodes/abc_decide.ts プロンプト SSoT (KV デプロイ): prompts/production/gate0b-abc-screen/prompt.md migrate: drp/migrate-v12-abc-screen.sql 基盤 ADR: ADR-0157 位置づけ: triage → recall_pre_gate → abc_screen → cost_gate → problem_space_pregate → socratic 本番稼働: 2026-06-22 (週次集計監視中)


1. 役割と位置づけ

Gate4 の 10 軸は 9 軸が解決策側で、問題側は痛みの記述精度を見る軸 1 つだけだった。本ノードは「問題の解く価値」を harm の性質で機械分類し、入口から審査の重みを決める。

  • 解決する課題: 論証だけ立派な非問題が高得点を取れてしまう問題と、不可逆 harm の取りこぼし。Gate4 だけでは捕まらない。
  • 設計思想: harm 性質 (severity) と triage の mode (priority) を 別軸 として駆動する。LLM は意味分類と evidence 抽出だけを担い、A/B/C 確定と routing はコードが下す。ADR-0142 (pregate) と同型の二段構成。
  • rejected は絶対に立てない: C も人間終端で差戻しではない。C のメッセージは「現時点で取り組む優先度が低い理由」を伝える HITL の旗。
  • 由来: ADR-0157 (Existence/Executive・Standard・2026-06-18 受理)。

2. フロー図

flowchart LR
    R[recall_pre_gate] --> ABC[abc_screen
gemini-flash 1 call] ABC -->|A 不可逆| FC[force-Critical
triageMode を Critical へ昇格] ABC -->|B 慢性流血| RM[require-measurement
実測必須タグ] ABC -->|C 軽微| DN[do-nothing
人間終端の旗] ABC -->|INVALID| PASS[pass] FC --> CG[cost_gate] RM --> CG DN --> CG PASS --> CG

すべての分岐が cost_gate へ流れる (差戻しはしない)。


3. トリガー条件

エントリポイント起動グラフ説明
POST /draftbuildGraphWithWebhookrecall_pre_gate 直後に実行
POST /chat/runbuildGraphwebhook を除く full pipeline

スキップ条件:

  • 既に判定済み (state.abcVerdict != null) は冪等化で no-op。
  • env ABC_SCREEN_ENABLED=false で素通し。state は PASS を入れる。

4. 入力 (State)

State フィールド必須用途
titlestring任意起案タイトル
contextstring必須背景・目的の自由記述
optionsstring任意検討した代替案
triageModeenum既定値昇格判定のため読む

入力は buildPregateInput() を流用する。pregate と同形のテキスト 1 本を作って LLM へ渡す。


5. 処理ロジック

0. 冪等化: state.abcVerdict が決定済みなら no-op
1. env ABC_SCREEN_ENABLED='false' なら素通し (PASS で state 注入)
2. プロンプト (gate0b-abc-screen) を KV から取得し gemini-flash で 1 call
   - 出力: harm_domain / irreversibility / urgency / blast_radius /
     workaround_exists / inaction_cost_measured / evidence_spans
   - 各 evidence span に axis (どの軸の根拠か) と text (本文逐語引用) を付す
3. JSON parse 失敗 / enum 不正は INVALID で素通し (差戻しはしない)
4. decide() (abc_decide.ts) がコードで判定
   ① evidence span 照合: 全 span を NFKC + 空白畳みで正規化して本文に存在するか機械照合
      - 最初の不一致で短絡しない (全 span を評価)
      - 不一致 span は unmatchedSpans に記録 (INVALID にはしない)
   ② irreversibility で switch:
      - 'irreversible' → verdict='A'
        - harm_domain が 'other' なら force-critical せず Confidence flag (人間レビュー)
        - 影響範囲 evidence が照合できない場合は fail-safe で force-critical + Confidence
        - 顧客級以上なら forceCritical=true, route='force-critical'
        - 顧客級未満なら route='pass' (A タグだけ立てる)
      - 'chronic_compounding' → verdict='B', route='require-measurement'
        - 放置コスト未実測なら reasons に 'inaction_cost_not_measured'
      - 'minor' → verdict='C', route='do-nothing'
   ③ 駆動 evidence (不可逆性) が照合できない A/B は Confidence flag (人間へ降格)
      - A の forceCritical は降格しても下げない (過剰 escalation = #safe)
5. force-Critical 安全ラチェット:
   - forceCritical=true かつ現 mode が Critical 未満なら triageMode を Critical へ昇格
   - 上げるのみ (ユーザ modeOverride が Light/Standard でも A の不可逆性が優先)
   - Critical 済なら no-op
6. abcMessage を組み立てる
   - A force-critical → A_FORCE_CRITICAL_NOTE
   - B → B_REQUIRE_MEASUREMENT_MESSAGE
   - C → C_DO_NOTHING_MESSAGE
   - Confidence flag があれば末尾に CONFIDENCE_NOTE を追記
7. state に全 abc* フィールドを書き込み終了 (rejected は触らない)

正規化の方針: NFKC + 空白畳み (全角/半角・合成/分解を吸収する方向)。abc_decide.ts の正規化は ADR-0142 の normalizeForQuoteMatch より緩く、A の取りこぼし防止 #safe を優先する。シノニム (例「コンプラ」↔「法令対応」) は文字正規化では救えず、LLM の意味分類が解決する。

ADR 本文との表記乖離 (注記): ADR-0157 §決定は "Unicode NFC" と書くが、実装は NFKC を採用している (詳細は abc_decide.ts の冒頭コメント)。doc 側で "NFKC" へ更新を申し送る予定。


6. LLM 設定

項目根拠
モデルgemini-flash (MODELS.triage)軽量分類 1 call で十分・最安・最速
temperature / seed0 / 42同一起案には同一判定
期待出力JSON object (7 フィールド)system prompt + output schema で形式強制
コスト目安1 起案あたり 1〜3 円月次 ~$1 未満 (ADR-0157 §コスト試算)
レイテンシ1〜3 秒パイプライン全体に対し無視できる

7. 副作用

なし。LiteLLM Gateway 経由の LLM 呼出のみ。GitHub API / KV 書込 / Webhook には触れない。

構造化ログ:

  • event: 'abc_screen_skipped' — env OFF で素通し
  • event: 'prompt_loaded' — KV / FALLBACK の出所
  • event: 'abc_screen_complete' — verdict / route / force_critical / confidence_flag / reasons / unmatched_count
  • event: 'abc_screen_error' — LLM 例外

8. 出力 (State)

PASS (env OFF・素通し)

{
  abcVerdict: 'PASS',
  abcRoute: 'pass',
  abcReasons: [],
}

INVALID (JSON parse 失敗・enum 不正)

{
  abcVerdict: 'INVALID',
  abcRoute: 'pass',
  abcConfidenceFlag: false,
  abcReasons: ['schema_parse_fail'],
  abcUnmatchedSpans: ['<schema_parse_fail>'],
}

INVALID は審査深度を上げも下げもしない素通し。rejected は立てない。

A / B / C (decide が確定したケース)

{
  abcVerdict: 'A' | 'B' | 'C',
  abcClass: HarmDomain,                                     // harm_domain (compliance 等)
  abcRoute: 'force-critical' | 'require-measurement' | 'do-nothing' | 'pass',
  abcConfidenceFlag: boolean,                               // true=人間レビュー要
  abcForcedCritical: boolean,                               // triageMode を Critical へ昇格したか
  abcOriginalMode: 'Light' | 'Standard' | 'Critical' | null,
  abcMessage: string,                                       // 起案者向けメッセージ
  abcReasons: string[],
  abcEvidenceSpans: string[],                               // 照合できた span
  abcUnmatchedSpans: string[],                              // 照合できなかった span
  triageMode?: 'Critical',                                  // force-critical 時のみ昇格
}

rejectedどの分岐でも絶対に立てない (C は人間終端)。webhook が PR 本文に abcMessage を転記する。


9. 分岐 (次ノード)

graph.ts の edge:

.addEdge('abc_screen', 'cost_gate')

無条件で cost_gate へ流れる。abc_screen 自身は差し戻しを起こさない。

abcVerdict次ノード後段への影響
A (force-critical)cost_gatetriageMode が Critical に昇格済み。下流 gate の閾値が上がる
A (sub-customer)cost_gateA タグのみ。コスト試算が A の場合は cost_gate で A_AWARE_PASS 扱い
Bcost_gate実測必須タグ・abcMessage が PR 本文に転記される
Ccost_gateDo Nothing 旗・人間終端 (rejected ではない)
PASS / INVALIDcost_gate触らない

10. エラー時の挙動

失敗パターン挙動影響
LLM 例外 / JSON parse 失敗INVALID で通過させる (abcRoute='pass')telemetry で別集計
evidence span 照合失敗INVALID にしない・Confidence flag で人間レビューへA の取りこぼし防止 (#safe)
irreversibility=irreversible なのに harm_domain=otherforce-critical せず Confidence flag不確かな A は人間判定へ降格
影響範囲 evidence が照合できない Afail-safe で force-critical + Confidence過剰 escalation は許容 (#safe)

設計方針は rejected を立てない fail-safe に倒す。pregate と違って差戻し権限がない。


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

ADR-0157 §5.2.1 盲点 6 件 + §撤退条件から抜粋:

  • C メッセージの読まれ方リスク: 「Do Nothing 旗」が「あなたの問題は無価値」と読まれ起案を萎縮させうる。再申請フロー・人間レビュー要求オプションが必要。再起案率を週次で監視する。
  • Confidence flag 起案の人間キュー滞留: 週次上限件数・SLA 日数・担当ロール・エスカレーション先を本番反映 2 週以内に数値で確定する (未確定時は env フラグ停止を発動)。
  • 日本語表記ゆれと言い換え: 全角/半角や LLM のシノニム言い換えで span 照合が失敗しうる。NFKC + 空白畳みで吸収するが、シノニムは LLM の意味分類に任せる。
  • 同一 harm の文体差: 婉曲表現 (例「GDPR 違反」→「個人情報の取り扱い改善」) で A 以外に着地しうる。複数ライター golden eval で verdict 一致率を検証する。
  • 法域依存・時間的割引: FMEA AP lookup-table が EU AI Act vs 国内規制や「3 年後に不可逆」パターンに適合しない恐れ。該当パターンは Confidence flag に自動分類する。
  • 新興ドメイン (AI 規制・新規 CVE): 四半期更新の空白で C 誤分類されうる。イベントドリブン更新を Confirmation に追加。
  • 撤退条件: A の人間 downgrade 率が 4 週連続 30% 超 (単週 50% 超は即時停止) / Confidence flag 率 20% 超 / Do Nothing 旗の人間覆し率 50% 超 で再較正。

12. テストケース

  • golden eval (A/B/C 各クラス): prompt-cicd フローで PR ごと CI ゲート化。FP / FN を追跡。
  • abc_decide.ts unit test: decide() と同型の純粋関数 test (worker / DO / langchain 非依存・vitest pool-workers 安全)。
  • 複数ライター golden: 同一問題を異なる文体で記述したサンプルで verdict 一致率を測る。一致率 80% 未満なら #reliable K.O. でシグナル定義を再較正。
  • 四半期再較正: 新規起案から無作為サンプリングして golden セットを更新。

実行: prompt-cicd フローの一部。詳しくは /Users/ts_kuma/projects/bizlp/doc/prompts/production/gate0b-abc-screen/ 配下の eval セット。


13. 過去の設計判断ログ

日時変更経緯
2026-06-18ADR-0157 受理 (PR #2123 マージ)Gate4 軸偏りと不可逆 harm 取りこぼしへの対処として起案。Pipeline 通常 flow Standard 42/50 通過
2026-06-18drp PR #2152 で本番反映 (worker v c2d51b1a)abc_screen ノード + abc_decide.ts pure module + プロンプト + telemetry 列追加
2026-06-18ADR-0158 (コストゲート独立ノード) を同梱起票・実装A の ROI 免除を分離。cost_gate_verdict='A_AWARE_PASS' で A は cost 未記載でも通過
2026-06-22本番稼働開始・撤退条件監視 4 週開始A downgrade 率 / Confidence flag 率 / C 覆し率を週次集計

14. 関連リンク