Bug → 規格(spec)回溯協定。當發現 Bug 或測試失敗時,深入追蹤根本原因,評估是否新增 §V 不變量(invariant)來防止問題復發,並將記錄追加至 §B。 這是 SDD(規格驅動開發)比「先規劃再執行」模式更深一層的核心精髓。 觸發時機:測試失敗、收到 Bug 報告、事後檢討(post-mortem),或使用者明確要求時。
backprop — Bug → 規格 (spec)
「先規劃再執行」模式只修程式碼,過後就忘。
SDD(規格驅動開發)在修復程式碼的同時同步修訂規格,讓問題絕不可能復發。
這個修訂規格的動作,就是反向傳播(backprop)。
何時執行 BACKPROP
- 在
/build驗證階段測試失敗。 - 使用者回報 Bug。
- 生產環境事故後進行事後檢討(post-mortem)。
/check標示 VIOLATE 且已找到根本原因。
執行六大步驟
1. 追蹤 (TRACE)
閱讀失敗輸出訊息或 Bug 報告。
找到異常行為發生的精確 檔案:行數。
用一句極簡直白的話點出根本原因。
2. 分析 (ANALYZE)
自問三個問題:
- 新增 §V 不變量(invariant)能否攔截這類 Bug?(最常見情況:可以)
- 是 §I 有誤——規格要求了程式碼無法提供的結構?(偶爾發生)
- 是 §T 有誤——我們自始至終做錯了功能?(罕見但確實存在)
3. 提案 (PROPOSE)
起草規格變更。絕對不可省略 §B;§V/§I/§T 則依實際狀況調整。
範本:
§B row: B<next>|<date>|<root cause>|V<N>
§V line: V<next>: <testable rule that would have caught it>
範例:
§B row: B3|2026-04-20|refund job ran twice on retry|V7
§V line: V7: ∀ refund → idempotency key check before charge reversal
4. 產生測試 (GENERATE TEST)
沒有搭配測試的新不變量等於是謊言。務必先新增會失敗的測試。
測試命名需明確引用該不變量:TestV7_RefundIdempotent。
5. 驗證 (VERIFY)
修復程式碼。執行該測試,必須通過。執行完整測試套件,確保沒有退化(regression)。
6. 記錄 (LOG)
將規格修改、測試案例與程式碼修復整合為單一 commit。
Commit 訊息格式:backprop §B.<n> + §V.<N>: <單行原因描述>。
甚麼是好的不變量(INVARIANT)
- 能在程式碼中被測試(可透過 grep 搜尋或透過 assert 斷言)。
- 作用域落在大於或等於某種行為,而非單一檔案。
- 儘可能使用正面敘述(如以
! 必須成立優先於⊥ 嚴格禁止)。 - 在適用處引用對應的 §I 介面。
不良範例:V8: code should be correct.
良好範例:V8: ∀ pg_query ! params interpolated via driver, ⊥ string concat.
何時不該新增 §V
- Bug 純粹是偶發的機械式打字錯誤,無規律或模式可言(例如一次性工具腳本中的
i++誤寫為i--)。 - 修復屬於一次性的資料搬遷(migration)。
- 根本原因出在外部套件依賴(應改為升級套件,並在 §C 中註記)。
但依然要追加 §B 記錄——記錄團隊已考量過此失敗模式。日後若出現相似特徵的 Bug,搜尋 §B 即可找到先例。
產出結構
每次執行 backprop 均會產生:
- §B 記錄條目(必備)。
- §V 記錄條目(通常有)。
- 測試檔案(新增 §V 時必備)。
- 程式碼修復。
- 一個 commit。
無須任何儀表板,無須額外日誌檔。SPEC.md 搭配 git 就是最完整的歷史紀錄。




