• Status: Accepted (PR #1386 merge = 受理の規約により 2026-06-04 受理。2026-06-11 の Status×Impl 整合調査で遡及反映・代表取締役指示)
  • Mode: Standard
  • Kruchten Type: Executive/Property
  • Scope: platform
  • Implementation Status: Done (PR #1375 / #1376 / #1377 / #1383 + フォローアップ 3 点 = PR #1418。詳細は §実装後 corrigendum (2026-06-04))
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-06-04 15:24
  • 承認日時 (JST): 2026-06-04 15:44
  • Deciders: [email protected] (単独)

1. コンテキスト

1.1 背景

decision-pipeline の Web UI (public/chat.html、約3,500行のSPA) には CI での回帰検知手段が存在しなかった。ADR-0101 実装では2日間で関連 PR 6 件と変更頻度が高く、chat.html は開始⇄停止トグル・キャンセル予約・リロード復元・polling 終端という状態機械を持つ。本起案の初回 pipeline 審査 (session bedb9912) では cross_validation gate が「mock drift 防止が人間の善意依存で機械的強制ゲート不在」を critical 盲点として差し戻した。本指摘は共有応答契約 + tsc 強制 (PR #1383) として実装済みであり、本版はその反映後の再投入である。

1.2 現状 (As-Is)

drp-test.yml は tsc + vitest のみで、vitest は langsmith の node:worker_threads 制約により worker 本体を import できず UI に到達できない。ADR-0101 のフロント検証で用いた唯一の手段は実 LLM full-run ブラウザ e2e で、1回あたり約2分 + LLM 課金 + gateway 依存という特性を持つ。

1.3 課題

実 LLM e2e はテスト失敗時にコード起因か gateway 不調起因かの切り分けが困難で flaky のため毎 PR ゲートに不向きであり、結果として UI 変更が無検証で merge され得る状態だった。

1.4 制約・要件

  • 毎 PR で決定論的に回帰検知 (flaky ゼロ)
  • CI 1 run 3分未満・追加課金ゼロ
  • モックとサーバ実応答の drift を機械的に検知できること
  • 既存 drp-test.yml の枠組みで実装可能なこと

1.5 目標 (To-Be)

Web UI テストを (1) 毎 PR ゲートの mocked-route e2e と (2) on-demand 実 LLM e2e の2層に標準化し、共有応答契約 + tsc で drift を機械強制する。Non-Goals: 電帳法・監査証跡の完全性検証 (本 ADR スコープ外、§5.3 参照)。

2. 決定

Web UI テストを2層に分離する。(1) Playwright の page.route() で chat.html 自体と全 API 応答をモックする完全密閉ブラウザ e2e (test/e2e/ui/) を毎 PR の CI ゲートにする (ui-e2e job)。(2) 実 LLM full-run スクリプト (test/e2e/real/) は on-demand に温存し、API 応答形式の変更時とリリース前のみ実行する。モックとサーバの drift は共有応答契約 src/contracts/chat_api_contract.ts (型のみ・依存ゼロ) をサーバ側とモック側双方が satisfies し、CI (ui-e2e job の Mock contract type-check = tsc) が毎 PR で検証する (PR #1383 実装済)。応答形式の変更は契約→サーバ→モックの3点同時更新が型エラーで強制される。CLAUDE.md 変更時テスト表の運用ルールはこの機械ゲートの補助に位置づける。

3. 判断基準 (Decision Drivers)

3.1 評価軸

#重要度 (係数)案件特有の解釈
1#reliable[Must] (×2.0)UI 回帰を毎 PR で決定論的に検知し flaky ゼロを維持。K.O.: モック起因の false-pass による本番 UI 障害発生で見直し
2#efficient[High] (×1.0)CI 1 run 3分未満・追加費用ゼロ
3#maintainable[High] (×1.0)API 形式変更時の追従先が共有契約 1ファイルに集約され、追従漏れは tsc が機械検知

K.O. criterion: Must 軸の score < 3 は不採用。

3.2 評価軸 × 案スコア表

係数採択案 (2層)案 A (実 LLM 毎 PR)案 B (nightly 実 LLM)案 C (on-demand のみ)
#reliable×2.05231
#efficient×1.05125
#maintainable×1.05332
加重和 (正規化)1.0000.4500.5500.500
K.O. 通過 (Must ≥3)

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

  • 案 A: 実 LLM e2e を毎 PR ゲート化 — 1回約2分 + LLM 課金 + gateway 依存。失敗時にコード起因か外部不調起因か切り分けられず、CI の信頼性自体を毀損するため不採用。
  • 案 B: 実 LLM e2e を nightly/scheduled 実行 — 本物の統合を毎晩確認できるが、PR への即時フィードバックがなく毎晩課金が発生し、夜間 fail の翌朝調査コストも大きい。毎 PR ゲートの代替にならないため不採用 (将来必要になれば本方式と併用可能)。
  • 案 C: on-demand スクリプトの commit のみ (CI 非ゲート) — 最小コストだが回帰検知が人間の手動実行頼みになり、ADR-0101 級の UI 変更が無検証で merge され得る現状課題を解決しないため不採用。

5. 影響 (Consequences)

5.1 正の影響 (Good)

  • UI 回帰の毎 PR 自動検知 (導入当日にバグ1件発見の実績: リロード復元セッション + フォーム空で停止トグルが HTML5 required バリデーションに遮断され無反応 → PR #1376 で修正)。
  • CI 追加費用ゼロ (GitHub Actions 無料枠内、+1分16秒〜1分24秒/PR)。
  • 実サーバでは再現困難なエラー系 (HTTP 500・status=error・cancelled) の描画検証が可能。
  • PR #1383 で導入された共有契約 + tsc は導入時に既存モックの非現実 2 件 (error.gate 欠落・triageMode の大文字小文字) を即検知した実績がある。

5.2 負の影響 (Bad)

  • モックとサーバ実応答の drift による false-pass リスク。緩和策: (1) 共有応答契約 + satisfies + CI type-check による機械的 drift 検知 (PR #1383)、(2) 実 LLM e2e で節目に整合検証 (導入時の本番 full run で整合確認済)、(3) CLAUDE.md 変更時テスト表。
  • 値セマンティクス drift は型検査で検知不能 (Gate 1 critical): chat_api_contract.ts の satisfies 検査は構造的部分型に基づくため、status が string 型を維持したまま新たな値 (例: 'timeout'、'in_progress') がサーバから返され始めても型エラーは出ない。自由な string 型フィールドの値セマンティクス変更は on-demand 実行の実施漏れにより無期限に本番に残り得ることを許容リスクとして明示する。緩和: §6 Confirmation に契約ファイル変更時の on-demand 自動実行義務を組み込み、契約定義は可能な限り literal union/enum を採用する方針を運用ルールに加える。
  • リリースゲートとしての実 LLM e2e が機械強制されていない (Gate 1 high): CI ダッシュボード上は ui-e2e が green を示すため、ステークホルダーが「UI は自動テストで完全保護」と誤認しやすい。緩和: §6 Confirmation にリリースブランチ merge/tag push トリガーでの実 LLM e2e 必須実行を機械強制として明記する。
  • 7シナリオの網羅性根拠が現時点で文書化されていない (Gate 1 high): chat.html の状態機械に対する遷移カバレッジマトリクスが未整備。緩和: test/e2e/README.md に状態×イベントマトリクスを添付し、新状態遷移追加 PR でのマトリクス更新を PR テンプレートのチェックボックスで要求する。
  • Playwright バージョンアップ起因の flaky 化リスク (Gate 1 high): polling 終端・リロード復元など描画タイミング依存シナリオで挙動変化の可能性。緩和: package.json で exact pin、専用 PR でのアップグレード、flaky 判定ログへの Playwright バージョン記録、明示的 waitForResponse による sleep 排除を運用に組み込む。
  • 成功体験による過信でシナリオ追加が後回しになる慢性化リスク (Gate 1 medium): 高変更頻度下でカバレッジ乖離が拡大する懸念。緩和: 上記マトリクスの PR テンプレート機械強制で対応。

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

  • 本番ホスティング基盤と CI 環境の構造的乖離 (Gate 1 medium): 本番の chat.html は Cloudflare Workers (decision-pipeline) が BasicAuth 付きで直接配信しており (GAS HTML Service ではない)、Queue/DO・LLM gateway 等の Workers ランタイム特性は Playwright 密閉環境では再現されない。本 ADR は「型検知で補完できないセマンティクス差異」として明示し、本番基盤の特性に依存する検証は実 LLM on-demand e2e で補完する。
  • 電帳法・監査証跡の完全性検証はスコープ外 (Gate 1 low): 本テスト設計は UI 状態機械の回帰検知に特化しており、UI 操作によるセッションキャンセル・リロード復元が監査証跡を破壊しないかは型検査では検証不能。decision-pipeline 出力物が監査対象となるか否かはステークホルダーと別途確認し、必要なら別 ADR で扱う。

コスト試算

  • 実装: 約 1.5 人日 (実装済み: PR #1375 標準化 / #1376 バグ修正 / #1377 CLAUDE.md / #1383 drift 機械ゲート)。
  • 運用 (CI): +1分16秒〜1分24秒/PR (GitHub Actions 無料枠内、追加課金 0 円)。
  • 運用 (on-demand): 実 LLM e2e 1 回約 2〜4 分 + LLM 課金 (節目のみ実行)。

6. 撤退条件 (Rollback Plan)

モック起因の false-pass (mocked e2e が green なのに本番 UI 障害) が四半期に2件以上発生、または ui-e2e job の flaky fail 率が5%超を1ヶ月継続したら、nightly 実 LLM 方式の併用または置換を再検討する。flaky 率集計時は Playwright バージョン変更起因を除外して評価する (§5.2 参照)。

Confirmation

  • 検証手段:
    1. drp-test.yml の ui-e2e job (7シナリオの mocked-route e2e + Mock contract type-check による drift 機械検知)。
    2. リリースゲート: 本番反映前 (本リポは main merge = 本番デプロイのため、deploy 影響のある変更の merge 前) に npm run e2e:real:toggle / e2e:real:reserve を手動実行し結果を PR に記録する (Gate 1 high 反映)。workflow による機械強制化は本 ADR のフォローアップ実装として管理する。
    3. 契約ファイル変更時の実 LLM e2e: chat_api_contract.ts またはサーバ側 /chat/* ハンドラ変更を含む PR では実 LLM e2e の手動実行を merge 条件とする (Gate 1 critical 反映)。CI 条件分岐による自動実行化はフォローアップ実装として管理する。
  • 実行頻度: ui-e2e は drp/** を変更する毎 PR、リリースゲート実 LLM は release branch merge / tag push、契約変更時実 LLM は該当 PR、最低保証として隔週の手動実行 (scheduled 化はフォローアップ実装)。
  • 違反時対応: テスト失敗で merge block。リリースゲート失敗時はリリース停止。
  • 観測可能 KPI: ui-e2e job の pass 率、実行時間 (3分未満維持)、flaky fail 率 (5% 未満を月次評価)。

API 形式変更時の mock 追従義務と状態遷移カバレッジマトリクス更新義務は CLAUDE.md 変更時テスト表・test/e2e/README.md・PR テンプレートに記載。

実装後 corrigendum (2026-06-04): Confirmation フォローアップ (実 LLM e2e の機械化) 実装完了

本 ADR は immutable。本節は ADR-0031 corrigendum 方式による実装後の追記で、決定本文は変更しない。

§6 Confirmation で「フォローアップ実装として管理する」とした 3 点を実装した:

  1. 契約変更時の CI 自動実行 (検証手段 3): drp-test.ymlreal-llm-e2e job — chat_api_contract.ts / src/index.ts / test/e2e/real/ を変更する PR で実 LLM e2e を自動実行。pre-merge 実行のため検証対象は現行 prod (PR 新コード自体は merge=デプロイ後に下記が担保)。
  2. 隔週 scheduled (実行頻度の最低保証): drp-real-e2e.yml — 偶数 ISO 週の月曜 06:00 JST に自動実行。
  3. リリースゲートの機械化 (検証手段 2): 本リポは main merge = 本番デプロイのため release branch / tag が存在しない。同 workflow の workflow_dispatch (ワンクリック手動) を deploy 影響の大きい merge 直後の本番 smoke として運用し、従来の「手動ローカル実行 + PR 記録」を置換する。

CI は GitHub Secrets DECISION_PIPELINE_AUTH_USER / DECISION_PIPELINE_AUTH_PASSWORD を使用。詳細: test/e2e/README.md。あわせて real/ スクリプト 2 本を DRP-379 (開始/キャンセル分離ボタン) の UI へ追従させた。

参照 (References)

  • 関連 ADR:
    • ADR-0101 実行中審査の協調キャンセル (補完: 本標準の最初の検証対象、導入当日のバグ発見・修正検証の実績対象)
    • ADR-0019 decision-pipeline toolchain (補完: toolchain のテスト基盤を拡充)
    • ADR-0020 決定の階層 (並立: 本決定はテスト方法論/CI ツール確立として Standard 相当)
  • 関連 PR/Issue: PR #1375 (標準化) / PR #1376 (バグ修正) / PR #1377 (CLAUDE.md) / PR #1383 (drift 機械ゲート)
  • 外部資料: -