ADR-0094: triage rejection 経路の意味論を分離する: triageRejectKind フィールドで pre-gate block と not-adr-worthy を判別
- 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 Pipeline の triage 段階で 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.tsのneedsAdr=falsereject 経路は現状 3 つ:- 真の「ADR 不要」判定 (line 154、
is_adr_worthy=false、triageMode=null): typo 修正など - ADR-0088 cost-missing 起案前ゲート差し戻し (line 173、
is_adr_worthy=true、triageMode 保持): PR #1155 で導入 - ADR-0091 3 ルール起案前ゲート差し戻し (line 198、同上、
rejection_reason_codeは placeholder-remaining/rollback-quantity-missing/confirmation-kpi-missing のいずれか): PR #1196 で導入 (本セッション)
- 真の「ADR 不要」判定 (line 154、
- UI (
public/chat.htmlshowResult3095-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
- 結果: web UI async 経路で 1 起案あたり triage が 2 回実行される。
triage.ts:111のif (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.ts に triageRejectKind: '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.0 | 5 | 2 | 3 | 2 | 3 | 3 |
#maintainable (×1.0) | 1.0 | 4 | 5 | 2 | 3 | 4 | 3 |
#operable (×1.0) | 1.0 | 5 | 2 | 3 | 2 | 2 | 4 |
#efficient (×0.5) | 0.5 | 4 | 4 | 2 | 1 | 3 | 4 |
#flexible (×0.5) | 0.5 | 4 | 4 | 2 | 3 | 3 | 2 |
| 加重和 (正規化) | 0.920 | 0.580 | 0.520 | 0.420 | 0.600 | 0.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-258のgetChurnSummary.by_mode_and_reasonがneeds_adr=false && rejected=1 && rejection_reason_codeで集計しており案 A 採択で意味論変更、既存 4 週レビュー集計 (~28 records) が遡及的に誤解釈されダッシュボード/GitHub Action exporter は無声破綻、(ii)pipeline_consumer.ts:150のif (!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_codeにpre-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:170 の by_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:150 の if (!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.put に allowConcurrency: 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/start で needsAdr=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_codeとtriageRejectKindの対応表を ADR 附録として管理、新規 reason_code 追加時は対応表更新を PR チェックリストに含める。
コスト試算
| 作業 | 工数 (人日) | 工数 (h) | Phase |
|---|---|---|---|
chat.html showResult / buildTriageBanner 分岐切替 + consumer.ts +1 行 | 0.25 | 1.5 | A |
PipelineSessionState 拡張 + /chat/start 保存 + consumer skip 判定 | 0.5 | 3 | B |
| state.ts kind Annotation + triage.ts 3 経路 kind 設定 | 0.25 | 1.5 | C |
| audit/types.ts + persistence.ts + consumer.ts telemetry 書込 | 0.25 | 1.5 | C |
| migrate-v5 SQL 作成 (backfill 含む) + ローカル/remote apply | 0.25 | 1.5 | C |
| Phase C chat.html kind 経由 explicit 化 | 0.1 | 0.6 | C |
| 動作確認 (manual e2e 各 Phase × 3 シナリオ + 並行リクエスト) | 0.25 | 1.5 | A/B/C |
| 入口差分 (web UI vs CI) の operator_guide 追記 + ADR-0073 スコープ確認 | 0.15 | 0.9 | C |
| GitHub Action audit exporter ソース調査 (盲点 #10) | 0.1 | 0.6 | C |
| 合計 | 約 2.1 人日 | ~12.6 h |
金額換算: 個人開発、自工数のみ、直接金銭支出 0 円。LLM コスト削減: Phase B で triage 2→1 → ~$0.02-0.05/起案、年 ~200 起案で $4-10/年削減。
6. 撤退条件 (Rollback Plan)
| # | 判定指標 | 期限 / 検知方法 | 代替アクション |
|---|---|---|---|
| 1 | Phase B 後も triage 二重実行が観測 (consumer log event=triage_call, skipped=false が 1 起案で 2 回) | 4 週後の log 集計 (triage_save_failed=true フラグで設計バグと保存失敗を区別) | session 保存ロジックを retry、または Phase B scope を縮小し Phase C のみ先行 |
| 2 | Phase 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 は維持可 |
| 4 | triageRejectKind と rejection_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 破壊リスクのため) |
| 6 | Phase A merge から 2 週超過しても Phase C 未完了 | Phase A merge 日 + 14 日の calendar check | Phase A の暗黙判別を revoke (showResult を旧表示にロールバック) し Phase C を強制マージ。Phase A〜C 中間期間中の新規 rejection_reason_code 追加 PR をブロック |
| 7 | D1 migrate-v5 apply 後 5 分以内に table has X columns エラーが worker log に出現 | migration apply 直後の log 監視 | application code (kind 書込) デプロイを延期、レプリカ伝播完了まで待機 |
Confirmation
- 検証手段:
- Phase A e2e: cost-missing 草案を web UI から fire → UI に「起案前ゲート差し戻し」+ rejectionMsg 表示、
[Standard]バッジ非表示。typo 草案で従来通り「ADR 対象外」表示。rejectionReasonCodeundefined 時の表示分岐統合テストを必須化 (盲点 #6)。 - 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)。 - 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, 2でpre-gate-block行は reason_code 全件埋まる、not-adr-worthy行は reason_code が NULL。backfill 後の過去レコードも同様に検証。 - 外部 consumer 互換性: Phase C migration 前に GitHub Action audit exporter のソースを調査し
SELECT *使用有無を確認 (盲点 #10)。migration 後、getChurnSummaryAPI 応答が v2 と同一 schema を返すこと、exporter 出力 diff テストで列ずれが発生しないこと。 - D1 レプリカ伝播: migrate-v5 apply 後 5 分間 worker log を監視し
table has X columnsエラー 0 件を確認してから application code をデプロイ (盲点 #8)。 adr-lint回帰: 各 Phase merge 後node scripts/adr-lint.mjs docs/adr/で 94/94 維持。- ADR-0073 スコープ確認: Phase B 完了時、ADR-0073 の seed 再現性回帰テストが web UI 経路をカバーしているか確認、未カバーなら ADR-0073 改訂または本 ADR Confirmation にスコープ明記 (盲点 #3)。
- Phase A e2e: cost-missing 草案を web UI から fire → UI に「起案前ゲート差し戻し」+ rejectionMsg 表示、
- 実行頻度: 修正 PR マージ時の手動 e2e、月次の audit_runs サンプリング (50 件)、4 週後の整合率集計、Phase A merge 後 2 週時点での Phase C 進捗チェック。
- 違反時対応: 撤退条件 (§6) 発動。
- 観測可能 KPI: triage 二重実行率 (目標 0%、許容上限 5%)、UI 矛盾表示の起案者報告件数 (目標 0/月、許容 1/月)、
triage_reject_kindとrejection_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 | 判断基準 | 5 | 5 軸 × 重要度係数、加重和、K.O. 基準、#operable に「外部 consumer 影響ゼロ」を明示 |
| 4 | 過去 ADR 整合性 | 5 | ADR-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 | 完了条件 | 5 | Confirmation 3 要素 + 観測可能 KPI 7 個 (整合率、二重実行率、外部 consumer 破綻件数、Phase 移行期間 等) |
| 10 | 長期影響 | 5 | Phase 分割で段階移行、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 の datakey 直書込で対応、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
allowConcurrencystorage API - SQLite 3.35+ DROP COLUMN サポート