ADR-0085: Prompt KV Lifecycle の全ノード適用完了
- 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:
なぜ実運用で問題にならないか (検証済み):
(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-0042 | Completes — 本 ADR で全ノード適用完了 |
| ADR-0056 | Confirms — temperature は loadLlmParams で既に KV 化済 |
| ADR-0071 | Confirms — 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.0 | 5 | 3 | 1 | 1 |
| #maintainable | ×2.0 | 4 | 2 | 2 | 2 |
| #reliable | ×1.0 | 4 | 2 | 3 | 4 |
| #secure | ×1.0 | 3 | 2 | 3 | 4 |
| #efficient | ×0.5 | 5 | 4 | 1 | 5 |
| 加重和 (正規化) | 0.830 | 0.470 | 0.430 | 0.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)
- 検証手段:
- tsc + smoke test (自動): 全 8 KV キーの応答が FALLBACK_PROMPT と異なることをアサート、空文字・不正 JSON・極端に短いプロンプト (< 50 chars) の誤書き込みフェイルセーフ検証 (盲点 #1, #4 反映)
- CI セマンティック差分チェック (自動): FALLBACK_PROMPT と KV 最新バージョンの差分が閾値超過時に警告 (盲点 #2 反映)
- LangSmith metadata / Telemetry DB 記録 (自動): 各 loadPrompt 呼び出し時の KV キー名・解決バージョン・KV hit / fallback フラグを記録し、「意図バージョン一致率」をダッシュボード化 (盲点 #3 反映)
- Runbook レビュー (手動): 担当者交代時に KV 更新手順・semver 採番ルール・immutable 原則強制を文書ベースで確認 (盲点 #6 反映)
- 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.mdはsocratic.tsのDA_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 で動作中)。