error-handling-typed-resultslisted
Install: claude install-skill zakariaf/CatchLaw
# Error Handling — Typed Results
Recoverable failures are typed **values** that flow through the layers and are switched on exhaustively; only genuine bugs and unrecoverable states throw, and those are caught once by a global net. Wrapped around both, never-lose-data — transactions, autosave drafts, soft-delete/Undo — is a first-class subsystem, not plumbing. Two tiers, no middle ground.
Read the reference for the task at hand:
- `references/result-failure-spine.md` — the `Result`/`Failure` source, the per-boundary taxonomy, convert-at-boundary, the global net, isolate re-wrapping, and local logging.
- `references/mechanism-selection.md` — throw vs `assert` vs `Exception` vs sealed outcome, `@useResult`, and the runZonedGuarded decision.
- `references/never-lose-data.md` — one transaction per mutation, debounced autosave drafts, optimistic soft-delete / Trash / Undo behind one filter.
Run `scripts/check-swallowed-catch.sh` and `scripts/check-softdelete-parity.sh` before a PR.
## Non-negotiable rules
1. **Model recoverable failures as values, not exceptions.** Anything that fails for a runtime reason the caller must handle — DB error, file/backup I/O, notification scheduling, an expected not-found, invalid input — returns `Result<T, F extends Failure>` (sealed `Ok`/`Err`). Throwing across a layer for an *expected* failure is a review reject.
2. **Hand-roll one zero-dependency sealed `Result` and `Failure` in a Flutter-free layer** so pure logic and repositories share ONE