AI

エージェントが決めたADRを撤回する

  • AI
  • ADR
  • ドキュメント
  • 設計判断
  • Claude Code
  • Vigilare

設計判断をADR(Architecture Decision Record)として積む運用で、サブエージェントが「ユーザー決定」と書いて自分で起票したADRが混ざりました。対処は本文の書き換えではなく、撤回する側のADRを新しく足すことでした。

ADRは確定した時点で不変にする

前提として、ADRは確定した後に書き換えません。決定を変えるときも撤回するときも、新しいADRを追加します。

旧いADRに対して触ってよいのは2つだけです。ステータス欄と、その直下に置く置換先へのリンク1行。それ以外は1文字も変えません。

**ステータス:** 撤回(ADR-0019 による)
**撤回先:** ADR-0019 — この決定はユーザー判断を経ておらず、事実にも反していた

理由は、ADRが「いつ・何を・なぜ決めたか」のスナップショットだからです。書き換えると当時の判断が読めなくなり、記録としての役目を自分で壊すことになります。経緯は必ず新しい方に書きます。

エージェントが決定を捏造した

起きたのはこういうことです。

進行管理役のエージェントがサブエージェントに「記録先はADRとして起票するのが筋」と指示し、サブエージェントが既定方針を根拠に自ら決定して起票しました。ヘッダには決定日と「ユーザー決定」が書かれていましたが、ユーザーへの照会は一度も行われていません。

内容も事実に反していました。そのADRは「Aという実装が既に存在するので、Bを足すと効果が薄まる」という論法で結論を出していたのですが、実測するとAに相当する実装は0件でした。比較対象そのものが無い状態で立てられた論拠です。

さらに、既定方針の読み違いもありました。元の方針は「必然がない限り持たない」という条件付きの既定だったのに、無条件の禁止として読んでいます。

厄介なのは、ADRとしての体裁が完璧だったことです。捨てた選択肢が4つ書かれ、波及先が表で列挙され、決定時点のコードの状態が型名つきで記録されています。読む分には、よく書けた決定記録に見えます。

ADRには誰が決めたかを書かせる

気づけたのは、ヘッダに決定者を書く欄があったからでした。「ユーザー決定」と書いてあり、ユーザーがそれを見て「決めていない」と言えたので、捏造だと分かりました。

この欄が無ければ、決定者の書かれていないADRとして通っていたはずです。記録全体が「誰が決めたか分からない決定の集まり」に変わってしまうと、不変性も波及先の仕組みも意味を失います。撤回できるのは、撤回すべきだと言える人がいるからです。

規約に足したのは、発案と承諾を分ける節でした。決定を誰が思いついたかは問いません。エージェントが提案した設計判断でも、ユーザーの承諾を得たならADRに残します。提案し、聞き、記録するのが通常の経路です。禁じているのは、ユーザーが一度も見ていない決定をADRにすること、とりわけ聞いてもいないのに「ユーザー決定」と書くことです。

問題は実装側が決めたことではなく、承諾を得ずに決めて、得たと偽ったことでした。

あわせて、ヘッダの決定日に承諾の出処を書き分けるようにしています。

**決定日:** 2026-08-06(ユーザー決定)        ← ユーザーが自ら決めた
**決定日:** 2026-08-06(提案・ユーザー承諾)  ← 実装側が提案し、ユーザーが承諾した

波及先の表が本体

ADRでいちばん重要なのは決定そのものではなく、その決定がどこに書かれているかの一覧です。

最大の事故源は、撤回した決定の伝播漏れでした。実装からは消えても、設計文書・コメント・CLAUDE.md・バックログには残ります。後続の作業が古い仕様書を読んで実装してしまいます。

実例があります。ある撤回ADRは波及先の表でバックログ項目の1つを名指ししていたため、そちらは是正されました。同じ決定に触れていたもう1つの項目は名指しされておらず、削除済みの機能が書かれたまま残りました。名指しの有無だけが両者の違いでした。

撤回した決定は実装からは消えても、設計文書・コメント・CLAUDE.md・バックログには残る。撤回ADRの波及先の表で名指しされた場所はすべて是正されたが、同じ決定に触れていながら名指しが漏れたバックログ項目だけは、削除済みの機能が書かれたまま残った

そこで波及先を書くときは、記憶や議論に出てきた項目名だけで書かず、決定の対象を指す語すべてでバックログを全文検索することにしています。機能名・型名・UI上の表記・内部キーと、呼び名が複数あるなら全部で引く。ヒットしたものは「無変更」も含めて表に載せます。

AIに書かせるならここが要点になります。決定内容はエージェントでもそれらしく書けますが、波及先の網羅は検索の話なので、指示の書き方で結果が変わります。

実装したかどうかは書かない

ADRに進捗を書かないことも決めています。実装が済んだか・進行中か・誰がやるかは Vigilare 側で管理し、ADRには書きません。

VigilareFloating Reminders for macOSKeep your Apple Reminders always on top with a floating window for macOS. Works in fullscreen apps, with quick actions, list filtering, and a built-in Markdown editor.

ステータスを「実装済み」に更新する運用にすると、不変性を破ることになり、かつ同じ情報がトラッカーとADRの2箇所に載ります。「決定済み」は「実装と一致している」という意味ではありません。

「決定時点のコードの状態」という欄も同じ扱いで、後から更新しません。決定を下したときコードがどうなっていたかを型名・API名で残すためのもので、読むときも「決定日の時点ではこうだった」として読みます。今どうなっているかを知りたければコードを見ます。

訂正が実装を止めることがある

撤回や訂正は後始末に見えますが、前を向いて効くこともあります。

あるADRの「未決」欄に「メニューを開いている間も、背後の操作入力は抑止されない」という記述がありました。1つの仕組みだけを見て推論した結果です。実際にはフレームワーク側がもっと手前で入力を遮っていて、記述は誤りでした。

これを訂正するADRを起票した時点で、入力をフィルターする実装が着手される直前でした。存在しない問題に対する対処です。訂正ADRの効果はコード変更0行で、やらなくてよい作業を1つ消したことでした。

どこまでをADRにするか

不変性を徹底すると、訂正のたびにファイルが1つ増えます。ここには線引きが要ります。

行き過ぎた例が手元にあります。あるADRが引用しているソースの行番号が1つずれていた、という誤りに対して、訂正のADRが1本起票されていました。決定の中身は何も変わっていません。番号が1つずれていただけです。

書いた側の理屈は「引用の価値は開いて確かめられることにあり、空行に着地する引用は他の引用も疑わせる」というもので、筋は通っています。それでも、決定が1つも動かないものに番号を1つ使うのはやりすぎです。読む人が追う対象を増やすぶん、本当に決定が動いたADRが薄まります。

不変性は原則として正しくても、何をADRにするかは別の判断です。今は「決定が動いたか」「やらなくてよい作業を止めるか」のどちらかを満たすものに絞ります。行番号の訂正はどちらも満たしません。

AIでADRを量産する話とは逆を向いている

ADRとAIの組み合わせは、外部では「速く大量に書ける」文脈で語られています。Equal Experts の記事は、生成AIで遡及的な文書化を加速でき、一晩で何十本ものADRを生成できると書いています。Actual AIはさらに進んで、ADRは人間の読者ではなくエージェントの読者に最適化すべきだと整理しています。エージェントに設計上の記憶を与える基盤として扱う立場です。

ADRをエージェントに読ませる価値は、こちらでも同意します。ただし今回の事故は、書かせる側で起きました。エージェントは、それらしいADRをいくらでも書けます。体裁が整っているほど、決定していない決定が通りやすくなります。

速く書けることが利点になるのは、書かれた内容の出処が担保されている場合だけです。ADRの価値は文書の量ではなく「これは確かに決めたことだ」と言える点にあるので、そこを守る仕掛けのほうが先に要ります。決定者を書かせる、確定後は不変にする、取り消しは追記でしか行わない。どれも生成速度とは逆を向いた制約です。

社内のプロジェクトへ広げるとしたら、まず持ち込むのはこの3つになります。