FA-77016 / Calendar recurrence rules / Open access
Splitting a series for a this-and-following edit: split beyond end · case 01
Splitting after the last occurrence of an UNTIL series creates an empty tail series past UNTIL.
ROOT CAUSE
Only COUNT series are checked for a split past the end.
VERIFIED REPAIR
At the split beyond end decision use `(count is not None and k >= count) or (until_d is not None and tail_start > until_d)`, leaving the other decision sites of the model unchanged.
Unsuccessful approach: The partial repair `(count is not None and k > count) or (until_d is not None and tail_start > until_d)` uses a strict comparison, so a split exactly at COUNT still creates a zero-count tail.
Case contract
A daily-interval series (dtstart, interval, and either count or until). Editing from 0-based occurrence k splits it: the head keeps occurrences 0..k-1 (count k, or until = its last retained occurrence date) and the tail starts at the original date of occurrence k with new_interval and the remaining count (or the original until). k <= 0 makes the head None; a split at or past the end makes the tail None. Return {"head": [dtstart, count, until] or None, "tail": [start, interval, count, until] or None}.
Why this case matters
Recurring calendar series are expanded into concrete instances for display, reminders and conflict checks.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(dtstart, interval, count, until, k, new_interval):
start = dt.date.fromisoformat(dtstart)
until_d = dt.date.fromisoformat(until) if until else None
tail_start = start + dt.timedelta(days=k * interval)
if count is not None and k >= count:
tail = None
else:
tail = [tail_start.isoformat(), new_interval, count - k if count is not None else None, until]
if k <= 0:
head = None
elif count is not None:
head = [dtstart, k, None]
else:
head = [dtstart, None, (start + dt.timedelta(days=(k - 1) * interval)).isoformat()]
return {'head': head, 'tail': tail}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']})],
[('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']})],
[('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None})],
[('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})],
[('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: count series split at 3 | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | Passed |
| until series split at 2 | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | Passed |
| split at first occurrence | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | Passed |
| until split at first | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | Passed |
| split exactly at count | {'head': ['2024-01-01', 4, None], 'tail': None} | {'head': ['2024-01-01', 4, None], 'tail': None} | Passed |
| split past until | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': ['2024-01-26', 2, None, '2024-01-20']} | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': None} | Failed |
| split at last until occurrence | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | Passed |
SHA-256 / 28980993a3d57055c61f9b8ddbe67be38beb25232a4e52fb5091f2f360c41e9e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(dtstart, interval, count, until, k, new_interval):
start = dt.date.fromisoformat(dtstart)
until_d = dt.date.fromisoformat(until) if until else None
tail_start = start + dt.timedelta(days=k * interval)
if (count is not None and k > count) or (until_d is not None and tail_start > until_d):
tail = None
else:
tail = [tail_start.isoformat(), new_interval, count - k if count is not None else None, until]
if k <= 0:
head = None
elif count is not None:
head = [dtstart, k, None]
else:
head = [dtstart, None, (start + dt.timedelta(days=(k - 1) * interval)).isoformat()]
return {'head': head, 'tail': tail}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']})],
[('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']})],
[('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None})],
[('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})],
[('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: count series split at 3 | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | Passed |
| until series split at 2 | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | Passed |
| split at first occurrence | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | Passed |
| until split at first | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | Passed |
| split exactly at count | {'head': ['2024-01-01', 4, None], 'tail': ['2024-01-05', 2, 0, None]} | {'head': ['2024-01-01', 4, None], 'tail': None} | Failed |
| split past until | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': None} | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': None} | Passed |
| split at last until occurrence | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | Passed |
SHA-256 / cedf2dd9e1918e057db8591a6341b7e81bac78e2043a2a9289834f815614f4a7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import datetime as dt
import calendar
N = 1
observations = []
def solve(dtstart, interval, count, until, k, new_interval):
start = dt.date.fromisoformat(dtstart)
until_d = dt.date.fromisoformat(until) if until else None
tail_start = start + dt.timedelta(days=k * interval)
if (count is not None and k >= count) or (until_d is not None and tail_start > until_d):
tail = None
else:
tail = [tail_start.isoformat(), new_interval, count - k if count is not None else None, until]
if k <= 0:
head = None
elif count is not None:
head = [dtstart, k, None]
else:
head = [dtstart, None, (start + dt.timedelta(days=(k - 1) * interval)).isoformat()]
return {'head': head, 'tail': tail}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']})],
[('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']})],
[('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None}),
('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None})],
[('split at last until occurrence',
['2024-01-01', 5, None, '2024-01-21', 4, 1],
{'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']}),
('count split near end',
['2024-05-10', 1, 6, None, 5, 3],
{'head': ['2024-05-10', 5, None], 'tail': ['2024-05-15', 3, 1, None]}),
('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})],
[('until split mid',
['2024-05-10', 4, None, '2024-07-01', 6, 2],
{'head': ['2024-05-10', None, '2024-05-30'], 'tail': ['2024-06-03', 2, None, '2024-07-01']}),
('interval 1 count split',
['2024-12-30', 1, 8, None, 2, 1],
{'head': ['2024-12-30', 2, None], 'tail': ['2025-01-01', 1, 6, None]}),
('split beyond count', ['2024-01-01', 1, 3, None, 7, 2], {'head': ['2024-01-01', 7, None], 'tail': None}),
('regression: count series split at 3',
['2024-01-01', 2, 10, None, 3, 7],
{'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]}),
('until series split at 2',
['2024-01-01', 3, None, '2024-02-01', 2, 1],
{'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']}),
('split at first occurrence',
['2024-01-01', 1, 5, None, 0, 2],
{'head': None, 'tail': ['2024-01-01', 2, 5, None]}),
('until split at first',
['2024-03-01', 7, None, '2024-06-01', 0, 14],
{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}),
('split exactly at count',
['2024-01-01', 1, 4, None, 4, 2],
{'head': ['2024-01-01', 4, None], 'tail': None}),
('split past until',
['2024-01-01', 5, None, '2024-01-20', 5, 2],
{'head': ['2024-01-01', None, '2024-01-21'], 'tail': None})]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: count series split at 3 | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | {'head': ['2024-01-01', 3, None], 'tail': ['2024-01-07', 7, 7, None]} | Passed |
| until series split at 2 | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | {'head': ['2024-01-01', None, '2024-01-04'], 'tail': ['2024-01-07', 1, None, '2024-02-01']} | Passed |
| split at first occurrence | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | {'head': None, 'tail': ['2024-01-01', 2, 5, None]} | Passed |
| until split at first | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | {'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']} | Passed |
| split exactly at count | {'head': ['2024-01-01', 4, None], 'tail': None} | {'head': ['2024-01-01', 4, None], 'tail': None} | Passed |
| split past until | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': None} | {'head': ['2024-01-01', None, '2024-01-21'], 'tail': None} | Passed |
| split at last until occurrence | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | {'head': ['2024-01-01', None, '2024-01-16'], 'tail': ['2024-01-21', 1, None, '2024-01-21']} | Passed |
SHA-256 / 1025298636f1a0f157379b638a3ddf925dfd3a40c6cd8a321e3e876bf6c4a4f9
Verification & scope
Stipulated, bounded recurrence-expansion model evaluated offline on explicit fixtures; it is not a complete iCalendar implementation and makes no claim of standards conformance. 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:49:21.668624+00:00.
Case digest / 59c3d613a169e9e98abff2b7b556282a7e4d8ca7ffe6b0e1d228c75bb2f80e95