「昨天講的 ADR 聽起來很有用,那乾脆把每個 ADR 的重點都摘要進 CLAUDE.md,AI 每次都能看到,不是更保險嗎?」
這個念頭很直覺,但今天要說清楚為什麼這樣做行不通——不是因為麻煩,是因為 CLAUDE.md/skill 跟 ADR 這兩種文件,回答的根本是兩個不同的問題,硬塞在一起,兩邊都會失靈。
昨天的案例裡,AI 把一段防止 webhook 重複觸發的檢查誤判成技術債清掉了,因為它讀不到「這段程式碼在防什麼」。ADR 補的正是這個缺口——但 ADR 補的資訊,跟 CLAUDE.md/skill 裡放的東西,性質完全不一樣。
CLAUDE.md/skill 回答的是「現在該怎麼做」:金額運算要用哪個函式庫、Repository 要放在哪個目錄、外部 API 呼叫要走哪個介面。這些是現在生效的規則,AI 動手寫程式碼的當下就要遵守。
ADR 回答的是「當初為什麼決定這樣做,還考慮過什麼替代方案」:為什麼選了這個架構、放棄了哪些選項、當時的限制條件是什麼。這是歷史決策的脈絡,不是「現在該怎麼做」的規則,而是「現在這條規則背後站著什麼理由」。
一個是行動指南,一個是背景知識——這個差異看起來抽象,但直接決定了兩種文件該怎麼被讀取。
CLAUDE.md/skill 的設計前提是「幾乎每次任務都要載入、或者按需載入」——這意味著它必須保持精簡,才能讓 AI 每次讀完都還抓得住重點。而 ADR 天生就是會持續累積的東西:一個活躍專案跑個幾年,可能會累積幾十上百份決策紀錄,涵蓋各種當初做過的取捨。
如果把所有 ADR 的重點都塞進 CLAUDE.md,等於把「每次都要讀」的文件,跟「持續累積、只在需要時才查」的文件混在一起——這正是我在《用 AI Agent 重構一套無框架的 legacy PHP 系統》系列裡也講過的權重稀釋問題的翻版:CLAUDE.md 會隨著 ADR 數量增加而不斷膨脹,真正每次都該遵守的核心規則,反而被淹沒在幾十條「當初為什麼這樣設計」的歷史脈絡裡。
用一組對照來看這個差異:
❌ 把 ADR 摘要塞進 CLAUDE.md:
# CLAUDE.md
- 金額運算一律用 bcmath
- ADR-0003:選擇這個資料庫是因為...(歷史脈絡)
- ADR-0007:付款 webhook 冪等性處理是因為...(歷史脈絡)
- ADR-0012:放棄微服務化是因為...(歷史脈絡)
...
→ 每次任務都要讀完所有歷史決策紀錄,
但大部分任務根本不會碰到這些決策涉及的程式碼
✅ 分工:CLAUDE.md 精簡,ADR 按需查閱
# CLAUDE.md
- 金額運算一律用 bcmath
- 改動前,先確認相關程式碼旁邊有沒有 ADR 連結,有就先讀過再動手
# docs/adr/0007-payment-webhook-idempotency.md
(只有真的要動這段付款邏輯的人,才會去查這份紀錄)
→ CLAUDE.md 只留一條「習慣性查 ADR」的提醒,
真正的歷史脈絡留在各自的 ADR 檔案裡,靠程式碼旁的連結指過去
CLAUDE.md/skill 教 AI「現在的規矩」,ADR 教 AI「這個規矩、或這段看起來奇怪的程式碼,背後站著什麼理由」——把兩者混在同一份文件裡,兩邊都會失去各自該有的精簡度。
昨天案例裡改進後的版本,程式碼旁邊只留了三行註解跟一個 ADR 連結,沒有把整份 ADR 內容複製進程式碼裡,也沒有把它塞進 CLAUDE.md。這正是分工該有的樣子:CLAUDE.md/skill 負責建立「習慣性查證」的紀律,具體的歷史脈絡留在 ADR 自己的檔案裡,靠程式碼旁的指標把兩者連起來。
這個設計也呼應了系列一路強調的:不是要求 AI 記住更多,而是把它需要的資訊放在它「查得到」而不是「每次都被迫讀過」的地方——跟《用 AI Agent 重構一套無框架的 legacy PHP 系統》系列講的按需載入 skill 是同一個判斷邏輯,只是換了一種文件類型。
回想你維護的專案:如果有 ADR(或類似的決策紀錄),它們是散落在自己的文件裡、靠程式碼旁的連結指過去,還是被複製貼上進了某份「所有人都要讀」的核心規範文件?如果是後者,那份文件現在讀起來還輕鬆嗎?
明天要講架構邊界的另一個容易失守的方向:AI 有時候不是忽略邊界,而是過度遵守邊界——把一個簡單功能硬套上多層抽象,只因為「架構規則說要分層」。邊界跟過度設計之間的分界線在哪裡。