首頁 / Skills / 開發提效 / 診斷 Bug Diagnosing Bugs
開發提效

診斷 Bug Diagnosing Bugs

Matt PocockMITSkill 語言: 英文
授權已核對含腳本
演示真實執行紀錄 · claude-opus-5-5 · 2026年10月
Customers report that invoices issued on a Friday get a due date that lands on a Saturday. Example: an invoice issued Friday 2026-10-02 with the default 10 business-day terms shows a due date of Saturday 2026-10-17. Finance says it should be Friday 2026-10-16. The code is in billing/due_dates.py and the tests run with `python3 -m pytest -q`. Debug this and fix it.
Skill: diagnosing-bugs
Bash: git ls-files && cat billing/due_dates.py && ls GLOSSARY.md 2>/dev/null; python3 -m pytest -q 2>&1 | tail -5
Bash: cat tests/test_due_dates.py; git log --format='%h %s' -- billing; python3 -c "…
Bash: python3 -c "…
Bash: cat >> tests/test_due_dates.py <<'EOF'…
Edit: billing/due_dates.py
Bash: python3 -m pytest -q 2>&1 | tail -2; python3 -c "…

I fixed it: an invoice issued Friday 2026-10-02 now gets a due date of Friday 2026-10-16, and all 4 tests pass.

Cause: invoice_due_date in billing/due_dates.py had an extra step, commented "Invoices issued late in the week reach customers after the weekend." It added one calendar day whenever the invoice was issued on a Friday, Saturday or Sunday (issued.weekday() >= 4). The business-day count by itself was already correct (2026-10-16). Adding one calendar day to that Friday moved it to Saturday.

How I confirmed it:

  • A one-line check of the reported invoice returned 2026-10-17 Saturday, matching the customer reports.
  • Running only the business-day count (add_business_days) gave 2026-10-16, so that part was fine.
  • I checked every issue weekday against terms of 1–30 days. 18 combinations gave a weekend due date, and every one was issued Fri/Sat/Sun, which are exactly the days the extra step applied to.

Fix: I removed that extra step, so invoice_due_date now just returns add_business_days(issued, terms_days). A Saturday or Sunday invoice is still handled sensibly, because the count already starts from Monday.

Regression tests, added to tests/test_due_dates.py. Both failed before the fix and pass now:

  • test_invoice_issued_on_friday_is_due_on_a_friday: the exact case Finance reported.
  • test_invoice_due_date_never_falls_on_a_weekend: checks every issue weekday with terms of 1–30 days.

For Finance to confirm: this removes a deliberate rule. Besides the weekend problem, it also moved some weekday due dates one day later (e.g. a Friday invoice with 3-day terms was due Thursday, and is now due Wednesday). Finance's expected date implies no grace day at all, so I removed it entirely. If they do want extra time for late-week invoices, it should be added as a business day instead (which would make the example due Monday 2026-10-19); that conflicts with the date they gave.

I haven't committed anything; the changes are in your working tree.

Code changes recorded in the trial sandbox (git diff):

diff --git a/billing/due_dates.py b/billing/due_dates.py
index 35d3932..1fd87e9 100644
--- a/billing/due_dates.py
+++ b/billing/due_dates.py
@@ -14,8 +14,4 @@ def add_business_days(start: date, days: int) -> date:
 
 def invoice_due_date(issued: date, terms_days: int = 10) -> date:
     """Due date for an invoice with `terms_days` business-day payment terms."""
-    due = add_business_days(issued, terms_days)
-    # Invoices issued late in the week reach customers after the weekend.
-    if issued.weekday() >= 4:
-        due += timedelta(days=1)
-    return due
+    return add_business_days(issued, terms_days)
diff --git a/tests/test_due_dates.py b/tests/test_due_dates.py
index 497750a..4d1cbde 100644
--- a/tests/test_due_dates.py
+++ b/tests/test_due_dates.py
@@ -1,4 +1,4 @@
-from datetime import date
+from datetime import date, timedelta
 
 from billing.due_dates import add_business_days, invoice_due_date
 
@@ -9,3 +9,14 @@ def test_add_business_days_skips_weekend():
 
 def test_invoice_issued_on_monday():
     assert invoice_due_date(date(2026, 9, 28)) == date(2026, 10, 12)
+
+
+def test_invoice_issued_on_friday_is_due_on_a_friday():
+    assert invoice_due_date(date(2026, 10, 2)) == date(2026, 10, 16)
+
+
+def test_invoice_due_date_never_falls_on_a_weekend():
+    for offset in range(7):
+        issued = date(2026, 9, 28) + timedelta(days=offset)
+        for terms in range(1, 31):
+            assert invoice_due_date(issued, terms).weekday() < 5, (issued, terms)

Real run recorded with claude-code / claude-opus-5-5. Run in a temporary directory containing a sample project, with Edit and Bash enabled. Tool-call lines show only the first line of each command. The last block is the git diff recorded when the trial ended. Both model outputs are unmodified.

它做什麼

一套針對疑難 bug 與效能退化的嚴謹流程。核心觀點:只要有了針對這個 bug、判定明確的通過/失敗訊號,找原因就只是機械性工作,所以大部分心力應先花在做出這個訊號上。

運作方式

  1. 回饋迴圈: 做出一條指令,它在這個具體 bug 上會變紅、結果穩定、執行快速,且代理能無人值守地執行。在它出現之前不准空想原因。
  2. 重現並縮小: 確認它重現的正是你描述的症狀,再逐項刪減輸入,直到剩下的每一項都不可或缺。
  3. 提出假設: 寫出 3 到 5 個排序後、可證偽的假設,測試前先給你看。
  4. 加探針: 一次只改一個變數,優先使用除錯器而非日誌,並為每條除錯日誌加上唯一前綴,方便一次搜尋全部清除。
  5. 修正: 若存在合適的測試切入點,先寫回歸測試再修。
  6. 清理: 重新執行最初的迴圈,刪除除錯程式碼,並把已證實的原因寫進提交訊息。

適合情境

偶發 bug、「以前好好的」這類退化,以及變慢的程式碼。

需要了解

若儲存庫中有 GLOSSARY.md 與 ADR,它會先讀。我們試用時,它刪掉了一段有問題的調整,並補了兩個測試。

說明與風險

含一個 bash 範本腳本(hitl-loop.template.sh),只負責顯示提示並等你按 Enter 或輸入答案;我們讀過它,它不連網、不寫入檔案。Skill 本身會讓代理執行指令、加入暫時的除錯日誌、撰寫回歸測試並修改你的程式碼,所以會變動你的儲存庫。它要求代理對顯示的內容先遮蔽金鑰。 壓縮檔中另附原始儲存庫的 MIT 授權檔 LICENSE 與 agents/openai.yaml(供 Codex 使用的顯示名稱)。