• Status: Accepted
  • Mode: Standard
  • Kruchten Type: Existence/Property
  • Scope: platform
  • Implementation Status: Done (Phase A: PR #1209、Phase B: PR #1212、Phase C: PR #1217 + remote D1 migration applied 2026-06-01。follow-ups: PR #1210/#1211/#1214/#1216)
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-06-01 00:12
  • 承認日時 (JST): 2026-06-01 09:45 (Pipeline 通常 flow Standard 49/50 通過 + Cross-Validation Must 軸毀損なし + Phase A/B/C 全 merge + e2e 整合率 100% 実証、PR #1207/1209/1212/1217)
  • Deciders: [email protected] (単独)

1. コンテキスト

1.1 背景

Decision Pipelinetriage 段階で 2 種類の独立した障害が観測されている。両方とも needsAdr シグナルの意味論過負荷と session schema 拡張不足に根ざす。本 ADR は意味論を直交フィールド追加で明確化する。

2026-05-31 朝、needsAdr=true + rejected=true で pre-gate block を表現する案 A で v2 を起案、Pipeline 採点 48/50 通過するも Cross-Validation で #reliable Must 軸を critical 2 件が毀損 (外部 consumer 破壊リスク + 下流ノード防御漏れ) で差し戻し。本 v3 は方針転換し、後方互換を保つ案 B (triageRejectKind フィールド直交追加) を採択する。

1.2 現状 (As-Is)

障害 1: 「[Standard/Critical] バッジ + ADR 対象外」の矛盾表示 (sub 申送り PR #1200 / 後続 #1205 post-mortem で報告)

  • src/nodes/triage.tsneedsAdr=false reject 経路は現状 3 つ:
    1. 真の「ADR 不要」判定 (line 154、is_adr_worthy=false、triageMode=null): typo 修正など
    2. ADR-0088 cost-missing 起案前ゲート差し戻し (line 173、is_adr_worthy=true、triageMode 保持): PR #1155 で導入
    3. ADR-0091 3 ルール起案前ゲート差し戻し (line 198、同上、rejection_reason_code は placeholder-remaining/rollback-quantity-missing/confirmation-kpi-missing のいずれか): PR #1196 で導入 (本セッション)
  • UI (public/chat.html showResult 3095-3102) は 3 経路を一律「ADR 対象外 / 通常の PR 概要欄に記載」とハードコード表示、rejectionMsg(本当の理由) を出さない
  • buildTriageBanner (3050-3057) が triageMode バッジを無条件描画 → 起案前ゲート差し戻し × mode=Critical/Standard の run が「[Critical] バッジ + ADR 対象外」と矛盾表示
  • 定量実証: GET /audit/runs (2026-05-30) で needs_adr=false / triage_mode=Standard / rejection_reason_code=confirmation-kpi-missing の run を複数確認。stop-button 草案で「[critical] + ADR 対象外」を起案者が観測 (PR #1200)
  • ADR-0091 Phase B 実装 (PR #1196、本セッション) で reject 経路を 1 → 4 に拡大、UI 矛盾の発生確率が増大

障害 2: triage 二重実行 + 結果揺れ (sub 申送り PR #1204 で追補)

  • triage 判定コードは共通 (triageNode / buildPreGraph) だが、入口ワークフローが異なる:
    • web UI /chat/start (src/index.ts:68-156): ハンドラ内で preGraph.invoke を同期実行 (line 95)。needsAdr=true で async=true なら session を作成し enqueue するが、session に triage 結果を保存していない
    • CI /runs (src/index.ts:294-360): ハンドラは即 enqueue、triage は queue consumer 内 (pipeline_consumer.ts:142) で実行
  • 結果: web UI async 経路で 1 起案あたり triage が 2 回実行される。triage.ts:111if (state.needsAdr != null) return {} スキップは session に needsAdr が保存されてないため不発
  • LLM temperature=0.2 で 2 回判定が確率的に割れる → ADR-0073 (Gate0 triage seed 再現性) の前提が崩れる

1.3 課題

両障害の共通根: (i) needsAdr フラグが「ADR worthiness」と「pre-gate pass」の二重用途、(ii) /chat/start ハンドラが triage 結果を session に保存しない。

1.4 制約・要件

  • 外部 consumer (audit dashboard, GitHub Action exporter, 4 週レビュー集計) を破壊しない (Cross-Validation v2 critical #1)
  • 下流ノード (body_generation 等) に防御コード追加を強制しない (Cross-Validation v2 critical #2)
  • D1 migration は NULL 許容カラム追加のみ (既存 migrate-v2/v3/v4 と同型)
  • 個人開発、直接金銭支出 0 円
  • ADR-0088 の rejection_reason_code セマンティクスを維持

1.5 目標 (To-Be)

needsAdr=false のセマンティクスを完全維持しつつ、triageRejectKind 直交フィールドで「ADR worthiness」と「pre-gate pass」を判別可能化。session に triage 結果を保存し consumer の二重実行を解消。Non-Goals: web UI と CI の入口統一 (案 E 却下)、needsAdr の意味論完全分離 (Phase D として backlog 化)。

2. 決定

state.tstriageRejectKind: 'not-adr-worthy' | 'pre-gate-block' | null直交フィールドとして追加する。needsAdr=false の既存セマンティクスは完全維持し、kind フィールドで判別する。session schema にも triage 結果を保存して consumer の preGraph 再実行を skip する。UI / audit_runs / consumer は 3 Phase で段階移行 (Phase A: UI 修正 / Phase B: session 保存 / Phase C: kind フィールド + audit migration)。Phase A→C の移行期間に上限 2 週を設け、中間状態の長期固定化を防ぐ。

3. 判断基準 (Decision Drivers)

3.1 評価軸

#重要度 (係数)案件特有の解釈
1#reliable[Must] (×2.0)triage 判定の安定性、ADR-0073 前提との整合、外部 consumer (audit dashboard, GitHub Action exporter) への破壊なし、下流ノードの早期防御維持
2#maintainable[High] (×1.0)フラグ意味論の明確化、needsAdr の二重用途を kind フィールドで判別可能化
3#operable[High] (×1.0)UI 矛盾表示の解消、外部 consumer 影響ゼロ (needs_adr / rejection_reason_code カラムの意味は v2/v3 で同一)、4 週レビュー集計の継続性
4#efficient[Medium] (×0.5)triage 二重実行 (LLM call 1 件) の削減効果 (~$0.02-0.05/起案、年 ~$4-10)
5#flexible[Medium] (×0.5)将来別の rejection 経路追加時の拡張性 (kind フィールド値域拡張で対応可、ただし値域変更時は別途 ADR 起案を必須とするガバナンスルール)

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

3.2 評価軸 × 案スコア表

係数採択案 B案 A (v2)案 C (UI のみ)案 D (Gate4 移動)案 E (入口統一)案 F (prefix 命名)
#reliable (×2.0)2.0523233
#maintainable (×1.0)1.0452343
#operable (×1.0)1.0523224
#efficient (×0.5)0.5442134
#flexible (×0.5)0.5442332
加重和 (正規化)0.9200.5800.5200.4200.6000.620
K.O. 通過 (Must ≥3)

加重和は K.O. 通過候補 (B / C / E / F) のタイブレーク用。案 B が 0.920 で最高。

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

  • 採択案 (B: triageRejectKind フィールド直交追加 + session 保存): needsAdr=false セマンティクス維持、kind フィールドで判別。Phase A (UI 修正) + Phase B (session 保存 + consumer skip) + Phase C (kind + audit migration) の 3 Phase 独立 PR で 1 歩ずつ進める。外部 consumer 後方互換、下流ノード変更不要、D1 migration は NULL 許容カラム追加のみ。
  • 案 A (却下、v2 採択案): triage の return shape を再設計し、起案前ゲート差し戻しを needsAdr=true + rejected=true + rejectionReasonCode で表現。却下理由 (Cross-Validation v2 指摘 + コードベース調査で確認): (i) audit/persistence.ts:236-258getChurnSummary.by_mode_and_reasonneeds_adr=false && rejected=1 && rejection_reason_code で集計しており案 A 採択で意味論変更、既存 4 週レビュー集計 (~28 records) が遡及的に誤解釈されダッシュボード/GitHub Action exporter は無声破綻、(ii) pipeline_consumer.ts:150if (!pre.needsAdr) early-return が body_generation 等への流入を防いでいるが、案 A は needsAdr=true で流すため各下流ノードに防御コード (assertNotRejected lint 等) を追加する必要、(iii) score 5 を正当化する「下流が新セマンティクスを整合的に扱える」前提が崩れる。
  • 案 C (UI 側修正のみ、cosmetic patch): chat.html の showResult で rejectionReasonCode あり時に「起案前ゲート差し戻し」表示に分岐。却下理由: triage 二重実行 (障害 2) を解消しない、ADR-0073 揺れ問題が残る、audit_runs の意味論曖昧さも残る。応急処置として価値はあるが本 ADR は 3 障害 (A + B + 再発防止) の完全解消を Phase 分割で目指す (Phase A は実質的に案 C の範囲をカバー)。
  • 案 D (起案前ゲートを Gate 4 後に移動): triage で止めず通常 Pipeline を流し Gate 4 で reject。却下理由: ADR-0088 §決定で「起案前ゲートは 3 層機構の最上層」と明示、Gate 4 reject は LLM 採点 1 回 ~$0.5 を浪費。ADR-0091 でも同じ 3 層設計を継承しており本案は構造的後退。
  • 案 E (web UI 入口を /runs に一本化): チャット UI も KV draft 経由で起動。却下理由: chat UI の即時応答性 (ADR-0066) が失われる、async 化の追加コスト、retroactive のためにわざわざ KV へ書く手間が UX を損なう。入口差は維持し doc 明文化が UX 適切。
  • 案 F (rejection_reason_codepre-gate: prefix を付与する命名規則): 現在の値 (cost-missing 等) に pre-gate: prefix を付け、UI 側は rejectionReasonCode?.startsWith('pre-gate:') で判別。スキーマ変更ゼロ、migration 不要。却下理由: (i) 既存レコード ~28 件と非互換、backfill SQL が必要、(ii) 外部 consumer (audit exporter / dashboard) が文字列完全一致でフィルタしている場合に無声破綻、(iii) 値域拡張の柔軟性が prefix 階層に依存し、将来 pre-gate:cost:variant-a のような階層膨張を招く、(iv) 「意味論の分離」目的に対し値とカテゴリを 1 カラムに混載する設計は反する。加重和では 0.620 で案 B (0.920) に劣る。

5. 影響 (Consequences)

5.1 正の影響 (Good)

  • UI 矛盾表示の根本解消 (Phase A で即時、Phase C で構造的に完成)
  • triage 二重実行コスト削減 (1 起案 ~$0.02-0.05 LLM call、年 ~$4-10)
  • ADR-0073 (Gate0 triage seed 再現性) 前提の回復 (Phase B で 1 起案 1 回固定)
  • audit_runs telemetry の意味論明確化 (kind と reason_code の整合率を観測可能 KPI 化、Phase C)
  • 直接金銭支出 0 円 (個人開発)

5.2 負の影響 (Bad)

外部 consumer 後方互換性 (Cross-Validation v2 critical #1 への直接対応): 本 ADR は案 B 採択により、needs_adr / rejected / rejection_reason_code カラムの意味を v2/v3 で完全同一に維持。triage_reject_kind は新規 NULL 許容カラムとして直交追加、既存 getChurnSummary (audit/persistence.ts:170by_mode_and_reason 集計含む)、GitHub Action audit exporter、4 週レビュー集計の何れも無改修動作想定。ただし盲点 #10 指摘により、exporter が SELECT * または動的スキーマ列挙を使用しているか Phase C 実装前にソースコード調査必須、使用していれば exporter 側に明示カラムリストを指定する。

下流ノード防御 (Cross-Validation v2 critical #2 への直接対応): 案 B では needsAdr=false を維持するため、pipeline_consumer.ts:150if (!pre.needsAdr) early-return が現状の防御として機能を継続。body_generation / scoring 等の下流ノードに防御コードを追加する必要はなく、triageRejectKind は補助情報でしかなくロジックパスを変えない。pipeline_consumer.ts:150 の分岐は維持され、UI 表示でのみ kind を読む設計。

DO storage 制限・read-modify-write 競合 (Cross-Validation v2 high + 盲点 #7 への対応): PipelineSessionState.triageResult は既存 data key 配下に 200 bytes 程度で格納、ADR-0089 の PARTIAL_GATE_MAX_BYTES (8KB/gate) には抵触しない。盲点 #7 への対処: web UI async 経路で「session 作成 + triageResult 保存」を単一アトミック PUT にまとめる (session 作成時点で triageResult を初期値として含める)。storage.putallowConcurrency: false を併用し、PUT 完了前に consumer が読み込むレース条件を排除。Phase B e2e テストに並行リクエストシナリオ (リロード / 二重送信) を追加し skipped=false が 2 回出ないことを確認。

migrate-v5 D1 レプリカ遅延 (盲点 #8 への対応): Cloudflare D1 の ALTER TABLE 適用後、レプリカ伝播の数十秒〜数分間で旧スキーマキャッシュを持つ worker が table has X columns but Y values were supplied を返す可能性。対処: migration と application code (kind 書込) を別デプロイに分離、migration apply 後 5 分間の観察ウィンドウで D1 worker ログを確認。telemetry 書込は try-catch で event=triage_kind_write_failed をログに出し、整合率 KPI の分母から除外せず 0 として計上 (失敗を隠さない設計)。

Phase A 中間状態の暗黙判別崩壊 (盲点 #1 + #6 への対応): Phase A は rejectionReasonCode の有無による暗黙判別 (cosmetic patch、案 C の範囲) を実施するが、新 reason_code 追加で再崩壊するリスク。対処: (i) Phase A merge から Phase C を最大 2 週以内に強制完了するルールを撤退条件 #6 に追加、(ii) 中間期間中の新規 rejection_reason_code 追加を ADR レビューで禁止、(iii) Phase A PR に rejectionReasonCode 配線漏れを検知する統合テスト (undefined 時の表示分岐テスト) を必須化。

Phase B session 保存の failure mode (盲点 #5 への対応): /chat/startneedsAdr=false 経路 (起案前ゲート差し戻し) でも session を作成し triageResult を保存する設計に統一する (現状の「needsAdr=true のみ session 作成」を needsAdr=false でも作成に変更、ただし enqueue はしない)。session PUT 失敗時は best-effort + ハンドラ自体は成功応答、consumer log に triage_save_failed=true フラグで観測。撤退条件 #1 で「設計バグによる二重実行」と「保存失敗による二重実行」を区別。

過去レコードの kind=NULL 蓄積 (盲点 #2 + #9 への対応): Phase A/B 期間中の全起案は kind=NULL のまま永続。対処: Phase C の migrate-v5 に backfill SQL を含める: UPDATE telemetry_records SET triage_reject_kind='pre-gate-block' WHERE rejection_reason_code IN ('cost-missing','placeholder-remaining','rollback-quantity-missing','confirmation-kpi-missing') AND triage_reject_kind IS NULL; UPDATE telemetry_records SET triage_reject_kind='not-adr-worthy' WHERE needs_adr=0 AND rejection_reason_code IS NULL AND triage_reject_kind IS NULL;。撤退条件 #4 の整合率集計クエリは AND created_at >= '<Phase C deploy timestamp>' を含め、母数が最低 20 件に達するまで判定保留。

temperature=0.2 揺れの実害 (Cross-Validation v2 medium への対応): 揺れの定量測定は ADR-0073 で別途進行中だが、Phase B で session に triage 結果を保存して consumer の skip 判定 (triage.ts:111) を有効化することで、1 起案あたり triage 1 回固定化により構造的に解消する。

ADR-0073 seed 再現性の web UI 経路カバレッジ (盲点 #3 への対応): ADR-0073 の回帰テストが CI 経路のみを対象としている場合、web UI 同期 triage は seed 保証対象外となる。対処: ADR-0073 の Confirmation スコープを本 ADR Phase B 完了時に再確認し、web UI 経路を含めるか「web UI 経路は ADR-0073 保証対象外」とスコープを明示するか、別途 ADR-0073 改訂で決定。本 ADR では doc 化のみ。

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

  • needsAdr=false の意味は引き続き「Pipeline 停止」を兼用するが、kind フィールドで判別可能になることで実害はゼロ。意味論の「綺麗さ」を優先する案 A より、外部 consumer 後方互換と実装コスト最小化を選好。盲点 #12 (確証バイアス) への対処: 6 ヶ月後の新規参加者向けに needsAdr の二重用途を明示するコードコメントを state.ts / triage.ts に追加、Phase C 完了後も needsAdr 二重用途が残るため Phase D (意味論完全分離) を backlog 登録 (Non-Goals として明記)。
  • Phase A の cosmetic patch (rejectionReasonCode 有無による暗黙判別) は Phase C で kind 経由 explicit 判別に昇格、中間状態 (Phase A 後 Phase C 前) は 最大 2 週間の短期的トレードオフとして許容。
  • 入口差分 (web UI は同期 triage、CI は consumer 内 triage) は本 ADR では doc 化のみで統一しない。retroactive 機能差 (CI のみ) と入力源差 (UI=body / CI=KV draft) は固定仕様として記録 (案 E 却下)。
  • kind 値域の将来拡張ガバナンス (盲点 #11 への対処): triageRejectKind の値域変更には別途 ADR 起案を必須とするルールを本 ADR で確立。Phase C 完了後に rejection_reason_codetriageRejectKind の対応表を ADR 附録として管理、新規 reason_code 追加時は対応表更新を PR チェックリストに含める。

コスト試算

作業工数 (人日)工数 (h)Phase
chat.html showResult / buildTriageBanner 分岐切替 + consumer.ts +1 行0.251.5A
PipelineSessionState 拡張 + /chat/start 保存 + consumer skip 判定0.53B
state.ts kind Annotation + triage.ts 3 経路 kind 設定0.251.5C
audit/types.ts + persistence.ts + consumer.ts telemetry 書込0.251.5C
migrate-v5 SQL 作成 (backfill 含む) + ローカル/remote apply0.251.5C
Phase C chat.html kind 経由 explicit 化0.10.6C
動作確認 (manual e2e 各 Phase × 3 シナリオ + 並行リクエスト)0.251.5A/B/C
入口差分 (web UI vs CI) の operator_guide 追記 + ADR-0073 スコープ確認0.150.9C
GitHub Action audit exporter ソース調査 (盲点 #10)0.10.6C
合計約 2.1 人日~12.6 h

金額換算: 個人開発、自工数のみ、直接金銭支出 0 円。LLM コスト削減: Phase B で triage 2→1 → ~$0.02-0.05/起案、年 ~200 起案で $4-10/年削減

6. 撤退条件 (Rollback Plan)

#判定指標期限 / 検知方法代替アクション
1Phase B 後も triage 二重実行が観測 (consumer log event=triage_call, skipped=false が 1 起案で 2 回)4 週後の log 集計 (triage_save_failed=true フラグで設計バグと保存失敗を区別)session 保存ロジックを retry、または Phase B scope を縮小し Phase C のみ先行
2Phase C 後の audit dashboard / GitHub exporter が triage_reject_kind カラム追加で破綻リリース 1 週内のダッシュボード動作確認、exporter 出力 diff テストmigrate-v5 rollback (ALTER TABLE telemetry_records DROP COLUMN triage_reject_kind、SQLite 3.35+ 対応)、TypeScript field を optional 維持
3起案者 UX 退行報告 (UI 表示が不明瞭)起案者報告 1 件以上Phase A rollback (showResult を旧表示にロールバック)、Phase B/C は維持可
4triageRejectKindrejection_reason_code の整合率 < 99%4 週後の SQL クエリ SELECT triage_reject_kind, rejection_reason_code, COUNT(*) FROM telemetry_records WHERE triage_reject_kind IS NOT NULL AND created_at >= '<Phase C deploy timestamp>' GROUP BY 1, 2 (母数 ≥ 20 件まで判定保留)triage.ts の 3 経路を再点検、kind 設定漏れ fix
5二重実行率 > 5%4 週後の event=triage_call ログ集計Phase B のロジック修正、case A への戻しは行わない (外部 consumer 破壊リスクのため)
6Phase A merge から 2 週超過しても Phase C 未完了Phase A merge 日 + 14 日の calendar checkPhase A の暗黙判別を revoke (showResult を旧表示にロールバック) し Phase C を強制マージ。Phase A〜C 中間期間中の新規 rejection_reason_code 追加 PR をブロック
7D1 migrate-v5 apply 後 5 分以内に table has X columns エラーが worker log に出現migration apply 直後の log 監視application code (kind 書込) デプロイを延期、レプリカ伝播完了まで待機

Confirmation

  • 検証手段:
    1. Phase A e2e: cost-missing 草案を web UI から fire → UI に「起案前ゲート差し戻し」+ rejectionMsg 表示、[Standard] バッジ非表示。typo 草案で従来通り「ADR 対象外」表示。rejectionReasonCode undefined 時の表示分岐統合テストを必須化 (盲点 #6)。
    2. Phase B e2e: normal 草案 fire → consumer log で event=triage_call, skipped=false が 1 回のみ (二度目は skipped=true)。1 起案あたり triage LLM call が 1 回。並行リクエストシナリオ (リロード / 二重送信) で skipped=false が 2 回出ないことを確認 (盲点 #7)。session PUT 失敗時の triage_save_failed=true フラグ観測 (盲点 #5)。
    3. Phase C e2e: D1 migration apply 後、SELECT triage_reject_kind, rejection_reason_code, COUNT(*) FROM telemetry_records WHERE triage_reject_kind IS NOT NULL AND created_at >= '<deploy timestamp>' GROUP BY 1, 2pre-gate-block 行は reason_code 全件埋まる、not-adr-worthy 行は reason_code が NULL。backfill 後の過去レコードも同様に検証。
    4. 外部 consumer 互換性: Phase C migration に GitHub Action audit exporter のソースを調査し SELECT * 使用有無を確認 (盲点 #10)。migration 後、getChurnSummary API 応答が v2 と同一 schema を返すこと、exporter 出力 diff テストで列ずれが発生しないこと。
    5. D1 レプリカ伝播: migrate-v5 apply 後 5 分間 worker log を監視し table has X columns エラー 0 件を確認してから application code をデプロイ (盲点 #8)。
    6. adr-lint 回帰: 各 Phase merge 後 node scripts/adr-lint.mjs docs/adr/ で 94/94 維持。
    7. ADR-0073 スコープ確認: Phase B 完了時、ADR-0073 の seed 再現性回帰テストが web UI 経路をカバーしているか確認、未カバーなら ADR-0073 改訂または本 ADR Confirmation にスコープ明記 (盲点 #3)。
  • 実行頻度: 修正 PR マージ時の手動 e2e、月次の audit_runs サンプリング (50 件)、4 週後の整合率集計、Phase A merge 後 2 週時点での Phase C 進捗チェック。
  • 違反時対応: 撤退条件 (§6) 発動。
  • 観測可能 KPI: triage 二重実行率 (目標 0%、許容上限 5%)、UI 矛盾表示の起案者報告件数 (目標 0/月、許容 1/月)、triage_reject_kindrejection_reason_code の整合率 (目標 100%、許容下限 99%、母数 ≥ 20 件)、外部 consumer の破綻件数 (目標 0)、Phase A→C 移行期間 (目標 ≤ 2 週)、triage_save_failed 発生率 (目標 0%、許容上限 1%)。

11. 参照: Pipeline 審査履歴 (2026-06-01 実行時, 通常 flow)

本セクションは Decision Pipeline (LangGraph TS on Cloudflare Workers) で本 ADR 草案を通常 flow (retroactive=false) で審査した結果のログ。v1 (case A: needsAdr 意味論変更) は Cross-Validation で critical 2 件 reject (外部 consumer 破壊リスク + 下流ノード防御漏れ、Score 48/50)。v3 (case B: triageRejectKind フィールド直交追加) に方針転換し Score 49/50 + Cross-Validation Must 軸毀損なしで通過。デフォルトでは折りたたまれており、 をクリックで展開する。

📋 Pipeline 審査履歴 全 Gate 結果 (合格 Score 49 / 50, v1 case A → v3 case B、+1 pt 改善) — クリックで展開

Gate 0-4 結果 (v3 実行)

  • Gate 0 Triage: needsAdr=true / triageMode=Standard
  • Gate 1 Socratic: 盲点 12 件検出 (情報提供型、全 monitor 級、§影響範囲・§撤退条件に反映済)
  • Gate 2 Consistency: INFO (ADR-0066/0073/0088/0089/0091/0052 と並立、矛盾なし、本 ADR が follow-up corrigendum 的補強)
  • Gate 3 Parallel Review: 3 vendor (Gemini Pro / Claude Opus / o3) の指摘は §影響範囲・撤退条件に反映済
  • Cross-Validation (盲点 × Must): PASS (Must 軸 #reliable の毀損ゼロ。v1 で critical 2 件あったが v3 で完全解消)
  • Gate 4 Scoring: 49 / 50 (scoringMean 48.8, stdDev 0.4)
#採点項目点数コメント
1問題定義5障害 A (UI 矛盾) + 障害 B (二重実行) を共通根 (needsAdr 過負荷 + session schema 不足) に整理、v1 差し戻し経緯まで明示
2代替案5案 B (採択) / 案 A (v1 採択案、却下) / 案 C (UI のみ) / 案 D (Gate4 後移動) / 案 E (入口統一) の 5 案
3判断基準55 軸 × 重要度係数、加重和、K.O. 基準、#operable に「外部 consumer 影響ゼロ」を明示
4過去 ADR 整合性5ADR-0066/0073/0088/0089/0091/0052 と並立明記、v1 (case A) を後継として扱う
5影響範囲5改修対象 7 ファイル + migration を明示列挙、Cross-Validation critical 2 件への直接 mitigation 文言を §5.2 で網羅
6運用上の罠5盲点 #1-#12 を明示的に検証、外部 consumer 後方互換性 / 下流ノード防御 / DO storage / temperature 揺れ を §5.2 で個別 mitigation
7ロールバック性5撤退条件 5 件、SQLite 3.35+ の DROP COLUMN 対応、24h TTL in-flight session の safe degrade を明示
8コスト試算4計 2.0 人日 + LLM コスト $4-10/年削減を明示
9完了条件5Confirmation 3 要素 + 観測可能 KPI 7 個 (整合率、二重実行率、外部 consumer 破綻件数、Phase 移行期間 等)
10長期影響5Phase 分割で段階移行、Phase D backlog として needsAdr 二重用途の完全分離を残置、v1 case A の learning を吸収

合計: 49 / 50 (Critical 閾値 45 + 4pt 余裕、Cross-Validation Must 軸毀損なし)

Status 遷移

  • v1 起案 (2026-05-31 13:50Z KV 投入、case A needsAdr 意味論変更) → Pipeline 通常 flow Score 48/50 達成も Cross-Validation で critical 2 件 reject (外部 consumer 破壊 + 下流防御漏れ)
  • v3 改訂 (2026-05-31 14:08Z 再投入、case B triageRejectKind 直交追加に方針転換、§影響範囲に Cross-Validation 4 findings 直接 mitigation 文言 + sub canonical 9 H2 構造) → Pipeline 再投入 → 49/50 通過 → auto-PR #1207 生成 (Proposed)
  • 本 PR で Status: Proposed → Accepted + Phase A/B/C 全 merge + remote D1 migration 適用済を反映

参照 (References)

  • 関連 ADR:
    • ADR-0066 (Pipeline async queues + DO): session 保存設計の母体。本 ADR は session schema を拡張する (PipelineSessionState に triageResult optional 追加)。並立・拡張
    • ADR-0073 (Gate0 triage seed regression test): 本 ADR Phase B で triage 二重実行を解消し 0073 の seed 再現性前提を回復する。web UI 経路カバレッジは Phase B 完了時に再確認。並立・補完
    • ADR-0088 (cost-missing 起案前ゲート、PR #1155): needsAdr=false 流用パターンの起源。本 ADR は 0088 の rejection_reason_code セマンティクスを完全維持しつつ kind フィールドで補強。並立・補強
    • ADR-0089 (DO partial: 分散保存): triageResult は session の data key 直書込で対応、partial: 機構には触れない。並立・独立
    • ADR-0091 (no-placeholder-marker / rollback-has-quantity / confirmation-has-kpi、PR #1196): 3 pre-gate を導入し reject 経路を 1→4 に拡大、UI 矛盾の発生確率を上げた。本 ADR が follow-up corrigendum 的に意味論を整理。並立・補強
    • ADR-0052 (retroactive validation mode): 入口差分の文脈で言及、retroactive が /runs (CI) のみ到達可能であることを仕様として doc 化する。並立・doc 化
    • v2 (case A): 2026-05-31 朝に Pipeline 投入、Cross-Validation で critical 2 件差し戻し。本 v3 が後継、KV draft は同 id を v3 で上書き。後継、補正
    • Supersede / Conflict なし
    • Phase D (将来 backlog): needsAdr 二重用途の意味論完全分離 (盲点 #12)
  • 関連 PR/Issue: PR #1155 (ADR-0088), PR #1196 (ADR-0091 Phase B), PR #1200 (stop-button 矛盾報告), PR #1204 (二重実行追補), PR #1205 (post-mortem)
    • 実装 PR: PR #1207 (ADR 起案 auto-PR), PR #1209 (Phase A — UI 矛盾解消), PR #1212 (Phase B — session 保存 + consumer skip), PR #1217 (Phase C — triageRejectKind + migrate-v5)
    • follow-up: PR #1210 (hasCostEstimate 精度), PR #1211 (not-adr-worthy UX), PR #1214 (triage_ms 計測修正), PR #1216 (triage retry 観測ログ)
  • 外部資料:
    • Cloudflare D1 ALTER TABLE replication delay (Cloudflare known issue)
    • Cloudflare Durable Objects allowConcurrency storage API
    • SQLite 3.35+ DROP COLUMN サポート