Files
Ferrous-Solitaire/SESSION_HANDOFF.md
T
funman300 f2d2119db5 docs: refresh handoff + populate CHANGELOG [Unreleased] for v0.20
The v0.19.0 handoff had drifted material across seven commits:
HEAD pointer was wrong (still claimed 6037596; actually 59424a3),
"Tags on origin" still claimed v0.19.0 wasn't pushed, the
known-flake list still mentioned `pull_failure_sets_error_status`
(fixed in 67c150b), and three of four v0.19.0 punch-list
"candidates" had silently shipped without the doc tracking it.
The Android build target landing in fb8b2ac wasn't mentioned at
all despite being the largest single change in the cycle.

CHANGELOG [Unreleased] populated with all seven commits grouped
into Added / Fixed:

  Added:
    - Android build target — first working APK (fb8b2ac)
    - Android developer setup + build runbook (59424a3)
    - F3 FPS / frame-time overlay (690e1d2)
    - "Smart window size" Settings toggle (e1b8766)
    - "Shareable" badge on Latest-win caption (9b065e5)
    - Help: M / P / Win-Summary-Enter rows (35516d3)

  Fixed:
    - pull_failure_sets_error_status flake (67c150b)

SESSION_HANDOFF.md fully rewritten:
  - Status section reflects HEAD 59424a3, clean working tree (apart
    from this commit's docs), 1170 passing tests, no known flakes
  - "Where we are" tracks v0.19.0 candidates' close status (3 of 4
    shipped, App icon still open and now blocked on a re-export)
  - New v0.20 candidates table covers all seven commits
  - New "Phase Android" punch-list section captures the unblocked-
    by-fb8b2ac work: APK launch verification, dirs::data_dir port,
    JNI ClipboardManager, Android Keystore, gpgs integration, the
    cosmetic cargo-apk panic workaround
  - Process notes call out the async-test starvation pattern
    (seen twice now), the bin→lib+shim refactor as a reusable
    pattern, and target-gating-by-default for cross-platform deps
  - Resume prompt's A–D menu refreshed to reflect actually-open
    work: APK verification, Phase-Android persistence, app icon,
    and a v0.20 cut

Build: cargo clippy --workspace --all-targets -- -D warnings clean.
Tests: 1170 passing / 0 failing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 13:28:04 -07:00

10 KiB
Raw Blame History

Solitaire Quest — Session Handoff

Last updated: 2026-05-07 — [Unreleased] accumulating v0.20 candidates. Seven commits sit on top of v0.19.0: three close items from v0.19.0's punch list (pull-failure flake, smart-window-size opt-out, Shareable badge), one extends Help cheat-sheet coverage, and three open a new performance / portability arc — F3 FPS overlay, Android build target (first working APK), and the matching developer-setup runbook. The Android build is the load-bearing change: solitaire_app now compiles into both a desktop bin and an Android cdylib from the same source.

Status at pause

  • HEAD on origin: 59424a3 (post-Android-runbook commit).
  • Working tree: modified — CHANGELOG.md and SESSION_HANDOFF.md carry the v0.20-candidates promotion + this refresh, ready to commit. artwork/ remains untracked.
  • Build: cargo clippy --workspace --all-targets -- -D warnings clean (verified this session).
  • Tests: 1170 passing / 0 failing across the workspace (verified this session). The previously-flaky pull_failure_sets_error_status is fixed; no known flakes remain.
  • Tags on origin: v0.9.0 through v0.19.0.

Where we are

v0.19.0's "Possible next-round candidates" list shipped 3 of 4:

  • pull_failure_sets_error_status flake fix: shipped at 67c150b.
  • Settings UI for smart-default-size opt-out: shipped at e1b8766.
  • Persistent share link URL on selector caption: shipped at 9b065e5 (as a "Shareable" badge on the Latest-win caption — the Prev/Next selector chips don't have a live spawn site yet, so the badge attaches to the existing single-replay caption).
  • App icon round — still open. 11 PNGs generated by artwork/Icon Export.html are not in the artwork/ directory any more (current artwork/ holds the reverted Rusty Pixel card PNGs); icon-export needs to be re-run before this item can be picked up.

Two new threads opened that weren't on any prior punch list:

  • F3 FPS / frame-time overlay (690e1d2). DiagnosticsHudPlugin wraps FrameTimeDiagnosticsPlugin; F3 toggles a top-right readout. Hidden by default; primarily a developer affordance.
  • Android build target (fb8b2ac + 59424a3). solitaire_app is now a bin + cdylib hybrid. cargo apk build produces a 54 MB APK with full assets. Five gating points resolved (split, manifest, bevy feature, arboard target-gate, keyring target-gate). What's not yet verified: APK launch on AVD/phone, dirs::data_dir() Android behaviour for the persistence/sync layer.

Design direction (unchanged)

  • Tone: Balatro — chunky readable type, theatrical hierarchy, satisfying micro-interactions.
  • Palette: Midnight Purple base + Balatro yellow primary + warm magenta secondary.

Canonical remote

github.com/funman300/Rusty_Solitaire is the canonical repo. Always push there.

v0.20 candidates ([Unreleased] in CHANGELOG)

Area Commit What landed
Async-pull flake fix 67c150b pull_failure_sets_error_status swaps a fixed 5-update budget for a 5-second wall-clock deadline + yield_now between pumps. Closes the last v0.19-era flake.
Smart window size opt-out e1b8766 New Settings::disable_smart_default_size: bool (#[serde(default)]). solitaire_app::main reads the flag at startup and skips apply_smart_default_window_size registration when set. Settings → Gameplay row toggles it; tooltip notes saved geometry always wins.
Shareable badge 9b065e5 Stats overlay's Latest-win caption gains \u{2022} Shareable when the displayed replay carries a share_url. Badge appears on the single-replay caption (no Prev/Next live spawn site yet).
Help: M / P / Win-Summary-Enter 35516d3 Three rows added to F1 Help → Overlays. Closes coverage drift on post-v0.18 keys.
F3 FPS overlay 690e1d2 DiagnosticsHudPlugin + FrameTimeDiagnosticsPlugin. Hidden by default; F3 toggle is not gated by pause/modal state. Smoothed FPS / frame_time. Anchored top-right at Z_SPLASH + 100.
Android first APK fb8b2ac solitaire_app split into bin + lib (cdylib). [package.metadata.android] pins SDK 34 / 26. Bevy gains android-native-activity. arboard and keyring/keyring-core target-gated to non-Android. 54 MB APK builds; launch on device not yet verified.
Android runbook 59424a3 Debian 13 toolchain install, cargo apk build invocation, post-sign panic workaround, wired-vs-stubbed table. Fresh-clone runnable.

Open punch list

Carried forward from v0.19.0

  • App icon round. Window::icon not yet wired; no .icns / .ico / Linux hicolor PNG hierarchy. The 11-size icon export the v0.19 handoff referenced is not currently in artwork/ — re-running artwork/Icon Export.html is the prerequisite. Half-day task once the PNGs are back in place. No cert dependency.

New — Phase Android (opened by fb8b2ac + 59424a3)

  • APK launch verification on AVD / device. adb install then adb logcat against the bevy_test AVD. Shakes out any Bevy/winit Android-specific runtime bugs not caught by the build alone.
  • dirs::data_dir() Android port. Persistence (settings, stats, achievements, replays, progress) all route through this function. Android sandboxing usually demands getFilesDir() via JNI. Until verified, the APK may launch but fail to persist anything across cold starts.
  • JNI ClipboardManager bridge. Replaces the Android stub for the Stats "Copy share link" toast. arboard doesn't ship an Android backend, so this is a small custom JNI call.
  • Android Keystore for credentials. keyring is target-gated to a stub that returns KeychainUnavailable; replace with Android Keystore via JNI when sync auth ships on mobile.
  • Google Play Games (gpgs) integration. Listed in solitaire_gpgs as a Phase-Android target since Phase 1; now unblocked by the build target.
  • Cosmetic cargo apk build --lib workaround. The post-sign panic doesn't affect the APK on disk but produces noisy stderr. Either upstream a cargo-apk fix or document the --lib invocation as canonical in the runbook.

Other small candidates

  • Cut v0.20.0 — the seven commits are a coherent bundle (3 punch-list closes, 1 docs polish, 1 perf tool, 2 Android arc starters). Tag whenever feels right; the Android arc has more surface to land before it's "done", but the build-works state is a defensible release point.
  • Prev/Next selector chips spawn site. 9b065e5 notes Prev/Next markers exist in stats_plugin but no spawn site renders them today — the Shareable badge therefore lands on the single-replay caption. If/when Prev/Next is plumbed to the Stats overlay, the badge will need to follow.

Process notes (from this round)

  • Async-test starvation pattern (resolved twice now). Auto-save flake (v0.19) and pull-failure flake (v0.20-candidates) shared the same root cause: a fixed N-update budget for an AsyncComputeTaskPool task to surface its result, which starves under cargo-test parallelism. The wall-clock-bounded loop pattern (std::thread::yield_now() between pumps, deadline = Instant::now() + Duration::from_secs(5)) is the canonical fix. Future async-test work should reach for this shape on the first commit, not after a flake materialises.
  • Bin → lib + thin shim refactor. The solitaire_app split for cargo-apk is a textbook cdylib-as-NativeActivity pattern. Worth knowing as a reusable shape for any future Bevy-on-mobile project: keep main.rs to ≤10 lines that delegate to pub fn run, put all setup in lib.rs, and let the build system pick which artifact (bin or cdylib) it needs.
  • Target-gating defensive defaults. Three of v0.20-candidates' Android-arc commits had to disable a default-on dependency (arboard, keyring, keyring-core) for the new target. When a future contributor adds a desktop-implicit dependency, reaching for [target.'cfg(not(target_os = "android"))'.dependencies] preemptively is cheaper than rediscovering the gating during the next platform port.

Resume prompt

You are a senior Rust + Bevy developer working on Solitaire Quest.
Working directory: <Rusty_Solitaire clone path on this machine>.
Branch: master. v0.19.0 is tagged on origin; seven commits sit on
top opening the v0.20 cycle (3 punch-list closes + a perf tool +
the Android build target).

State: HEAD at 59424a3 + the v0.20-candidates docs commit on top
(this session). Working tree may carry the doc updates if not yet
committed.

READ FIRST (in order, before doing anything):
  1. SESSION_HANDOFF.md  — this file
  2. CHANGELOG.md        — [Unreleased] holds the v0.20 draft
  3. CLAUDE.md           — unified-3.0 rule set
  4. CLAUDE_SPEC.md      — formal architecture spec
  5. ARCHITECTURE.md     — crate responsibilities + data flow
  6. docs/android/*      — Android setup + build runbook (59424a3)
  7. ~/.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. APK launch verification — `adb install` + `adb logcat` on
     bevy_test AVD or a physical x86_64 device. Shakes out
     runtime bugs the build can't catch.
  B. Phase-Android persistence — port dirs::data_dir() through a
     JNI getFilesDir() bridge so the APK can survive a cold
     start. Largest unblocked Android piece.
  C. App icon — re-run artwork/Icon Export.html, then wire
     Window::icon + generate .icns / .ico. Half-day task. No
     cert dependency.
  D. Cut v0.20.0 — promote [Unreleased] to [0.20.0], tag,
     push. Mechanical close-out; the Android arc has more
     surface to land but the build-works state is a defensible
     release point.

WORKFLOW NOTES:
  - Use the system git config (already correct).
  - 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) — gh auth setup-git wired on
    primary dev box; verify on laptop before first push.

OPEN AT THE START: ask which of AD. Don't pick unilaterally.