SIGN IN SIGN UP

fix(history): harden session index against corruption and cross-process races

Two gaps from the recent production-readiness review, both silent —
neither crashes, which is exactly why they were easy to miss:

1. A corrupted/truncated rigstats-sessions.json was loaded as an empty
   list with no complaint, and the next save (start/stop/pin/rename/
   delete/prune) would happily persist that empty list, permanently
   erasing all session metadata. `save_sessions` now mirrors every
   successful write into a `.bak` file; `load_sessions` falls back to
   it on a parse failure instead of silently treating corruption as
   "no history", and preserves the bad content as `.corrupt` for
   forensics either way.

2. This app and the `rigstats-wallpaper` host both read-modify-write
   the same index (recording toggle, daily pruning) with no
   coordination, so a lost-update race was possible — e.g. a rename
   committed by one process getting silently discarded by the other's
   concurrent prune. A small file-based lock (plain atomic file
   creation, no new dependency, no `unsafe`) now guards that cycle in
   every mutating function, with a short bounded wait so a UI-thread
   caller can never hang, and stale-lock reclamation so a crash while
   holding it can't wedge future runs.

Covered by 6 new tests: corrupt-index recovery (with and without a
usable backup), missing-index is not treated as corruption, the lock
waiting for and then acquiring a just-released lock, stale-lock
reclamation, and a real two-thread concurrent pin+rename that asserts
neither update is lost.

Refs #175
D
Daniel Valfridsson committed
3ee91868c0e9bc6933e9bdb91b6a6acfde524090
Parent: 4401f47