Attempt carries its LevelId so settlement decides First Clear vs Replay
without trusting the caller. Outcome is terminal and refuses to change:
one death costs one life, one completion banks once.
Coins.Zero/Add driven out by the ledger rather than added up front.
21 tests. ADR-0005: Playthrough settles Attempts, has no LoseLife.
Lives (floors at zero, exhaustion observable), LevelId, SkillId,
PlaythroughId (never self-generates, keeps tests deterministic),
StatName enum, LevelTime rejects NaN/infinity.
14 tests. Arithmetic/comparison members deferred to the slices whose
behaviour needs them rather than added speculatively.
three bug-encoding invariants, one red/green cycle each:
- Coins.TrySubtract fails instead of clamping
- LevelTime rejects zero (continued-run zero best-times)
- SkillLevel has no zero (unowned is absence, not Level=1)
plan: drop signed NetCoins; add Attempt outcome as idempotency guard