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

コンテキスト

1.1 背景 (Background)

Decision Pipeline (ADR-0019) の chat UI (https://decision-pipeline.t-saitoh.workers.dev/chat) で新規 ADR を起案する際、起案者は author / title / context / options の 4 フィールドを Web UI の textarea に手入力 or 別タブ・別エディタからの clipboard paste で投入する必要がある。

本日 (2026-05-14) の ADR-0035 投入時、Claude Code 経由で /tmp/adr0035_draft.json をローカルに用意した上で、python3 -c "...print(r['context'])" | pbcopy で 1 フィールドずつ clipboard 経由 paste する運用を実施した。この運用で実際に発生した問題:

  • Claude が context + options を結合して clipboard に投入してしまい、Web UI の context テキストエリアに options が混入する誤りが発生 (修正のため再 pbcopy)
  • ADR-0035 投入準備中に ADR-0036 用 pbcopy を上書き実行してしまい、ADR-0035 投入前に clipboard が ADR-0036 に書き換わる事故
  • 起案者は 4 フィールドそれぞれに focus → cmd+v → 確認 → 次のフィールドへ移動 を繰り返す必要があり、注意散漫時に取り違えが発生しやすい

1.2 現状 (Current State / As-Is)

  • chat UI の入力フィールド: author / title / context / options の 4 つ (現状すべて手入力 or paste のみ)
  • 1 ADR 投入あたりの paste 回数: 4 回 (各フィールド 1 回)
  • 1 paste あたりの手順: clipboard 用 pbcopy コマンド実行 → Web UI でフィールドに focus → cmd+v → 内容確認 (約 15-30 秒)
  • 1 ADR 投入の paste 累積時間: 1-2 分
  • 失敗時のリカバリ: 全フィールド再 paste で約 1-2 分追加
  • 本日の Claude 起因のミス発生率: 4 paste のうち 1-2 件で誤投入 (内容混入 / 上書き) を観測 (n=1 セッション)
  • 既に手元に存在する draft 形式: /tmp/adrNNNN_draft.json (author / title / context / options の 4 キーを持つ JSON、本日 ADR-0035 / 0036 用に用意済)

1.3 課題 (Problem)

  1. paste 運用の脆弱性: 4 フィールド paste の途中で clipboard を上書きするコマンドを並行実行すると即座に内容が壊れる。Claude Code 経由で複数 ADR を投入準備する際に頻発しやすい (本日実証済)
  2. paste 内容の検証困難: pbcopy 後に clipboard に何が入っているかを起案者が直接確認する手段がなく、Web UI に paste して初めて気付く。誤投入時のリカバリコストが高い
  3. Pipeline 再投入時の手戻り: /draft が中途失敗した時 (本日 ADR-0035 の 1 回目投入で発生した JSON escape error 等)、4 フィールドの paste を最初からやり直す必要があり 1-2 分の再作業
  4. 手元 draft 形式が活用しきれない: 既に JSON 4 キー形式で draft をローカルに用意しているのに、Web UI 側に取り込み口がないため毎回 pbcopy + paste 経由になる

1.4 制約・要件 (Constraints & Requirements)

  • 既存 chat UI / Pipeline の動作を破壊しない (新規 UI 要素の追加のみ、既存 textarea の削除・改名なし)
  • Backend 変更なし (frontend のみで完結、Cloudflare Workers の Worker コード更新は不要)
  • ファイル読み込みはローカル (input type file + FileReader API)、サーバーアップロードしない
  • 既存 Basic 認証で保護されている chat UI 上に追加するため、追加認証不要
  • 実装規模 1 時間以下 (HTML + JS 約 20-30 行)
  • 既存の paste 入力フローも併存させる (ロード対象 JSON を持たない場合の従来運用を保持)

1.5 目標 (Goals / To-Be)

  • chat UI に draft JSON をロードボタンを追加、ローカル .json ファイル選択で author / title / context / options の 4 フィールドを一括 populate する
  • 1 ADR 投入の paste 累積時間を 1-2 分から 5 秒以下に短縮 (約 95% 削減)
  • Claude Code 経由の clipboard 上書き事故をゼロにする (clipboard 経由を廃止)
  • /draft 失敗時の再投入もボタン 1 押しで全フィールド再投入可能にする

決定

drp/public/chat.html に非表示 input type=file (accept=.json) + ロード起動ボタンを追加し、FileReader API でローカル .json を読み込み、JSON.parse で {author, title, context, options} を抽出して 4 フィールドに一括 populate する frontend 完結の機能を実装する。バリデーションは「4 キー欠落時に alert + 投入中止」「JSON.parse 失敗時 alert + console.error + フォーム不変」とし、既存 textarea 値の上書きは確認なしで許可する (起案者の明示的選択行為のため)。既存 paste 入力フローも併存させ後方互換を保つ。start-form と /chat エンドポイントの form 両方に同じ機構を適用する。

検討した代替案 (Alternatives Considered)

  • 案 A (採用): chat.html に input type=file (accept=.json) とロードボタンを追加、FileReader で 4 フィールドを一括 populate

    • Good: frontend 完結で実装規模 1 時間以下、Backend 変更なし
    • Good: clipboard 経由 paste の上書き事故 (本日実証済) を構造的に排除
    • Good: /draft 再投入時のリカバリが 1-2 分から 5 秒以下に短縮
    • Good: 既存 paste 入力も併存させる後方互換性
    • Bad: draft JSON の 4 キースキーマが暗黙固定、将来フィールド追加時に UI 改修必要
    • Bad: 起案者が無関係な 4 キー揃った JSON をロードした場合のフィールド誤上書きを完全には防げない
  • 案 B: drag-and-drop ファイル領域を追加 (ボタンの代わりに drop zone) — 不採用理由: 実装複雑度がやや増す (drag enter/over/leave/drop の 4 イベント処理 + visual feedback) のに対し UX 改善はわずか。Claude Code 経由の自動投入には不向き (drag 動作の自動化不可)

  • 案 C: URL ベースのリモート draft load (gist URL 等を入力して fetch) — 不採用理由: 外部依存が増える (gist サービス可用性、CORS、機密 draft の URL 露出リスク)。本機能の主目的 (ローカル /tmp/adrNNNN_draft.json の即時投入) を満たさない

  • 案 D: Cloudflare KV に server-side draft storage を構築、UI からは draft ID で参照 — 不採用理由: Backend 変更 + 新規ストレージ + 認証境界の再設計が必要、実装規模 8 時間超。本 ADR の目的 (paste 廃止) に対して過剰投資

  • 案 E: 現状維持 (clipboard pbcopy + Web UI paste) — 不採用理由: 本日実証された Claude 起因の clipboard 上書き事故が継続。paste 累積時間 1-2 分/ADR が月 5-10 件起案で継続損失

影響 (Consequences)

5.1 正の影響 (Good)

  • clipboard 上書き事故のゼロ化: 本日実証された Claude 起因のミス (context + options 結合誤り、ADR-0036 用 pbcopy による ADR-0035 上書き) を構造的に排除
  • paste 累積時間 95% 削減: 1 ADR あたり 1-2 分 → 5 秒以下。月 5-10 件起案で月 5-20 分節約 = 年 1-4 時間削減
  • frontend 完結: Backend 変更不要、Cloudflare Workers デプロイなしで chat.html の即時更新が可能 (実装規模 0.5 時間 + 動作確認 0.5 時間)
  • /draft 失敗時のリカバリ高速化: 1-2 分の再 paste → ボタン 1 押し (5-10 秒)
  • 後方互換: 既存 paste 入力も併存、draft JSON を持たないケースで従来運用が壊れない
  • コスト効果: 投資約 1.75 時間 + LLM 約 $3 (約 [MASKED:AMOUNT]) に対し年間 [MASKED:AMOUNT]-17,000 削減見込み (投資回収 6-23 ヶ月)

5.2 負の影響 (Bad)

  • draft JSON 形式の暗黙固定: 4 キー (author/title/context/options) を超える将来フィールド追加時に chat.html 側のパース処理も更新必要。スキーマバージョン管理が未整備
  • 誤ったファイルロード: 起案者が無関係な JSON ファイルをロードした場合、フォームが上書きされてしまう (alert + キー欠落チェックで緩和、ただし 4 キー揃った無関係 JSON は防げない)
  • chat UI のモノリス化リスク: 機能追加が続くと chat.html の単一ファイルが肥大化、別 ADR で UI コンポーネント分離検討が必要

Status / Mode / Scope は 2026-06-11 に遡及追加 (ADR-0031 corrigendum パターン)。出典: Status = 旧形式「## ステータス」節の機械転記 / Mode = 旧 README §既存 ADR 一覧の推定値 (git 履歴) / Scope = ADR-0049 4 層分類の遡及付与 (PR レビューで確定)。

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

  • ブラウザ互換: ブラウザの file picker は localhost / 本番ドメインのいずれでも動作するが、Safari の一部バージョンでは file:// 経由アクセス時に挙動が変わる (chat UI は https:// 配信のため実質影響なし)
  • 既存値の上書き許可: 確認ダイアログなしで上書きする設計は UX 摩擦を減らす一方、誤操作時のリカバリは起案者責任
  • 手元 draft 形式の他経路統合: /draft 直接 POST スクリプト (/tmp/submit_adr_json.mjs 等) との draft 形式統一は本 ADR 範囲外、別途運用ルールで担保

撤退条件 (Rollback Plan)

判定指標閾値判定タイミング対応
起案者がボタンを使わない3 ヶ月後の起案 PR 履歴で 1 回も利用なし3 ヶ月後 Review After機能削除、git revert
誤ロード事故が頻発月 2 件超「無関係 JSON ロード」発生月次振り返りキー欠落チェック強化、ロード時に diff プレビュー表示 ADR を別途起案
Safari 等ブラウザ互換問題主要ブラウザでロード失敗報告障害発生時FileReader → text/plain 入力フォールバック実装

Review After:

  • 1 ヶ月後 (2026-06-14): 利用率測定、paste との併用率確認
  • 3 ヶ月後 (2026-08-14): 撤退条件 (利用ゼロ) 判定、誤ロード事故有無確認
  • 6 ヶ月後 (2026-11-14): Jr 入社後の運用感ヒアリング、draft 形式拡張要否判定

観測指標 (月次):

  • draft ロードボタン利用率: ADR 起案数のうちボタン経由投入の割合 (目標 80% 以上)
  • paste 経由投入時の事故率: clipboard 起因のミス件数 (目標 0 件)
  • 投入失敗時のリカバリ時間 (中央値): paste 時 1-2 分 → ボタン使用時 5-10 秒

完了条件 (定量メトリクス):

  1. chat.html にロードボタン実装済: load-draft-btn と draft-file の id を持つ要素が存在 (grep で 2 件以上ヒット)
  2. JSON パース + フィールド投入 JS 実装済: FileReader 利用箇所と JSON.parse 利用箇所が chat.html に存在
  3. ローカル wrangler dev で動作確認: /tmp/adrNNNN_draft.json 形式を選択 → 4 フィールド populate を目視確認
  4. 本番デプロイ後の動作確認: 実 draft で 1 回投入成功 (paste 経由なし)
  5. CI markdown-link-check PASS / TypeScript build PASS

Confirmation (準拠確認 / Fitness Function)

本セクションは ADR-0036 (Accepted 2026-05-14) で遡及追加された。ADR-0031 パターン (業界標準準拠メタデータ後付け = 誤字修正範疇) に準拠する遡及で本文の意思決定内容は不変。

  • 検証手段: 月次レビューで hidden field loaded-from-file の利用率測定 + 手動 QA
  • 実行頻度: 月次
  • 違反時の対応: 月次レビューで集計

参照 (References)

  • 関連 ADR: ADR-0019 (Decision Pipeline 基盤), ADR-0035 (本日投入時に問題実証), ADR-0036 (本日 pbcopy 上書き事故の対象)
  • 関連 PR/Issue: -(要追記、ADR-0035 Accepted 後の実装 PR で採番)
  • 外部資料:
    • 改修対象ファイル: drp/public/chat.html
    • draft 形式参照: /tmp/adrNNNN_draft.json (4 キー: author/title/context/options)
    • FileReader API (MDN)