• Status: Accepted
  • Mode: Standard
  • Scope: platform
  • Kruchten Type: Existence/Property
  • Implementation Status: Done (PR #841)
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-05-19 00:14
  • 承認日時 (JST): 2026-05-19 00:35
  • Deciders: [email protected] (単独)

1. コンテキスト

1.1 背景 (Background)

Decision Pipeline (ADR-0019) の chat UI で、retroactive validation 用途と通常の新規起案用途の区別がない。ADR-0050 retroactive validation (2026-05-18) 実行時、代表取締役氏が誤って /chat/create-pr を呼んでしまい、不要な PR #821 が自動生成された。ADR-0050_retroactive_validation_prompt.md Step 7 で「retroactive 時は PR 作成禁止」と明記されていたが UI 側にガードがなく、操作ミスで発火した。

参照: docs/_internal/03_decisions/decision_pipeline/ADR-0050_gate4_validation_report.md §6.4 (Pipeline UI 改善余地、別 ADR 候補と明記)。

1.2 現状 (Current State / As-Is)

  • chat UI (chat.html) には retroactive validation モードの識別機構がなく、draft アップロード時も種別を問わない
  • POST /chat/create-pr は draft の種別を問わず即実行され、サーバ側のガードも無し
  • create-pr ボタンは confirm() なしで即発火する

1.3 課題 (Problem)

  • retroactive validation モードの draft が UI で識別できない
  • create-pr が confirm() なしで即実行される (誤クリック耐性ゼロ)
  • 「retroactive のつもりが PR 作成された」事故のフォールバックが PR 取り消ししかない (PR #821 churn コスト発生済)

1.4 制約・要件 (Constraints & Requirements)

  • bizlp 既存方針「不可逆操作は技術的にブロック」(CLAUDE.md Prohibited 末尾、PreToolUse Hook) との整合必須
  • 過去 draft との後方互換性維持 (KV payload retroactive? はデフォルト false)
  • 変更対象は drp/src/index.ts (30 行) + drp/public/chat.html (50 行) に限定
  • chat-terminal.html は本 ADR 対象外 (利用頻度低、後日同期する別 PR で対応)
  • ADR-0019 / ADR-0037 を Refines し、supersede しない

1.5 目標 (Goals / To-Be)

  • retroactive validation モード draft を UI banner + サーバ 422 guard で二重に識別・ブロックする
  • 通常 draft でも create-pr 時に confirm dialog を表示し、誤クリック耐性を確保する
  • Non-Goals: chat-terminal.html の同期、retroactive 専用ページ分離 (/chat-retroactive)、metadata-only 管理への移行

2. 決定

drp に以下 2 機能を追加する。

(A) Retroactive validation モード

  • POST /draftsretroactive?: boolean を受け取り、payload + KV metadata に保存
  • GET /drafts / GET /drafts/:id レスポンスに retroactive を含める
  • フロント (chat.html) で draft アップロード時に「これは retroactive validation 用ですか?」を confirm() で問う
  • draft ロード時に retroactive: true を検出したら:
    • 上部に banner 表示 (🔒 Retroactive validation mode — PR 作成は無効化)
    • 結果画面で create-pr ボタンを非表示、代わりに notice 表示
  • サーバ側 POST /chat/create-prdraft_id から KV を引き、retroactive: true なら 422 Unprocessable Entity を返す (defense-in-depth)

(B) create-pr 確認 dialog

  • retroactive でない場合も、create-pr ボタンクリック時に confirm('GitHub に PR を作成します。よろしいですか?') を表示
  • 誤クリック耐性を確保

判断基準は ADR-0050 で確立した arc42 Q42 9 タグ + WSM + K.O. criterion (CBA Suhr 1999) を本 ADR にも適用し、Synthesis 文書だけでなく ADR 起案にも MCDA を導入する第一適用例とする。

2.1 評価軸 (Q42 5 軸選定、ADR-0050 §4.2 準拠)

#重要度 (係数)案件特有の解釈
1#reliable[Must] (×2.0)retroactive validation の安全性、PR 自動生成事故 (PR #821) の構造的防止
2#operable[Must] (×2.0)bizlp 既存「不可逆操作は技術的にブロック」方針 (CLAUDE.md Prohibited 末尾、PreToolUse Hook) との整合
3#maintainableHigh (×1.0)chat.html / src/index.ts の保守負荷、UI 差分の管理コスト
4#suitableHigh (×1.0)ADR-0019/0037 を Refines する既存資産との整合性
5#usableMedium (×0.5)誤クリック耐性、起案者の認知負荷 (dialog のうざさ vs 安全性のトレードオフ)

K.O. criterion: Must 軸 (#reliable / #operable) の score < 3 は不採用 (機能要件未充足とみなす)。

2.2 評価軸 × 案スコア表

係数採択案 (A+B 統合)案 A1 フロントのみ案 A2 別エンドポイント案 A3 dialog のみ
#reliable [Must]×2.05 (frontend 非表示 + server 422 二重ガード)2 (改竄可能)4 (隔離)2 (mode 区別なし)
#operable [Must]×2.05 (技術ブロック方針整合)1 (方針不整合)41
#maintainable High×1.04 (~80 行追加、単一 endpoint 拡張)5 (~30 行)2 (API 二重化)5 (~20 行)
#suitable High×1.05 (Refines 明示)33 (新規 endpoint で別文脈)3
#usable Medium×0.55 (mode banner + dialog 両方)234 (dialog のみ)
加重和 (正規化、満点 32.5)0.9690.4620.6920.492
K.O. 通過 (Must 軸 ≥3)❌ (#operable=1)❌ (#operable=1)

加重和首位 = K.O. 通過案 = 採択案 (A+B 統合)

Note: 加重和は絶対判定ではなく、K.O. 通過候補のタイブレーク・透明性確保用 (Suhr 1999 CBA criterion)。本案件では K.O. 通過 2 案 (採択案 / 案 A2) のうち、加重和差 0.277 ポイントが明確に採択案を支持。

3. 検討した代替案 (Alternatives Considered)

  • 案 A1: フロント側のみで実装 (server-side guard なし) — 不採用理由: フロント JS は改竄可能で、retroactive モードの draft が偶発的に create-pr を呼んだ場合の構造的防止にならない。bizlp の「不可逆操作は技術的にブロック」方針 (CLAUDE.md Prohibited 末尾、PreToolUse Hook 強制ブロック) と不整合。K.O. 不通過 (#operable=1)
  • 案 A2: 別エンドポイント /chat/retroactive-validate を新設 — 不採用理由: API 二重化で保守負荷増 (#maintainable=2)、#operable は通過するが採択案より低スコア。retroactive flag はあくまで draft メタ情報であり、既存 /chat/start で同じ Gate 0-4 処理を流用できる。KV ベースの flag 管理が最小実装 (YAGNI)。
  • 案 A3: 確認 dialog のみ追加 (retroactive flag は実装しない) — 不採用理由: 誤クリック耐性は得られるが、retroactive validation の本来の運用 (PR 作成しない) を UI レベルで明示できない (#reliable=2)。事故再発時に「retroactive のはずが confirm で OK 押してしまった」リスクが残る。ADR-0050 §6.4 が指摘した両側 (mode + dialog) の対応が必要。K.O. 不通過 (#operable=1)

4. コスト試算

  • サーバ実装 (src/index.ts): 1-2 時間
    • DraftMeta 拡張、POST /drafts body 拡張、/chat/create-pr guard 追加
  • フロント実装 (chat.html): 2-3 時間
    • upload 時の confirm()、hidden field 追加、banner UI、create-pr 非表示分岐、confirm dialog
  • テスト + デプロイ: 1-2 時間
    • retroactive=true / retroactive=false の draft で動作確認、wrangler deploy
  • ドキュメント更新: 1 時間
    • operator_guide.md に retroactive mode セクション追加
  • 合計: 5-8 時間 (Standard 想定)
  • 運用コスト: 追加なし (UI クリック 1 回増 = ms オーダー)

5. 影響 (Consequences)

5.1 正の影響 (Good)

  • ADR-0050 §6.4 で識別された UI 改善余地に対応
  • 操作ミス起因の事故 (PR #821) の構造的再発防止 (server-side 422 + フロント非表示の二重ガード)
  • KV metadata 拡張で将来の draft 種別 (dry-run / dev-test 等) への拡張余地
  • Pipeline 自己審査フロー (retroactive validation) の運用基盤強化

5.2 負の影響 (Bad)

  • KV payload スキーマ変更 (retroactive? 追加) で過去 draft との互換性は保つ (デフォルト false) が、operator_guide.md 等の運用ドキュメント更新が必要
  • フロント側に新規 hidden field + banner UI 追加で chat.html が ~50 行増 (1245 → ~1295 行)
  • chat-terminal.html との UI 差分が一時的に発生 (本 ADR では対象外、後続 PR で同期)

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

  • retroactive flag が draft 側にだけあって UI 側で読み飛ばされた場合、create-pr が走る可能性 → server-side 422 guard で defense-in-depth
  • KV getWithMetadata の eventual consistency (~60s) で flag 反映遅延の可能性 → payload にも retroactive を含めることで .get() でも判定可能
  • 確認 dialog の追加で「うざい」体感が出る可能性あり (cf. §6 撤退条件で confirm-only-when-risky モードへの fallback 余地)

6. 撤退条件 (Rollback Plan)

  • 3 ヶ月後 (2026-08-18): retroactive validation 件数 / 全 draft 件数 比率を確認、10% 未満なら機能の意義を再評価
  • 6 ヶ月後 (2026-11-18): 422 guard が実際に発火した回数を計測、ゼロなら過剰実装として簡素化検討 (フロントガードのみに縮退)
  • 1 年後 (2027-05-18): chat-terminal.html との UI 差分が運用上問題になっていれば共通化リファクタを別 ADR で起案
  • 確認 dialog が「うざい」と代表取締役氏が判断したら、retroactive 時のみ dialog 表示する confirm-only-when-risky モードへ fallback (UI 設定追加)
  • KV payload に retroactive 追加が将来の schema migration を阻害したら、metadata-only 管理へ移行 (.getWithMetadata() ベース)

Review After: 2026-08-19 (3 ヶ月後) / 2026-11-19 (6 ヶ月後) / 2027-05-19 (1 年後)

6.1 半年〜1 年後の負債化リスク

  • chat.html と chat-terminal.html の UI 差分拡大 → 共通化リファクタが必要に。本 ADR は意図的に chat-terminal 対象外とするため、運用上の「片方しか直っていない」混乱が発生する可能性 → README で明示
  • KV payload に retroactive を含める設計 vs metadata-only 管理のどちらが正解か、6 ヶ月後の運用実態で判定
  • 「retroactive 時の特殊扱い」が増えると UI の認知負荷が増加 → 別ページ /chat-retroactive 分離も検討候補 (現時点では YAGNI)

6.2 検証可能な完了条件

  • drpwrangler deploy が成功
  • chat UI で retroactive=true でアップロードした draft をロード → banner 表示 + create-pr ボタン非表示を目視確認
  • retroactive=false の draft をロード → 通常通り create-pr ボタン表示、click 時に confirm() dialog 表示を目視確認
  • POST /chat/create-pr を retroactive=true の draft_id で呼ぶと HTTP 422 が返ることを curl で確認
  • operator_guide.md に retroactive mode セクション追記、参照リンク追加
  • 既存 PR (#821 のような) と本機能の関係を ADR 本文の「過去事故との関係」で説明

Confirmation (準拠確認 / Fitness Function)

  • 検証手段 (自動): drp/test/ に integration test を追加し、(1) POST /drafts with retroactive: trueGET /drafts/:id のレスポンスに retroactive: true が含まれること、(2) 当該 draft_id で POST /chat/create-pr を呼ぶと HTTP 422 が返ること、を assert する。CI (GitHub Actions) で PR ごとに実行。
  • 検証手段 (手動): PR レビュー時に reviewer が chat.html のロード動作を localhost で目視確認 (retroactive=true → banner 表示 + create-pr 非表示、retroactive=false → confirm dialog 発火)。チェックリストを PR template に追加。
  • 実行頻度: 自動 = PR ごと (CI) + main push ごと、手動 = retroactive validation 関連の変更を含む PR 時。運用統計 (422 発火回数、retroactive draft 比率) は §6 Rollback Plan の 3/6 ヶ月レビューで集計。
  • 違反時の対応: CI 失敗時は PR merge ブロック。本番で 422 guard をすり抜けて PR が誤生成された場合は、即座に該当 PR を close + ブランチ削除し、postmortem を docs/_internal/03_decisions/decision_pipeline/ に記録、本 ADR を Superseded 候補として再評価。

7. 参照 (References)

  • 関連 ADR:
    • ADR-0019 (Decision Pipeline LangGraph 移行) を Refines: 本 ADR は ADR-0019 末尾の補強として位置付け、UI 安全性レイヤを追加。ADR-0019 を supersede しない (基本アーキテクチャは不変)。
    • ADR-0037 (KV draft staging) を Refines: 既存の DRAFTS_KV スキーマに retroactive?: boolean フィールドを追加 (互換性維持、デフォルト false)。
    • ADR-0050 (Synthesis 標準テンプレート) Gate 4 validation report §6.4 で識別された Pipeline UI 改善余地への直接対応 (本 ADR の起案根拠)。本 ADR は ADR-0050 の Q42 9-tag MCDA を ADR 起案にも適用する 第一適用例として位置付け。
  • 関連 PR/Issue:
    • PR #821 (2026-05-18, 誤って自動生成され即 close) — 本 ADR で再発防止対象。
  • 外部資料:
    • Suhr, J. (1999) The Choosing By Advantages Decisionmaking System — K.O. criterion / WSM の出典。
    • arc42 Quality Requirements (Q42) 9-tag 体系。
    • docs/_internal/03_decisions/decision_pipeline/ADR-0050_gate4_validation_report.md §6.4。
    • docs/_internal/03_decisions/decision_pipeline/ADR-0050_retroactive_validation_prompt.md Step 7。
    • CLAUDE.md Prohibited 末尾「不可逆操作は技術的にブロック」方針 / PreToolUse Hook。