oficina / calendar Public
Recurrence stepping bounds
Status: revision 2 APPROVED by Claude Fable5.1 (claude-fable-5-1), 2026-09-07. Evidence: /tmp/oficina-calendar-recurrence-review/design-review2.json. Baseline: application branch 2074881; live binary d961b65. This support branch does not approve the application's entire unmerged history.
Scope: bounded, exact stepping within the existing recurrence subset. Keep every currently parsed positive INTERVAL; no parser or picker limit. No UI copy, schema, migrations, COUNT fast-forwarding or new RRULE shapes.
Evidence
Weekly INTERVAL=100000000 with BYDAY exceeds a two-second child deadline. Civil 1600-01-01 to 2000-01-01 saturates at 106751 rather than146097 days. A valid INTERVAL=20871 Saturday series silently loses its2000 occurrence and reports complete. Yearly MaxInt wraps backwards. Invalid zone/start/end reports complete, and a store-level test confirms strict busy-time reads return nil rather than ErrIncompleteExpansion for those invalid fields.
Revised implementation contract
- Use civil(t).Unix()/86400 for integer civil days within the representable record domain: year0000 through9999, the four-digit local date format. All parsed source dates fit this domain. Generated candidates are bounded before arithmetic; no arbitrary-year Unix round-trip machinery is needed. daysBetween subtracts civil-day integers, never time.Duration or floats.
- Weekly BYDAY considers remaining selected weekdays in the current eligible week, then the first selected weekday in the next INTERVAL-th week, ordered from WKST. cur is eligible by induction from DTSTART. At most13 weekday candidates; no scanning proportional to INTERVAL and no saturated phase. Construct each candidate with the original proto clock as before.
- Check distance to the final representable civil date by division before multiplying. Daily compares interval with remaining civil days; weekly compares interval with remaining days/7 before computing its week jump. Monthly compares interval with remaining month indexes/step; yearly with remaining years/step. Thus every addition/product stays inside the small four-digit date domain. Do not change parsing or stored INTERVAL.
- Test calendar-date existence before zone resolution. Yearly checks month length before constructing the candidate; monthly ordinal weekday arithmetic uses UTC civil weekdays, then resolves the selected date in loc. A complete flat4800-month-step or400-year-step search covers every Gregorian residue reachable by any integer interval, because those periods repeat the calendar. No match after that full search proves exhaustion. A horizon reached first does not prove exhaustion. No gcd machinery is required.
- Stepping distinguishes candidate, proved exhaustion and incomplete. A horizon refusal is ALWAYS INCOMPLETE, regardless of query end: this avoids claiming a UTC cutoff for zones whose next local year starts before UTC's. Invalid Rule construction, non-advancing resolved candidates and resolved dates outside year0000..9999 also report incomplete. Ordinary DST clock normalization remains unchanged; intended-versus-resolved dates across a midnight gap remain a separate pre-existing issue, not silently redesigned.
- Invalid zone/start/end or reversed event/window intervals make strict expansion incomplete. For an unreadable end preserve tolerant instantaneous output where possible, but retain an input-validity flag so no stop reason can turn it into complete. Existing canceled/note exceptions remain.
- COUNT/UNTIL satisfaction, passing the window, a valid one-off or proved exhaustion are completion proofs. Check COUNT after generating its final candidate so no unneeded next step can turn completed COUNT into a horizon failure. Keep existing100000 outer/1000 output caps and EXDATE ordering.
Validation
Adapt the two-second huge-interval probe to expect prompt incomplete refusal; add INTERVAL=400000 within year9999 with exact date/weekday/clock. Keep the four-century observable regression, reversed civil span, huge-interval cases for every frequency, exact near-horizon boundaries, monthly31st/fifth weekday and leap-day skips, WKST/DTSTART phase and existing DST/span tests.
Strict store regression must fail before the fix and pass after it while the view remains tolerant. Test invalid input, COUNT completion near the horizon, query beyond the horizon and unsupported direct Rule values. Mutation-prove bounded stepping, exact day arithmetic and incomplete propagation. Run make ci, then independent Fable branch review and actual CI before owner integration. No production rollout of the unmerged application history is authorized here.
Revision1 was REQUEST CHANGES by Claude Fable5.1 (claude-fable-5-1), evidence /tmp/oficina-calendar-recurrence-review/design-review.json. This revision accepts the four-digit horizon, exact civil-day arithmetic, pre-zone cycle proof and bounded weekly induction; explicitly chooses safe incomplete horizon handling from the review's allowed alternatives.