• Status: Proposed
  • Mode: Standard
  • Kruchten Type: Existence/Executive
  • Scope: platform
  • Implementation Status: Not Started
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-06-22 17:14
  • 承認日時 (JST): -
  • Approver Role: platform
  • Approver Who: [email protected]
  • Driver: [email protected]
  • Consulted: Decision Pipeline AI 審査 (Gate 0-4)

コンテキスト

§1.1 背景

DRP の起案体験は https://drp.bizlp.dev/chat (chat.html・3631 行) に集約されており、1 画面に「起案する人格」と「審査する人格」の機能が同居している。起案フォーム / Socratic / triage 結果 / Step indicator (Gate1-15) / partial-results-card / 3 モデルレビュー / PR 作成ボタン / /audit/* 系がすべて同じ SPA 内に存在する。ADR-0157 で C 萎縮 (起案中に verdict プレビューを見て自己検閲) が問題視されており、構造的な対処を求められている。

§1.2 現状 (As-Is)

  • chat.html = 3631 行の単一 SPA に起案者向け要素と審査者向け要素が同居
  • telemetry_records 直近 30 日 (n=212) の triage_ms 計測: p50 = 47ms / p95 = 431ms (LLM 経路 n=136) / p99 = 27,833ms / max = 40,679ms
  • triage の LLM 経路は 95% が 0.5 秒以内、99% が 28 秒以内
  • scripts/lib/adr-lint-rules.mjs::checkTriageGate(text, mode) が純粋関数として既に存在 (placeholder 残存 / コスト試算 H2 / 撤退条件 H2 / Confirmation KPI の 4 ルール)
  • 現状 graph 構成は 4 種: buildPreGraph / buildGraph / buildCheckpointedGraph / buildGraphWithWebhook

§1.3 課題

  1. C 萎縮 (ADR-0157): 起案中に ABC verdict プレビュー・補強策プレビューが画面に出ると、起案者は「これは C 判定になりそう」と推測して自己検閲し、本来書くべき問題提起を取り下げる。
  2. JTBD 境界の不明瞭: 起案者の functional ゴール (「ADR 起案として土俵に乗る形」になっているか確定する) と、審査者の functional ゴール (「価値ある起案か裁く」) が UI 上で区別されていない。代表取締役単独運用でも人格切替の認知コストが発生し、Jr 起案者導入時には Jr が審査画面の verdict / 補強策を見て萎縮するリスクが顕在化する。

§1.4 制約・要件

  • Cloudflare Workers の wall-time 上限 30 秒以内に /intake/commit が完了すること
  • 現状 4 graph (buildPreGraph / buildGraph / buildCheckpointedGraph / buildGraphWithWebhook) の構成は変更しない (drift 防止)
  • checkTriageGate が Worker ランタイムから呼出可能であること (Node.js 固有 API 非依存)
  • ADR-0142 の problem_space_pregate LLM ゲートの挙動を変えない
  • ADR-0120 (Workflows 移行) の checkpointed graph に触らない

§1.5 目標 (To-Be)

/intake 起案者専用 SPA を新設し、起案者の責任境界 (「土俵に乗ったかの確定」) を UI 上で完結させる。verdict プレビュー・補強策プレビュー・3 モデルレビュー・PR 作成ボタンは intake.html から排除し、/chat は審査者ビューとして維持する。Non-Goals: hostname 分割 (draft.drp.bizlp.dev) / LLM 由来 reject の通知設計 / chat.html の起案者要素削除 (別 PR) / triage 非同期化。

決定

drp worker に /intake/* route (Hono sub-app) を追加し、起案者専用 SPA drp/public/intake.html を新設する。POST /intake/commit で (a) buildPreGraph().invoke() を同期実行、(b) scripts/lib/adr-lint-rules.mjs::checkTriageGate(text, 'Standard') を純粋関数として呼出、(c) 両方 pass で DRAFTS_KV.put(id, payload, overwrite=1) を実行する。graph 定義は一切変更せず、LLM 由来 reject (problem_space_pregate の suspect_multiple 判定) は審査側に残す。env flag INTAKE_SITE_ENABLED=false で即時無効化できる構造を入れる。

intake.html に含む画面: 起案フォーム (author/title/context/options) / Socratic 質問パネル (triage 通過に必要な盲点ループのみ) / triage 結果カード (mode/reason/起案前ゲート逐語引用) / KV draft 一覧 (100 件上限の見える化) / 保存完了画面 (draft_id + 「審査キューに入れる」CTA)。

intake.html に含めない画面: Step indicator (Gate1-15) / partial-results-card / 3 モデルレビュー結果 / PR 作成ボタン / cancel ボタン / /audit/* 系画面 / ABC verdict プレビュー / 補強策プレビュー。

route 構成:

  • GET /intakedrp/public/intake.html
  • POST /intake/triagebuildPreGraph().invoke() 同期実行 (triageOnly 経路)
  • POST /intake/drafts / GET /intake/drafts / DELETE /intake/drafts/:id → 既存 /drafts 系を sub-app 再 export
  • POST /intake/commit → triage + 静的 lint pass を条件に KV put し {draft_id, triage_mode, review_url} を返す
  • /chat, /runs, /audit/*, /debug/* → 既存のまま審査者ビュー

判断基準 (Decision Drivers)

3.1 評価軸

#重要度 (係数)案件特有の解釈
1#safe (起案者入力テキスト保護)Must (×2.0)/intake/commit 中の wall-time 30s 超過率 = 0% (本番反映後 4 週で確認・triage p99 = 28s + 静的 lint + KV put が 30s 内に収まる前提)
2#reliable (graph drift 防止)High (×1.0)graph 構成は本 ADR で変更しない (4 graph 維持・新ノード追加なし)
3#maintainable (変更局在化)High (×1.0)新コードは drp worker の /intake/* route + intake.html + checkTriageGate 呼出 1 行に閉じる / graph.ts / nodes/*.ts / mainGraphDefinition は無変更
4#safe (起案者 reject 体験の予測性)Medium (×0.5)静的 lint 由来 reject (placeholder / コスト試算 H2 / 撤退条件 H2 / Confirmation KPI) を OK 押下時に即座に画面で返す / LLM 由来 reject 件数 ≤ 静的 lint 由来 reject 件数 を 4 週で確認
5#operable (将来移行容易性)Medium (×0.5)C 案 (triage 非同期化) への移行が /intake/commit handler 書換のみで完結する設計を維持

K.O. criterion: Must 軸 (#safe wall-time) score < 3 は不採用。

3.2 評価軸 × 案スコア表

係数採択案 (B + 静的 lint)案 A (両方同期)案 C (triage 非同期化)案 D (chat 内 mode 切替)
#safe wall-time×2.04254
#reliable graph drift×1.05245
#maintainable 変更局在化×1.04322
#safe reject 予測性×0.55553
#operable 移行容易性×0.55352
加重和 (正規化)0.8800.5200.8400.660
K.O. 通過 (Must ≥3)

案 A は wall-time Must 軸で K.O.。案 C は wall-time が最良だが状態管理複雑度で #maintainable が低い。採択案は加重和最大かつ K.O. 通過。

検討した代替案 (Alternatives Considered)

  • 案 A (両方同期): buildPreGraphproblem_space_pregate を追加し、起案者の OK 押下時に triage + 起案前ゲートを LLM 2 回で同期実行 — 不採用。graph drift リスク (problem_space_pregatebuildPreGraphmainGraphDefinition の 2 箇所に重複・edge 更新漏れ事故源) / wall-time 30s 超過確率上昇 (p99 = 28s + LLM 1 回追加) / 起案テキスト消失の不可逆事故源。
  • 案 B 素 (triage のみ同期、静的 lint なし): 静的 lint プリチェックを入れない — 不採用。静的に検出可能な reject (placeholder / コスト試算 H2 / 撤退条件 H2 / Confirmation KPI) まで審査キュー投入後に流れて LLM コストの無駄。checkTriageGate が既に純粋関数として存在するのに使わない理由がない。
  • 案 C (triage 非同期化): OK 押下で即 KV 仮 put、triage はバックグラウンド起動、polling で結果待ち — 不採用。状態管理の複雑度が一気に上がる (KV status 列追加 / 仮 put → triage 起動 → 結果書戻し → 確定 put の 4 操作の race 整合 / polling endpoint / UI 状態遷移 / 仮 put cleanup)。triage p99 = 28s で wall-time 30s に収まっており現時点で過剰技術。将来 triage が重くなった時点で /intake/commit の handler 書換で移行可能。
  • 案 D (chat.html 内 mode 切替): route を分けず chat.html 内で ?mode=intake のような query で起案者ビューと審査者ビューを切替 — 不採用。3631 行の単一 SPA が更に肥大化。「同居解消」という本 ADR の目的を達成できない。起案者と審査者の bundle が分離されないので Jr 起案者導入時のセキュリティ境界が引けない。

影響 (Consequences)

§5.1 正の影響 (Good)

  • 起案者の C 萎縮 (ADR-0157) を構造的に塞ぐ (verdict プレビューが画面にない)
  • JTBD 境界が UI に反映され、起案者の責任範囲 (= 土俵に乗ったかの確定) が一発で完了する体験になる
  • 静的 lint 由来 reject が起案者画面で即時返答され、審査キューに流れる reject 件数が減る (LLM コスト削減・小)
  • 将来の hostname 分割 (draft.drp.bizlp.dev) への移行余地が Hono sub-app として残る
  • chat.html (3631 行) の段階的縮退の足掛かりになる

§5.2 負の影響 (Bad)

  • /intake/commit の handler に LLM 同期呼出 + 純粋関数呼出が増える (worker code 量増)
  • LLM 由来 reject (problem_space_pregate の suspect_multiple) の通知設計が宙ぶらりんになる (本 ADR スコープ外で別タスク化)
  • 兼務人格 (起案者と審査者を同一人物が兼ねる) の場合、/intake/chat の行き来が認知コストとして増える
  • 兼務人格が /intake/commit 後に /chat を開くと同一 draft_id に対して triage が 2 回実行され、コスト試算「LLM 増分 = 0」が崩れる可能性 → §採用したい方針で KV triage_done フラグを持たせる設計を採用 (PR 1 スコープ)
  • hostname 分割が完了するまでは Jr 起案者がブラウザ履歴・URL 共有で /chat に到達して verdict プレビューを閲覧する経路が残る (Jr 導入時期までは代表取締役単独運用で許容)

§5.3 中立・トレードオフ (Neutral / Trade-offs)

  • triage の LLM モデルが将来 thinking モード等で重くなると wall-time 30s に常時引っかかる可能性 → 撤退条件で監視 → C 案へ移行
  • LLM 由来 reject の通知が漏れると起案者が「土俵に乗った」気で離脱した draft が放置される → 通知設計を本 ADR 受理後 4 週以内に別 ADR で確定 (PR 1 merge 条件)
  • 暫定措置として /intake/commit のレスポンスと保存完了画面に「LLM ゲートは審査時に再チェックされ差し戻しの可能性がある」旨の警告 banner を PR 1 スコープに含める
  • 「静的 lint が多数派 reject」仮説の事前検証 (telemetry_records からの実績比率集計) が PR 1 着手前に必要

撤退条件 (Rollback Plan)

  • wall-time 超過: 本番反映後 4 週連続で /intake/commit の wall-time 30s 超過率が 0.5% を超過 → C 案 (triage 非同期化) へ移行する別 ADR を起案
  • LLM reject 多数派化: 本番反映後 4 週連続で (LLM 由来 reject 件数 / 全 reject 件数) > 50% → 静的 lint の網羅性が不十分 → 静的ルール拡張を scripts/lib/adr-lint-rules.mjs で実施
  • 起案者離脱率上昇: 本番反映後 4 週で /intake 起案完了率 (= POST /intake/commit 成功数 / GET /intake セッション数) が pre-ADR 比で 20% 以上低下 → intake.html の UX 設計に問題あり → 別 PR で UX 修正
  • KV 100 件上限到達: KV draft 一覧が 100 件上限に達して新規起案 DRAFTS_KV.put がエラーを返す → LLM 由来 reject 通知設計 ADR の緊急受理 + 放置 draft の cleanup batch を別 PR で投入
  • 無効化手順: env INTAKE_SITE_ENABLED=falsewrangler secret put で即時設定 → /intake/* は 410 Gone を返し起案者は /chat へ誘導 (rollback コスト = secret 操作 1 つ)

コスト試算

  • 実装工数: 1.5 人日
    • PR 1 (intake 新設・本 ADR スコープ): 1 人日 (/intake/* route + intake.html ~1500 行 + POST /intake/commit handler + 静的 lint 呼出 + intake.html 用 mocked e2e + intake_commit_ms 観測列追加 migrate-v18)
    • PR 2 (chat.html 縮退・本 ADR スコープ外・別 PR): 0.5 人日 (chat.html から起案フォーム・Socratic・draft セレクト削除 / real-llm-e2e の admin merge 運用)
  • 運用コスト増分:
    • LLM コール増分: 0 (triage と problem_space_pregate の LLM 呼出は審査経路でも起案経路でも同じ回数 / 起案前 reject 件数だけ LLM コストが減る方向)。ただし兼務人格の二重 triage 防止のため KV triage_done フラグを PR 1 で導入する前提
    • subrequest 増分: 0 (worker 内で完結・新規外部呼出なし)
    • KV 書込増分: 0 (既存 DRAFTS_KV.put と同じ操作)
    • 観測 SQL 増分: /intake/commit の reject 内訳 (静的 lint 由来 vs LLM 由来) を月次で観測する SQL を 1 本追加 (drp/queries/adr-E-intake-reject-breakdown.sql)
  • 撤退時コスト: /intake/* route の handler 削除 + intake.html 削除 + chat.html の起案者要素は無変更 (PR 2 を merge していない前提) ので素直に rollback 可能。env flag INTAKE_SITE_ENABLED=false で即時無効化 (secret 操作 1 回)

Confirmation

  • 検証手段:
    1. wall-time 実測: /intake/commit の wall-time 分布を week 単位で観測 (telemetry_records に intake_commit_ms 列追加 / migrate-v18-intake-commit-timing.sql) し、p99 が 30s を下回ることを確認。受理前提: staging 環境で checkTriageGate + KV put + Hono routing + JSON シリアライズ の合算レイテンシを 1,000 回計測し、triage p99 (27,833ms) との合算が 29 秒以内に収まることを PR 1 merge 条件とする。29 秒を超える場合は C 案を初期設計として再採用するか ADR 採用方針を再起案する
    2. 静的 lint 仮説検証: 既存 telemetry_records から checkTriageGate 4 ルール別 reject 件数と problem_space_pregate LLM reject 件数の実績比率を PR 1 着手前に集計し、「静的 lint 由来が多数派 (≥ 50%)」仮説の事前検証結果を ADR Implementation Status に追記
    3. reject 内訳観測: /intake/commit の reject 内訳 (reject_source ∈ {static_lint, triage_llm, problem_space_pregate_llm}) を月次で観測し、static_lint が多数派 (≥ 50%) であることを確認
    4. C 萎縮緩和観測: ADR-0157 の C 萎縮観測 SQL (abc_verdict='C' 件数 / abc_confidence=1 率) と本 ADR の起案完了率の相関を観測。観測タイミングは hostname 分割 ADR 受理後 に変更 (現時点では「C 萎縮の構造的解消の第一歩」と位置付け、Jr 起案者の /chat 到達経路が残る限り完全解消は計測不能)
    5. chat.html 起案経路の縮退観測: chat.html の起案フォーム経由の draft 投入数が本 ADR 反映後に減少することを確認 (= 起案者が /intake を使っている証跡)
    6. PR 1 merge 条件: (a) staging wall-time 1,000 回計測 ≤ 29 秒、(b) adr-lint-rules.mjs の import ツリー静的解析で Node.js 固有 API (fs/path/process) 非依存を確認 (依存があれば Worker 向けサブモジュール分離)、(c) LLM 由来 reject 通知設計 ADR の起案完了、(d) 暫定 banner (「LLM ゲートは審査時に再チェックされ差し戻しの可能性がある」) を保存完了画面に実装、(e) KV triage_done フラグによる二重 triage 防止実装
  • 実行頻度: 週次 (本番反映後 8 週まで) / それ以降は月次 telemetry レビューに同期
  • 違反時対応: 撤退条件のいずれかに該当した時点で env flag INTAKE_SITE_ENABLED=false で即時無効化 → ADR 本文 Implementation Status に「撤退・原因」を追記 → 再評価後に C 案 (非同期化) や A 案 (両方同期) を再検討

参照 (References)

  • 関連 ADR:
    • ADR-0071 (socratic 盲点検出エンジン化 + wall-time 制約 graph 分割): 準拠。buildPreGraph (triage のみ軽量 graph) を起案者サイトの境界として再利用。buildPreGraph 構成は変更しない
    • ADR-0120 (decision-pipeline Cloudflare Workflows 移行 / durable execution): 準拠。buildCheckpointedGraph (Workflows 専用) に触らない。intake サイトは worker 同期経路で完結し Workflows には乗らない
    • ADR-0142 (問題空間プリゲート受付): 準拠。problem_space_pregate の LLM 部分は審査側 main graph に残し挙動不変。静的部分 (checkTriageGate) のみ起案者側で先行実行
    • ADR-0157 (ABC スクリーン): 補強。C 萎縮の構造的解消の第一歩として intake.html に verdict プレビューを含めない設計が ADR-0157 §Confirmation の補強となる
    • ADR-0158 (コストゲート独立ノード): 独立。cost_gate ノードに触らない。cost_gate は審査側で従来どおり動作 (A_AWARE_PASS / BLOCK)
    • ADR-0159 (mas 専属クローン化・main orchestrator 化): 準拠。本 ADR は drp 専属クローンの実装スコープ。main 役割 (orchestrator) には ADR 受理と関連 docs/_internal 更新を委譲
    • ADR-0163 (事業軸ドメイン分類基準 4 種): 準拠。本 ADR は ADR-0163 §2.1 定義表の DRP ドメインに該当 (Decision Pipeline の挙動を変える: /intake/* route + buildPreGraph 同期実行 + checkTriageGate 起案者側先行実行)。frontmatter business: drp を ADR-0163 §2.6 運用に従い明示
    • ADR-D (緩やかコンプラ違反 cross-rule・data-waiting): 独立。abc_decide.ts の判定ロジック側に対し本 ADR は intake UI 側
  • 関連 PR/Issue: PR 1 (intake 新設) / PR 2 (chat.html 縮退・別 PR・admin merge 運用) / 別 ADR (LLM 由来 reject 通知設計・本 ADR 受理後 4 週以内・PR 1 merge ブロッカー)
  • 外部資料: telemetry_records 直近 30 日 triage_ms 集計 (n=212, LLM 経路 n=136) / Cloudflare Workers wall-time 上限 30 秒仕様