d948fa862a
CHANGELOG gains a [0.14.0] section covering 18 commits since v0.13.0 across three threads: the v0.13.0-era UX candidates that missed the v0.13.0 tag (theme thumbnails, daily-challenge calendar, Time Attack auto-save, per-mode bests, time-bonus slider), Quat's three bug fixes from a smoke-test round (multi-card lift validation, softlock detection, deal-tween information leak), and the major new replay pipeline (record → persist → upload → web viewer with a new solitaire_wasm crate). The bottom-of-file compare links thread the new tag into the chain. Test count updated to 1134. SESSION_HANDOFF rewritten as the session 9 / post-v0.14.0 doc. The session 8 changelog table is preserved alongside a new "v0.14.0 shipped" rollup. The next-round candidates list seeds six fresh ideas (deferred Bevy audio trim, solver toggle, in-engine replay playback, per-replay history, solver-driven hints, "won via replay" achievement). Resume prompt asks A–F about smoke-test, audio trim, solver toggle, in-engine playback, fresh UX, or packaging. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
141 lines
11 KiB
Markdown
141 lines
11 KiB
Markdown
# Solitaire Quest — Session Handoff
|
||
|
||
**Last updated:** 2026-05-02 (session 9, post-v0.14.0 release prep) — v0.14.0 cut. The Quat bug fixes, the rest of the v0.13.0 candidate list, and the entire replay → upload → web-viewer pipeline are all bundled in this release. Direction now opens for the next round.
|
||
|
||
## Status at pause
|
||
|
||
- **HEAD on origin:** v0.14.0's tag commit (CHANGELOG + handoff refresh).
|
||
- **Working tree:** clean apart from untracked `CARD_PLAN.md` (intentional).
|
||
- **Build:** `cargo clippy --workspace --all-targets -- -D warnings` clean.
|
||
- **Tests:** **1134 passed / 0 failed** across the workspace.
|
||
- **Tags on origin:** `v0.9.0`, `v0.10.0`, `v0.11.0`, `v0.12.0`, `v0.13.0`, `v0.14.0`.
|
||
|
||
## Where we are
|
||
|
||
v0.14.0 is the largest release since the card-theme system. Three threads land together:
|
||
|
||
1. **The remaining v0.13.0-era UX candidates** — theme thumbnails, daily-challenge calendar, Time Attack auto-save, per-mode bests, time-bonus multiplier slider.
|
||
2. **Quat smoke-test bug fixes** — multi-card move validation, softlock detection, deal-tween information leak.
|
||
3. **The replay pipeline** — record on win, persist to disk, upload to server, view in browser via a new `solitaire_wasm` crate. The biggest single feature since the card-theme system.
|
||
|
||
The card-flight web animations and replay E2E test coverage close out the pipeline.
|
||
|
||
### Design direction (unchanged)
|
||
|
||
- **Tone:** Balatro — chunky readable type, theatrical hierarchy, satisfying micro-interactions.
|
||
- **Palette:** Midnight Purple base + Balatro yellow primary + warm magenta secondary.
|
||
- See `~/.claude/projects/-home-manage-Rusty-Solitare/memory/project_ux_overhaul_2026-04.md` (machine-local).
|
||
|
||
### Canonical remote
|
||
|
||
`github.com/funman300/Rusty_Solitaire` is the canonical repo. Always push there.
|
||
|
||
## Session 8 + 9 (shipped 2026-05-02) — v0.14.0
|
||
|
||
### v0.13.0-era UX candidates (had landed but missed v0.13.0's tag)
|
||
|
||
| Area | Commit | What landed |
|
||
|---|---|---|
|
||
| Theme thumbnails | `ba527de` | Each Settings → Cosmetic theme chip renders an Ace + back preview pair via `rasterize_svg`. Cached per theme. Missing-SVG themes show a transparent placeholder rather than crashing. |
|
||
| Daily-challenge calendar | `1a10476` | 14-dot horizontal calendar in the Profile modal. Today is ringed, completed days fill `STATE_SUCCESS`, missed days fill `BG_ELEVATED`. Caption: "Current streak: N · Longest: M". `PlayerProgress` gains `daily_challenge_history` (capped at 365) and `daily_challenge_longest_streak`. |
|
||
| Time Attack auto-save | `0001432` | New sibling `time_attack_session.json` next to `game_state.json`. Atomic .tmp + rename. 30 s auto-save while active + on `AppExit`. Sessions whose 10-min window expired in real time while the app was closed are discarded on load. |
|
||
| Per-mode bests | `3984231` | StatsSnapshot gains six `#[serde(default)]` fields (Classic / Zen / Challenge × best_score + fastest_win_seconds). Stats screen renders a "Per-mode bests" section. Lifetime totals continue to roll all modes together. |
|
||
| Time-bonus slider | `89c51ab` | Settings → Gameplay slider 0.0–2.0, default 1.0, "Off" at zero. Multiplies the time-bonus shown in the win modal. Cosmetic only — does NOT affect achievement unlock thresholds. |
|
||
|
||
### Quat smoke-test bug fixes
|
||
|
||
| Area | Commit | What landed |
|
||
|---|---|---|
|
||
| Move validation (#1) | `f1aeb24` | `solitaire_core::rules::is_valid_tableau_sequence(&[Card]) -> bool` checks every adjacent pair in a moved stack descends one rank with alternating colour. Wired into `move_cards`. Closes the bug where any multi-card lift could be dropped as long as the bottom landed legally. |
|
||
| Deal-tween leak (#4) | `3eabc14` | New-game snaps every card sprite to the stock pile position before writing `StateChangedEvent`, so all 52 cards animate from a single deck point during the deal. Previously sprites started from previous-game positions, briefly revealing the prior deal. |
|
||
| Softlock detection (#2) | `2716472` | `has_legal_moves` rewritten: walks every potential move source (every stock card, every waste card, the face-up top of every tableau column) against every foundation and every tableau. Previous heuristic returned `true` whenever stock had cards, hiding genuine softlocks. `GameOverScreen` now actually fires for true softlocks. |
|
||
| End-game screen (#3) | — | Resolved as downstream of #2. The pre-existing `GameOverScreen` and `WinSummaryOverlay` already cover the close-out paths; the softlock screen just never spawned because the old `has_legal_moves` lied. |
|
||
|
||
### Replay pipeline (the major feature)
|
||
|
||
| Area | Commit | What landed |
|
||
|---|---|---|
|
||
| Replay storage | `42535f5` | `solitaire_data::replay::Replay` (seed + draw_mode + mode + score + time + recorded date + ordered move list) and atomic save/load helpers under `<data_dir>/latest_replay.json`. Schema v1; `load` returns None for any other version. |
|
||
| Engine recording | `57d1c58` | `RecordingReplay` resource + `ReplayPath` settings. Every successful `MoveRequestEvent` / `DrawRequestEvent` appends to recording; `GameWonEvent` freezes the recording into a `Replay` and persists. Undo intentionally not recorded. New game clears the recording. |
|
||
| Stats button | `d9f36bf` | Stats overlay surfaces a "Latest win:" caption + "Watch replay" button. Loads from disk via `LatestReplayResource`. (Full in-engine playback deferred — button currently fires an `InfoToastEvent` describing the replay.) |
|
||
| Server upload + fetch | `93182fa` | `POST /api/replays` accepts a `Replay` JSON; `GET /api/replays/:id` returns it. JWT-gated. SQL migration for the new `replays` table. |
|
||
| Engine sync | `23c9704` | Engine uploads winning replays automatically when the player has cloud sync configured. Re-uses the existing JWT/refresh-token flow. |
|
||
| WASM crate | `5bed43e` | New workspace member `solitaire_wasm` compiles replay-relevant `solitaire_core` types to WebAssembly so a browser can re-execute a replay client-side. `wasm-bindgen` glue. |
|
||
| Web viewer | `07b8ecd` | `GET /replays/:id` returns HTML + CSS + the wasm bundle. Browser fetches the replay JSON, rasterises a deal from the seed, and animates the recorded moves. |
|
||
| E2E coverage | `3081505` | Server tests covering the full upload → fetch round-trip via `axum::test`. |
|
||
| Web flight anim | `1fcd032` | Card-flight tweens on the web side so the browser viewer reads as a real game replay rather than a static dump. |
|
||
|
||
## Open punch list
|
||
|
||
### Release prep
|
||
1. **Smoke-test on the alex machine** after pulling — confirm Quat's three bug fixes hold up in real gameplay, and try the new replay button + web viewer end-to-end.
|
||
2. **Desktop packaging** per `ARCHITECTURE.md §17`. The Arch PKGBUILD exists in `/home/manage/solitaire-quest-pkgbuild/` (separate repo). Pending: app icon, macOS `.icns` + notarisation cert, Windows `.ico` + Authenticode cert, AppImage recipe.
|
||
|
||
### UX iteration (next-round candidates)
|
||
|
||
- **Solver-at-deal toggle** (Quat investigation #1, still deferred): add a Settings → Gameplay toggle "Winnable deals only" rather than baking solver-only into every deal. Lightest middle ground.
|
||
- **Disable Bevy's default audio feature** (Quat investigation #2, still deferred): one-line `default-features = false` swap on the workspace `bevy =` line, re-enable explicitly the features the engine uses (`render`, `bevy_winit`, `2d`, `bevy_window`, `png`, `bevy_text`, `bevy_ui`, `bevy_log`, `bevy_asset`, `default_font`, `bevy_state`). Drops ~50 transitive crates including the rodio + symphonia stack the project doesn't use (kira handles audio).
|
||
- **In-engine replay playback** — promote the "Watch replay" button from a stub toast to a real playback overlay that re-runs the recorded moves with `CardAnimation` tweens. The wasm crate already proves the playback math; the in-engine version reuses the same execute logic against the live game state.
|
||
- **Per-replay history** — currently single-slot at `latest_replay.json`. A "best replay per mode" bucket or a recent-N rolling list would let players revisit notable wins.
|
||
- **Solver-driven hint system** — extend the existing hint toggle so a deal-time solver provides higher-quality hints (currently a heuristic). Requires the solver from the toggle work above.
|
||
- **Achievement: "won via replay path"** — track when a player wins a deal whose previously-saved replay also won the same deal. Mostly fun; trivial scope.
|
||
|
||
## Card-theme system (CARD_PLAN.md, fully shipped)
|
||
|
||
Seven phases landed across `b8fb3fb` → `924a1e2` in v0.11.0; v0.13.0's `7ed4f2c` consumes the per-theme `back.svg`; v0.14.0's `ba527de` adds preview thumbnails. End-to-end:
|
||
|
||
- **Bundled default theme** ships in the binary via `embedded://` — 52 hayeah/playing-cards-assets SVGs + a midnight-purple `back.svg`.
|
||
- **User themes** under `themes://`. Drop a directory containing `theme.ron` + 53 SVGs.
|
||
- **Importer** at `solitaire_engine::theme::import_theme(zip)` validates archives and atomically unpacks.
|
||
- **Picker UI** in Settings → Cosmetic; thumbnails + the active theme's `back` override the legacy `back_N.png` picker when present.
|
||
|
||
## Resume prompt
|
||
|
||
```
|
||
You are a senior Rust + Bevy developer working on Solitaire Quest.
|
||
Working directory: <Rusty_Solitaire clone path on this machine — local
|
||
directory may still be named Rusty_Solitare from earlier; that's fine>.
|
||
Branch: master. Direction is OPEN — v0.14.0 just shipped covering the
|
||
Quat bug fixes, the v0.13.0 candidate tail, and the entire
|
||
replay-pipeline feature.
|
||
|
||
State: HEAD at v0.14.0. Working tree clean apart from untracked
|
||
CARD_PLAN.md (intentional).
|
||
Build: cargo clippy --workspace --all-targets -- -D warnings clean.
|
||
Tests: 1134 passed / 0 failed.
|
||
|
||
READ FIRST (in order, before doing anything):
|
||
1. SESSION_HANDOFF.md — v0.14.0 changelog + open punch list
|
||
2. CHANGELOG.md — release-by-release record
|
||
3. CLAUDE.md — hard rules (UI-first, no panics, etc.)
|
||
4. ARCHITECTURE.md — crate responsibilities + data flow
|
||
5. ~/.claude/projects/<this-project>/memory/MEMORY.md
|
||
— saved feedback / project context (machine-local;
|
||
may be missing on a fresh machine)
|
||
|
||
DECISION TO ASK THE PLAYER FIRST:
|
||
A. Smoke-test v0.14.0 on the alex machine first to confirm the
|
||
three Quat bug fixes hold up in real gameplay and the replay
|
||
pipeline works end-to-end (record → upload → web viewer).
|
||
B. Take the deferred Bevy-audio-feature trim (Quat investigation
|
||
#2) — one-line workspace edit, ~50 fewer transitive crates.
|
||
C. Take the deferred solver toggle (Quat investigation #1): add
|
||
"Winnable deals only" Settings toggle. Larger.
|
||
D. Promote the in-engine "Watch replay" button to real playback.
|
||
E. Pick from the remaining "next-round candidates" in this doc.
|
||
F. Take the deferred desktop-packaging item (needs artwork +
|
||
signing certs from the user).
|
||
|
||
WORKFLOW NOTES:
|
||
- Commits use:
|
||
git -c user.name=funman300 -c user.email=root@vscode.infinity \
|
||
commit -m "..."
|
||
- When attributing playtester feedback in commits/docs, use "Quat"
|
||
not "Rhys" (saved feedback memory).
|
||
- Sub-agents stage + verify only; orchestrator commits.
|
||
- Every commit must pass build / clippy / test before pushing.
|
||
- Push to GitHub (origin) — that is the canonical remote.
|
||
|
||
OPEN AT THE START: ask which of A–F. Don't pick unilaterally.
|
||
```
|