• Status: Accepted
  • Mode: Standard
  • Kruchten Type: Existence/Property
  • Scope: platform
  • Implementation Status: Partial (Phase 1 完了 + Phase 2 大半完了。残=KV AuditRecord 廃止 + edit diff GitHub Webhook。Phase 3 は別 ADR スポーン待ち)
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-05-27 17:05
  • 承認日時 (JST): 2026-06-21
  • Deciders: [email protected] (単独)

コンテキスト

1.1 背景 (Background)

Decision Pipeline の AuditRecord は PR #1034 で KV 永続化済であり、sessionId / author / title / triageMode / score / scoringMean / scoringStdDev / scoringSamples / consistencyVerdict/Detail / parallelReviewDetail / policyAlignmentDetail / adrBody / promptRefs / gateTimings / completedAt / durationMs を記録している。RQ-062 の 3 モデル Deep Research (Claude/OpenAI/Gemini) によって、現状の AuditRecord ではフィードバックループ構築に必要なデータが不足していることが判明した。

1.2 現状 (Current State / As-Is)

既存 AuditRecord は最終集計値のみを KV に記録しており、以下が観察される:

  1. 「各ステージの出力品質」が per-stage で記録されていない (最終集計のみ)
  2. Gate 1 盲点検出の有効性 (precision/recall) を測定するデータがない
  3. プロンプト改善の A/B 比較に必要なデータが不足
  4. 人間のフィードバック (edit diff) が全く記録されていない
  5. Post-decision outcome (ADR が後日 amended/superseded されたか) の遡及記録がない

3 モデル一致点として「per-stage diagnostic data が最大のギャップ」が指摘されており、Gemini 固有提案として「意味的エントロピー」「KBV 比率」「TelemetryRecord スキーマ」が挙がっている。

1.3 課題 (Problem)

KV はポイントルックアップ専用であり、date-range / triageMode / scoringEffort での集計クエリが構造的に不可能。前回起案時には「Phase 1 は KV、Phase 2 で D1 移行」を計画していたが、盲点 #1「KV の構造的限界を過小評価: クエリ不能データは分析基盤にならない」により、判断基準に「分析可能性」を Must で掲げながら Phase 1 で分析不能な KV に記録する自己矛盾が露呈した。フィードバックループが回らないことで Decision Pipeline の品質改善サイクル自体が成立しない。

1.4 制約・要件 (Constraints & Requirements)

  • D1 Free Tier 5GB、1 record あたり ~10KB を想定 (50 万件収容可能、ただし盲点 #6 で過小評価リスクあり、§5 参照)
  • 既存 KV AuditRecord は readonly 維持、1 年 TTL で自然消滅
  • 既存 /audit/scoring-stats API は後方互換を維持
  • D1 binding を wrangler.toml に追加する必要
  • Workers CPU time 30ms / wall time 30s の上限内に収まること (盲点 #1 参照)
  • schema_version によるスキーマ進化管理 (D1 は ALTER TABLE ADD COLUMN のみサポート)

1.5 目標 (Goals / To-Be)

AuditRecord を TelemetryRecord に拡張し、Phase 1 から D1 (SQLite) に直接書き込む。KV は既存 AuditRecord の後方互換のみ維持し、TelemetryRecord の SSoT は D1 とする。Phase 1 (Must) → Phase 2 (Should) → Phase 3 (Nice) の 3 段階で段階的に拡張する。Non-Goals: フル TelemetryRecord の一括実装、外部 observability への移行、Phase 3 の自動実装着手。

決定

AuditRecord を TelemetryRecord に拡張し、Phase 1 から D1 に直接書き込む。docs-search-worker で D1 は既にスタック内にあり、Phase 1 から D1 に書くことで (a) 即座に SQL クエリで分析可能 (date-range, triageMode, score 等)、(b) Phase 2 の KV→D1 マイグレーション (盲点 #9) が不要、(c) schema_version フィールドで将来のスキーマ拡張にも対応可能となる。Phase 1 は Must、Phase 2 は Should (商用化前)、Phase 3 は Nice (各概念の実現可能性スパイクを Phase 2 完了後に実施してから別 ADR で判断) とする。

Phase 1 (Must — 今すぐ):

  • D1 テーブル telemetry_records を新設 (schema_version='v1')
  • input context (起案者の原文、8000 トークン上限) の記録
  • blindSpotFindings (Gate 1 出力、50 件上限) の記録
  • rejectionMsg (差し戻し理由) の記録
  • scoringDetail (10 項目 x 5 点の内訳テーブル) の記録
  • crossValidationDetail (ADR-0076 Cross-Validation Gate 出力) の記録
  • pipeline config (scoringEffort, thinkingBudget, reviewEffort) の記録
  • 既存 KV AuditRecord は readonly で維持 (後方互換、1 年 TTL で自然消滅)
  • /audit/runs API で date-range, triageMode フィルタが動作すること

Phase 2 (Should — 商用化前):

  • per_criterion_variance (項目別 scoring ばらつき)
  • user feedback (accepted/edited/rejected のタグ付け)。edit diff の捕捉は GitHub Webhook 連携を別 ADR で設計してから実装 (前回盲点 #3 を反映: 捕捉アーキテクチャ未定義のまま工数見積もりしない)
  • post-decision outcome (amended/superseded/bug-caused)。Git 自動抽出には confidence_score を付与し低信頼は outcome='unverified' として分析除外 (前回盲点 #7 反映)
  • token usage per gate (コスト最適化。ただし品質指標との並列表示を必須化、前回盲点 #11 反映)
  • KV AuditRecord の廃止 (TTL 満了で自然消滅、新規書込み停止)

Phase 3 (Nice — 将来、各概念の実現可能性スパイクを Phase 2 完了後に実施してから別 ADR で判断):

  • 意味的エントロピー (N=5 推論テキストの embedding → クラスタリング)
  • KBV (Knows-But-Violates) 比率 (Gate 1 制約注入 vs body 充足率)
  • 複雑性のインフレーション (AST 深度 x トークン密度)
  • クロスモデル・セマンティック距離 (Gate 3 annotations の embedding 間距離)
  • decision-maker bias fingerprint — BIG5 連携は科学的妥当性が疑わしいため削除 (前回盲点 #5 反映)。代替として行動パターン (triageMode 採用率、Gate 1 findings 無視率) を用いる

注: Phase 3 の各概念は Gemini 固有提案であり 3 モデル一致ではない (前回盲点 #12 反映)。自動的に実装フェーズに入らず、go/no-go 判断ゲートを設ける。

判断基準 (Decision Drivers)

3.1 評価軸 (Q42 9 タグから 3-5 個選定)

#重要度 (係数)案件特有の解釈
1#suitable[Must] (×2.0)分析可能性: D1 の SQL クエリで date-range / triageMode / score 等の集計が即座に実行できること
2#maintainable[Must] (×2.0)schema_version によるスキーマ進化管理が成立し、Phase 2 のマイグレーション運用が確立されていること
3#operable[High] (×1.0)ストレージコストが D1 Free tier (5GB) 内に収まり、D1 書き込みがパイプライン本体のレイテンシ・タイムアウトを引き起こさないこと
4#flexible[High] (×1.0)既存 KV AuditRecord の後方互換 (readonly) と /audit/scoring-stats API の継続動作
5#reliable[High] (×1.0)商用化スケーラビリティ: D1 が本番対応済サービスであること (リードレプリカ GA 状況は要確認、盲点 #8 参照)

K.O. criterion: Must 軸 (#suitable, #maintainable) の score < 3 は不採用。

3.2 評価軸 × 案スコア表

係数採択案 (A: Phase 1 から D1)案 B (KV→D1 移行)案 C (フル一括)案 D (現状維持)案 E (外部 observability)
#suitable (分析可能性)×2.051505
#maintainable×2.042232
#operable×1.033252
#flexible (後方互換)×1.044353
#reliable (スケール)×1.043324
加重和 (正規化)0.8000.4400.5800.5000.620
K.O. 通過 (Must ≥3)❌ (#suitable=1)❌ (#maintainable=2)❌ (#suitable=0)❌ (#maintainable=2)

加重和満点: (5+5+5+5+5) × 重み = (10+10+5+5+5) = 35。正規化分母 35、係数合計 7。

検討した代替案 (Alternatives Considered)

  • 案 A (採用): Phase 1 から D1 に直接書込み (段階的拡張 Phase 1-3) — 分析可能性を Phase 1 から担保。
  • 案 B (却下): KV → Phase 2 で D1 移行 — 却下理由: Phase 1 の分析可能性が空白になる矛盾 (盲点 #1)。Must 軸 #suitable を Phase 1 で満たせず K.O.。
  • 案 C (却下): フル TelemetryRecord を一括実装 — 却下理由: 未検証の概念 (意味的エントロピー、KBV、embedding 格納戦略) を含むリスク。Phase 3 概念の実現可能性スパイクが未実施で #maintainable K.O.。
  • 案 D (却下): 現状維持 — 却下理由: フィードバックループ構築不可。#suitable で K.O.。
  • 案 E (却下): 外部 observability (Langfuse/Arize) — 却下理由: Workers 統合コスト大、schema 制御権をベンダーに渡すため #maintainable で K.O.。

影響 (Consequences)

5.1 正の影響 (Good)

  • Phase 1 完了時点で SQL による date-range / triageMode / score 集計クエリが可能になり、フィードバックループの第一歩が確立される。
  • KV→D1 の二段階移行を回避し、Phase 2 でのマイグレーション工数 (前回盲点 #9) が不要。
  • schema_version フィールドにより将来のスキーマ拡張に対応可能。
  • 既存 KV AuditRecord を readonly で維持することで /audit/scoring-stats API の後方互換が保たれる。
  • docs-search-worker で D1 は既にスタック内にあるため新規依存追加コストが低い。

5.2 負の影響 (Bad)

  • D1 書き込みレイテンシリスク (盲点 #1, critical): D1 は SQLite ベースで WAL モードでも単一ライター制約があり、Workers HTTP 経由の同期書き込みは P99 で 50-200ms 以上の追加レイテンシが報告されている。パイプライン完了ごとの同期書き込みは Workers CPU time 30ms / wall time 30s の上限を圧迫し、商用化フェーズの並列セッション増加時に SQLITE_BUSY/LOCKED のリトライループでパイプライン全体が詰まる可能性がある。
  • D1 Free Tier 5GB 上限の静かな到達 (盲点 #2, critical): Cloudflare D1 は使用量超過時に書き込みを静かに拒否しエラーがパイプライン側に伝播しない可能性があり、単独ステークホルダー運用では定期確認漏れで数週間分のテレメトリ欠損が発生し得る。
  • input context への個人情報・機密情報の無期限永続化 (盲点 #3, high): input context (8000 トークン) には顧客名・内部システム仕様・未公開戦略情報が含まれ得るが、KV の 1 年 TTL と異なり D1 には明示的 TTL がなくデータが無期限に残る。GDPR/個人情報保護法の削除権対応手段が現設計に含まれていない。
  • Measurement Theater リスク (盲点 #4, high): Phase 1-3 の実装タスクはすべてデータ収集基盤であり、収集したデータを使った改善アクションは ADR スコープ外。撤退条件の「改善アクション 1 件」は閾値が低く形骸化しやすい。
  • blindSpotFindings 50 件上限による分析バイアス (盲点 #5, high): 切り捨て発生時に真陽性が記録されず、切り捨て前総数を記録するフィールドが現スキーマに無いため 50 件上限がバインディングになっているケースを後から識別できない。「複雑な ADR ほど Gate 1 精度が高い」という誤った結論を導く構造的バイアスが発生し得る。
  • input context 8000 トークン上限の根拠未定義と分析汚染 (盲点 #6, high): 8000 トークン上限の根拠 (モデルのコンテキスト長 / D1 行サイズ制限 / コスト) が未説明。切り捨てが発生したレコードでは「記録された input」と「実際に処理された input」が乖離し、プロンプト改善 A/B 比較に使用すると分析汚染になる。1 レコード最大 32KB になり得るため「10KB/record」試算が過小評価。
  • N=1 問題と Phase 3 統計的無効性 (盲点 #7, high): 単独ステークホルダー前提では Phase 3 の triageMode 採用率・Gate 1 findings 無視率の「パターン」検出に必要なサンプル数が確保できない可能性が高い。
  • schema_version 進化管理と Phase 3 データ型の実現可能性 (盲点 #8, medium): D1 は ALTER TABLE ADD COLUMN のみサポート。Phase 3 の embedding (float[]) は SQLite ネイティブ型で表現できず JSON Text/Blob 格納となり SQL 集計が事実上不可能になる自己矛盾。D1 リードレプリカは 2025 年時点で GA 未確認。

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

  • KV AuditRecord は readonly で維持しつつ自然消滅 (1 年 TTL) を待つため、Phase 1 期間中は KV と D1 の二重管理状態になる。
  • Phase 3 の各概念は Gemini 固有提案であり 3 モデル一致ではないため、go/no-go ゲートで除外される可能性がある。
  • D1 リードレプリカの GA 状況によっては「商用化スケーラビリティ」の根拠を再評価する必要がある。

撤退条件 (Rollback Plan)

  • D1 ストレージが 4GB (80%) を超えた場合 → 古いレコードのアーカイブ or 有料プラン移行を検討。
  • Phase 1 完了から 90 日以内に、記録データを用いた具体的な改善アクション (プロンプト変更 PR、gate 設定変更) が 1 件も実施されなかった場合 → Phase 2 を凍結し Phase 1 フィールドを readonly に降格 (前回盲点 #4/#8 反映: 定量的・検証可能な撤退条件)。撤退条件の「改善アクション」定義は盲点 #4 反映で「テレメトリデータから導出した仮説に基づき、測定可能な指標の変化を事前予測した上で実施した変更」に厳格化する(要追記: 具体運用ルール)。
  • D1 書き込み P99 レイテンシがパイプライン全体の wall time に対して支配的になり Workers タイムアウトが発生する場合 → waitUntil 非同期化または Cloudflare Queue 経由への切替 (盲点 #1 推奨対応、要追記: 非同期化時の書き込みロスト率許容値)。
  • Review After: 2026-11-27 (6 ヶ月後)

Confirmation (準拠確認 / Fitness Function)

  • 検証手段:
    1. drp の CI に D1 スキーマ検証テスト (telemetry_records テーブル存在、schema_version='v1' カラム存在、必須カラム input_context / blind_spot_findings / rejection_msg / scoring_detail / cross_validation_detail / pipeline_config) を追加。
    2. /audit/runs?from=YYYY-MM-DD&to=YYYY-MM-DD&mode=Standard の E2E テストで date-range + triageMode フィルタの動作確認。
    3. /audit/scoring-stats API の後方互換 E2E テスト (D1 ベース移行後も既存レスポンス形状を維持)。
    4. Cloudflare Workers scheduled trigger (cron) による D1 使用量取得 + 80% 超過時の Discord/Slack webhook 通知 (盲点 #2 対応、Phase 1 完了条件に追加)。
    5. persistence.ts での D1 書き込み失敗キャッチ + 専用エラーログ記録 (欠損検出、盲点 #2 対応)。
    6. P95/P99 書き込みレイテンシの計測ログ (盲点 #1 対応、Phase 1 完了条件に追加)。
  • 実行頻度: CI は PR ごと、scheduled trigger は日次、レイテンシ計測は全パイプライン実行ごとに記録し週次でレビュー。
  • 違反時の対応: スキーマ検証失敗 → PR ブロック。使用量 80% 超 → 通知受信後 7 日以内にアーカイブ判断。書き込み失敗ログが連続 5 件 → Phase 1 を一時停止し原因調査。P99 レイテンシが Workers wall time の 30% を超えた場合 → 撤退条件発動 (waitUntil/Queue 化検討)。

参照 (References)

  • 関連 ADR:
    • ADR-0056 (observability KV submission): Supersedes — KV AuditRecord を D1 TelemetryRecord に移行
    • ADR-0019 (Decision Pipeline): Confirms — Pipeline 強化の一環
    • ADR-0071 (Gate 1 盲点検出エンジン): Confirms — blindSpotFindings の永続化
    • ADR-0076 (Cross-Validation Gate): Confirms — crossValidationDetail の永続化
  • 関連 PR/Issue: PR #1034 (既存 AuditRecord KV 永続化)
  • 外部資料: RQ-062 (3 モデル Deep Research: Claude/OpenAI/Gemini)
  • 影響ファイル:
    • drp/src/audit/types.ts — TelemetryRecord 型定義 + D1 スキーマ
    • drp/src/audit/persistence.ts — D1 書込みロジック
    • drp/src/queues/pipeline_consumer.ts — 追加フィールドの抽出
    • drp/src/index.ts/audit/runs API を D1 クエリに移行
    • drp/wrangler.toml — D1 binding 追加
  • コスト試算: Phase 1 実装 2-3 日 / Phase 2 実装 3-5 日 (GitHub Webhook 連携別 ADR 設計含む) / Phase 3 実装 5-10 日 + 各概念の実現可能性スパイク 1-2 日/概念