ADR 技能
理念
使用此技能建立的 ADR 是編碼代理程式的可執行規格。人類核准決策;代理程式實作它。ADR 必須包含代理程式撰寫正確程式碼所需的一切,無須再提出追問。
這代表:
- 限制條件必須明確且可衡量,而非模糊的感覺
- 決策必須具體到可以執行(使用「採用 PostgreSQL 16 搭配 pgvector」,而非「使用一個資料庫」)
- 後果必須對應到具體的後續任務
- 必須說明非目標,以防止範圍蔓延
- ADR 必須是自足的——不得假設存在團隊專有知識
- ADR 必須包含實作計畫——說明要觸碰哪些檔案、遵循哪些模式、撰寫哪些測試,以及如何驗證決策已正確實作
何時撰寫 ADR
當一項決策符合以下條件時,應撰寫 ADR:
- 改變系統的建置或運作方式(新的依賴項、架構模式、基礎設施選擇、API 設計)
- 一旦根據它撰寫程式碼就很難逆轉
- 會影響日後在此程式碼庫中工作的其他人或代理程式
- 有實際考慮過但已否決的其他替代方案
在下列情況下不需要撰寫 ADR:
- 在既定模式內的例行實作選擇
- 錯誤修正或錯字更正
- 已由現有 ADR 涵蓋的決策(應改為更新它)
- 已由 linter 或格式化工具涵蓋的風格偏好
當不確定時:如果日後在此程式碼庫中工作的代理程式會因了解「為何做出此選擇」而受益,就撰寫 ADR。
主動觸發情境(適用於代理程式)
如果您是在某個儲存庫中進行編碼的代理程式,且遇到以下任何情況,請先暫停並提案一個 ADR,然後再繼續:
- 您正要引入一個專案中尚不存在的新依賴項
- 您正要建立一個其他程式碼需要遵循的新架構模式(新的錯誤處理方式、新的資料存取層、新的 API 慣例)
- 您正要兩個或多個實際替代方案之間做出選擇,且權衡取捨並非顯而易見
- 您正要變更某個與現有已接受 ADR 相牴觸的事項
- 您發現自己正在寫一段解釋「為什麼」的冗長程式碼註解——這些理由應該屬於 ADR
如何提案:告知人類您遇到了什麼決策、為何重要,並詢問他們是否想將其記錄為 ADR。如果是,則執行完整的四階段工作流程。如果否,則在程式碼註解中記錄該決策並繼續前進。
建立 ADR:四階段工作流程
每個 ADR 都經過四個階段。請勿跳過任何階段。
第 0 階段:掃描程式碼庫
在提出任何問題之前,先從儲存庫收集脈絡:
-
**尋找現有 ADR。**檢查
contributing/decisions/、docs/decisions/、adr/、docs/adr/、decisions/是否有現有記錄。閱讀它們。注意:- 現有慣例(目錄、命名、範本風格)
- 與目前決策相關或約束它的決策
- 這個新決策可能取代的任何 ADR
-
**檢查技術棧。**閱讀
package.json、go.mod、requirements.txt、Cargo.toml或同等檔案。注意相關的依賴項與版本。 -
**尋找相關的程式碼模式。**如果決策涉及特定領域(例如「我們如何處理認證」),則掃描現有實作。找出會受此決策影響的特定檔案、目錄和模式。
-
**檢查程式碼中的 ADR 參考。**在註解和文件中尋找 ADR 參考(請參閱下方的「程式碼 ↔ ADR 連結」)。這會揭示哪些現有決策管轄程式碼庫的哪些部分。
-
**記錄您發現的內容。**將此脈絡帶入第 1 階段——它將使您的問題更精確,並防止 ADR 與現有決策相牴觸。
第 1 階段:捕捉意圖(蘇格拉底式)
訪談人類以了解決策空間。一次問一個問題,並根據先前的答案逐步深入。請勿一次拋出一串問題。
核心問題(大致按此順序提問,如果從脈絡或第 0 階段已清楚則跳過):
- 您正在決定什麼?——獲得一個簡短、具體的標題。鼓勵使用動詞片語(「選擇 X」、「採用 Y」、「用 Z 取代 W」)。
- 為什麼是現在?——是什麼出了問題、正在改變,或者如果什麼都不做將會出什麼問題?這是觸發點。
- 存在哪些限制條件?——技術棧、時間表、預算、團隊規模、現有程式碼、合規性。要具體。參考您在第 0 階段的發現(「我看到您已經在使用 X——這會限制這個決策嗎?」)。
- 成功看起來像什麼?——可衡量的成果。不要只停留在「它能運作」,要深入到具體細節(延遲、吞吐量、開發者體驗、維護負擔)。
- 您考慮過哪些選項?——至少兩個。對於每個選項:核心權衡是什麼?如果他們只有一個選項,請協助他們闡明為什麼否決了其他選項。
- 您目前的傾向是什麼?——及早捕捉直覺。這通常能揭示未明說的優先事項。
- 誰需要知道或核准?——決策者、諮詢的專家、被告知的利害關係人。
- 代理程式需要什麼來實作這個決策?——哪些檔案/目錄會受影響?應該遵循哪些現有模式?應該避免什麼?哪些測試可以證明它正常運作?這會直接導入實作計畫。
適應性追問:根據答案,在決策模糊的地方深入探究。常見的追問:
- 「如果這個決策錯了,最壞的結果是什麼?」
- 「什麼情況會讓您在 6 個月後重新審視這個決策?」
- 「有沒有您明確選擇不去做的事?」
- 「程式碼庫中是否有與此相關的先例或現有模式?」
- 「我發現了[現有 ADR/模式]——這個新決策會與它互動嗎?」
何時停止:當您可以在不捏造任何內容的情況下,填滿 ADR 的每個章節(包括實作計畫)時,就足夠了。如果您對任何章節還在猜測,請再問一個問題。
意圖摘要關卡:在進入第 2 階段之前,呈現一個結構化的摘要,說明您所捕捉到的內容,並請人類確認或更正:
以下是我也要為 ADR 記錄的內容:
- 標題:{title}
- 觸發點:{why now}
- 限制條件:{list}
- 選項:{option 1} vs {option 2} [vs ...]
- 傾向:{which option and why}
- 非目標:{what's explicitly out of scope}
- 相關 ADR/程式碼:{what exists that this interacts with}
- 受影響的檔案/領域:{where in the codebase this lands}
- 驗證方式:{how we'll know it's implemented correctly}
這是否捕捉到您的意圖?需要補充或更正嗎?
在人類確認摘要之前,請勿進入第 2 階段。
第 2 階段:草擬 ADR
-
選擇 ADR 目錄。
- 如果存在一個目錄(在第 0 階段找到),則使用它。
- 如果不存在,則建立
contributing/decisions/(如果contributing/存在)、docs/decisions/(MADR 預設值)或adr/(較簡單的儲存庫)。
-
選擇檔案命名策略。
- 如果現有 ADR 使用日期前綴(
YYYY-MM-DD-...),則繼續使用。 - 否則,僅使用 slug 的檔案名稱(
choose-database.md)。
- 如果現有 ADR 使用日期前綴(
-
選擇範本。
- 對於直接了當的決策(一個明確的贏家,最小的權衡取捨),使用
assets/templates/adr-simple.md。 - 當需要記錄多個選項並帶有結構化的優點/缺點/驅動因素時,使用
assets/templates/adr-madr.md。 - 請參閱
references/template-variants.md以獲取指導。
- 對於直接了當的決策(一個明確的贏家,最小的權衡取捨),使用
-
**根據已確認的意圖摘要填寫每個章節。**請勿留下佔位符文字。每個章節都應包含真實內容,否則就將其刪除(僅限可選章節)。
-
**撰寫實作計畫。**這是代理程式優先 ADR 中最重要的章節。它告訴下一個代理程式確切要做什麼。請參閱範本以了解結構。
-
**將驗證標準撰寫為核取方塊。**這些標準必須足夠具體,讓代理程式可以以程式化方式或手動檢查每一項。
-
產生檔案。
- 首選:執行
scripts/new_adr.js(處理目錄、命名和可選的索引更新)。 - 如果無法執行指令碼,請從
assets/templates/複製一個範本並手動填寫。
- 首選:執行
第 3 階段:根據檢查清單進行審查
草擬完成後,根據 references/review-checklist.md 中的「代理程式就緒檢查清單」審查 ADR。
以摘要形式呈現審查結果,而非原始檢查清單轉儲。格式如下:
ADR 審查
✅ 通過項目:{列出穩固的項目——例如「脈絡自足、實作計畫涵蓋受影響檔案、驗證標準可勾選」}
⚠️ 發現的差距:
- {具體差距 1——例如「實作計畫未提及測試檔案——應該由哪個測試套件來涵蓋?」}
- {具體差距 2}
建議:{直接發布 / 先修正差距 / 需要更多第 1 階段的工作}
僅突顯失敗項目和顯著的優勢——無需逐一列出每個通過的核取方塊。
如果存在差距,請提出具體的修正方案。不要只標記問題——提供解決方案並請人類核准。
在 ADR 通過檢查清單或人類明確接受這些差距之前,請勿最終定稿。
查閱 ADR(讀取工作流程)
代理程式在實作變更之前,應先閱讀程式碼庫中現有的 ADR。這不是建立 ADR 工作流程的一部分——這是任何代理程式都應執行的獨立操作。
何時查閱 ADR
- 在開始處理觸及架構(認證、資料層、API 設計、基礎設施)的功能之前
- 當您在程式碼中遇到某個模式並納悶「為什麼用這種方式實作?」時
- 在提案一個可能與現有決策相牴觸的變更之前
- 當有人類說「檢查 ADR」或「這裡有一個關於此事的決策」時
- 當您在程式碼註解中找到 ADR 參考時
如何查閱 ADR
-
**找到 ADR 目錄。**檢查
contributing/decisions/、docs/decisions/、adr/、docs/adr/、decisions/。同時檢查是否有索引檔案(README.md或index.md)。 -
**掃描標題和狀態。**閱讀索引或列出檔名。專注於
accepted狀態的 ADR——這些是活躍的決策。 -
完整閱讀相關的 ADR。不要只閱讀標題——還要閱讀脈絡、決策、後果、非目標以及實作計畫。實作計畫會告訴您要遵循哪些模式以及哪些檔案受此決策管轄。
-
**尊重決策。**如果一個已接受的 ADR 說「使用 PostgreSQL」,請勿在未建立一個新的 ADR 來取代它的情況下,就提案改用 MongoDB。如果您發現程式碼的實作與 ADR 所述之間存在衝突,請向人類提出。
-
**遵循實作計畫。**當在受 ADR 管轄的領域中實作程式碼時,請遵循其實作計畫中指定的模式。如果計畫說「所有新查詢都通過
src/db/的資料存取層」,就照做。 -
**在您的工作中參考 ADR。**在程式碼註解和 PR 描述中新增 ADR 參考(請參閱下方的「程式碼 ↔ ADR 連結」)。
程式碼 ↔ ADR 連結
ADR 應與其管轄的程式碼之間建立雙向連結。
ADR → 程式碼(在實作計畫中)
實作計畫章節會命名特定的檔案、目錄和模式:
## 實作計畫
- **受影響路徑**:`src/db/`、`src/config/database.ts`、`tests/integration/`
- **模式**:所有資料庫查詢都通過 `src/db/client.ts`
程式碼 → ADR(在註解中)
當根據 ADR 的指導實作程式碼時,請新增一個註解來參考它:
// ADR: 使用 better-sqlite3 作為測試資料庫
// 參閱:docs/decisions/2025-06-15-use-sqlite-for-test-database.md
import Database from 'better-sqlite3';
保持輕量——在入口點新增一個註解即可,無需在每一行都加上。目標是可發現性:當未來的代理程式閱讀此程式碼時,可以找到背後的推理。
為何這很重要
- 在
src/db/中工作的代理程式可以找到管轄該領域的 ADR - 閱讀 ADR 的代理程式可以找到實作它的程式碼
- 當一個 ADR 被取代時,程式碼中的參考可以輕鬆找到所有需要更新的程式碼
其他操作
更新現有 ADR
-
識別意圖:
- 接受 / 拒絕:變更狀態,新增任何最終脈絡。
- 廢棄:狀態 →
deprecated,說明替代路徑。 - 取代:建立一個新的 ADR,雙向連結(舊 → 新,新 → 舊)。
- 新增學習心得:附加到
## 更多資訊並加上日期戳記。請勿改寫歷史。
-
對於狀態變更,使用
scripts/set_adr_status.js(支援 YAML 前言、項目符號狀態和章節狀態)。
接受後的生命週期
ADR 被接受後:
- **建立實作任務。**實作計畫中的每個項目以及後果中的每個後續行動都應轉換為可追蹤的任務(議題、工單或 TODO)。
- **在 PR 中參考 ADR。**在 PR 描述中連結到 ADR,例如「實作
contributing/decisions/2025-06-15-use-sqlite-for-test-database.md」。 - **新增程式碼參考。**在關鍵的實作點新增 ADR 路徑註解。
- **檢查驗證標準。**實作完成後,逐一檢查驗證核取方塊。在
## 更多資訊中更新 ADR 並記錄結果。 - **在觸發條件發生時重新審視。**如果 ADR 指定了重新審視的條件(「如果 X 發生,請重新考慮」),請監控這些條件。
索引
如果儲存庫中有一個 ADR 索引/日誌檔案(通常在 ADR 目錄中的 README.md 或 index.md),請保持更新。
首選:讓 scripts/new_adr.js --update-index 來處理。否則:
- 為新的 ADR 新增一個項目符號條目。
- 保持排序一致(如果使用數字則依數字排序;如果使用日期或 slug 則依日期或字母排序)。
初始化
當將 ADR 引入一個還沒有任何 ADR 的儲存庫時:
node /path/to/adr-skill/scripts/bootstrap_adr.js
這會建立目錄、一個索引檔案,以及一個已填寫內容的第一個 ADR(「採用架構決策記錄」),其中包含實際內容,說明團隊為何使用 ADR。使用 --json 參數以取得機器可讀的輸出。使用 --dir 參數來覆蓋目錄名稱。
類別(大型專案)
對於有許多 ADR 的儲存庫,可按子目錄進行組織:
docs/decisions/
backend/
2025-06-15-use-...