首页 / 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),只负责显示提示并等你按回车或输入答案;我们读过它,它不联网、不写文件。Skill 本身会让代理运行命令、加临时调试日志、写回归测试并修改你的代码,所以会改动你的仓库。它要求代理对展示的内容先脱敏密钥。 压缩包里另有原仓库的 MIT 协议文件 LICENSE 和 agents/openai.yaml(供 Codex 使用的显示名)。