-
v0.14.0 — replay pipeline + Quat bug fixes + UX tail
released this
2026-05-05 19:44:03 +00:00 | 475 commits to master since this releaseLargest release since the card-theme system. Three threads land
together: the v0.13.0-era UX candidate tail (theme thumbnails,
daily-challenge calendar, Time Attack auto-save, per-mode bests,
time-bonus slider), Quat smoke-test bug fixes (multi-card move
validation, softlock detection, deal-tween information leak), and
the entire replay pipeline (record → persist → upload → web viewer).Added
- Theme-picker thumbnails. Each Settings → Cosmetic chip renders an
Ace + back preview pair via the existing rasterize_svg path. - 14-day daily-challenge calendar in the Profile modal. PlayerProgress
gains daily_challenge_history (capped at 365) and
daily_challenge_longest_streak. - Time Attack session auto-save to time_attack_session.json sibling
next to game_state.json. 30 s cadence + on AppExit. Sessions whose
10-min window expired in real time during a closed launch are
discarded. - Per-mode best-score and fastest-win readouts in Stats. Six new
#[serde(default)] StatsSnapshot fields (Classic / Zen / Challenge
× best_score + fastest_win_seconds). - Time-bonus multiplier slider in Settings → Gameplay (0.0–2.0,
default 1.0). Cosmetic; doesn't affect achievement thresholds. - Win-replay recording + storage. Every successful move appends to
a RecordingReplay; GameWonEvent freezes it into a Replay and
persists to latest_replay.json. Single-slot. - "Watch replay" button in Stats overlay (full in-engine playback
is the next iteration; the button surfaces an InfoToastEvent for
now). - Replay upload + fetch endpoints on the server, JWT-gated. Engine
uploads winning replays automatically when cloud sync is on. - New solitaire_wasm crate compiling replay-relevant solitaire_core
types to WebAssembly. Browser-side replay re-execution. - Web replay viewer served from the server. GET /replays/:id returns
HTML + CSS + wasm bundle. Card-flight animations included. - E2E test coverage for the full upload → fetch path.
Fixed
- Multi-card lift validation. solitaire_core::rules::is_valid_
tableau_sequence rejects stacks whose adjacent cards don't form a
descending alternating-colour run. Wired into move_cards. - Softlock detection. has_legal_moves walks every potential move
source against every destination instead of early-returning on
non-empty stock. GameOverScreen now actually fires. - Deal-tween information leak. New-game snaps every card sprite to
the stock position before writing StateChangedEvent so all 52
cards animate from a single deck point during the deal.
By the numbers: 1134 passing tests (was 1053 at v0.13.0), zero
clippy warnings under --workspace --all-targets -- -D warnings.Downloads
- Theme-picker thumbnails. Each Settings → Cosmetic chip renders an