FAILURE MAP
← Case archive

FA-77026 / Calendar recurrence rules / Open access

Splitting a series for a this-and-following edit: degenerate split · case 01

Editing from the first occurrence leaves an empty head series behind.

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

ROOT CAUSE

A split at occurrence 0 still produces a head with zero occurrences.

VERIFIED REPAIR

At the degenerate split decision use `k <= 0`, leaving the other decision sites of the model unchanged.

Unsuccessful approach: The partial repair `k == 0 and count is not None` only handles COUNT series; an UNTIL series split at 0 still leaves a head.

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) 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 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 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']}),
  ('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']})],
 [('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']})]]
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: 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': ['2024-01-01', 0, None], 'tail': ['2024-01-01', 2, 5, None]}{'head': None, 'tail': ['2024-01-01', 2, 5, None]}Failed
until split at first{'head': ['2024-03-01', None, '2024-02-23'], 'tail': ['2024-03-01', 14, None, '2024-06-01']}{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}Failed
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 / 99165f92976876c5899f6a5d88f48ba7b842b6d6cc35d936a798fa5eec6c1fa6

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 and count is not None:
        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 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 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']}),
  ('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']})],
 [('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']})]]
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: 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': ['2024-03-01', None, '2024-02-23'], 'tail': ['2024-03-01', 14, None, '2024-06-01']}{'head': None, 'tail': ['2024-03-01', 14, None, '2024-06-01']}Failed
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 / 1a5a84ac2cd82e9ccf07dcc4dc7c44f5a2153506af50d15e7875377b0ce92112

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 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 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']}),
  ('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']})],
 [('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']})]]
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: 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 / e358c86ae8d73e8117d7d48bd6494dce3b61d4b27fd71bb01100d93b522b7070

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.764188+00:00.

Case digest / 1ca7ee8db0cab980299a273ac156d46e7713962a3aa05945c66264c3fa1e57ab