From 0c1cc4026691aa572ba9d27132682d00cee60538 Mon Sep 17 00:00:00 2001 From: funman300 Date: Fri, 8 May 2026 10:53:24 -0700 Subject: [PATCH] =?UTF-8?q?docs(handoff):=20refresh=20post-v0.21.0=20?= =?UTF-8?q?=E2=80=94=20drop=20historical=20sections,=20retune=20Resume=20p?= =?UTF-8?q?rompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the v0.20.0 → post-cut refresh pattern (commit a65e5b8): the cut commit (04f9bf9) only edits CHANGELOG.md; this follow-up resets the handoff so it serves a fresh session cleanly rather than carrying forward the v0.20.0-era narrative as cruft. Removed (now redundant with CHANGELOG.md § [0.21.0]): - The full "Since the v0.20.0 cut (un-pushed)" section — ~300 lines of per-commit narratives for the post-tag work. - The "What shipped in v0.20.0 (frozen at 41a009a)" section — v0.20.0 detail lives in CHANGELOG.md § [0.20.0]. Replaced with: - Short header pointing to CHANGELOG.md § [0.21.0] for cycle detail. - "Since the v0.21.0 cut" placeholder ("No threads in flight"). Refreshed: - Status at pause: HEAD on origin matches local; latest tag v0.21.0 at 04f9bf9; tests 1184; references to v0.20.0 baseline preserved as audit trail. - Visual-identity follow-ups: dropped the closed entries (card-face arc, splash polish, replay banner pieces). Added what's still open: replay screen-takeover redesign, floating MOVE chip above focused card, toast Warning/Error wiring, high-contrast accessibility, reduced-motion accessibility. - Canonical remote: dropped the "unpushed commits" warning since origin is caught up. - Design direction palette: brick-red primary instead of cyan, red→lime CBM swap instead of red→cyan, glyph orientation upright. v0.21.0 source commits cited. - Resume prompt: rebased to v0.21.0 anchor. Decision options rewritten — closed B/C/D dropped; live A/E/F renumbered into fresh A/B/C plus three new candidates (Toast variants, Phase 8 sync, accessibility modes). Workflow notes gain the token-port-pattern lesson from v0.21.0's three "fallback path the migration walked past" follow-ups. Net diff: −513 / +117 lines; file shrinks from 668 to 272. v0.20.0 historical context preserved in CHANGELOG.md. Co-Authored-By: Claude Opus 4.7 --- SESSION_HANDOFF.md | 628 +++++++++------------------------------------ 1 file changed, 116 insertions(+), 512 deletions(-) diff --git a/SESSION_HANDOFF.md b/SESSION_HANDOFF.md index 4ebd9a0..c013a84 100644 --- a/SESSION_HANDOFF.md +++ b/SESSION_HANDOFF.md @@ -1,403 +1,44 @@ # Solitaire Quest — Session Handoff -**Last updated:** 2026-05-08 — v0.20.0 cut and tagged at `41a009a`, -all post-cut commits pushed to origin (HEAD = `dd101b3`), working -tree clean. -The cut itself shipped two through-lines: a full **Terminal visual- -identity port** (token system, modal scaffold, gameplay-feedback, -toasts, table / card chrome, splash cursor) and the **Android -persistence shim** that closes the `dirs::data_dir() = None` pitfall -flagged in CLAUDE.md §10. Since the cut, the post-tag work split -into two arcs: (1) splash boot-screen port + replay-overlay -banner enrichments + desktop-adaptation spec — closing Resume-prompt -Options B and C (see "Since the v0.20.0 cut" entries below); and -(2) **the card-face artwork regeneration arc — Option D, closed -2026-05-08** — full Terminal cards rendering on every face, plus -three follow-up fixes that surfaced during sign-off (default-theme -SVG override, table backgrounds, top-bar overlap), plus a -glyph-orientation tweak (no 180° inverted-corner rotation). +**Last updated:** 2026-05-08 — **v0.21.0 cut and tagged at `04f9bf9`**, +working tree clean, all post-tag work pushed to origin. + +v0.21.0 closes the visual-identity arc opened in v0.20.0. Three +through-lines landed in this cycle: the **card-face / suit / +card-back artwork migration** that v0.20.0 deliberately deferred +(both rendering paths in lockstep — `assets/cards/*.png` fallback +plus the bundled-default theme SVGs at +`solitaire_engine/assets/themes/default/*.svg` that +`include_bytes!()`-embed into the binary), the **splash boot- +screen + replay-overlay polish** that closed Resume-prompt +Options B and C, and a late-cycle **`ACCENT_PRIMARY` palette +swap** from cyan `#6fc2ef` to brick red `#a54242` after a quick +stakeholder review of the shipped art. + +Full v0.21.0 detail lives in `CHANGELOG.md` § [0.21.0]. This +file from here on focuses on what's *open* post-cut and how to +resume. ## Status at pause -- **HEAD locally:** see `git rev-parse HEAD`. Most recent narrative - entry below names the latest substantive commit; this status line - intentionally avoids hard-coding the SHA so a docs-only edit - doesn't immediately stale the handoff. -- **HEAD on origin:** matches local. All post-cut commits pushed - through `dd101b3`. Decide whether to roll the post-tag work - into v0.20.1 / v0.21.0-candidates the next time a release is cut. +- **HEAD locally:** see `git rev-parse HEAD`. The cut commit is + `04f9bf9`; any post-cut docs edits ride on top of that. +- **HEAD on origin:** matches local. v0.21.0 is fully on origin. - **Working tree:** clean. No WIP outstanding. - **`artwork/` directory:** still untracked. Intentional. - **Build:** `cargo clippy --workspace --all-targets -- -D warnings` clean. -- **Tests:** **1184 passing / 0 failing** across the workspace. - Net delta from the 1180 baseline: splash polish added two - (`build_scanline_image_has_expected_2x2_rgba_bytes`, - `scanline_overlay_spawns_and_fades_with_splash`); the - card-face migration added one (`card_face_svg_pin` integration - test) and consolidated two (`face_colour` CBM tests folded - into `text_colour` CBM tests, net −2 then +1 from pin); - call it +4 net. -- **Tags on origin:** `v0.9.0` through `v0.20.0`. v0.20.0 is on - `41a009a`. +- **Tests:** **1184 passing / 0 failing** across the workspace + (net +8 from v0.20.0's 1176 baseline). Detail in + `CHANGELOG.md` § [0.21.0] § Stats. +- **Tags on origin:** `v0.9.0` through `v0.21.0`. v0.21.0 is on + `04f9bf9`; v0.20.0 stays on `41a009a`. -## Since the v0.20.0 cut (un-pushed) +## Since the v0.21.0 cut -### `39b8496` `docs(ui): add Terminal desktop-adaptation spec` - -`docs/ui-mockups/desktop-adaptation.md` — 283 lines covering -viewport assumptions, seven universal adaptation rules, and per- -screen geometry rules for the priority surfaces (Game Table, Win -Summary, Settings, Help, Pause, Home, Splash, Stats, and the -modal-pattern screens Profile / Achievements / Theme Picker / -Daily Challenge). Closes the spec gap — 23 of 24 mockups were -mobile-only, but the v0.20.0 token-port pass was already layout- -agnostic so nothing shipped broken. The spec matters for *next* -ports. - -**Why rules > visual mockups for this gap:** Stitch's -`generate_variants` API timed out on the layout-only adaptation -prompt (server-side flake, not a prompt-shape issue — confirmed -by polling `list_screens` with no new variant landing). A markdown -rules file applies to every screen including the 9 missing-plugin -surfaces (splash, challenge, time-attack, weekly-goals, -leaderboard, sync, level-up, replay-overlay, radial-menu) that -aren't in the Stitch project at all. It's also referenceable from -code comments and commit messages without loading an image. - -### `cacb19c` `feat(engine): port the splash to the Terminal boot-screen treatment` - -Implements the full mockup-spec splash from -`docs/ui-mockups/splash-mobile.html` plus the desktop adaptation -rules: - -- **Header**: cursor block (96 px `▌`), wordmark ("Solitaire - Quest"), 192 px divider, "TERMINAL EDITION" subtitle. -- **Boot log**: three ✓ check rows (`assets loaded`, - `theme: terminal`, `progress restored`) + a `▌ ready_` line. - Capped at 480 px width on desktop (else 70 % viewport). -- **Progress bar**: 1 px track (`BORDER_SUBTLE`) with a 100 %- - width cyan (`ACCENT_PRIMARY`) fill + `DONE · 247 ASSETS` - caption. Capped at 720 px on desktop (else 80 %). -- **Footer**: `BASE16-EIGHTIES` label, eight palette swatches - (12 × 12 px each — one per named token in the design system), - version line. - -**Refactored the alpha-fade scaffold** from per-marker queries -(`SplashTitle` / `SplashSubtitle` / `SplashCursor`) to a single -`SplashFadable { base_color: Color }` + `SplashFadableBg` -variant. ~15 fadable elements share one global query each; -adding more is one component-attach, not three new query types. - -**Skipped, with rationale captured in the commit:** -- Scanline overlay (needs a tiled-pattern asset or custom shader). - *Open in "Visual-identity follow-ups" below.* -- Pulsing cursor on the "ready_" line (would fight the global - fade timeline). *Open in "Visual-identity follow-ups" below.* -- "RUSTY SOLITAIRE" wordmark from the mockup (the actual product - is "Solitaire Quest"; the mockup leaked the repo name). *Closed - — the in-engine wordmark stays "Solitaire Quest".* - -### `c84d9f4` `feat(engine): scrub fill bar + per-frame updater for replay overlay` - -Closes the WIP described in the prior handoff. Adds the 1 px cyan -scrub bar called for in `docs/ui-mockups/replay-overlay-mobile.html`: -a track in `BORDER_SUBTLE` spans the bottom edge of the banner and -the cyan `ACCENT_PRIMARY` fill mirrors `cursor / total` via a new -`ReplayOverlayScrubFill` component + `update_scrub_fill` system. -The pure `scrub_pct` helper is shared between the spawn path -(initial fill width) and the per-frame updater so the first paint -already reflects state instead of popping `0 → cursor` on the -first tick — same shape as the existing `format_progress` / -`update_progress_text` split. Two new tests cover the four corners -of `scrub_pct` and an end-to-end drive of `ReplayPlaybackState` -asserting `Node.width` on the unique scrub-fill entity. Same -change-detection guard as the text updaters, so an idle replay -leaves the node untouched. - -Header text treatment (closed by `6204db8` immediately below), -move-log scroll, MOVE chip, and WIN MOVE callout from the same -mockup are still open — separate commits. - -### `6204db8` `feat(engine): port replay banner label to ▌ cursor-block treatment` - -Aligns the replay overlay's headline with the splash boot-screen -idiom landed in `cacb19c`: `Replay` → `▌ replay` and -`Replay complete` → `▌ replay complete`. The cursor block (`▌`, -U+258C) prefixed to a lowercased label reads as a Terminal output -line rather than a generic UI title, tightening the family -resemblance between the two top-level overlay surfaces. Pure -text-content change; no behavioural shift, no new components, no -new systems. - -**Mockup deviation (intentional):** the source mockup string in -`docs/ui-mockups/replay-overlay-mobile.html` is `▌replay.tsx`. The -`.tsx` is a prototyping leak — Stitch renders in React, so the -mockup author reached for a familiar filename — and was dropped -for the in-engine version since the codebase is Rust. The `▌` + -lowercase pattern is what reads as a Terminal-output-line; the -extension is incidental. (Same shape as the "RUSTY SOLITAIRE" -wordmark deviation noted under `cacb19c` — the mockup leaked the -repo name; the actual product is "Solitaire Quest".) - -### `54005d5` `feat(engine): add GAME #YYYY-DDD caption beneath the replay headline` - -Adds the right-anchored game-identifier piece of the replay-overlay -mockup, adapted to live *under* the existing "▌ replay" headline as -a `TYPE_CAPTION` (11 px) / `TEXT_SECONDARY` subtitle. Format is -`GAME #{year}-{ordinal:03}` (e.g. `GAME #2026-122` for a replay -recorded 2026-05-02) — year + chrono ordinal gives a compact, -monotonically-increasing identifier matching the mockup's -`GAME #2024-127` motif. New `ReplayOverlayGameCaption` marker, new -pure helper `format_game_caption(state) -> Option` (None -for Inactive / Completed since the replay is consumed in those -branches; spawn-time fall-through to empty string). - -**Layout impact:** `BANNER_HEIGHT` bumped 48 → 60 px so the new -left column (headline + 2 px gap + caption ≈ 39 px content) fits -under the scrub bar with room to spare. +12 px banner mass is the -deliberate cost of the new content; no other plugin observes -`BANNER_HEIGHT` so the change is local. - -Two new tests (1180 → 1182): `format_game_caption_covers_state_corners` -pins the three branches plus the zero-pad-to-3-digits invariant -for early-January ordinals; `overlay_game_caption_shows_replay_date` -drives `ReplayPlaybackState` end-to-end. - -### `e080b49` `feat(engine): restyle replay progress text as Terminal MOVE chip` - -Closes the centre-text half of the replay-overlay enrichments. The -plain "Move N of M" text becomes a 1px `ACCENT_PRIMARY`-bordered -chip containing "MOVE N/M" — uppercase + slash separator reads as -a Terminal output line and matches the floating-chip motif in -`docs/ui-mockups/replay-overlay-mobile.html`. The chip lives -in-banner rather than floating above the focused card (the -screen-takeover treatment that requires plumbing cursor → card -identity remains deferred). - -**Implementation note:** `BorderColor` in Bevy 0.18 is a per-side -struct, not a tuple — `BorderColor::all(ACCENT_PRIMARY)` is the -correct constructor. Worth pinning for next time we touch a -border-painted UI surface. The `ReplayOverlayProgressText` marker -stays on the inner Text rather than the new chip Node so -`update_progress_text` keeps repainting unchanged — a deliberate -"markers belong on the entity that updates change" choice. - -Test count unchanged (1182); `overlay_progress_text_reflects_cursor` -swapped its assertion from "Move 5 of 10" to "MOVE 5/10". - -This pair (`54005d5` + `e080b49`) closes Option C from the -SESSION_HANDOFF Resume prompt's banner-local enrichments. Floating- -chip-above-focused-card and the full screen-takeover redesign -remain — both data-layer or cross-plugin and intentionally still -open. - -### `29136d8` `feat(engine): add pulsing trailing cursor to splash "▌ ready_" line` - -Closes the cursor-pulse half of the splash polish arc deferred in -`cacb19c`. The "▌ ready_" line now ends with a 6×12 px cyan Node -that pulses on a 1 s sine cadence, multiplied with the global -splash fade timeline so the cursor never reaches full alpha while -the rest of the splash is still fading in. - -**The "multiply, don't override" pattern.** Two systems write the -same `BackgroundColor` per frame: `advance_splash` writes the -global-fade alpha, `pulse_splash_cursor` overwrites with -`global_alpha × pulse_factor`. Both derive from `SplashAge` on the -root, so the writes are commensurate — the second one isn't -"fighting" the first, just refining it. This is the cleanest fix -for the "fight the global fade timeline" warning the original -`cacb19c` skip note flagged. - -**Defensive division guard.** `cursor_pulse_factor(age, period, min)` -short-circuits to `1.0` when `period <= 0.0` so a future -misconfiguration produces a steady cursor rather than NaN -propagation (NaN in alpha = invisible UI, hard to debug). Worth -mirroring on every trig/division helper, not just this one. - -One new test (1182 → 1183): `cursor_pulse_factor_corners` pins the -peak (factor = 1 at age = period / 4), trough (factor = min at age = -period × 3 / 4), and the zero/negative-period guard. - -### `a27cf5a` `feat(engine): add tiled scanline overlay to splash` - -Closes the scanline half of the splash polish arc. A fullscreen -`ImageNode` tiles a runtime-generated 2×2 RGBA8 texture over the -splash content — top row transparent, bottom row `#1a1a1a` at -~30 % alpha — producing the 1 px-pitch horizontal scanline pattern -called for in `docs/ui-mockups/splash-mobile.html`. - -**Texture-α × tint-α composite for fade integration.** The 30 % -alpha is baked into the texture pixels, not the `ImageNode.color` -tint. `advance_splash`'s new third query writes -`(1, 1, 1, global_alpha)` into the tint each tick; the GPU -multiplies texture-α by tint-α, so the visible composite is -`0.3 × global_alpha`. Cleaner than building a "multiplicative -fadable" abstraction in the ECS — the GPU already does this -multiplication for free. - -**Bevy 0.18 API surprises (worth pinning):** -- `RenderAssetUsages` re-exports under `bevy::asset::`, not - `bevy::render::render_asset::`. Type name unchanged; module - path moved. -- `TextureFormat::pixel_size()` returns `Result` rather - than the bare `usize` you'd expect for a static format query. - Annoying enough that the `debug_assert_eq!` against the buffer - length just hard-codes the `2 × 2 × 4 = 16` literal. - -Headless test fixture now also `init_resource::>()` -since `MinimalPlugins` doesn't pull `AssetPlugin` — same pattern -`settings_plugin::tests` already used. Without it, the -`Option>>` parameter on `spawn_splash` would -fall through and the scanline overlay would silently skip, -defeating the new tests. - -Two new tests (1183 → 1185): -`build_scanline_image_has_expected_2x2_rgba_bytes` locks the -texture pixels literally so a future tweak can't drift the -appearance silently; `scanline_overlay_spawns_and_fades_with_splash` -asserts spawn placement under `SplashRoot` and the new -fade-images branch's correctness end-to-end. - -This pair (`29136d8` + `a27cf5a`) closes Option B from the -SESSION_HANDOFF Resume prompt — both splash polish pieces now -shipped. - -### `5623368`…`dd101b3` — Option D card-face migration arc - -Closed 2026-05-08 across nine commits. The full Terminal card -artwork now renders end-to-end. Detail breakdown lives in the -"Visual-identity follow-ups" punch-list entry below; the short -version: - -- Migration plan + pipeline tooling: `5623368` (plan doc), - `3a4bb63` (single-card PoC proving the `usvg`/`resvg` pipeline - at per-card grain), `babe5cc` (full - `solitaire_engine/examples/card_face_generator.rs` example - emitting 52 faces + 5 backs into `assets/cards/`), `48b28d2` - (the `card_face_svg_pin` integration test pinning rasteriser - output via inline FNV-1a hashing of raw RGBA8 bytes — the - pin's bootstrap pattern, "empty `EXPECTED` → run → paste", - is the maintenance interface for future intentional changes). -- Lockstep step 4+5: `e8bf9d7`. New PNG bytes + the 5 - `card_plugin` constants (`CARD_FACE_COLOUR`, - `RED_SUIT_COLOUR`, `BLACK_SUIT_COLOUR`, - `CARD_FACE_COLOUR_RED_CBM` → `RED_SUIT_COLOUR_CBM`, - `card_back_colour`) + signature shifts in one commit. - `face_colour` deleted — Terminal face is uniformly - `CARD_FACE_COLOUR` regardless of CBM, so the function - collapsed to a constant. `text_colour` gained a - `color_blind: bool` parameter (red→cyan suit-glyph swap when - CBM is on). Four `face_colour` CBM tests folded into two - `text_colour` CBM tests in lockstep. -- Three follow-ups that surfaced during sign-off, all from the - same "fallback path the migration walked past" pattern: - `a14200a` regenerated the embedded **default-theme SVGs** at - `solitaire_engine/assets/themes/default/*.svg`; those bytes - `include_bytes!()`-embed into the binary and override - `assets/cards/*.png` at startup, so the PNG migration alone - didn't change what production rendered. `8719f77` - regenerated `assets/backgrounds/bg_*.png` to flat Terminal - near-black (5 solid-colour PNGs via a new - `solitaire_engine/examples/background_generator.rs` example). - `ae84dc1` cleared the **top-bar overlap** at portrait/narrow - window widths by swapping the action-button row's hardcoded - `font_size: 16.0` to `TYPE_BODY` (a typography-migration - miss) and stepping horizontal padding from `VAL_SPACE_3` - to `VAL_SPACE_2`. -- Glyph-rendering fix: `af414b6`. The bundled `FiraMono` - doesn't carry usable U+2660-2666 glyphs at the requested - size — `usvg` was silently substituting tiny "tofu" marks. - Switched suit glyphs from `` elements to inline SVG - `` elements via a new `suit_path_d` helper. Path-based - rendering bypasses the font system entirely; same bytes on - every machine, no fontdb dependency, no substitution risk. - Same path data renders correctly whether filled (♥ ♠) or - outlined (♦ ♣ — the always-on color-blind glyph - differentiation). -- Glyph-orientation tweak: `dd101b3`. Removed the 180° rotation - from the bottom-right large suit glyph at user request. Both - glyphs now render upright. `design-system.md` § Game Cards - line 220 updated in lockstep — the deliberate deviation from - the traditional inverted-corner-indicator convention is - documented in the spec, not just the code. - -The pin test fired exactly twice during this arc (once for the -text→path switch, once for the unrotation) and rebaselined -cleanly each time via the empty-then-paste pattern. The 5 -`back_*` hashes stayed identical across both rebaselines — -secondary signal that the FNV-1a fingerprinting is purely -deterministic on rasteriser output. - -This arc closes Option D from the SESSION_HANDOFF Resume prompt -and effectively completes the Terminal visual-identity port — -only the toast warning/error variant slots remain wired-but- -unused. - -## What shipped in v0.20.0 (frozen at `41a009a`) - -### Terminal visual-identity port - -Top-down stack — every commit downstream of the token system -reads from it, so swapping the palette is now a one-file edit: - -- **`ui_theme` token system** (`0d477ac`). base16-eighties - palette, 5-rung type scale, 7-rung 4-multiple spacing scale, - 3-step radius, 14-rung z-index hierarchy, full motion budget, - 4 invariant-pinning unit tests. Card-shadow alphas pinned to 0 - (Terminal achieves depth via 1px borders + tonal layering). -- **Modal scaffold already on tokens** — `ui_modal` was ported - in the same commit's wake; three stale "loud yellow" / - "magenta secondary" doc comments fixed. -- **Gameplay feedback → semantic state tokens** (`ceec4fc`). - Selection / valid-drop tints route through `ACCENT_PRIMARY` / - `STATE_WARNING` / `STATE_SUCCESS`. -- **Toasts** (`a137607`). New `ToastVariant` enum - (Info / Warning / Error / Celebration); opaque `BG_ELEVATED` - + 1px accent border + bottom-anchor. All ten call sites pass - their semantic variant. -- **`table_plugin` chrome** (`651f406`). - `PILE_MARKER_DEFAULT_COLOUR` promoted; `cursor_plugin` imports - it, replacing a "kept in sync" doc comment with a compile- - enforced invariant. `HINT_PILE_HIGHLIGHT_COLOUR` → - `STATE_WARNING`. -- **`card_plugin` chrome** (`d752870`). Drag-elevation shadow - routes through `CARD_SHADOW_*` tokens. `RIGHT_CLICK_HIGHLIGHT_COLOUR` - → `STATE_SUCCESS`. Stock recycle "↺" text → `TEXT_PRIMARY @ 0.7α`. - Card-face / suit / card-back palette intentionally NOT migrated - (artwork dependency — see open-list item below). -- **Splash cursor** (`cdcadda`). The signature `▌` cyan glyph - (96 px) added above the wordmark, matching the spec. - *Subsequently expanded post-cut by `cacb19c` into the full - boot-screen treatment.* -- **Hint-source / dest pairing** (`9891ae4`). `input_plugin`'s - source-card tint now matches the destination pile's - `STATE_WARNING`. -- **Design system + 24-mockup library** (`fa7f98a`). - `docs/ui-mockups/design-system.md` + 24 Stitch mockups (HTML + - PNG) covering every screen plus 9 missing-plugin surfaces. -- **`card_shadow_params` test aligned** (`1d1543e`). Drag-vs- - idle shadow assertion loosened to `>=` to accept the Terminal - "no shadow" intent without losing the regression-guard. - -### Android persistence - -- **`solitaire_data::data_dir` shim** (`4b51e50`). New - `solitaire_data::platform::data_dir()` falls through to - `dirs::data_dir()` on desktop and returns the per-app sandbox - at `/data/data/com.solitairequest.app/files` on Android — no - JNI needed (package id pinned in `[package.metadata.android]`). - Six `solitaire_data` callsites + `solitaire_engine/assets/user_dir.rs` - migrated. Settings, stats, achievements, replays, game-state, - time-attack sessions, and user themes now persist on Android. - -### Inherited from earlier in the cycle (pre-session) - -- Android build target + APK (`fb8b2ac`), runbook (`59424a3`), - F3 FPS overlay (`690e1d2`), Smart Window Size opt-out - (`e1b8766`), Shareable badge (`9b065e5`), Help cheat-sheet - M/P/Enter rows (`35516d3`), `pull_failure_sets_error_status` - flake fix (`67c150b`). +No threads in flight. Working tree clean as of 2026-05-08. New +work since the cut would land here as commit narratives; for the +v0.21.0 contents themselves, see `CHANGELOG.md` § [0.21.0]. ## Open punch list @@ -422,81 +63,36 @@ reads from it, so swapping the palette is now a one-file edit: Either upstream a cargo-apk fix or document `--lib` as canonical in the runbook. -### Visual-identity follow-ups (opened by v0.20.0's port) +### Visual-identity follow-ups (post-v0.21.0) -- *Card-face / suit / card-back artwork regeneration — closed - 2026-05-08 by the commit chain `5623368` → `dd101b3`.* The - Terminal spec called for dark `#1a1a1a` cards with light suit - pips (pink for hearts/diamonds, foreground gray for spades/ - clubs). Closed across nine commits over two arcs: - - **Plan + tooling (`5623368`–`48b28d2`):** migration plan - doc, single-card PoC, full `card_face_generator` example - (52 faces + 5 backs into `assets/cards/`), and the - `card_face_svg_pin` integration test pinning rasteriser - output via FNV-1a so future `usvg`/`resvg` upgrades surface - as test failures rather than silent visual drift. - - **Lockstep step 4+5 (`e8bf9d7`):** PNGs + the 5 `card_plugin` - constants + signature shifts in one commit. - `CARD_FACE_COLOUR_RED_CBM` renamed to `RED_SUIT_COLOUR_CBM` - and repurposed from a face-tint to a suit-glyph swap (the - Terminal face is uniform `CARD_FACE_COLOUR` regardless of - CBM; CBM only swaps red suits to cyan in the glyph itself). - `face_colour` deleted, `text_colour` gained a `color_blind` - parameter. - - **Three follow-ups that surfaced during sign-off:** - `a14200a` regenerated the **default-theme SVGs** at - `solitaire_engine/assets/themes/default/*.svg` — those - `include_bytes!()`-embed into the binary and override - `assets/cards/*.png` at runtime, so the PNG migration alone - didn't change what production rendered. `8719f77` - regenerated `assets/backgrounds/bg_*.png` to flat Terminal - near-black (5 solid-colour PNGs via a new - `background_generator` example). `ae84dc1` cleared the - **top-bar overlap** at portrait/narrow window widths by - swapping the action-button row's hardcoded `font_size: 16.0` - to `TYPE_BODY` and stepping horizontal padding from - `VAL_SPACE_3` to `VAL_SPACE_2`. - - **Glyph-rendering fix (`af414b6`):** suit glyphs render as - inline SVG paths (not ``) because the bundled - `FiraMono` doesn't carry usable U+2660-2666 at the - requested size — `usvg` was silently substituting tiny - "tofu" marks. Path-based rendering bypasses the font system - entirely; same bytes on every machine. The pin test - rebaselined cleanly via the empty-then-paste pattern. - - **Glyph-orientation tweak (`dd101b3`):** removed the 180° - rotation from the bottom-right large suit glyph at user - request — both glyphs now render in the same upright - orientation. `design-system.md` § Game Cards line 220 - updated in lockstep to document the deliberate deviation - from the traditional inverted-corner-indicator convention. -- *Splash boot-loader scanline overlay — closed by `a27cf5a`.* - Runtime-generated 2 × 2 RGBA8 texture tiled via - `NodeImageMode::Tiled`; per-pixel alpha × tint alpha gives - multiplicative fade integration without new abstractions. -- *Splash cursor pulse — closed by `29136d8`.* Trailing 6 × 12 px - cyan Node, sine-pulsed, multiplied with the global splash fade - (the "multiply, don't override" pattern that resolves the - original `cacb19c` skip-rationale). -- **Replay-overlay enrichments beyond the scrub bar.** Banner-local - pieces of the mockup (`docs/ui-mockups/replay-overlay-mobile.html`) - all shipped: scrub bar (`c84d9f4`), `▌ replay` cursor-block label - (`6204db8`), `GAME #YYYY-DDD` caption (`54005d5`), `MOVE N/M` - chip restyle (`e080b49`). What's still open are the cross-plugin - / data-layer pieces: a `MOVE N/M` chip *floating above the - focused card* during playback (would need to thread the cursor - through to the card layer — `update_progress_text` writes the - banner chip but the card-position lookup belongs in `card_plugin`). - The full mockup's screen-takeover treatment — mini-tableau - preview, playback controls, move-log scroll, WIN MOVE marker on - the scrub bar — is a multi-session redesign with - data-layer impact (move-log scroller; the WIN MOVE marker - needs a `win_move_index` field on `Replay` that doesn't yet - exist). Banner-overlay behaviour is intentionally preserved - for now. -- **Toast Warning / Error variants.** The `ToastVariant` enum - has slots for `Warning` (gold) and `Error` (pink) but no - in-engine event uses them yet. Wire when a warning- or error- - flavoured toast event materialises. +The visual-identity arc is effectively complete: token system, +chrome migration, splash boot screen, replay-overlay banner, +card-face artwork (both rendering paths), and the `ACCENT_PRIMARY` +palette refresh all shipped in v0.20.0 + v0.21.0. What stays open: + +- **Replay-overlay screen-takeover redesign.** The full mockup + (`docs/ui-mockups/replay-overlay-mobile.html`) calls for a + mini-tableau preview, playback controls, move-log scroll, and + a WIN MOVE marker on the scrub bar. Banner-local pieces all + shipped in v0.21.0 (`c84d9f4` + `6204db8` + `54005d5` + + `e080b49`); the screen-takeover is a multi-session redesign + with data-layer impact (move-log scroller; WIN MOVE needs a + `win_move_index` field on `Replay` that doesn't yet exist). +- **Floating `MOVE N/M` chip above the focused card during + playback.** Cross-plugin work — `update_progress_text` writes + the banner chip but the card-position lookup belongs in + `card_plugin`. Smaller scope than the screen-takeover. +- **Toast Warning / Error variants.** `ToastVariant` has slots + for `Warning` (gold) and `Error` (pink) but no in-engine + event uses them yet. Wire when a warning- or error-flavoured + toast event materialises. +- **High-contrast accessibility mode.** `design-system.md` line + 274 mentions it (boost foreground from `#d0d0d0` to `#f5f5f5`, + suit-red from `#fb9fb1` to `#ff8aa0`). Not implemented; no + Settings toggle. +- **Reduced-motion mode** for card lift / drop transitions. + `design-system.md` accessibility item, separate from + artwork. Not implemented. ### Carried forward from v0.19.0 @@ -568,10 +164,9 @@ reads from it, so swapping the palette is now a one-file edit: ### Canonical remote `github.com/funman300/Rusty_Solitaire` is the canonical repo. -Always push there. **Local master has unpushed post-cut commits** -— run `git log --oneline origin/master..HEAD` for the live list; -`git push` is the next durability step (or roll the post-cut -commits into v0.20.1). +Always push there. As of v0.21.0 origin matches local; the next +push happens when post-cut work accumulates and is ready to roll +into a v0.21.1 / v0.22.0 cut. ### Design direction (Terminal — base16-eighties) @@ -579,35 +174,41 @@ commits into v0.20.1). monospaced-forward typography (JetBrains Mono / FiraMono), tight 16 px edge margins, 8 px card radius. - **Palette:** near-black surface ramp (`#151515` / `#202020` / - `#2a2a2a` / `#353535`), cyan primary CTA (`#6fc2ef`), lime + `#2a2a2a` / `#353535`), brick-red primary CTA (`#a54242` — + swapped from cyan `#6fc2ef` in v0.21.0 commit `a292a7e`), lime success (`#acc267`), gold warning (`#ddb26f`), pink error / suit-red (`#fb9fb1`), lavender celebration (`#e1a3ee`), teal info (`#12cfc0`). - **Two-color suits.** Red = `#fb9fb1`, black = `#d0d0d0`. Outlined glyphs for diamonds & clubs are *always on*; the - Settings "color-blind mode" toggle only swaps red → cyan. + Settings "color-blind mode" toggle swaps red → lime `#acc267` + (was red → cyan pre-v0.21.0; lime is the next-best non-red + base16-eighties accent now that the primary itself is red). +- **Card glyphs render upright in both corners** — no 180° + inverted-corner-indicator rotation. Single-orientation + digital play doesn't benefit from the traditional flip- + readback convention. `design-system.md` § Game Cards + documents this deliberate deviation. ## Resume prompt ``` You are a senior Rust + Bevy developer working on Solitaire Quest. Working directory: . -Branch: master. v0.20.0 is tagged at 41a009a; the post-cut work -through dd101b3 is pushed to origin (Options B, C, D all closed). -Run `git log --oneline 41a009a..HEAD` to see what landed since the -tag — substantives: desktop-adaptation spec, splash boot-screen -port, replay-overlay banner enrichments, and the full card-face -artwork arc (52 faces + 5 backs as Terminal SVG-rasterised PNGs, -default-theme SVGs in lockstep, table backgrounds flattened, -top-bar layout fix, glyph orientation upright). +Branch: master. v0.21.0 is tagged at 04f9bf9 (cut 2026-05-08). +Working tree clean. v0.21.0 closed the visual-identity arc that +v0.20.0 deferred — full Terminal cards on both rendering paths +(asset PNGs + bundled-default theme SVGs), splash boot screen, +replay-overlay banner enrichments, and a project-wide ACCENT_PRIMARY +swap from cyan to brick red `#a54242`. See CHANGELOG.md § [0.21.0] +for full detail. -State: HEAD locally — see `git rev-parse HEAD`. Working tree is -clean. All workspace tests pass (~1180+; check with -`cargo test --workspace`), clippy clean. +State: HEAD locally — see `git rev-parse HEAD`. All workspace tests +pass (1184+; check with `cargo test --workspace`), clippy clean. READ FIRST (in order, before doing anything): 1. SESSION_HANDOFF.md — this file - 2. CHANGELOG.md — [0.20.0] section is the most recent cut + 2. CHANGELOG.md — [0.21.0] section is the most recent cut 3. CLAUDE.md — unified-3.0 rule set 4. CLAUDE_SPEC.md — formal architecture spec 5. ARCHITECTURE.md — crate responsibilities + data flow @@ -622,38 +223,34 @@ READ FIRST (in order, before doing anything): fresh machine) DECISION TO ASK THE PLAYER FIRST: - A. Push the post-cut commits to origin. Either as-is on master - or rolled into a v0.20.1 cut (CHANGELOG entry + tag). - Mechanical, but local master diverges from origin until done. - B. *Closed by `29136d8` + `a27cf5a`.* Both splash polish - pieces shipped (cursor pulse + scanline overlay). No further - splash work pending unless a new mockup detail surfaces. - C. *Closed by `54005d5` + `e080b49`.* Banner-local replay-overlay - pieces all shipped (scrub bar, ▌ label, GAME caption, MOVE - chip). Remaining are cross-plugin (floating MOVE chip above - the focused card — needs cursor → card-position plumbing) or - multi-session (full screen-takeover redesign — move-log - scroll, mini tableau, WIN MOVE marker, data-layer impact). - Either belongs in its own decision tree the next time replay - work surfaces. - D. *Closed 2026-05-08 by `5623368`…`dd101b3`.* The full - card-face / suit / card-back / default-theme / table- - background / top-bar / glyph-orientation arc landed across - nine commits. Terminal cards rendering on every face (dark - `#1a1a1a` background, pink/gray suit glyphs as inline SVG - paths, scanline-pattern cyan-accent backs); both rendering - paths (`assets/cards/*.png` and the bundled-default theme - SVGs at `solitaire_engine/assets/themes/default/*.svg`) in - lockstep; pin test (`card_face_svg_pin`) guards against - future rasteriser drift. Visual-identity arc effectively - complete — only the toast warning/error variant slots - remain wired-but-unused. - E. App icon round — re-run artwork/Icon Export.html (the + A. App icon round — re-run artwork/Icon Export.html (the export PNGs are not currently in `artwork/`), then wire - Window::icon + generate .icns / .ico. Half-day task. No - cert dependency. - F. APK launch verification on AVD / device + the JNI bridges - it would shake out (ClipboardManager, Keystore). + Window::icon + generate .icns / .ico / Linux hicolor PNG + hierarchy. Half-day task. No cert dependency. Pure + desktop work. + B. APK launch verification on AVD / device — `adb install` + + `adb logcat` to shake out runtime bugs the build / unit + tests can't catch. Likely surfaces JNI ClipboardManager + and Android Keystore stubs that need real bridges. Larger + scope than A; needs an Android device or emulator running. + C. Replay-overlay extensions — either the floating `MOVE N/M` + chip above the focused card (smaller, cross-plugin; needs + cursor → card-position plumbing in `card_plugin`) or the + full screen-takeover redesign (multi-session: move-log + scroll, mini tableau preview, WIN MOVE marker, data-layer + impact for `Replay::win_move_index`). + D. Toast Warning / Error variant wiring. UI infrastructure + exists in `ToastVariant`; no in-engine event uses Warning + (gold) or Error (pink) yet. Wire when a real warning- or + error-flavoured event materialises. + E. Phase 8 (sync) — local storage scaffolding, self-hosted + Axum server, `SolitaireServerClient` impl, GPGS stub + wired into Settings. The biggest open arc by scope; rolls + up several Phase Android dependencies (Keystore, + ClipboardManager). + F. High-contrast and reduced-motion accessibility modes. + Both flagged in design-system.md but unimplemented; needs + Settings toggles + token alternates. WORKFLOW NOTES: - Use the system git config (already correct). @@ -663,6 +260,13 @@ WORKFLOW NOTES: - 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. + - Token-port pattern: when migrating tokens, walk every + concrete artifact downstream of the token (PNG textures, + embedded SVGs, hardcoded literals, comment color names), + not just the token name. v0.21.0 surfaced three "the + migration walked past this" follow-ups that all matched + this shape — codified here so future similar work can + pattern-match instead of rediscovering. OPEN AT THE START: ask which of A–F. Don't pick unilaterally. ```