Dinner Split

Splitting a bill is arithmetic until it is not. Divide $100 three ways and the cents do not close: three shares of $33.33 sum to $99.99. Something has to absorb the difference, and the choice is a business rule, not a rounding mode.

Here the host absorbs it. Per-attendee :owes is rounded at the boundary, and the host's share takes the drift so that the invariant holds:

Σ(round attendee.owes) == round(grandTotal)

That is enforced by the property test roundoff-host-absorbs-drift rather than left as a comment. Arithmetic is double throughout, rounded once at the edge – never accumulated pre-rounded.

Status

Core-only. core.cljc holds the bill math, the attendee/item shapes, and the tempId to real-id mapping; app.cljs is a stub. There is no UI on this page yet.

Piece Namespace State
Pure logic wal-sh.projects.dinner-split.core complete
Storage wal-sh.projects.dinner-split.storage complete
SPA entry wal-sh.projects.dinner-split.app stub

24 example-based tests and 12 test.check properties are defined under test/wal_sh/projects/dinner_split/.