Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.8 KiB
Ferrous Solitaire — Session Handoff
Last updated: 2026-05-18 — Three leaderboard bugs fixed, tagged v0.35.1. All commits on origin/master.
Current state
- HEAD on origin/master:
8f86d66(fix: three leaderboard bugs) - Latest tag:
v0.35.1 - Working tree: clean
- Build:
cargo clippy --workspace -- -D warningsclean - Tests: 1277 passing / 0 failing across the workspace
What shipped since the last handoff (v0.23.0 → v0.35.1)
v0.34.0 — Android polish + code-quality sweep (2026-05-16/17)
| Commit | Summary |
|---|---|
9623bde |
Wire FiraMono to Android corner label; CardImageSet load tests |
980312c |
Fix wrong bottom-right suit symbol on JS/QS/KS card assets |
04e99a8 |
Correct Android waste fan overlap and resume layout desync |
3bb3ddb |
Eliminate panics, fix dismiss hit-test scope, guard home respawn |
f8f1f26 |
Adaptive drop zones, touch event correctness, modal lifecycle guards |
1eb4043 |
Auth-guard avatar serving; atomic write; user_id assertion in merge |
69c6e88 |
Deterministic pile serialization, undo skip, url-encode bytes, merge_at |
aa7b0f6 |
Gate frame-hot ECS systems on resource changes (perf) |
6727126 |
Consolidate APP_DIR_NAME; add #[must_use] on pure fns |
a4dfb0c |
Differentiate leaderboard opt-in vs opt-out error toasts (M-12) |
7fc98f8 |
WASM: state() and step() return Result, errors throw JS exceptions (CR-6) |
ffed6b2 |
Share Tokio runtime across all network tasks (M-16) |
fa84152 |
Correct Android help hint label → to ! (M-17) |
18d7937 |
Derive Copy for DrawMode; drop redundant .clone() calls (M-18) |
132fea9 |
Use saturating_add for move_count increments (M-19) |
0ecc1a9 |
Add missing derives to AchievementContext (M-20) |
2301cc6 |
Align android_keystore temp extension with cleanup glob (M-21) |
2e52f54 |
Enforce 32-char display_name limit at sync client boundary (M-22) |
c8878d6 |
Fix stale FOCUS_RING colour comment (M-23) |
4aafc0a |
Name HUD popover Z-layers; replace raw Z arithmetic (M-24) |
v0.35.0 — Accessibility + sync reliability (2026-05-18)
| Commit | Summary |
|---|---|
eb6c93f |
Silence B0004 by adding Transform to ModalScrim |
6f5cebd |
Fire WarningToastEvent on sync pull failure (was InfoToastEvent) |
87aec5b |
Gate all decorative motion animations under reduce_motion_mode |
reduce_motion_mode now gates: score pulse, score floater, streak flourish
(hud_plugin), card-shake on rejected move, foundation completion flourish
(feedback_anim_plugin). Pattern: gate at the trigger/start system, never at
the tick system — if the component isn't inserted, the tick path never runs.
v0.35.1 — Leaderboard bug fixes (2026-05-18)
| Commit | Summary |
|---|---|
8f86d66 |
Fix three leaderboard bugs: wrong toast type, stale label, name not synced |
Three bugs fixed:
-
Wrong toast type on error —
poll_opt_in_task/poll_opt_out_taskerror branches now fireWarningToastEventinstead ofInfoToastEvent. -
Display name not pushed to server on change —
Settingsgainsleaderboard_opted_in: bool(serde-defaultedfalse). Settrue/falsewhen opt-in/out tasks succeed and persisted tosettings.json.handle_display_name_confirmnow spawns anopt_in_leaderboardtask when already opted in — the server's upsert endpoint updates onlydisplay_namewithout re-opting-in. -
"Public name" label stale after name change —
LeaderboardPublicNameTextmarker component added to the label node.update_leaderboard_public_name_labelsystem rewrites the text each frame the panel is open; O(0) cost when panel is closed.
5 new regression tests cover all three bugs.
Open punch list
1. CHANGELOG documentation debt
CHANGELOG.md currently ends at v0.33.0. Entries for v0.34.0, v0.35.0, and v0.35.1 are missing. Low priority (git log is authoritative) but worth closing before the next release.
2. Android APK launch verification (Option A)
Physical device test: install the latest APK on a real Android device (not AVD), confirm:
- App launches without crash
- Safe area insets arrive and shift HUD correctly after ~3 frames
- All modal Done buttons are above the gesture bar
- Drag-and-drop works on all pile types
- Leaderboard panel opens and the "Public name" label updates correctly after using "Set Name"
This has never been gated in CI. AVD adb shell input tap doesn't deliver real
touch events, so physical-device smoke testing is the only gate.
3. Matomo analytics wiring
Settings has analytics_enabled: bool and matomo_url: Option<String> but no
engine code consumes them — the analytics toggle in Settings is a no-op. If
analytics are ever needed, the Matomo HTTP Tracking API client needs to be written
and wired to GameStateResource events.
Architectural notes for next session
-
Reduce-motion pattern: always gate in the
start_*/detect_*system (the trigger), not thetick_*system. If the component is never inserted, the tick path never runs. Seehud_plugin.rs::detect_score_changeandfeedback_anim_plugin.rs::start_shake_animfor the canonical pattern. -
Leaderboard server upsert:
POST /api/leaderboard/opt-inis idempotent — calling it when already opted in just updatesdisplay_name. Safe to call fromhandle_display_name_confirmwithout tracking a separate "needs update" flag. -
Messages<T>API (Bevy 0.18.1): write withresource_mut::<Messages<T>>().write(value); read in tests withmsgs.get_cursor()+cursor.read(msgs).next(). -
Test input-state pitfall:
MinimalPluginshas no input-tick system, soButtonInput::just_pressedstate persists across frames unless explicitly cleared withinput.release(key); input.clear()between updates.