FAILURE MAP
← Case archive

FA-61271 / Bond day-count conventions / Open access

Adjusted versus unadjusted accrual periods: the accrual end always equals the payment date · case 01

Unadjusted accrual periods gain or lose days whenever the payment date moves.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

After computing the payment date the code overwrites the accrual end with it.

VERIFIED REPAIR

Keep the unadjusted end for accrual unless the flag requests adjustment.

Unsuccessful approach: Tying only the final period end to the payment date still distorts that period.

Case contract

Inputs an unadjusted schedule (first element is the accrual start), holidays and a flag. Business days are weekdays not in holidays; adjustment is modified following. For each period the payment date is the adjusted end date; accrual days use adjusted start and end if the flag is set, otherwise the unadjusted dates. Return [[payment date, accrual days], ...].

Why this case matters

Bond accrual and pricing systems depend on exact day-count arithmetic; a single-day error changes settlement cash.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = mf(e)
        e = pay
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression accrual end source 1', [[[2020, 4, 30], [2020, 10, 30], [2021, 4, 30], [2021, 10, 30], [2022, 4, 30]], [[2020, 5, 2]], False], [[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]], ['regression accrual end source 2', [[[2026, 3, 28], [2026, 6, 28], [2026, 9, 28], [2026, 12, 28], [2027, 3, 28]], [[2027, 3, 28]], False], [[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]], ['partial repair probe 1', [[[2021, 4, 29], [2021, 5, 29]], [], False], [[[2021, 5, 31], 30]]], ['partial repair probe 2', [[[2022, 12, 31], [2023, 1, 31], [2023, 2, 28], [2023, 3, 31], [2023, 4, 30]], [[2023, 4, 2]], False], [[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]], ['normal control 1', [[[2023, 8, 30], [2023, 9, 30], [2023, 10, 30]], [], True], [[[2023, 9, 29], 30], [[2023, 10, 30], 31]]], ['normal control 2', [[[2023, 4, 8], [2023, 5, 8], [2023, 6, 8]], [], False], [[[2023, 5, 8], 30], [[2023, 6, 8], 31]]], ['normal control 3', [[[2023, 2, 28], [2023, 3, 28], [2023, 4, 28], [2023, 5, 28]], [[2023, 3, 2], [2023, 3, 29], [2023, 4, 29]], True], [[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]], ['normal control 4', [[[2022, 11, 26], [2023, 2, 26], [2023, 5, 26], [2023, 8, 26], [2023, 11, 26]], [], True], [[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]]], [['regression accrual end source 1', [[[2022, 10, 31], [2023, 1, 31], [2023, 4, 30]], [], False], [[[2023, 1, 31], 92], [[2023, 4, 28], 89]]], ['regression accrual end source 2', [[[2019, 7, 31], [2019, 8, 31], [2019, 9, 30], [2019, 10, 31], [2019, 11, 30]], [[2019, 9, 1], [2019, 10, 2]], False], [[[2019, 8, 30], 31], [[2019, 9, 30], 30], [[2019, 10, 31], 31], [[2019, 11, 29], 30]]], ['partial repair probe 1', [[[2025, 3, 8], [2025, 6, 8], [2025, 9, 8], [2025, 12, 8], [2026, 3, 8]], [[2025, 9, 9]], False], [[[2025, 6, 9], 92], [[2025, 9, 8], 92], [[2025, 12, 8], 91], [[2026, 3, 9], 90]]], ['partial repair probe 2', [[[2025, 8, 21], [2025, 9, 21], [2025, 10, 21], [2025, 11, 21], [2025, 12, 21]], [[2025, 10, 23], [2025, 11, 22], [2025, 12, 23]], False], [[[2025, 9, 22], 31], [[2025, 10, 21], 30], [[2025, 11, 21], 31], [[2025, 12, 22], 30]]], ['normal control 1', [[[2024, 3, 29], [2024, 4, 29], [2024, 5, 29]], [[2024, 3, 31]], False], [[[2024, 4, 29], 31], [[2024, 5, 29], 30]]], ['normal control 2', [[[2028, 10, 31], [2029, 4, 30], [2029, 10, 31]], [[2028, 10, 31]], True], [[[2029, 4, 30], 182], [[2029, 10, 31], 184]]], ['normal control 3', [[[2024, 2, 27], [2024, 3, 27]], [], False], [[[2024, 3, 27], 29]]], ['normal control 4', [[[2022, 11, 30], [2023, 2, 28], [2023, 5, 30], [2023, 8, 30]], [[2023, 3, 2]], False], [[[2023, 2, 28], 90], [[2023, 5, 30], 91], [[2023, 8, 30], 92]]]], [['regression accrual end source 1', [[[2029, 5, 31], [2029, 11, 30], [2030, 5, 31], [2030, 11, 30]], [[2030, 6, 1]], False], [[[2029, 11, 30], 183], [[2030, 5, 31], 182], [[2030, 11, 29], 183]]], ['regression accrual end source 2', [[[2024, 6, 29], [2024, 9, 29], [2024, 12, 29], [2025, 3, 29], [2025, 6, 29]], [[2024, 10, 1], [2025, 6, 30]], False], [[[2024, 9, 30], 92], [[2024, 12, 30], 91], [[2025, 3, 31], 90], [[2025, 6, 27], 92]]], ['partial repair probe 1', [[[2027, 5, 28], [2027, 11, 28]], [], False], [[[2027, 11, 29], 184]]], ['partial repair probe 2', [[[2026, 8, 15], [2026, 9, 15], [2026, 10, 15], [2026, 11, 15]], [], False], [[[2026, 9, 15], 31], [[2026, 10, 15], 30], [[2026, 11, 16], 31]]], ['normal control 1', [[[2029, 12, 12], [2030, 6, 12]], [[2029, 12, 13]], True], [[[2030, 6, 12], 182]]], ['normal control 2', [[[2025, 4, 30], [2025, 5, 30]], [], True], [[[2025, 5, 30], 30]]], ['normal control 3', [[[2030, 6, 29], [2030, 7, 29], [2030, 8, 29]], [[2030, 6, 30], [2030, 7, 31], [2030, 8, 31]], True], [[[2030, 7, 29], 31], [[2030, 8, 29], 31]]], ['normal control 4', [[[2027, 9, 11], [2028, 3, 11], [2028, 9, 11], [2029, 3, 11], [2029, 9, 11]], [[2028, 3, 11], [2028, 9, 12]], True], [[[2028, 3, 13], 182], [[2028, 9, 11], 182], [[2029, 3, 12], 182], [[2029, 9, 11], 183]]]], [['regression accrual end source 1', [[[2030, 8, 30], [2030, 11, 30], [2031, 2, 28], [2031, 5, 30], [2031, 8, 30]], [[2030, 9, 1], [2031, 5, 30], [2031, 9, 1]], False], [[[2030, 11, 29], 92], [[2031, 2, 28], 90], [[2031, 5, 29], 91], [[2031, 8, 29], 92]]], ['regression accrual end source 2', [[[2030, 5, 31], [2030, 6, 30], [2030, 7, 31], [2030, 8, 31], [2030, 9, 30]], [[2030, 7, 1]], False], [[[2030, 6, 28], 30], [[2030, 7, 31], 31], [[2030, 8, 30], 31], [[2030, 9, 30], 30]]], ['partial repair probe 1', [[[2024, 5, 14], [2024, 6, 14], [2024, 7, 14]], [[2024, 7, 14]], False], [[[2024, 6, 14], 31], [[2024, 7, 15], 30]]], ['partial repair probe 2', [[[2022, 7, 31], [2023, 1, 31], [2023, 7, 31]], [[2022, 8, 2], [2023, 7, 31]], False], [[[2023, 1, 31], 184], [[2023, 7, 28], 181]]], ['normal control 1', [[[2030, 10, 31], [2031, 1, 31], [2031, 4, 30]], [[2030, 11, 1]], False], [[[2031, 1, 31], 92], [[2031, 4, 30], 89]]], ['normal control 2', [[[2027, 5, 2], [2027, 8, 2], [2027, 11, 2]], [], False], [[[2027, 8, 2], 92], [[2027, 11, 2], 92]]], ['normal control 3', [[[2025, 9, 19], [2026, 3, 19], [2026, 9, 19], [2027, 3, 19]], [[2026, 9, 19]], True], [[[2026, 3, 19], 181], [[2026, 9, 21], 186], [[2027, 3, 19], 179]]], ['normal control 4', [[[2023, 3, 29], [2023, 9, 29], [2024, 3, 29], [2024, 9, 29], [2025, 3, 29]], [[2023, 3, 30]], True], [[[2023, 9, 29], 184], [[2024, 3, 29], 182], [[2024, 9, 30], 185], [[2025, 3, 31], 182]]]], [['regression accrual end source 1', [[[2024, 9, 30], [2024, 10, 30], [2024, 11, 30], [2024, 12, 30], [2025, 1, 30]], [[2024, 12, 30]], False], [[[2024, 10, 30], 30], [[2024, 11, 29], 31], [[2024, 12, 31], 30], [[2025, 1, 30], 31]]], ['regression accrual end source 2', [[[2026, 4, 3], [2026, 7, 3], [2026, 10, 3], [2027, 1, 3], [2027, 4, 3]], [[2026, 7, 5], [2027, 1, 4]], False], [[[2026, 7, 3], 91], [[2026, 10, 5], 92], [[2027, 1, 5], 92], [[2027, 4, 5], 90]]], ['partial repair probe 1', [[[2022, 4, 30], [2022, 7, 30], [2022, 10, 30]], [], False], [[[2022, 7, 29], 91], [[2022, 10, 31], 92]]], ['partial repair probe 2', [[[2019, 8, 1], [2020, 2, 1], [2020, 8, 1]], [[2020, 8, 1]], False], [[[2020, 2, 3], 184], [[2020, 8, 3], 182]]], ['normal control 1', [[[2028, 4, 29], [2028, 5, 29], [2028, 6, 29]], [[2028, 6, 30]], True], [[[2028, 5, 29], 31], [[2028, 6, 29], 31]]], ['normal control 2', [[[2024, 2, 28], [2024, 8, 28], [2025, 2, 28]], [[2024, 2, 28]], True], [[[2024, 8, 28], 181], [[2025, 2, 28], 184]]], ['normal control 3', [[[2023, 4, 29], [2023, 5, 29]], [], True], [[[2023, 5, 29], 31]]], ['normal control 4', [[[2021, 9, 7], [2021, 12, 7], [2022, 3, 7], [2022, 6, 7]], [[2021, 9, 7], [2022, 3, 9]], True], [[[2021, 12, 7], 90], [[2022, 3, 7], 90], [[2022, 6, 7], 92]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 fixtureActualExpectedOutcome
regression accrual end source 1[[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 182], [[2022, 4, 29], 181]][[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]Failed
regression accrual end source 2[[[2026, 6, 29], 93], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 91]][[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]Failed
partial repair probe 1[[[2021, 5, 31], 32]][[[2021, 5, 31], 30]]Failed
partial repair probe 2[[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 28]][[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]Failed
normal control 1[[[2023, 9, 29], 30], [[2023, 10, 30], 31]][[[2023, 9, 29], 30], [[2023, 10, 30], 31]]Passed
normal control 2[[[2023, 5, 8], 30], [[2023, 6, 8], 31]][[[2023, 5, 8], 30], [[2023, 6, 8], 31]]Passed
normal control 3[[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]][[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]Passed
normal control 4[[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]][[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]Passed

SHA-256 / 224e6d8ad156f5c1261166fce141d824bf000c5e04ed12b2c2782d4e8db97af4

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = mf(e)
        e = pay if i == len(dates) - 1 else e
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression accrual end source 1', [[[2020, 4, 30], [2020, 10, 30], [2021, 4, 30], [2021, 10, 30], [2022, 4, 30]], [[2020, 5, 2]], False], [[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]], ['regression accrual end source 2', [[[2026, 3, 28], [2026, 6, 28], [2026, 9, 28], [2026, 12, 28], [2027, 3, 28]], [[2027, 3, 28]], False], [[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]], ['partial repair probe 1', [[[2021, 4, 29], [2021, 5, 29]], [], False], [[[2021, 5, 31], 30]]], ['partial repair probe 2', [[[2022, 12, 31], [2023, 1, 31], [2023, 2, 28], [2023, 3, 31], [2023, 4, 30]], [[2023, 4, 2]], False], [[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]], ['normal control 1', [[[2023, 8, 30], [2023, 9, 30], [2023, 10, 30]], [], True], [[[2023, 9, 29], 30], [[2023, 10, 30], 31]]], ['normal control 2', [[[2023, 4, 8], [2023, 5, 8], [2023, 6, 8]], [], False], [[[2023, 5, 8], 30], [[2023, 6, 8], 31]]], ['normal control 3', [[[2023, 2, 28], [2023, 3, 28], [2023, 4, 28], [2023, 5, 28]], [[2023, 3, 2], [2023, 3, 29], [2023, 4, 29]], True], [[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]], ['normal control 4', [[[2022, 11, 26], [2023, 2, 26], [2023, 5, 26], [2023, 8, 26], [2023, 11, 26]], [], True], [[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]]], [['regression accrual end source 1', [[[2022, 10, 31], [2023, 1, 31], [2023, 4, 30]], [], False], [[[2023, 1, 31], 92], [[2023, 4, 28], 89]]], ['regression accrual end source 2', [[[2019, 7, 31], [2019, 8, 31], [2019, 9, 30], [2019, 10, 31], [2019, 11, 30]], [[2019, 9, 1], [2019, 10, 2]], False], [[[2019, 8, 30], 31], [[2019, 9, 30], 30], [[2019, 10, 31], 31], [[2019, 11, 29], 30]]], ['partial repair probe 1', [[[2025, 3, 8], [2025, 6, 8], [2025, 9, 8], [2025, 12, 8], [2026, 3, 8]], [[2025, 9, 9]], False], [[[2025, 6, 9], 92], [[2025, 9, 8], 92], [[2025, 12, 8], 91], [[2026, 3, 9], 90]]], ['partial repair probe 2', [[[2025, 8, 21], [2025, 9, 21], [2025, 10, 21], [2025, 11, 21], [2025, 12, 21]], [[2025, 10, 23], [2025, 11, 22], [2025, 12, 23]], False], [[[2025, 9, 22], 31], [[2025, 10, 21], 30], [[2025, 11, 21], 31], [[2025, 12, 22], 30]]], ['normal control 1', [[[2024, 3, 29], [2024, 4, 29], [2024, 5, 29]], [[2024, 3, 31]], False], [[[2024, 4, 29], 31], [[2024, 5, 29], 30]]], ['normal control 2', [[[2028, 10, 31], [2029, 4, 30], [2029, 10, 31]], [[2028, 10, 31]], True], [[[2029, 4, 30], 182], [[2029, 10, 31], 184]]], ['normal control 3', [[[2024, 2, 27], [2024, 3, 27]], [], False], [[[2024, 3, 27], 29]]], ['normal control 4', [[[2022, 11, 30], [2023, 2, 28], [2023, 5, 30], [2023, 8, 30]], [[2023, 3, 2]], False], [[[2023, 2, 28], 90], [[2023, 5, 30], 91], [[2023, 8, 30], 92]]]], [['regression accrual end source 1', [[[2029, 5, 31], [2029, 11, 30], [2030, 5, 31], [2030, 11, 30]], [[2030, 6, 1]], False], [[[2029, 11, 30], 183], [[2030, 5, 31], 182], [[2030, 11, 29], 183]]], ['regression accrual end source 2', [[[2024, 6, 29], [2024, 9, 29], [2024, 12, 29], [2025, 3, 29], [2025, 6, 29]], [[2024, 10, 1], [2025, 6, 30]], False], [[[2024, 9, 30], 92], [[2024, 12, 30], 91], [[2025, 3, 31], 90], [[2025, 6, 27], 92]]], ['partial repair probe 1', [[[2027, 5, 28], [2027, 11, 28]], [], False], [[[2027, 11, 29], 184]]], ['partial repair probe 2', [[[2026, 8, 15], [2026, 9, 15], [2026, 10, 15], [2026, 11, 15]], [], False], [[[2026, 9, 15], 31], [[2026, 10, 15], 30], [[2026, 11, 16], 31]]], ['normal control 1', [[[2029, 12, 12], [2030, 6, 12]], [[2029, 12, 13]], True], [[[2030, 6, 12], 182]]], ['normal control 2', [[[2025, 4, 30], [2025, 5, 30]], [], True], [[[2025, 5, 30], 30]]], ['normal control 3', [[[2030, 6, 29], [2030, 7, 29], [2030, 8, 29]], [[2030, 6, 30], [2030, 7, 31], [2030, 8, 31]], True], [[[2030, 7, 29], 31], [[2030, 8, 29], 31]]], ['normal control 4', [[[2027, 9, 11], [2028, 3, 11], [2028, 9, 11], [2029, 3, 11], [2029, 9, 11]], [[2028, 3, 11], [2028, 9, 12]], True], [[[2028, 3, 13], 182], [[2028, 9, 11], 182], [[2029, 3, 12], 182], [[2029, 9, 11], 183]]]], [['regression accrual end source 1', [[[2030, 8, 30], [2030, 11, 30], [2031, 2, 28], [2031, 5, 30], [2031, 8, 30]], [[2030, 9, 1], [2031, 5, 30], [2031, 9, 1]], False], [[[2030, 11, 29], 92], [[2031, 2, 28], 90], [[2031, 5, 29], 91], [[2031, 8, 29], 92]]], ['regression accrual end source 2', [[[2030, 5, 31], [2030, 6, 30], [2030, 7, 31], [2030, 8, 31], [2030, 9, 30]], [[2030, 7, 1]], False], [[[2030, 6, 28], 30], [[2030, 7, 31], 31], [[2030, 8, 30], 31], [[2030, 9, 30], 30]]], ['partial repair probe 1', [[[2024, 5, 14], [2024, 6, 14], [2024, 7, 14]], [[2024, 7, 14]], False], [[[2024, 6, 14], 31], [[2024, 7, 15], 30]]], ['partial repair probe 2', [[[2022, 7, 31], [2023, 1, 31], [2023, 7, 31]], [[2022, 8, 2], [2023, 7, 31]], False], [[[2023, 1, 31], 184], [[2023, 7, 28], 181]]], ['normal control 1', [[[2030, 10, 31], [2031, 1, 31], [2031, 4, 30]], [[2030, 11, 1]], False], [[[2031, 1, 31], 92], [[2031, 4, 30], 89]]], ['normal control 2', [[[2027, 5, 2], [2027, 8, 2], [2027, 11, 2]], [], False], [[[2027, 8, 2], 92], [[2027, 11, 2], 92]]], ['normal control 3', [[[2025, 9, 19], [2026, 3, 19], [2026, 9, 19], [2027, 3, 19]], [[2026, 9, 19]], True], [[[2026, 3, 19], 181], [[2026, 9, 21], 186], [[2027, 3, 19], 179]]], ['normal control 4', [[[2023, 3, 29], [2023, 9, 29], [2024, 3, 29], [2024, 9, 29], [2025, 3, 29]], [[2023, 3, 30]], True], [[[2023, 9, 29], 184], [[2024, 3, 29], 182], [[2024, 9, 30], 185], [[2025, 3, 31], 182]]]], [['regression accrual end source 1', [[[2024, 9, 30], [2024, 10, 30], [2024, 11, 30], [2024, 12, 30], [2025, 1, 30]], [[2024, 12, 30]], False], [[[2024, 10, 30], 30], [[2024, 11, 29], 31], [[2024, 12, 31], 30], [[2025, 1, 30], 31]]], ['regression accrual end source 2', [[[2026, 4, 3], [2026, 7, 3], [2026, 10, 3], [2027, 1, 3], [2027, 4, 3]], [[2026, 7, 5], [2027, 1, 4]], False], [[[2026, 7, 3], 91], [[2026, 10, 5], 92], [[2027, 1, 5], 92], [[2027, 4, 5], 90]]], ['partial repair probe 1', [[[2022, 4, 30], [2022, 7, 30], [2022, 10, 30]], [], False], [[[2022, 7, 29], 91], [[2022, 10, 31], 92]]], ['partial repair probe 2', [[[2019, 8, 1], [2020, 2, 1], [2020, 8, 1]], [[2020, 8, 1]], False], [[[2020, 2, 3], 184], [[2020, 8, 3], 182]]], ['normal control 1', [[[2028, 4, 29], [2028, 5, 29], [2028, 6, 29]], [[2028, 6, 30]], True], [[[2028, 5, 29], 31], [[2028, 6, 29], 31]]], ['normal control 2', [[[2024, 2, 28], [2024, 8, 28], [2025, 2, 28]], [[2024, 2, 28]], True], [[[2024, 8, 28], 181], [[2025, 2, 28], 184]]], ['normal control 3', [[[2023, 4, 29], [2023, 5, 29]], [], True], [[[2023, 5, 29], 31]]], ['normal control 4', [[[2021, 9, 7], [2021, 12, 7], [2022, 3, 7], [2022, 6, 7]], [[2021, 9, 7], [2022, 3, 9]], True], [[[2021, 12, 7], 90], [[2022, 3, 7], 90], [[2022, 6, 7], 92]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 fixtureActualExpectedOutcome
regression accrual end source 1[[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 181]][[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]Failed
regression accrual end source 2[[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 91]][[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]Failed
partial repair probe 1[[[2021, 5, 31], 32]][[[2021, 5, 31], 30]]Failed
partial repair probe 2[[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 28]][[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]Failed
normal control 1[[[2023, 9, 29], 30], [[2023, 10, 30], 31]][[[2023, 9, 29], 30], [[2023, 10, 30], 31]]Passed
normal control 2[[[2023, 5, 8], 30], [[2023, 6, 8], 31]][[[2023, 5, 8], 30], [[2023, 6, 8], 31]]Passed
normal control 3[[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]][[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]Passed
normal control 4[[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]][[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]Passed

SHA-256 / f9a1d367f1db061df3aa119c6c8b9d51a113b7f10eecc8d685fd16b7c6498244

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import datetime
N = 1
observations = []
def solve(dates, holidays, adjust_accrual):
    H = {datetime.date(*h) for h in holidays}
    def biz(x):
        return x.weekday() < 5 and x not in H
    def fwd(x):
        while not biz(x):
            x += datetime.timedelta(days=1)
        return x
    def bwd(x):
        while not biz(x):
            x -= datetime.timedelta(days=1)
        return x
    def mf(x):
        f = fwd(x)
        return f if f.month == x.month else bwd(x)
    out = []
    for i in range(1, len(dates)):
        s = datetime.date(*dates[i - 1])
        e = datetime.date(*dates[i])
        pay = mf(e)
        if adjust_accrual:
            s, e = mf(s), mf(e)
        out.append([[pay.year, pay.month, pay.day], (e - s).days])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression accrual end source 1', [[[2020, 4, 30], [2020, 10, 30], [2021, 4, 30], [2021, 10, 30], [2022, 4, 30]], [[2020, 5, 2]], False], [[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]], ['regression accrual end source 2', [[[2026, 3, 28], [2026, 6, 28], [2026, 9, 28], [2026, 12, 28], [2027, 3, 28]], [[2027, 3, 28]], False], [[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]], ['partial repair probe 1', [[[2021, 4, 29], [2021, 5, 29]], [], False], [[[2021, 5, 31], 30]]], ['partial repair probe 2', [[[2022, 12, 31], [2023, 1, 31], [2023, 2, 28], [2023, 3, 31], [2023, 4, 30]], [[2023, 4, 2]], False], [[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]], ['normal control 1', [[[2023, 8, 30], [2023, 9, 30], [2023, 10, 30]], [], True], [[[2023, 9, 29], 30], [[2023, 10, 30], 31]]], ['normal control 2', [[[2023, 4, 8], [2023, 5, 8], [2023, 6, 8]], [], False], [[[2023, 5, 8], 30], [[2023, 6, 8], 31]]], ['normal control 3', [[[2023, 2, 28], [2023, 3, 28], [2023, 4, 28], [2023, 5, 28]], [[2023, 3, 2], [2023, 3, 29], [2023, 4, 29]], True], [[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]], ['normal control 4', [[[2022, 11, 26], [2023, 2, 26], [2023, 5, 26], [2023, 8, 26], [2023, 11, 26]], [], True], [[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]]], [['regression accrual end source 1', [[[2022, 10, 31], [2023, 1, 31], [2023, 4, 30]], [], False], [[[2023, 1, 31], 92], [[2023, 4, 28], 89]]], ['regression accrual end source 2', [[[2019, 7, 31], [2019, 8, 31], [2019, 9, 30], [2019, 10, 31], [2019, 11, 30]], [[2019, 9, 1], [2019, 10, 2]], False], [[[2019, 8, 30], 31], [[2019, 9, 30], 30], [[2019, 10, 31], 31], [[2019, 11, 29], 30]]], ['partial repair probe 1', [[[2025, 3, 8], [2025, 6, 8], [2025, 9, 8], [2025, 12, 8], [2026, 3, 8]], [[2025, 9, 9]], False], [[[2025, 6, 9], 92], [[2025, 9, 8], 92], [[2025, 12, 8], 91], [[2026, 3, 9], 90]]], ['partial repair probe 2', [[[2025, 8, 21], [2025, 9, 21], [2025, 10, 21], [2025, 11, 21], [2025, 12, 21]], [[2025, 10, 23], [2025, 11, 22], [2025, 12, 23]], False], [[[2025, 9, 22], 31], [[2025, 10, 21], 30], [[2025, 11, 21], 31], [[2025, 12, 22], 30]]], ['normal control 1', [[[2024, 3, 29], [2024, 4, 29], [2024, 5, 29]], [[2024, 3, 31]], False], [[[2024, 4, 29], 31], [[2024, 5, 29], 30]]], ['normal control 2', [[[2028, 10, 31], [2029, 4, 30], [2029, 10, 31]], [[2028, 10, 31]], True], [[[2029, 4, 30], 182], [[2029, 10, 31], 184]]], ['normal control 3', [[[2024, 2, 27], [2024, 3, 27]], [], False], [[[2024, 3, 27], 29]]], ['normal control 4', [[[2022, 11, 30], [2023, 2, 28], [2023, 5, 30], [2023, 8, 30]], [[2023, 3, 2]], False], [[[2023, 2, 28], 90], [[2023, 5, 30], 91], [[2023, 8, 30], 92]]]], [['regression accrual end source 1', [[[2029, 5, 31], [2029, 11, 30], [2030, 5, 31], [2030, 11, 30]], [[2030, 6, 1]], False], [[[2029, 11, 30], 183], [[2030, 5, 31], 182], [[2030, 11, 29], 183]]], ['regression accrual end source 2', [[[2024, 6, 29], [2024, 9, 29], [2024, 12, 29], [2025, 3, 29], [2025, 6, 29]], [[2024, 10, 1], [2025, 6, 30]], False], [[[2024, 9, 30], 92], [[2024, 12, 30], 91], [[2025, 3, 31], 90], [[2025, 6, 27], 92]]], ['partial repair probe 1', [[[2027, 5, 28], [2027, 11, 28]], [], False], [[[2027, 11, 29], 184]]], ['partial repair probe 2', [[[2026, 8, 15], [2026, 9, 15], [2026, 10, 15], [2026, 11, 15]], [], False], [[[2026, 9, 15], 31], [[2026, 10, 15], 30], [[2026, 11, 16], 31]]], ['normal control 1', [[[2029, 12, 12], [2030, 6, 12]], [[2029, 12, 13]], True], [[[2030, 6, 12], 182]]], ['normal control 2', [[[2025, 4, 30], [2025, 5, 30]], [], True], [[[2025, 5, 30], 30]]], ['normal control 3', [[[2030, 6, 29], [2030, 7, 29], [2030, 8, 29]], [[2030, 6, 30], [2030, 7, 31], [2030, 8, 31]], True], [[[2030, 7, 29], 31], [[2030, 8, 29], 31]]], ['normal control 4', [[[2027, 9, 11], [2028, 3, 11], [2028, 9, 11], [2029, 3, 11], [2029, 9, 11]], [[2028, 3, 11], [2028, 9, 12]], True], [[[2028, 3, 13], 182], [[2028, 9, 11], 182], [[2029, 3, 12], 182], [[2029, 9, 11], 183]]]], [['regression accrual end source 1', [[[2030, 8, 30], [2030, 11, 30], [2031, 2, 28], [2031, 5, 30], [2031, 8, 30]], [[2030, 9, 1], [2031, 5, 30], [2031, 9, 1]], False], [[[2030, 11, 29], 92], [[2031, 2, 28], 90], [[2031, 5, 29], 91], [[2031, 8, 29], 92]]], ['regression accrual end source 2', [[[2030, 5, 31], [2030, 6, 30], [2030, 7, 31], [2030, 8, 31], [2030, 9, 30]], [[2030, 7, 1]], False], [[[2030, 6, 28], 30], [[2030, 7, 31], 31], [[2030, 8, 30], 31], [[2030, 9, 30], 30]]], ['partial repair probe 1', [[[2024, 5, 14], [2024, 6, 14], [2024, 7, 14]], [[2024, 7, 14]], False], [[[2024, 6, 14], 31], [[2024, 7, 15], 30]]], ['partial repair probe 2', [[[2022, 7, 31], [2023, 1, 31], [2023, 7, 31]], [[2022, 8, 2], [2023, 7, 31]], False], [[[2023, 1, 31], 184], [[2023, 7, 28], 181]]], ['normal control 1', [[[2030, 10, 31], [2031, 1, 31], [2031, 4, 30]], [[2030, 11, 1]], False], [[[2031, 1, 31], 92], [[2031, 4, 30], 89]]], ['normal control 2', [[[2027, 5, 2], [2027, 8, 2], [2027, 11, 2]], [], False], [[[2027, 8, 2], 92], [[2027, 11, 2], 92]]], ['normal control 3', [[[2025, 9, 19], [2026, 3, 19], [2026, 9, 19], [2027, 3, 19]], [[2026, 9, 19]], True], [[[2026, 3, 19], 181], [[2026, 9, 21], 186], [[2027, 3, 19], 179]]], ['normal control 4', [[[2023, 3, 29], [2023, 9, 29], [2024, 3, 29], [2024, 9, 29], [2025, 3, 29]], [[2023, 3, 30]], True], [[[2023, 9, 29], 184], [[2024, 3, 29], 182], [[2024, 9, 30], 185], [[2025, 3, 31], 182]]]], [['regression accrual end source 1', [[[2024, 9, 30], [2024, 10, 30], [2024, 11, 30], [2024, 12, 30], [2025, 1, 30]], [[2024, 12, 30]], False], [[[2024, 10, 30], 30], [[2024, 11, 29], 31], [[2024, 12, 31], 30], [[2025, 1, 30], 31]]], ['regression accrual end source 2', [[[2026, 4, 3], [2026, 7, 3], [2026, 10, 3], [2027, 1, 3], [2027, 4, 3]], [[2026, 7, 5], [2027, 1, 4]], False], [[[2026, 7, 3], 91], [[2026, 10, 5], 92], [[2027, 1, 5], 92], [[2027, 4, 5], 90]]], ['partial repair probe 1', [[[2022, 4, 30], [2022, 7, 30], [2022, 10, 30]], [], False], [[[2022, 7, 29], 91], [[2022, 10, 31], 92]]], ['partial repair probe 2', [[[2019, 8, 1], [2020, 2, 1], [2020, 8, 1]], [[2020, 8, 1]], False], [[[2020, 2, 3], 184], [[2020, 8, 3], 182]]], ['normal control 1', [[[2028, 4, 29], [2028, 5, 29], [2028, 6, 29]], [[2028, 6, 30]], True], [[[2028, 5, 29], 31], [[2028, 6, 29], 31]]], ['normal control 2', [[[2024, 2, 28], [2024, 8, 28], [2025, 2, 28]], [[2024, 2, 28]], True], [[[2024, 8, 28], 181], [[2025, 2, 28], 184]]], ['normal control 3', [[[2023, 4, 29], [2023, 5, 29]], [], True], [[[2023, 5, 29], 31]]], ['normal control 4', [[[2021, 9, 7], [2021, 12, 7], [2022, 3, 7], [2022, 6, 7]], [[2021, 9, 7], [2022, 3, 9]], True], [[[2021, 12, 7], 90], [[2022, 3, 7], 90], [[2022, 6, 7], 92]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), 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 fixtureActualExpectedOutcome
regression accrual end source 1[[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]][[[2020, 10, 30], 183], [[2021, 4, 30], 182], [[2021, 10, 29], 183], [[2022, 4, 29], 182]]Passed
regression accrual end source 2[[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]][[[2026, 6, 29], 92], [[2026, 9, 28], 92], [[2026, 12, 28], 91], [[2027, 3, 29], 90]]Passed
partial repair probe 1[[[2021, 5, 31], 30]][[[2021, 5, 31], 30]]Passed
partial repair probe 2[[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]][[[2023, 1, 31], 31], [[2023, 2, 28], 28], [[2023, 3, 31], 31], [[2023, 4, 28], 30]]Passed
normal control 1[[[2023, 9, 29], 30], [[2023, 10, 30], 31]][[[2023, 9, 29], 30], [[2023, 10, 30], 31]]Passed
normal control 2[[[2023, 5, 8], 30], [[2023, 6, 8], 31]][[[2023, 5, 8], 30], [[2023, 6, 8], 31]]Passed
normal control 3[[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]][[[2023, 3, 28], 28], [[2023, 4, 28], 31], [[2023, 5, 29], 31]]Passed
normal control 4[[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]][[[2023, 2, 27], 91], [[2023, 5, 26], 88], [[2023, 8, 28], 94], [[2023, 11, 27], 91]]Passed

SHA-256 / c285319975890a9beb8c2475622726a846f1c9d903699739ddd8007419ac94a5

Verification & scope

A deterministic toy contract stated explicitly in the contract field; no claim of conformance to any published convention text. 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:53.663012+00:00.

Case digest / c3ab05588cca0c913e46ff0a2110bba94ab29c438ba0379b74f088a73e16418b