系統化調試
在遇到任何 bug、測試失敗或意外行為時使用。分為四個階段的根本原因調查——在未理解問題之前,嚴禁進行修復。
技能元數據
| 來源 | 捆綁(默認安裝) |
| 路徑 | skills/software-development/systematic-debugging |
| 版本 | 1.1.0 |
| 作者 | Hermes Agent(改編自 obra/superpowers) |
| 許可證 | MIT |
| 標籤 | debugging, troubleshooting, problem-solving, root-cause, investigation |
| 相關技能 | test-driven-development, writing-plans, subagent-driven-development |
參考:完整 SKILL.md
以下是 Hermes 在觸發此技能時加載的完整技能定義。這是技能激活時代理所看到的指令。
系統化調試
概述
隨意修復會浪費時間並引入新的 bug。快速補丁會掩蓋潛在問題。
核心原則: 在嘗試修復之前,務必找到根本原因。僅修復症狀即為失敗。
違反此流程的字面要求,即違背了調試的精神實質。
鐵律
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
如果未完成第一階段,不得提出修復方案。
何時使用
適用於任何技術問題:
- 測試失敗
- 生產環境中的 bug
- 意外行為
- 性能問題
- 構建失敗
- 集成問題
尤其在以下情況下使用:
- 時間緊迫(緊急情況容易讓人傾向於猜測)
- “只需快速修復一下”看起來顯而易見
- 已經嘗試過多次修復
- 之前的修復未生效
- 尚未完全理解問題
以下情況不要跳過:
- 問題看似簡單(簡單的 bug 也有根本原因)
- 趕時間(匆忙必然導致返工)
- 有人要求立即修復(系統化方法比盲目嘗試更快)
四個階段
在進入下一階段之前,必須完成當前階段。
第一階段:根本原因調查
在嘗試任何修復之前:
1. 仔細閱讀錯誤信息
- 不要跳過錯誤或警告
- 它們通常包含確切的解決方案
- 完整閱讀堆棧跟蹤
- 注意行號、文件路徑、錯誤代碼
操作: 對相關源文件使用 read_file。使用 search_files 在代碼庫中搜索錯誤字符串。
2. 穩定復現
- 能否可靠地觸發它?
- 確切步驟是什麼?
- 是否每次都會發生?
- 如果無法復現 → 收集更多數據,不要猜測
操作: 使用 terminal 工具運行失敗的測試或觸發 bug:
# Run specific failing test
pytest tests/test_module.py::test_name -v
# Run with verbose output
pytest tests/test_module.py -v --tb=long
3. 檢查近期變更
- 哪些變更可能導致此問題?
- Git diff、最近的提交
- 新依賴項、配置變更
操作:
# Recent commits
git log --oneline -10
# Uncommitted changes
git diff
# Changes in specific file
git log -p --follow src/problematic_file.py | head -100
4. 在多組件系統中收集證據
當系統包含多個組件時(API → 服務 → 數據庫,CI → 構建 → 部署):
在提出修復方案之前,添加診斷 instrumentation:
對於每個組件邊界:
- 記錄進入組件的數據
- 記錄離開組件的數據
- 驗證環境/配置的傳播
- 檢查每一層的狀態
運行一次以收集證據,顯示問題出現在何處。 然後分析證據以識別失敗的組件。 接著調查該特定組件。
5. 追蹤數據流
當錯誤位於調用棧深處時:
- 不良值源自何處?
- 是誰用不良值調用了此函數?
- 持續向上遊追蹤,直到找到源頭
- 在源頭修復,而非在症狀處修復
操作: 使用 search_files 追蹤引用:
# Find where the function is called
search_files("function_name(", path="src/", file_glob="*.py")
# Find where the variable is set
search_files("variable_name\\s*=", path="src/", file_glob="*.py")
第一階段完成檢查清單
- 已充分閱讀並理解錯誤信息
- 問題已穩定復現
- 已識別並審查近期變更
- 已收集證據(日誌、狀態、數據流)
- 問題已隔離到特定組件/代碼
- 已形成根本原因假設
停止: 在理解問題發生的原因之前,不要進入第二階段。
第二階段:模式分析
在修復之前先找到模式:
1. 尋找可行的示例
- 在同一代碼庫中定位類似的可行代碼
- 有哪些與破損部分相似且正常工作的代碼?
操作: 使用 search_files 查找可比模式:
search_files("similar_pattern", path="src/", file_glob="*.py")
2. 與參考實現對比
- 如果在實現某種模式,請完整閱讀參考實現
- 不要略讀——逐行閱讀
- 在應用之前充分理解該模式
3. 識別差異
- 正常工作部分與破損部分之間有何不同?
- 列出每一個差異,無論多麼微小
- 不要假設“那應該無關緊要”
4. 理解依賴關係
- 這需要其他哪些組件?
- 需要哪些設置、配置、環境?
- 它做出了哪些假設?
第三階段:假設與測試
科學方法:
1. 形成單一假設
- 清晰陳述:“我認為 X 是根本原因,因為 Y”
- 寫下來
- 具體明確,避免模糊
2. 最小化測試
- 進行最小可能的更改以測試假設
- 一次只改變一個變量
- 不要同時修復多個問題
3. 在繼續之前驗證
- 生效了嗎?→ 進入第四階段
- 沒生效?→ 形成新假設
- 不要在此基礎上添加更多修復
4. 當你不知道時
- 說“我不理解 X”
- 不要假裝知道
- 向用戶尋求幫助
- 進行更多研究
第四階段:實施
修復根本原因,而非症狀:
1. 創建失敗的測試用例
- 儘可能簡單的復現步驟
- 如果可能,使用自動化測試
- 在修復之前必須擁有測試用例
- 使用
test-driven-development技能
2. 實施單一修復
- 針對已識別的根本原因
- 一次僅做一個更改
- 不進行“既然都在這兒了”式的改進
- 不進行捆綁式重構
3. 驗證修復
# Run the specific regression test
pytest tests/test_module.py::test_regression -v
# Run full suite — no regressions
pytest tests/ -q
4. 如果修復無效——三次法則
- 停止。
- 計數:你嘗試了多少次修復?
- 如果 < 3 次:返回第一階段,利用新信息重新分析
- 如果 ≥ 3 次:停止並質疑架構(見下文步驟 5)
- 在沒有進行架構討論的情況下,不要嘗試第 4 次修復
5. 如果 3 次或更多修復失敗:質疑架構
表明存在架構問題的模式:
- 每次修復都在不同位置揭示了新的共享狀態/耦合
- 修復需要“大規模重構”才能實施
- 每次修復都在其他地方產生了新的症狀
停止並質疑基礎:
- 這種模式在根本上是否健全?
- 我們是否只是“因慣性而堅持”?
- 我們應該重構架構,還是繼續修復症狀?
在嘗試更多修復之前,與用戶討論。
這不是假設失敗——這是架構錯誤。
危險信號——停止並遵循流程
如果你發現自己在想:
- “先快速修復,稍後再調查”
- “試著改一下 X 看看是否有效”
- “添加多個更改,運行測試”
- “跳過測試,我會手動驗證”
- “可能是 X,讓我修復它”
- “我不完全理解,但這可能有效”
- “模式說是 X,但我會用不同的方式適配”
- “主要問題是:[未經調查就列出修復方案]”
- 在追蹤數據流之前提出解決方案
- “再試一次修復”(當已經嘗試過 2 次或更多時)
- 每次修復都在不同位置揭示出新問題
所有這些都意味著:停止。返回第一階段。
如果 3 次或更多修復失敗: 質疑架構(第四階段步驟 5)。
常見的合理化藉口
| 藉口 | 現實 |
|---|---|
| “問題很簡單,不需要流程” | 簡單問題也有根本原因。對於簡單 bug,流程很快。 |
| “緊急情況,沒時間走流程” | 系統化調試比盲目猜測和反覆試錯更快。 |
| “先試試這個,然後再調查” | 第一次修復確立了模式。從一開始就要做對。 |
| “確認修復有效後我再寫測試” | 未經測試的修復無法持久。先寫測試才能證明有效性。 |
| “一次性修復多個問題節省時間” | 無法隔離真正生效的部分。會導致新 bug。 |
| “參考資料太長,我會適配模式” | 部分理解必然導致 bug。完整閱讀資料。 |
| “我看到了問題,讓我修復它” | 看到症狀 ≠ 理解根本原因。 |
| “再試一次修復”(在 2 次或更多失敗後) | 3 次或更多失敗 = 架構問題。質疑模式,不要再次修復。 |
快速參考
| 階段 | 關鍵活動 | 成功標準 |
|---|---|---|
| 1. 根本原因 | 閱讀錯誤信息、復現問題、檢查變更、收集證據、追蹤數據流 | 理解是什麼和為什麼 |
| 2. 模式 | 查找有效示例、進行比較、識別差異 | 知道不同之處 |
| 3. 假設 | 形成理論、最小化測試、一次一個變量 | 確認假設或形成新假設 |
| 4. 實施 | 創建迴歸測試、修復根本原因、驗證 | Bug 已解決,所有測試通過 |
Hermes Agent 集成
調查工具
在第一階段使用這些 Hermes 工具:
search_files— 查找錯誤字符串、追蹤函數調用、定位模式read_file— 讀取帶行號的源代碼以進行精確分析terminal— 運行測試、檢查 git 歷史、復現 bugweb_search/web_extract— 研究錯誤消息、庫文檔
配合 delegate_task
對於複雜的多組件調試,分派調查子代理:
delegate_task(
goal="Investigate why [specific test/behavior] fails",
context="""
Follow systematic-debugging skill:
1. Read the error message carefully
2. Reproduce the issue
3. Trace the data flow to find root cause
4. Report findings — do NOT fix yet
Error: [paste full error]
File: [path to failing code]
Test command: [exact command]
""",
toolsets=['terminal', 'file']
)
配合 test-driven-development
修復 bug 時:
- 編寫復現 bug 的測試(RED)
- 系統化調試以找到根本原因
- 修復根本原因(GREEN)
- 測試證明修復有效並防止迴歸
實際影響
來自調試會話的數據:
- 系統化方法:15-30 分鐘修復
- 隨機修復方法:2-3 小時的反覆試錯
- 首次修復成功率:95% vs 40%
- 引入的新 bug:接近零 vs 常見
沒有捷徑。沒有猜測。系統化方法永遠勝出。