• Status: Accepted
  • Mode: Standard
  • Kruchten Type: Property/Executive
  • Scope: platform
  • Implementation Status: Done
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-05-28 06:29
  • 承認日時 (JST): 2026-06-21
  • Deciders: [email protected] (単独)

コンテキスト

1.1 背景

ADR-0042 の Prompt KV Lifecycle パターンは body_generation.ts でのみ実装済。他 6 ノードは SYSTEM_PROMPT が hardcoded されており、ADR-0042 の Implementation Status: Done という記録と実態が乖離している。

1.2 現状

loadPrompt は body-generation のみで呼び出されている。他 6 ノードは loadLlmParams のみを呼び出し、プロンプト本体はコード内定数 (SYSTEM_PROMPT) に固定されている。

1.3 課題

(1) プロンプト改善にコード変更 + deploy が必要 (Git commit/push/CI の ~5min が省略可能)。 (2) ADR-0042 の Implementation Status: Done だが実態は部分的であり、ADR の正確性が損なわれている。

1.4 制約・要件

  • 既存 loadPrompt + fallback パターンをそのまま適用する
  • SYSTEM_PROMPT → FALLBACK_PROMPT にリネームする
  • parallel_review はスコープ外 (動的テンプレートのため)
  • KV キー: 8 キー
  • KV 書き込み権限は最小化し、プロンプト更新を PR + 承認必須のデプロイスクリプト経由に限定する (盲点 #5 反映、要追記: 具体的な IAM/トークン設計)

1.5 KV Eventual Consistency への対処 (#operable の根拠)

問題の構造: Active Pointer パターンは pointer キー (bizlp:prompts::active → '1.0.0') と body キー (bizlp:prompts::1.0.0 → prompt text) の 2 段階 KV 読み取り。Cloudflare KV は eventually consistent のため、pointer 更新後に body が古い PoP に残るウィンドウが理論上存在する。

なぜ実運用で問題にならないか (検証済み): (1) Pipeline は Queue consumer で直列実行 (max_batch_size=1)。1 run あたり 5min。全ノードの loadPrompt は同一 run 内の同一 colo で実行されるため、KV の read は同一 PoP の同一キャッシュから返される。run をまたぐ不整合は発生しうるが、次の run では伝播済み (Cloudflare docs: 通常 60s 以内)。 (2) body キーは immutable (append-only semver)。pointer を '1.0.0' → '1.1.0' に切り替える際、body キー '1.0.0' は削除せず残す。したがって pointer が古い PoP で '1.0.0' を返しても、body '1.0.0' は常に存在し、有効なプロンプトが返る。不整合は「新バージョンが使われない」(安全側) であり「無効なプロンプトが使われる」(危険側) ではない。 (3) 実環境テスト結果 (2026-05-28 実施): body_generation.ts で既に本パターンが稼働中。2026-04-20 の ADR-0042 実装以降、40 runs で pointer/body 不整合によるエラーは 0 件 (LangSmith trace + Telemetry DB で検証)。 (4) 更新頻度の希少性: プロンプト更新は月 1-2 回。Pipeline 実行は月 5-15 回。同時発生確率: (更新時間 60s / 月) × (Pipeline 実行時間 75min / 月) / (月 43200min) ≈ 0.001 (0.1%)。

1.6 コスト試算

項目工数金銭
実装 (6 ノード × loadPrompt)3h$0
テスト (tsc + smoke)1h$0
KV 初期アップロード0.5h$0
Runbook 更新0.5h$0
合計5h$0
KV 読み取り増 (120 reads/月)$0 (free tier)

なお Runbook 更新 0.5h は盲点 #6 で過小評価の指摘があり、KV 更新コマンド例・semver 採番ルール・immutable 原則の強制方法を含める場合は再評価が必要 (要追記)。

1.7 ロールバック戦略

  • ノード単位: KV active pointer 削除 → FALLBACK_PROMPT にフォールバック
  • 全体: 全 8 キーの active pointer 削除 (one-liner)
  • 判断基準: 3 runs 平均で Gate 4 スコア 5 点低下 → ノード単位。通過率 80%→60% → 全体
  • 即時トリガー (盲点 #4 反映): 1 run 内でのプロンプト取得エラー率 > 0、または LLM 出力のパース失敗が発生 → 即時ロールバック
  • 撤退条件: Review After 2026-08-28 時点で「KV 更新回数 ≥ 2 かつ Gate 4 スコア改善が確認できること」(盲点 #9 反映、Go/No-Go 二値判定)。未達なら撤退作業 (推定 3-4h: 8 キー KV 削除 + FALLBACK_PROMPT 復元 + テスト + deploy) を実施

Review After: 2026-08-28 (3 ヶ月後) / 2026-11-28 (6 ヶ月後)

1.8 過去 ADR との関係

ADR関係
ADR-0042Completes — 本 ADR で全ノード適用完了
ADR-0056Confirms — temperature は loadLlmParams で既に KV 化済
ADR-0071Confirms — socratic DA/PM/Judge のプロンプトも KV 化

1.9 ステークホルダー

  • 運用者 (代表取締役): プロンプト改善が KV 更新のみで可能
  • 将来 Jr: Runbook に従いプロンプト更新可能

決定

ADR-0042 で確立した Prompt KV Lifecycle パターン (loadPrompt + FALLBACK_PROMPT) を、parallel_review を除く全 6 ノードに適用する。8 KV キーを as const 定数で型安全に一元管理し、プロンプト更新を PR + 承認必須のデプロイスクリプト経由に限定する。ロールバックは active pointer 削除によるフォールバック + 即時エラートリガーの 2 段構えとする。

判断基準 (Decision Drivers)

3.1 評価軸

#重要度 (係数)案件特有の解釈
1#operable[Must] (×2.0)プロンプト改善が deploy なしで可能。Eventual Consistency が安全側に倒れる
2#maintainable[Must] (×2.0)ADR-0042 の実態乖離を解消。Runbook + 型安全定数で属人化を排除
3#reliable[High] (×1.0)誤書き込み・silent degradation の即時検出。フォールバック先の鮮度維持
4#secure[High] (×1.0)KV 書き込み権限の最小化、変更承認フローによるコンプライアンス維持
5#efficient[Medium] (×0.5)工数 5h で完了、KV 読み取り増は free tier 内

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

3.2 評価軸 × 案スコア表

係数案A (採択)案B (1 JSON)案C (env)案D (現状維持)
#operable×2.05311
#maintainable×2.04222
#reliable×1.04234
#secure×1.03234
#efficient×0.55415
加重和 (正規化)0.8300.4700.4300.560
K.O. 通過 (Must ≥3)

検討した代替案 (Alternatives Considered)

  • 案 A【採用】: 各ノードで loadPrompt を呼び出す。8 KV キー。工数 5h。金銭 $0。body キー immutable + Pipeline 直列実行で安全側不整合のみ (§1.5 検証済み: 40 runs で 0 件)。
  • 案 B: 全プロンプト 1 JSON — 不採用: blast radius 拡大 (1 キーの誤更新で全ノード影響、#maintainable / #reliable で低スコア)。
  • 案 C: env 変数 — 不採用: Workers にファイルシステムなし、deploy 必須となり #operable Must を満たさない。
  • 案 D: 現状維持 — 不採用: ADR-0042 未完了が放置、#operable / #maintainable Must を満たさない。

影響 (Consequences)

5.1 正の影響 (Good)

  • プロンプト改善が KV 更新のみで可能となり、deploy 5min が省略される (月 1-2 回 × 12 ヶ月 = 年 1-2h 削減)
  • ADR-0042 の Implementation Status: Done と実態が一致、ADR の信頼性が回復
  • 8 キーを as const 型安全定数で一元管理することで、KV キー typo の silent wrong-prompt 参照リスクを排除 (盲点 #1 反映)
  • 各 loadPrompt 呼び出し時に解決された KV キー名とバージョンを LangSmith metadata / Telemetry DB に記録することで、障害原因追跡が可能になる (盲点 #3 反映)
  • ADR-0056 (temperature KV 化) / ADR-0071 (socratic プロンプト KV 化) との一貫性が確立

5.2 負の影響 (Bad)

  • FALLBACK_PROMPT の陳腐化リスク (盲点 #2): KV 運用が定着すると FALLBACK_PROMPT が更新されなくなり、6 ヶ月後の障害時に古い・非推奨プロンプトが全 6 ノードで一斉適用される可能性。緩和策: CI に FALLBACK_PROMPT と KV 最新バージョンのセマンティック差分チェックを組み込む。各ノードの実行ログに「KV hit / fallback」フラグを必ず出力し、Runbook に確認コマンドを明記する
  • silent degradation 検出困難性 (盲点 #3): 「エラー 0 件」指標は旧バージョン使用継続を検出できないため、正当化指標を「意図バージョン一致率」に再定義する必要がある
  • 遅延検出による劣化期間 (盲点 #4): 「3 runs 平均 Gate 4 スコア 5 点低下」基準では Pipeline 月 5-15 回実行のため検出に 2-3 週間かかる。即時トリガー (プロンプト取得エラー率 > 0、パース失敗) を §1.7 に追加して対処
  • KV 更新権限の民主化リスク (盲点 #5): Git 差分レビューを迂回でき、法的免責事項・個人情報取扱い指示・ブランドトーン変更が承認なしに本番適用される懸念。緩和策: KV 書き込みを PR + 承認必須のデプロイスクリプト経由に限定 (§1.4 要件)
  • Runbook 工数 0.5h の過小評価 (盲点 #6): 完全なコマンド例・semver 採番ルール・immutable 原則の強制方法を含める場合は工数再評価が必要 (要追記)
  • タイトル「全ノード適用完了」と parallel_review 除外の乖離 (盲点 #7): Jr が parallel_review の動的テンプレート部分を壊すリスク。緩和策: タイトルを「全ノード適用完了 (parallel_review を除く)」へ修正検討、Runbook で parallel_review 更新手順を分離記載
  • 単一ノード実績の他ノードへの一般化 (盲点 #8): §1.5 の根拠は body_generation.ts (n=1) のみ。Judge ノードはスコアリングロジック直結のため非線形影響の可能性。緩和策: Judge 等高影響ノードは A/B shadow run を検討

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

  • KV 読み取り増 (120 reads/月) は free tier 内で金銭影響なし
  • parallel_review の静的部分 KV 化可否は別途 spike で調査 Issue を起票 (盲点 #7 反映)
  • 撤退作業 (推定 3-4h) は導入コスト 5h と同等規模であり、撤退判断は Review After で Go/No-Go の二値で確定させる (盲点 #9 反映)
  • Eventual Consistency による安全側不整合 (新バージョンが反映されるまで最大 60s) は許容範囲

撤退条件 (Rollback Plan)

  • 即時ロールバック (盲点 #4): 1 run 内でのプロンプト取得エラー率 > 0、または LLM 出力のパース失敗発生時 → 該当ノードの active pointer 削除
  • 段階的ロールバック: 3 runs 平均で Gate 4 スコア 5 点低下 → ノード単位で active pointer 削除。通過率 80%→60% → 全体ロールバック (8 キーの active pointer 一括削除)
  • 撤退判断 (Review After 2026-08-28): 「KV 更新回数 ≥ 2 かつ Gate 4 スコア改善が確認できること」を満たさない場合 No-Go、撤退作業 (8 キー KV 削除 + FALLBACK_PROMPT 復元 + テスト + deploy、推定 3-4h) を実施
  • 撤退手順:
対象具体手順影響範囲
ノード単位wrangler kv:key delete --binding=PROMPTS "bizlp:prompts:<id>:active"該当 1 ノードが FALLBACK_PROMPT にフォールバック
全体全 8 キーの active pointer 削除 one-liner 実行全ノードが FALLBACK_PROMPT にフォールバック
完全撤退KV キー全削除 + loadPrompt 呼び出し除去 + SYSTEM_PROMPT 復元 + tsc + smoke + deploy全ノードが ADR-0042 適用前の状態に戻る

Confirmation (準拠確認 / Fitness Function)

  • 検証手段:
    1. tsc + smoke test (自動): 全 8 KV キーの応答が FALLBACK_PROMPT と異なることをアサート、空文字・不正 JSON・極端に短いプロンプト (< 50 chars) の誤書き込みフェイルセーフ検証 (盲点 #1, #4 反映)
    2. CI セマンティック差分チェック (自動): FALLBACK_PROMPT と KV 最新バージョンの差分が閾値超過時に警告 (盲点 #2 反映)
    3. LangSmith metadata / Telemetry DB 記録 (自動): 各 loadPrompt 呼び出し時の KV キー名・解決バージョン・KV hit / fallback フラグを記録し、「意図バージョン一致率」をダッシュボード化 (盲点 #3 反映)
    4. Runbook レビュー (手動): 担当者交代時に KV 更新手順・semver 採番ルール・immutable 原則強制を文書ベースで確認 (盲点 #6 反映)
    5. scripts/adr-lint.mjs: ADR-0042 と本 ADR の Implementation Status 整合性を検証
  • 実行頻度:
    • tsc + smoke / CI 差分チェック: PR ごと + main push ごと
    • メタデータ記録 / ダッシュボード: Pipeline run ごと (リアルタイム)
    • Runbook レビュー: 四半期ごと + 担当者交代時
    • adr-lint: PR ごと
  • 違反時の対応:
    • smoke test / CI 失敗 → PR ブロック、修正必須
    • 意図バージョン一致率低下 → §1.7 の即時ロールバックトリガー発火
    • Runbook 陳腐化発覚 → 工数再見積もり + 即時更新 Issue 起票

参照 (References)

  • 関連 ADR:
    • ADR-0042 (Completes — Prompt KV Lifecycle パターンの全ノード適用完了)
    • ADR-0056 (Confirms — temperature loadLlmParams KV 化)
    • ADR-0071 (Confirms — socratic DA/PM/Judge プロンプト KV 化)
  • 関連 PR/Issue: - (要追記)
  • 外部資料: Cloudflare KV Eventual Consistency docs (通常 60s 以内伝播)

Notes

  • 2026-05-29 (PR #1129): gate1-da の prompt files (prompts/production/gate1-da/{prompt.md, prompt.meta.yaml, output_schema.json}) を canonical 化。prompt.mdsocratic.tsDA_FALLBACK_PROMPT を canonical 化したもの、meta.yaml は ADR-0071 仕様 (claude-sonnet / T=0.95)。これにより prompt-meta-lint の MISSING が解消。KV active pointer は未設定で FALLBACK_PROMPT 動作のまま (必要に応じて将来 KV push)。gate1-pm / gate1-judge の prompt files 整備は未着手 (loadPrompt fallback で動作中)。