O

systematic-debugging

作者 obra

四階段除錯工作流程,強制先查明根本原因再進行任何修正,並提供處理 flaky tests、驗證與測試汙染的實用工具。

Stars0
收藏0
評論0
分類调试
安裝指令
npx skills add https://github.com/obra/superpowers --skill systematic-debugging
總覽

概觀

什麼是 systematic-debugging?

systematic-debugging 技能是一套結構化的四階段流程,用來處理各種技術問題的除錯:測試失敗、正式環境的 bug、flaky tests、效能問題、建置錯誤,或整合失敗等。

與其一開始就試一個「快速修正」,或直接改動錯誤行所在的程式碼,這個技能會強迫你先找出問題的根本原因,再設計與驗證能長久維持的修正方案。它來自實際程式庫的實戰模式與腳本,包括 TypeScript 條件式等待 helper,以及用來找出測試汙染源的 Bash 腳本。

核心原則與鐵律

systematic-debugging 的核心其實很單純:

  • 核心原則: 一律先找出 root cause(根本原因)再試圖修正。只處理症狀的修正等同失敗。

  • 鐵律(Iron Law):

    NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
    

只要還沒完成調查階段,就不能提出或套用任何修正。這個設計就是要幫你抵抗時間壓力、瞎猜,以及「這次就例外」的理由。

適合哪些人使用?

systematic-debugging 適用於:

  • 開發者:在 JavaScript/TypeScript 專案中工作,希望修正可重現且可靠
  • 測試與 QA 工程師:經常面對 flaky 行為、隨機 timeout 與測試狀態汙染
  • CI/CD 與工具工程師:需要診斷偶發性的建置或整合失敗
  • Tech lead 與程式碼審查者:希望團隊有共用且嚴謹的除錯流程

如果你比起快速補破洞,更在意高品質的根因分析,這個技能會非常合適。

它能解決什麼問題?

在以下情境時,使用 systematic-debugging 技能:

  • 調查反覆出現、屢修屢掛的 測試失敗
  • 追查仰賴任意 timeout 或 race condition 的 flaky tests
  • 釐清 非預期行為 的實際原因,而非只是把錯誤訊息消音
  • 診斷 效能問題,或節奏、時間高度敏感的流程
  • 除錯只在 CI 或高負載情況才發生的 建置或整合失敗
  • 找出哪個 測試汙染狀態,或留下不該存在的檔案/目錄

此 repository 也包含:

  • condition-based-waiting.mdcondition-based-waiting-example.ts:示範如何在 TypeScript 中以穩定的條件式等待取代 setTimeout/sleep
  • defense-in-depth.md:說明如何在多層加入驗證,讓某些 bug 在結構上根本不可能發生
  • find-polluter.sh:Bash helper,用來找出會產生不該存在檔案或狀態的特定測試
  • root-cause-tracing.md:教你如何沿著呼叫鏈一路往回追,找到錯誤的真正起點

什麼時候適合用 systematic-debugging?

在這些情況下,systematic-debugging 非常適合:

  • 你正遭受時間壓力,很想直接猜一個修正
  • 某個問題多次重現、修了又壞
  • 你希望有一套自己或團隊都可重複使用的除錯流程
  • 你正在穩定一套 flaky 的測試組合,或清理被汙染的測試環境

它可能 比較不適合 用在:

  • 你只需要一次性的快速產生程式碼或 refactor,不打算做深入調查
  • 除錯範圍不在這裡描述的技術領域內(例如純流程或組織問題)
  • 你不想照步驟走,更偏好完全 ad-hoc 式的嘗試

如果你的目標是「先快補一個,之後再重修也沒關係」,這個流程會讓你覺得有點嚴格。如果你的目標是「一次修好,之後不再返工」,systematic-debugging 就是為你而設計的。

如何使用

安裝與設定

要在相容的 agent 或工具環境中安裝 systematic-debugging 技能,使用提供的 npx 指令:

npx skills add https://github.com/obra/superpowers --skill systematic-debugging
``

這會從 `obra/superpowers` repository 中的 `skills/systematic-debugging` 下載技能定義,以及相關文件與腳本。

安裝完成後:

1. 在你的 agent 或 skills 介面中開啟 `systematic-debugging` 技能。
2. 確認你的 workspace 能存取專案 repository、測試指令與 log。
3. 確認你可以看到隨附的 markdown 說明與腳本:
   - `SKILL.md`
   - `condition-based-waiting.md`
   - `defense-in-depth.md`
   - `root-cause-tracing.md`
   - `find-polluter.sh`

### 需要認識的檔案與元件
在評估是否安裝,以及日常使用時,以下檔案最關鍵:

- **`SKILL.md`** – 定義完整的四階段系統化除錯流程、規則與反模式;這是技能的核心。
- **`condition-based-waiting.md`** – 說明如何用條件式等待取代測試中的任意 timeout。
- **`condition-based-waiting-example.ts`** – 提供 `waitForEvent` 等 TypeScript utility,示範如何在 `ThreadManager` 與 event types 上實作條件式等待。
- **`defense-in-depth.md`** – 示範如何在多個層級(入口、商業邏輯、環境防護、logging)加入驗證,讓整個 bug 類別無法再出現。
- **`find-polluter.sh`** – Bash 腳本,透過逐一執行測試檔,找出會產生指定路徑(狀態汙染)的那個測試。
- **`root-cause-tracing.md`** – 帶你從 stack trace 一路追到原始觸發點,再結合 defense-in-depth 一起使用。
- **`CREATION-LOG.md`** – 描述這套框架是如何被抽取與強化的 meta-log,有助於理解設計思路,但不是日常使用必讀。

對 **JavaScript/TypeScript** 開發者來說,TypeScript 範例與 Bash 腳本通常可以直接調整後放進自己的專案。

### 執行四階段工作流程
`systematic-debugging` 流程分成四個必經階段(詳見 `SKILL.md`)。你必須在完成前一階段後,才能進入下一階段。

#### Phase 1 – 根本原因調查
在動任何程式碼、設定或測試之前:

- **仔細閱讀錯誤訊息與 log。**
  - 不要只是掃過 stack trace 或警告。
  - 把行號、檔案路徑與錯誤碼都記錄下來。
- **讓問題可以穩定重現。**
  - 找出最小且可靠的重現指令。
  - 記錄需要哪些輸入與環境因素。

這個階段不能提出或實作修正。目標是徹底搞清楚:到底哪裡、在什麼情況下、發生了什麼樣的失敗。

#### Phase 2 – 模式分析
一旦你可以穩定重現問題:

- 一次只改變一個因素(輸入、設定、環境),觀察結果如何改變。
- 找出「邊界」:在哪些數值或條件下,行為從通過變成失敗。
- 使用 log、assertion 或暫時性的 instrumentation 來縮小失敗路徑。

在 Phase 2 結束時,你應該已經理解問題的輪廓與觸發條件,而不只是最後看到的錯誤訊息。

#### Phase 3 – 假設與設計
現在你可以提出假設:

- 清楚說出你認為的 root cause 是什麼(資料流、缺少驗證、時間問題、路徑錯誤等等)。
- 設計一個**單一且聚焦**的變更,專門對準這個 root cause。
- 規劃你要如何用前面整理好的重現步驟來驗證這個假設。

如果假設被推翻,你就回到調查/分析階段,而不是不停疊加更多「可能有用」的修正。

#### Phase 4 – 實作與驗證
只有在有明確假設之後,才可以改動程式碼或設定:

- 套用最小但能直接針對 root cause 的變更。
- 先跑最小重現步驟,再跑完整的測試組合。
- 參考以下文件的建議:
  - `defense-in-depth.md`:在多層加入驗證
  - `root-cause-tracing.md`:確認你修正的是實際根源
- 確認修正具有韌性(例如在高負載、CI,以及 Phase 2 找出的邊界情境下都能正常運作)。

如果修正結果不如預期,你**不要**再堆更多變更,而是回到前面階段重新調查。

### 在專案中使用除錯 utilities

#### 用條件式等待處理 flaky tests(JavaScript/TypeScript)
依賴 `setTimeout` 或 `sleep` 的測試,常會在機器變慢、變快或高負載時出問題。`condition-based-waiting.md` 與 `condition-based-waiting-example.ts` 提出更好的做法:改成等待你真正關心的條件成立。

典型遷移範例:

```typescript
// ❌ Before: guessing timing
await new Promise(r => setTimeout(r, 50));
const result = getResult();
expect(result).toBeDefined();

// ✅ After: waiting for condition
await waitFor(() => getResult() !== undefined);
const result = getResult();
expect(result).toBeDefined();

condition-based-waiting-example.ts 中提供如下 helper:

export function waitForEvent(
  threadManager: ThreadManager,
  threadId: string,
  eventType: LaceEventType,
  timeoutMs = 5000
): Promise<LaceEvent> { /* ... */ }

將這些模式套用到你的測試基礎建設中:

  1. 將 utility 複製或重寫到專案的測試 helper 中。
  2. 用條件式等待取代任意的 setTimeout/sleep 呼叫。
  3. 重跑測試組合,確認 flaky 程度明顯降低。

這直接呼應 systematic-debugging 的目標:消除 root cause,而不是亂加 timeout 來碰運氣。

使用 find-polluter.sh 找出測試汙染源

如果測試跑完會留下多餘檔案或目錄,或在其他方面汙染狀態,可以用 find-polluter.sh 來找出真正的責任測試。

在專案根目錄執行(依需求調整參數):

./find-polluter.sh <file_or_dir_to_check> <test_pattern>

# Example
./find-polluter.sh '.git' 'src/**/*.test.ts'

腳本會:

  • 找出符合 pattern 的測試檔案
  • 逐一以 npm test <file> 執行
  • 每次跑完後檢查指定檔案或目錄是否出現
  • 發現第一個建立該路徑的測試後停止,並輸出可以重跑與檢查該測試的指令

這個工具非常符合 systematic-debugging 的 Phase 1 與 Phase 2:幫你可靠地重現並隔離狀態汙染問題。

套用 defense-in-depth 驗證

當你的調查顯示 bug 是由無效資料或錯誤假設引起時,defense-in-depth.md 建議在多個層級加上驗證:

  • 入口驗證(Entry point validation) – 在邊界(API、CLI、UI handler)就拒絕明顯無效的輸入。
  • 商業邏輯驗證(Business logic validation) – 確認資料在特定操作下是合理的。
  • 環境防護(Environment guards) – 防止在錯誤的環境或路徑執行危險操作。
  • 診斷用 logging – 當問題仍然溜過來時,提供足夠的背景資訊。

例如,在驗證 workingDirectory 參數時:

function createProject(name: string, workingDirectory: string) {
  if (!workingDirectory || workingDirectory.trim() === '') {
    throw new Error('workingDirectory cannot be empty');
  }
  if (!existsSync(workingDirectory)) {
    throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
  }
  if (!statSync(workingDirectory).isDirectory()) {
    throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
  }
  // ... proceed
}

在 Phase 4 實作修正時套用這些模式,可以大幅降低同類問題經由其他程式路徑再度出現的機會。

什麼時候不一定需要用到這個技能

以下情況可能不需要或可以延後使用 systematic-debugging

  • 你目前正在做 prototype,接受程式碼可拋棄、bug 也暫時無妨
  • 問題非常瑣碎且完全理解(例如開發中立刻發現的 typo),不值得動用完整四階段流程
  • 你只想拿走單一 utility(像條件式等待),不打算採用整套流程

即便如此,這條鐵律仍然很有參考價值:如果你發現自己開始一個接一個地瞎猜修正,那就代表該切換到 systematic-debugging 的作法了。

常見問題(FAQ)

systematic-debugging 實際上會怎麼改變我的工作流程?

你不再從錯誤訊息直接跳到改程式碼,而是先經過調查、模式分析,再提出假設,最後才實作。實務上代表:

  • 你會在改碼前先取得穩定的重現方式
  • 你會刻意變動條件,了解問題所在的範圍
  • 你會針對每個已驗證的假設,只寫一個聚焦的修正

結果通常是:更少的 revert、更少隱性回歸,除錯時間也更可預測。

要如何安裝 systematic-debugging 技能?

使用 npx skills 指令:

npx skills add https://github.com/obra/superpowers --skill systematic-debugging

安裝完成後,在你的 agent 或 skills 目錄中開啟該技能,接著閱讀 SKILL.md 了解完整流程,並參考其他 markdown 檔案取得模式與實例。

systematic-debugging 是否支援 JavaScript 和 TypeScript 除錯?

是的。雖然這套框架本身與語言無關,但 repository 內提供了多個針對 JavaScript/TypeScript 的實作工具:

  • condition-based-waiting-example.ts:用於測試中的條件式等待
  • defense-in-depth.mdroot-cause-tracing.md 中以 TypeScript 例子說明的模式
  • find-polluter.sh 預設假設使用 npm test,與常見的 JS/TS 測試框架非常相容

你可以依照專案結構與工具鏈自行調整這些 utility。

我可以用 systematic-debugging 來處理 flaky test 自動化問題嗎?

可以,而且這是它最擅長的場景之一。你可以結合:

  • SKILL.md 中的四階段流程來調查與理解 flakiness
  • condition-based-waiting.md 與 TypeScript 範例,用條件式等待取代時間猜測
  • find-polluter.sh 來找出汙染狀態或建立多餘檔案的測試

搭配使用這些工具,可以把原本不穩定的測試,轉成穩定且可重現的檢查。

systematic-debugging 只適用在測試,還是也適合正式環境的 bug?

這套流程適用於任何技術性問題:

  • 測試失敗與 flakiness
  • 正式環境 bug 與事故
  • 效能問題
  • 建置與整合失敗

範例與工具偏重在測試與開發流程,但各個階段與原則也明確涵蓋正式環境情境。

如果我時間壓力很大,只想快點修掉怎麼辦?

這個技能就是為了對抗「先試一個 quick fix 再說」的衝動而寫的。它強調:

  • 在不做 root-cause 調查的情況下急著修,通常只會造成反覆嘗試與返工
  • 只處理症狀的修正,往往會帶來新的問題

實務經驗顯示,就算在緊急狀況下,花幾分鐘走過 Phase 1 與 Phase 2,通常也能在整體上節省時間。

我一定要每次都完整走完四個階段嗎?

systematic-debugging 的設計精神是:跳過階段應該是少數例外,而不是常態。對於小型、且你已完全掌握原因的問題(例如在小 refactor 中立刻看出來的錯誤),你可以壓縮步驟。但只要:

  • 問題會反覆出現
  • 你並不真正理解它為何發生
  • 之前的修正都沒有成功

……那就非常建議完整走過四階段流程。

root-cause tracing 跟 defense-in-depth 之間有什麼關係?

root-cause-tracing.md 幫你從可見的錯誤一路沿著呼叫鏈追溯,直到原始觸發點;defense-in-depth.md 則說明如何透過以下方式防止類似 bug 再次出現:

  • 在真正的根源完成修正
  • 在多個層級加入驗證

例如,如果 git init 在錯誤目錄下執行而失敗,tracing 會指出是什麼函式傳入了錯誤路徑;接著 defense-in-depth 則在更早的層級加入驗證與防護,讓無效路徑直接被拒絕。

不複製任何 repo 裡的程式碼,只用這個技能可以嗎?

可以。systematic-debugging 的核心價值在於 SKILL.md 描述的結構化除錯流程。你可以:

  • 直接在自己的環境中遵循這些階段與規則
  • 把調查與分析的模式套用到任何語言或技術堆疊

TypeScript 與 Bash helper 只是額外加速工具,對 JS/TS 與類 Unix 環境特別好用,但並非必須。

要到哪裡查看 systematic-debugging 的所有內容?

安裝後,在 obra/superpowersskills/systematic-debugging 底下開啟檔案或 repository 檢視。建議優先查看:

  • SKILL.md
  • condition-based-waiting.md
  • condition-based-waiting-example.ts
  • defense-in-depth.md
  • root-cause-tracing.md
  • find-polluter.sh

這些檔案提供完整的 systematic-debugging 工作流程,以及用來除錯與穩定測試的具體工具。

評分與評論

尚無評分
分享你的評論
登入後即可為這項技能評分並留言。
G
0/10000
最新評論
儲存中...