Files
budget2.0/docs/specs
Lucas WintherandClaude Opus 5 596de45525 docs(specs): recurring costs, expected against actual
Bills that repeat: rent monthly, a subscription every 28 days, a phone bill
every 30 days whose clock restarts when the data cap is hit early.

A recurring cost projects expected charges forward; each occurrence is
confirmed into a real Purchase when the money moves. The fold gains a second
balance, so `remaining` never shifts and `projected` says what is left after
commitments. The two reconverge as a month settles.

The phone bill reads like a third recurrence kind and is not one. It charges
30 days after the PREVIOUS CHARGE, and the data cap only makes a charge happen
early — a date two-stage confirmation already records. So `anchoring` is one
field, `calendar` or `lastCharge`, and the domain never learns what a data cap
is. That collapse is most of why this design is small.

Two consequences worth not re-litigating later:

- `everyNMonths` carries no day. Rent occurs IN September, and `IsoDate`
  already permits a bare "YYYY-MM", so the commonest case needs no day
  arithmetic and no February clamping rule.
- `amount` is a single mutable Money with no RuleVersion-style series. Safe
  ONLY because confirmed purchases hold what was actually paid; under
  projection-only it would destroy history.

Occurrences are computed, never stored — materialised snapshots were rejected
in the original design, and an unbounded recurrence would otherwise need a
horizon. `upToMonth` comes from the caller, so src/domain/ stays clock-free.

Takes schema 6. The global-decimals spec claimed 6 too and is reassigned to 7;
both specs now say so. The steps are independent and compose in either order.

Spec only. The two settings-layout fixes in the tree are unrelated and stay
unstaged.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-03 02:50:05 +02:00
..