FA-58776 / Loan amortization schedules / Open access
Installment due date calendar: month boundary test · case 01
Modified-following due dates roll into the next month.
ROOT CAUSE
Only year changes trigger the roll-back.
VERIFIED REPAIR
Roll back whenever the roll leaves the original month.
Unsuccessful approach: A greater-than test misses December rolling into January.
Case contract
x = {'first_due': [y, m, d] (d may exceed the month length), 'count', 'roll': 'none'|'following'|'modified_following', 'holidays': ISO dates}. Installment i falls in month m+i on the anchor day d clamped to the month length (later months return to d). Unless roll is 'none', a Saturday, Sunday or holiday rolls forward to the next business day; under modified_following a roll that leaves the month instead rolls back to the previous business day. Return ISO date strings.
Why this case matters
Amortization engines drive borrower statements, payoff quotes and investor remittances; a misplaced rounding step, boundary or ordering rule compounds across hundreds of periods.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
import calendar
N = 1
observations = []
def solve(x):
y, m, d = x['first_due']
hol = set(x['holidays'])
def bad(t):
return t.weekday() >= 5 or t.isoformat() in hol
out = []
for i in range(x['count']):
mm = m - 1 + i
yy = y + mm // 12
mm = mm % 12 + 1
dd = min(d, calendar.monthrange(yy, mm)[1])
date = datetime.date(yy, mm, dd)
adj = date
if x['roll'] != 'none':
while bad(adj):
adj += datetime.timedelta(days=1)
if x['roll'] == 'modified_following' and adj.year != date.year:
adj = date
while bad(adj):
adj -= datetime.timedelta(days=1)
out.append(adj.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: month boundary test', {'first_due': [2023, 3, 31], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-03-29']}, ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 9, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2023-12-25']}, ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30']], ['control 1', {'first_due': [2023, 9, 1], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31']}, ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02']], ['control 2', {'first_due': [2024, 7, 28], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2024-01-01']}, ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28']], ['control 3', {'first_due': [2024, 11, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15']], ['control 4', {'first_due': [2024, 2, 5], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31', '2023-12-25']}, ['2024-02-05', '2024-03-05', '2024-04-05']], ['control 5', {'first_due': [2023, 8, 15], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-02-29', '2023-06-30']}, ['2023-08-15', '2023-09-15', '2023-10-16']]], [['regression: month boundary test', {'first_due': [2023, 7, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-12-31']}, ['2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 9, 5], 'count': 13, 'roll': 'following', 'holidays': []}, ['2024-09-05', '2024-10-07', '2024-11-05', '2024-12-05', '2025-01-06', '2025-02-05', '2025-03-05', '2025-04-07', '2025-05-05', '2025-06-05', '2025-07-07', '2025-08-05', '2025-09-05']], ['control 2', {'first_due': [2023, 4, 5], 'count': 6, 'roll': 'following', 'holidays': ['2024-01-01', '2024-05-31', '2023-06-30']}, ['2023-04-05', '2023-05-05', '2023-06-05', '2023-07-05', '2023-08-07', '2023-09-05']], ['control 3', {'first_due': [2023, 6, 5], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05']], ['control 4', {'first_due': [2023, 11, 1], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-06-30', '2024-05-31']}, ['2023-11-01', '2023-12-01', '2024-01-01']], ['control 5', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'following', 'holidays': ['2024-01-01', '2024-12-31']}, ['2023-10-30', '2023-11-30', '2024-01-02', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 6', {'first_due': [2023, 5, 5], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-03-29', '2024-02-29']}, ['2023-05-05', '2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05', '2023-12-05', '2024-01-05', '2024-02-05', '2024-03-05', '2024-04-05', '2024-05-05']]], [['regression: month boundary test', {'first_due': [2024, 11, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2023-06-30']}, ['2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 5, 31], 'count': 13, 'roll': 'modified_following', 'holidays': []}, ['2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31', '2023-09-29', '2023-10-31', '2023-11-30', '2023-12-29', '2024-01-31', '2024-02-29', '2024-03-29', '2024-04-30', '2024-05-31']], ['control 1', {'first_due': [2023, 9, 1], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-09-01', '2023-10-02', '2023-11-01']], ['control 2', {'first_due': [2024, 5, 1], 'count': 13, 'roll': 'none', 'holidays': []}, ['2024-05-01', '2024-06-01', '2024-07-01', '2024-08-01', '2024-09-01', '2024-10-01', '2024-11-01', '2024-12-01', '2025-01-01', '2025-02-01', '2025-03-01', '2025-04-01', '2025-05-01']], ['control 3', {'first_due': [2024, 10, 30], 'count': 3, 'roll': 'following', 'holidays': ['2024-05-31', '2023-06-30', '2024-03-29']}, ['2024-10-30', '2024-12-02', '2024-12-30']], ['control 4', {'first_due': [2023, 8, 30], 'count': 13, 'roll': 'following', 'holidays': []}, ['2023-08-30', '2023-10-02', '2023-10-30', '2023-11-30', '2024-01-01', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30']], ['control 5', {'first_due': [2023, 3, 15], 'count': 13, 'roll': 'none', 'holidays': []}, ['2023-03-15', '2023-04-15', '2023-05-15', '2023-06-15', '2023-07-15', '2023-08-15', '2023-09-15', '2023-10-15', '2023-11-15', '2023-12-15', '2024-01-15', '2024-02-15', '2024-03-15']]], [['regression: month boundary test', {'first_due': [2024, 4, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-12-25', '2024-05-31']}, ['2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30', '2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 10, 31], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-10-31', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 8, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-08-15', '2024-09-16', '2024-10-15', '2024-11-15', '2024-12-16', '2025-01-15']], ['control 2', {'first_due': [2023, 10, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30']], ['control 3', {'first_due': [2023, 8, 1], 'count': 3, 'roll': 'following', 'holidays': []}, ['2023-08-01', '2023-09-01', '2023-10-02']], ['control 4', {'first_due': [2023, 2, 28], 'count': 3, 'roll': 'following', 'holidays': ['2023-12-25', '2024-05-31']}, ['2023-02-28', '2023-03-28', '2023-04-28']], ['control 5', {'first_due': [2024, 9, 28], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-01-01', '2024-05-31']}, ['2024-09-28', '2024-10-28', '2024-11-28', '2024-12-28', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-28', '2025-07-28', '2025-08-28', '2025-09-28']]], [['regression: month boundary test', {'first_due': [2023, 6, 30], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2023-06-30', '2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 11, 30], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-01-01', '2024-12-31', '2023-12-25']}, ['2023-11-30', '2023-12-29', '2024-01-30']], ['control 1', {'first_due': [2024, 1, 29], 'count': 6, 'roll': 'none', 'holidays': []}, ['2024-01-29', '2024-02-29', '2024-03-29', '2024-04-29', '2024-05-29', '2024-06-29']], ['control 2', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'none', 'holidays': ['2024-01-01', '2024-03-29']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30', '2024-04-30', '2024-05-30', '2024-06-30', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 3', {'first_due': [2024, 8, 5], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2024-08-05', '2024-09-05', '2024-10-07']], ['control 4', {'first_due': [2024, 9, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-02-29']}, ['2024-09-30', '2024-10-30', '2024-11-30', '2024-12-30', '2025-01-30', '2025-02-28']], ['control 5', {'first_due': [2023, 10, 28], 'count': 3, 'roll': 'following', 'holidays': ['2024-12-31']}, ['2023-10-30', '2023-11-28', '2023-12-28']]]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'raised ' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: month boundary test | ['2023-03-31', '2023-05-01', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | Failed |
| regression: month boundary test, partial-repair probe | ['2023-10-02', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30', '2024-09-30'] | ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30'] | Failed |
| control 1 | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | Passed |
| control 2 | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | Passed |
| control 3 | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | Passed |
| control 4 | ['2024-02-05', '2024-03-05', '2024-04-05'] | ['2024-02-05', '2024-03-05', '2024-04-05'] | Passed |
| control 5 | ['2023-08-15', '2023-09-15', '2023-10-16'] | ['2023-08-15', '2023-09-15', '2023-10-16'] | Passed |
SHA-256 / 43b96854a51189a73aa75e19c81ad16f91661418e6ac7c6c6026d7669120459c
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
import calendar
N = 1
observations = []
def solve(x):
y, m, d = x['first_due']
hol = set(x['holidays'])
def bad(t):
return t.weekday() >= 5 or t.isoformat() in hol
out = []
for i in range(x['count']):
mm = m - 1 + i
yy = y + mm // 12
mm = mm % 12 + 1
dd = min(d, calendar.monthrange(yy, mm)[1])
date = datetime.date(yy, mm, dd)
adj = date
if x['roll'] != 'none':
while bad(adj):
adj += datetime.timedelta(days=1)
if x['roll'] == 'modified_following' and adj.month > date.month:
adj = date
while bad(adj):
adj -= datetime.timedelta(days=1)
out.append(adj.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: month boundary test', {'first_due': [2023, 3, 31], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-03-29']}, ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 9, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2023-12-25']}, ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30']], ['control 1', {'first_due': [2023, 9, 1], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31']}, ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02']], ['control 2', {'first_due': [2024, 7, 28], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2024-01-01']}, ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28']], ['control 3', {'first_due': [2024, 11, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15']], ['control 4', {'first_due': [2024, 2, 5], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31', '2023-12-25']}, ['2024-02-05', '2024-03-05', '2024-04-05']], ['control 5', {'first_due': [2023, 8, 15], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-02-29', '2023-06-30']}, ['2023-08-15', '2023-09-15', '2023-10-16']]], [['regression: month boundary test', {'first_due': [2023, 7, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-12-31']}, ['2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 9, 5], 'count': 13, 'roll': 'following', 'holidays': []}, ['2024-09-05', '2024-10-07', '2024-11-05', '2024-12-05', '2025-01-06', '2025-02-05', '2025-03-05', '2025-04-07', '2025-05-05', '2025-06-05', '2025-07-07', '2025-08-05', '2025-09-05']], ['control 2', {'first_due': [2023, 4, 5], 'count': 6, 'roll': 'following', 'holidays': ['2024-01-01', '2024-05-31', '2023-06-30']}, ['2023-04-05', '2023-05-05', '2023-06-05', '2023-07-05', '2023-08-07', '2023-09-05']], ['control 3', {'first_due': [2023, 6, 5], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05']], ['control 4', {'first_due': [2023, 11, 1], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-06-30', '2024-05-31']}, ['2023-11-01', '2023-12-01', '2024-01-01']], ['control 5', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'following', 'holidays': ['2024-01-01', '2024-12-31']}, ['2023-10-30', '2023-11-30', '2024-01-02', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 6', {'first_due': [2023, 5, 5], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-03-29', '2024-02-29']}, ['2023-05-05', '2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05', '2023-12-05', '2024-01-05', '2024-02-05', '2024-03-05', '2024-04-05', '2024-05-05']]], [['regression: month boundary test', {'first_due': [2024, 11, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2023-06-30']}, ['2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 5, 31], 'count': 13, 'roll': 'modified_following', 'holidays': []}, ['2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31', '2023-09-29', '2023-10-31', '2023-11-30', '2023-12-29', '2024-01-31', '2024-02-29', '2024-03-29', '2024-04-30', '2024-05-31']], ['control 1', {'first_due': [2023, 9, 1], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-09-01', '2023-10-02', '2023-11-01']], ['control 2', {'first_due': [2024, 5, 1], 'count': 13, 'roll': 'none', 'holidays': []}, ['2024-05-01', '2024-06-01', '2024-07-01', '2024-08-01', '2024-09-01', '2024-10-01', '2024-11-01', '2024-12-01', '2025-01-01', '2025-02-01', '2025-03-01', '2025-04-01', '2025-05-01']], ['control 3', {'first_due': [2024, 10, 30], 'count': 3, 'roll': 'following', 'holidays': ['2024-05-31', '2023-06-30', '2024-03-29']}, ['2024-10-30', '2024-12-02', '2024-12-30']], ['control 4', {'first_due': [2023, 8, 30], 'count': 13, 'roll': 'following', 'holidays': []}, ['2023-08-30', '2023-10-02', '2023-10-30', '2023-11-30', '2024-01-01', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30']], ['control 5', {'first_due': [2023, 3, 15], 'count': 13, 'roll': 'none', 'holidays': []}, ['2023-03-15', '2023-04-15', '2023-05-15', '2023-06-15', '2023-07-15', '2023-08-15', '2023-09-15', '2023-10-15', '2023-11-15', '2023-12-15', '2024-01-15', '2024-02-15', '2024-03-15']]], [['regression: month boundary test', {'first_due': [2024, 4, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-12-25', '2024-05-31']}, ['2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30', '2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 10, 31], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-10-31', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 8, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-08-15', '2024-09-16', '2024-10-15', '2024-11-15', '2024-12-16', '2025-01-15']], ['control 2', {'first_due': [2023, 10, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30']], ['control 3', {'first_due': [2023, 8, 1], 'count': 3, 'roll': 'following', 'holidays': []}, ['2023-08-01', '2023-09-01', '2023-10-02']], ['control 4', {'first_due': [2023, 2, 28], 'count': 3, 'roll': 'following', 'holidays': ['2023-12-25', '2024-05-31']}, ['2023-02-28', '2023-03-28', '2023-04-28']], ['control 5', {'first_due': [2024, 9, 28], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-01-01', '2024-05-31']}, ['2024-09-28', '2024-10-28', '2024-11-28', '2024-12-28', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-28', '2025-07-28', '2025-08-28', '2025-09-28']]], [['regression: month boundary test', {'first_due': [2023, 6, 30], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2023-06-30', '2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 11, 30], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-01-01', '2024-12-31', '2023-12-25']}, ['2023-11-30', '2023-12-29', '2024-01-30']], ['control 1', {'first_due': [2024, 1, 29], 'count': 6, 'roll': 'none', 'holidays': []}, ['2024-01-29', '2024-02-29', '2024-03-29', '2024-04-29', '2024-05-29', '2024-06-29']], ['control 2', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'none', 'holidays': ['2024-01-01', '2024-03-29']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30', '2024-04-30', '2024-05-30', '2024-06-30', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 3', {'first_due': [2024, 8, 5], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2024-08-05', '2024-09-05', '2024-10-07']], ['control 4', {'first_due': [2024, 9, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-02-29']}, ['2024-09-30', '2024-10-30', '2024-11-30', '2024-12-30', '2025-01-30', '2025-02-28']], ['control 5', {'first_due': [2023, 10, 28], 'count': 3, 'roll': 'following', 'holidays': ['2024-12-31']}, ['2023-10-30', '2023-11-28', '2023-12-28']]]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'raised ' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: month boundary test | ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | Passed |
| regression: month boundary test, partial-repair probe | ['2023-09-29', '2023-10-30', '2023-11-30', '2024-01-01', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30'] | ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30'] | Failed |
| control 1 | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | Passed |
| control 2 | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | Passed |
| control 3 | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | Passed |
| control 4 | ['2024-02-05', '2024-03-05', '2024-04-05'] | ['2024-02-05', '2024-03-05', '2024-04-05'] | Passed |
| control 5 | ['2023-08-15', '2023-09-15', '2023-10-16'] | ['2023-08-15', '2023-09-15', '2023-10-16'] | Passed |
SHA-256 / e883e67cebffd23582d3fcf8d48af7601d3a9e1dee3d9a052ed397e82faf1ef6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
import calendar
N = 1
observations = []
def solve(x):
y, m, d = x['first_due']
hol = set(x['holidays'])
def bad(t):
return t.weekday() >= 5 or t.isoformat() in hol
out = []
for i in range(x['count']):
mm = m - 1 + i
yy = y + mm // 12
mm = mm % 12 + 1
dd = min(d, calendar.monthrange(yy, mm)[1])
date = datetime.date(yy, mm, dd)
adj = date
if x['roll'] != 'none':
while bad(adj):
adj += datetime.timedelta(days=1)
if x['roll'] == 'modified_following' and adj.month != date.month:
adj = date
while bad(adj):
adj -= datetime.timedelta(days=1)
out.append(adj.isoformat())
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: month boundary test', {'first_due': [2023, 3, 31], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-03-29']}, ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 9, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2023-12-25']}, ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30']], ['control 1', {'first_due': [2023, 9, 1], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31']}, ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02']], ['control 2', {'first_due': [2024, 7, 28], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2024-01-01']}, ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28']], ['control 3', {'first_due': [2024, 11, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15']], ['control 4', {'first_due': [2024, 2, 5], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-03-29', '2024-05-31', '2023-12-25']}, ['2024-02-05', '2024-03-05', '2024-04-05']], ['control 5', {'first_due': [2023, 8, 15], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-02-29', '2023-06-30']}, ['2023-08-15', '2023-09-15', '2023-10-16']]], [['regression: month boundary test', {'first_due': [2023, 7, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2024-12-31']}, ['2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 9, 5], 'count': 13, 'roll': 'following', 'holidays': []}, ['2024-09-05', '2024-10-07', '2024-11-05', '2024-12-05', '2025-01-06', '2025-02-05', '2025-03-05', '2025-04-07', '2025-05-05', '2025-06-05', '2025-07-07', '2025-08-05', '2025-09-05']], ['control 2', {'first_due': [2023, 4, 5], 'count': 6, 'roll': 'following', 'holidays': ['2024-01-01', '2024-05-31', '2023-06-30']}, ['2023-04-05', '2023-05-05', '2023-06-05', '2023-07-05', '2023-08-07', '2023-09-05']], ['control 3', {'first_due': [2023, 6, 5], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05']], ['control 4', {'first_due': [2023, 11, 1], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-06-30', '2024-05-31']}, ['2023-11-01', '2023-12-01', '2024-01-01']], ['control 5', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'following', 'holidays': ['2024-01-01', '2024-12-31']}, ['2023-10-30', '2023-11-30', '2024-01-02', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 6', {'first_due': [2023, 5, 5], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-03-29', '2024-02-29']}, ['2023-05-05', '2023-06-05', '2023-07-05', '2023-08-05', '2023-09-05', '2023-10-05', '2023-11-05', '2023-12-05', '2024-01-05', '2024-02-05', '2024-03-05', '2024-04-05', '2024-05-05']]], [['regression: month boundary test', {'first_due': [2024, 11, 30], 'count': 6, 'roll': 'modified_following', 'holidays': ['2023-06-30']}, ['2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 5, 31], 'count': 13, 'roll': 'modified_following', 'holidays': []}, ['2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31', '2023-09-29', '2023-10-31', '2023-11-30', '2023-12-29', '2024-01-31', '2024-02-29', '2024-03-29', '2024-04-30', '2024-05-31']], ['control 1', {'first_due': [2023, 9, 1], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-09-01', '2023-10-02', '2023-11-01']], ['control 2', {'first_due': [2024, 5, 1], 'count': 13, 'roll': 'none', 'holidays': []}, ['2024-05-01', '2024-06-01', '2024-07-01', '2024-08-01', '2024-09-01', '2024-10-01', '2024-11-01', '2024-12-01', '2025-01-01', '2025-02-01', '2025-03-01', '2025-04-01', '2025-05-01']], ['control 3', {'first_due': [2024, 10, 30], 'count': 3, 'roll': 'following', 'holidays': ['2024-05-31', '2023-06-30', '2024-03-29']}, ['2024-10-30', '2024-12-02', '2024-12-30']], ['control 4', {'first_due': [2023, 8, 30], 'count': 13, 'roll': 'following', 'holidays': []}, ['2023-08-30', '2023-10-02', '2023-10-30', '2023-11-30', '2024-01-01', '2024-01-30', '2024-02-29', '2024-04-01', '2024-04-30', '2024-05-30', '2024-07-01', '2024-07-30', '2024-08-30']], ['control 5', {'first_due': [2023, 3, 15], 'count': 13, 'roll': 'none', 'holidays': []}, ['2023-03-15', '2023-04-15', '2023-05-15', '2023-06-15', '2023-07-15', '2023-08-15', '2023-09-15', '2023-10-15', '2023-11-15', '2023-12-15', '2024-01-15', '2024-02-15', '2024-03-15']]], [['regression: month boundary test', {'first_due': [2024, 4, 30], 'count': 13, 'roll': 'modified_following', 'holidays': ['2024-12-31', '2023-12-25', '2024-05-31']}, ['2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30', '2024-11-29', '2024-12-30', '2025-01-30', '2025-02-28', '2025-03-31', '2025-04-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 10, 31], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2023-10-31', '2023-11-30', '2023-12-29']], ['control 1', {'first_due': [2024, 8, 15], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2024-08-15', '2024-09-16', '2024-10-15', '2024-11-15', '2024-12-16', '2025-01-15']], ['control 2', {'first_due': [2023, 10, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-01-01']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30']], ['control 3', {'first_due': [2023, 8, 1], 'count': 3, 'roll': 'following', 'holidays': []}, ['2023-08-01', '2023-09-01', '2023-10-02']], ['control 4', {'first_due': [2023, 2, 28], 'count': 3, 'roll': 'following', 'holidays': ['2023-12-25', '2024-05-31']}, ['2023-02-28', '2023-03-28', '2023-04-28']], ['control 5', {'first_due': [2024, 9, 28], 'count': 13, 'roll': 'none', 'holidays': ['2023-06-30', '2024-01-01', '2024-05-31']}, ['2024-09-28', '2024-10-28', '2024-11-28', '2024-12-28', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-28', '2025-07-28', '2025-08-28', '2025-09-28']]], [['regression: month boundary test', {'first_due': [2023, 6, 30], 'count': 6, 'roll': 'modified_following', 'holidays': []}, ['2023-06-30', '2023-07-31', '2023-08-30', '2023-09-29', '2023-10-30', '2023-11-30']], ['regression: month boundary test, partial-repair probe', {'first_due': [2023, 11, 30], 'count': 3, 'roll': 'modified_following', 'holidays': ['2024-01-01', '2024-12-31', '2023-12-25']}, ['2023-11-30', '2023-12-29', '2024-01-30']], ['control 1', {'first_due': [2024, 1, 29], 'count': 6, 'roll': 'none', 'holidays': []}, ['2024-01-29', '2024-02-29', '2024-03-29', '2024-04-29', '2024-05-29', '2024-06-29']], ['control 2', {'first_due': [2023, 10, 30], 'count': 13, 'roll': 'none', 'holidays': ['2024-01-01', '2024-03-29']}, ['2023-10-30', '2023-11-30', '2023-12-30', '2024-01-30', '2024-02-29', '2024-03-30', '2024-04-30', '2024-05-30', '2024-06-30', '2024-07-30', '2024-08-30', '2024-09-30', '2024-10-30']], ['control 3', {'first_due': [2024, 8, 5], 'count': 3, 'roll': 'modified_following', 'holidays': []}, ['2024-08-05', '2024-09-05', '2024-10-07']], ['control 4', {'first_due': [2024, 9, 30], 'count': 6, 'roll': 'none', 'holidays': ['2024-02-29']}, ['2024-09-30', '2024-10-30', '2024-11-30', '2024-12-30', '2025-01-30', '2025-02-28']], ['control 5', {'first_due': [2023, 10, 28], 'count': 3, 'roll': 'following', 'holidays': ['2024-12-31']}, ['2023-10-30', '2023-11-28', '2023-12-28']]]]
for label, args, expected in fixtures[N-1]:
try:
actual = solve(args)
except Exception as exc:
actual = 'raised ' + type(exc).__name__
check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: month boundary test | ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | ['2023-03-31', '2023-04-28', '2023-05-31', '2023-06-30', '2023-07-31', '2023-08-31'] | Passed |
| regression: month boundary test, partial-repair probe | ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30'] | ['2023-09-29', '2023-10-30', '2023-11-30', '2023-12-29', '2024-01-30', '2024-02-29', '2024-03-28', '2024-04-30', '2024-05-30', '2024-06-28', '2024-07-30', '2024-08-30', '2024-09-30'] | Passed |
| control 1 | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | ['2023-09-01', '2023-10-02', '2023-11-01', '2023-12-01', '2024-01-01', '2024-02-01', '2024-03-01', '2024-04-01', '2024-05-01', '2024-06-03', '2024-07-01', '2024-08-01', '2024-09-02'] | Passed |
| control 2 | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | ['2024-07-29', '2024-08-28', '2024-09-30', '2024-10-28', '2024-11-28', '2024-12-30', '2025-01-28', '2025-02-28', '2025-03-28', '2025-04-28', '2025-05-28', '2025-06-30', '2025-07-28'] | Passed |
| control 3 | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | ['2024-11-15', '2024-12-16', '2025-01-15', '2025-02-17', '2025-03-17', '2025-04-15'] | Passed |
| control 4 | ['2024-02-05', '2024-03-05', '2024-04-05'] | ['2024-02-05', '2024-03-05', '2024-04-05'] | Passed |
| control 5 | ['2023-08-15', '2023-09-15', '2023-10-16'] | ['2023-08-15', '2023-09-15', '2023-10-16'] | Passed |
SHA-256 / 3275f912b58b679f1078f9b90c39780c95a2052b76af5eb11173e46decef6c2c
Verification & scope
A deterministic bounded teaching model with stipulated toy lending rules stated in the contract; money is integer cents and rates are basis points; it makes no claim of conformance to any regulation, servicing standard or product. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:46:29.988806+00:00.
Case digest / f488a47dc59cae37bb70a10297c310ec21c555fc1650524b67b09521e8e6ed1e