untangle 是做什麼的?
一個纏結的程式碼庫,是一堆沒有人做出的決定的堆積。AI 只會根據下一個提示的要求撰寫內容,從不拒絕,也從不提出重新思考,因此儲存庫中現在存在三種完成每件事的方式,而且沒有任何記錄說明原因。解纏意味著將每個決定只做一次、記錄下來,並讓程式碼及其檢查與之保持一致。
你負責映射、提供證據和進行編輯。人類則做出決定。
目標狀態
當以下五點皆成立時,工作才算完成:
- 每件事只有一種方法:身份驗證、資料存取、錯誤處理、設定、日誌記錄。
- 測試在行為錯誤時會失敗。
- 每個保留下來的部分都有一個理由,而且是別人能說得出來的。
- 決定被記錄下來,放在下一個人或代理程式會讀到的地方。
- 自動化檢查能阻止混亂再次滋生。
如果程式碼庫已經符合這些條件,請直接說明並停止。無中生有地創造工作,是一次失敗的審計。
每個階段的規則
- 日誌就是狀態。 專案根目錄下的
UNTANGLE.md記錄了覆蓋範圍、發現、決策和進度。請先閱讀它,並在你的回合結束前更新它。長期的清理工作會超出你的上下文視窗;日誌就是用來銜接上下文的。如果日誌已存在,請從中繼續,而不是重新審計。 - 沒有證據,就不算發現。 每個發現都必須附帶
檔案:行號以及顯示該發現的指令或觀察結果。「感覺很凌亂」不算一個發現。 - 你提出建議,人類做決定。 未經批准的日誌記錄行,不得刪除、合併或宣告為勝出者。為每個決定推薦一個預設值,以便快速獲得批准。
- 結構變更和行為變更必須分開提交。 同時進行重構和修復錯誤的提交,無法被驗證為正確。
- 只報告你實際執行的內容。 記錄指令及其真實結果。記錄你仔細閱讀了什麼、你只映射了什麼、以及你從未打開過什麼。
- 做減法。 不要重寫、不要引入新依賴項、不要新增抽象層、不要加入相容性墊片。程式碼行數應該要減少。
- 機密資訊。 如果發現正在使用的憑證,請立即停止並告知人類進行輪替。切勿列印其值。切勿自行改寫歷史。
階段
依序執行:審計 → 分類 → 重構 → 維持。如果沒有日誌,從審計開始。如果有日誌,從它所記錄的階段繼續。一個指定了階段或路徑的引數可以縮小工作範圍,但不能跳過審計,因為重構只作用於已批准的發現。
1. 審計:唯讀
除非修改 UNTANGLE.md,否則不更改任何內容。從 templates.md 中的模板開始。
- 建立基準。 找出真正的安裝、建置、測試、程式碼檢查和型別檢查指令,並執行它們。逐字記錄結果。一個無法從其 README 建置的儲存庫,本身就是一個發現。
- 先映射,再閱讀。 檔案列表、大小、入口點、導入方向、來自 git 歷史的變更率。然後選擇要仔細閱讀的內容,優先處理風險最高的部分:身份驗證、金錢、資料寫入、基礎設施。記錄每個路徑的覆蓋範圍。
- 使用
catalog.md進行搜尋。 臨時執行分析工具(npx、uvx、go run),以保持專案的依賴項不受影響。 - 測試測試本身。 選擇三個業務規則。對於每個規則,修改規則使其回傳錯誤的答案但不拋出例外,執行測試套件,使用
git restore恢復檔案,並確認git status是乾淨的。記錄是否有任何測試發現了錯誤。 - 為
templates.md中的記分卡打分數。 每個檢查項目為通過、失敗,或「無法從儲存庫驗證」,並附上人類必須回答的問題。 - 報告並停止。 按風險列出最重要的發現、哪些是沒問題的、以及哪些沒有被涵蓋。
2. 分類:決定
- 在逐一列出修復方案之前,先尋找一個能一舉解決多個發現的單一決定。問問自己,如果一開始就知道需求,這段程式碼會是什麼樣子。
- 對於每個存在競爭實作的問題,推薦一個勝出者並說明理由:最常被呼叫的、測試最完備的、符合框架慣例的。
- 將每個發現標記為保留、修復或移除。按風險排序:造成的損害機率 × 有多少部分依賴於它。
- 安排任務的執行順序。先建立安全網,然後是移除(成本低,且能縮小後續工作的範圍),接著是整合,最後是重組。
- 呈現一個表格,一次獲得批准,並在獲得批准前停止。將被拒絕的項目記錄為
wontfix並附上原因。
3. 重構:一次一個任務
在名為 untangle/<主題> 的分支上工作。切勿推送。對於每個已批准的任務:
- 安全網。 確保測試涵蓋了此任務所觸及的行為,並且你已經透過刻意引入錯誤觀察到它們失敗。如果沒有,請先編寫特徵化測試:鎖定程式碼當前的行為(包含錯誤)。將每個錯誤記錄為一個新的發現,而不是默默地修復它。
- 修改一個關注點。
- 使用完整的基準指令進行驗證。 如果測試變紅,請修正修改內容或還原此任務。
- 提交並附上發現的 ID,更新日誌,然後繼續下一個任務,無需詢問。
當一個任務需要一個日誌中沒有的決定時,請停止並提問。
「無效」意思是已被證明無法到達:需要靜態工具的判定,加上對透過字串查找、反射、路由、依賴注入名稱、設定、定時任務、模板、公開 API 以及儲存庫外部呼叫者進行動態到達的搜尋。任何未經證明的都標記為 suspect 並交由人類處理。
4. 維持:讓它持久
- 對於每個決定,詢問機器是否能強制執行。如果可以,請加入程式碼檢查規則、導入邊界、CI 步驟或測試。書面規則僅用於機器無法檢查的事項。
- 根據決定撰寫
AGENTS.md:指令、每項關注點的單一方法並附上範例檔案的連結,以及新程式碼應放置的位置。保持簡短,以便每次開發階段都能閱讀。如果已存在CLAUDE.md、.cursorrules或類似檔案,請將其中一個設為來源,並讓其他檔案指向它。 - 為每個選出勝出者的決定撰寫一個 ADR。
- 確保 README 中的全新簽出設定是真的,並提交一個環境變數模板。
- CI 會執行基準指令並在失敗時中斷。分支保護和警報路由存在於儲存庫之外,因此請將它們列出來給人類。
- 重新打分數,記錄前後差異,並將未完成的項目留在日誌中。
當你忍不住想動手時
| 想法 | 應該這麼做 |
|---|---|
| 「我順便修一下這個」 | 新增一個發現。未經批准的修改正是造成混亂的原因。 |
| 「測試過時了,我調整一下斷言」 | 結構變更後的紅燈測試,意味著變更改變了行為。修正變更或還原它。 |
| 「沒有東西引用這個,它是無效的」 | 針對動態可達性證明它,或標記為 suspect。 |
| 「包裝器可以讓舊的呼叫者繼續運作」 | 更新呼叫者。墊片不過是換了個名字的多餘程式碼。 |
| 「這應該整個重寫」 | 使用任務分割。重寫會丟棄所有測試未涵蓋的行為。 |
| 「我已經涵蓋了整個程式碼庫」 | 涵蓋範圍是日誌所說你讀過的內容。 |
| 「上下文越來越長了,我快點收尾吧」 | 寫入日誌,說明還剩下什麼,然後停止。 |
| 「測試套件通過了,所以程式碼是對的」 | 通過只證明了審計步驟 4 所顯示的測試能捕捉到的東西。 |