Files
budget2.0/src
Lucas Winther f8591fdc57 feat(types): occurrenceDate is optional, stepFrom takes anchoring
A lastCharge cost has no grid of slots, so a purchase against one settles
nothing — its own date is the whole story. occurrenceDate stays required for
calendar, where a slot is exactly what a payment settles.

stepFrom needs the anchoring because everyNMonths means two different things:
a month-granular grid under calendar, a day-precise clamped step under
lastCharge. The lastCharge branch only takes the day-precise path when its
input actually carries a day (date !== monthOf(date)) — a still-unconfirmed
or paid-on-schedule everyNMonths cost has no day to be precise about yet
(its startDate is documented as month-only), and without this guard the
existing walk crashes calling addMonthsToDate on a bare month. This also
means an off-schedule confirmation that rebases the series now correctly
stays day-precise afterward, which updates one pre-existing occurrencesOf
expectation (I3's "paying after the month" case) to match.

Three call sites read source.occurrenceDate as definite and are rewritten
properly in later tasks (3, 5, 6); each gets a narrow scaffolding guard
with a `// rewritten in Task N` comment rather than a cast or `!`.
2026-09-05 01:03:57 +02:00
..