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.
できること
手強いバグや性能の劣化に取り組むための規律ある手順です。中心となる考えは、そのバグに対する明確な成功/失敗のシグナルさえ手に入れば原因探しは機械的な作業になる、だから労力の大半はまずそのシグナル作りに使う、というものです。
仕組み
- フィードバックループ: このバグで確実に失敗し、結果が安定していて高速で、エージェントが無人で実行できるコマンドを 1 つ作ります。これができるまで原因の推測はしません。
- 再現と最小化: あなたの言う症状が再現されることを確かめ、残りの要素がすべて不可欠になるまで入力を削ります。
- 仮説: 反証可能な仮説を順位付けして 3〜5 個書き、検証の前にあなたに見せます。
- 計測: 一度に変える変数は 1 つ。ログよりデバッガーを優先し、デバッグログにはすべて固有の接頭辞を付けて、1 回の検索で消せるようにします。
- 修正: 適切なテストの接点があれば、先に回帰テストを書いてから直します。
- 後片付け: 最初のループを再実行し、デバッグ用コードを消し、確認できた原因をコミットメッセージに書きます。
向いている場面
たまにしか起きないバグ、「前は動いていた」という退行、遅いコード。
知っておきたいこと
リポジトリに GLOSSARY.md や ADR があれば先に読みます。私たちの試用では、問題のある補正を削除し、テストを 2 つ追加しました。
bash のテンプレートスクリプト(hitl-loop.template.sh)を 1 つ含みます。プロンプトを表示して Enter や回答の入力を待つだけで、読んだ限りネットワーク通信もファイル書き込みもありません。Skill 自体はエージェントにコマンドの実行、一時的なデバッグログの追加、回帰テストの作成、コードの修正を行わせるため、リポジトリが変更されます。表示する内容では秘密情報を伏せるよう指示しています。 パッケージには元リポジトリの MIT ライセンス(LICENSE)と agents/openai.yaml(Codex 用の表示名)も含まれます。