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>
This commit is contained in:
funman300
2026-05-07 13:28:04 -07:00
parent 59424a370c
commit f2d2119db5
2 changed files with 232 additions and 114 deletions
+94 -1
View File
@@ -6,7 +6,100 @@ project follows [Semantic Versioning](https://semver.org/).
## [Unreleased] ## [Unreleased]
_Nothing yet._ Two threads in flight: closing the v0.19.0 punch list (settings opt-out
for the smart-default sizer, share-link discoverability, the last
async-pull test flake) and a new performance / portability arc (F3
diagnostics overlay landing first, then a working Android build
target via `cargo apk`). 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 tree, so subsequent work
can iterate on a phone or AVD without forking the codebase.
### Added
- **Android build target — first working APK** (`fb8b2ac`).
`cargo apk build -p solitaire_app --target x86_64-linux-android`
now produces a 54 MB debug-signed APK at
`target/debug/apk/solitaire-quest.apk`. Five gating points
resolved end-to-end:
- **`solitaire_app` split into bin + lib.** cargo-apk needs a
`cdylib` to bundle as `libmain.so`; pure-bin crates panic
with "Bin is not compatible with Cdylib". `src/lib.rs`
carries the ECS bootstrap as `pub fn run`; `src/main.rs` is
a 3-line shim that delegates for the desktop path.
- **`[package.metadata.android]`** pins target SDK 34 / min
SDK 26 and points `assets = "../assets"` at the workspace
asset directory so desktop and APK share one set.
- **Workspace `bevy` features** add `android-native-activity`
(target-gated inside bevy_internal — desktop builds compile
it out). Pairs with cargo-apk's NativeActivity wrapper.
- **`arboard` target-gated** to `cfg(not(target_os =
"android"))`. The crate has no Android backend; cargo apk
fails with E0433 on `platform::Clipboard` if left
unconditional. Stats's "Copy share link" surfaces an
informational toast on Android until JNI ClipboardManager
lands in the Phase-Android round.
- **`keyring` + `keyring-core` target-gated.** Bionic doesn't
expose `libc::__errno_location` so the transitive
`rpassword` won't compile. `auth_tokens` ships an Android
stub returning `KeychainUnavailable` for every call —
matches the existing fallback for a Linux box without
Secret Service.
- Cosmetic: cargo-apk panics post-sign when it tries to also
wrap the bin target. The APK on disk is unaffected;
`cargo apk build --lib` is the small workaround.
- **Android developer setup + build runbook** (`59424a3`).
Captures Debian 13 toolchain install (JDK 21, unzip, SDK
licence prompts), the `cargo apk build` invocation, the
cosmetic post-sign panic workaround, and a what-is-wired-vs-
stubbed table for the android target. Runnable on a fresh
clone — no machine-local context required.
- **F3-toggleable FPS / frame-time overlay** (`690e1d2`).
`DiagnosticsHudPlugin` wraps Bevy's `FrameTimeDiagnosticsPlugin`
and renders a corner readout the developer toggles with F3.
Hidden by default; F3 is not gated by pause / modal state.
Reads `smoothed()` so the cell isn't a per-frame jittery
scoreboard. Format: `FPS NN \u{2022} M.MM ms`. Anchored
top-right at `z = Z_SPLASH + 100` above every modal / toast /
splash. Update system bails when hidden so the
diagnostic-store lookup is free when nobody's looking.
- **"Smart window size" Settings toggle** (`e1b8766`). Gameplay
section gains an opt-out toggle for v0.19.0's
`apply_smart_default_window_size` system. New
`Settings::disable_smart_default_size: bool` with
`#[serde(default)]` so legacy `settings.json` files load to
the shipped behaviour (smart sizer enabled). `solitaire_app::main`
reads the flag once at startup and skips the system's
registration when set. Saved window geometry still wins over
both branches; tooltip on the row makes that explicit.
- **"Shareable" badge on the Latest-win caption** (`9b065e5`).
The Stats overlay's Latest-win caption now appends
`\u{2022} Shareable` when the displayed replay carries a
populated `share_url`. Players can see at a glance whether the
Copy share link button will produce a URL or surface the
upload-prerequisite toast.
- **Help overlay covers M / P / Win-Summary-Enter** (`35516d3`).
Three new rows in the Overlays section: M (Home / Mode
launcher), P (Profile), and the Enter accelerator that
dismisses the Win Summary modal. Three post-v0.18 entries
that had drifted out of the cheat sheet are now listed.
### Fixed
- **`pull_failure_sets_error_status` test flake** (`67c150b`).
The fixed 5-update budget was the last test still subject to
the AsyncComputeTaskPool starvation mode that v0.19.0's
auto-save fix already cleared. Replaced with a wall-clock-
bounded loop (5-second deadline, `std::thread::yield_now`
between iterations) that exits as soon as the status flips.
Mirrors the auto-save flake fix shape.
### Stats
- 1170 passing tests / 0 failing (matches v0.19.0; the
pull-failure flake fix changed the test's pumping shape but
not its count).
- Zero clippy warnings under `--workspace --all-targets -- -D warnings`.
## [0.19.0] — 2026-05-06 ## [0.19.0] — 2026-05-06
+138 -113
View File
@@ -1,59 +1,58 @@
# Solitaire Quest — Session Handoff # Solitaire Quest — Session Handoff
**Last updated:** 2026-05-06 (post-v0.19.0) — Tagged + pushed at **Last updated:** 2026-05-07 — `[Unreleased]` accumulating v0.20
`6037596`. v0.19.0 closes the v0.18.0 punch list (async H-key hint, candidates. Seven commits sit on top of v0.19.0: three close items
persistent replay share URLs), expands desktop platform fit (Wayland from v0.19.0's punch list (pull-failure flake, smart-window-size
session support + monitor-aware default window size), polishes the opt-out, Shareable badge), one extends Help cheat-sheet coverage,
win-celebration and double-click animation paths, and clears two and three open a new performance / portability arc — F3 FPS
test-flake contributors. A short-lived "Rusty Pixel" pixel-art card overlay, Android build target (first working APK), and the matching
theme was prototyped and reverted in the same window. 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 ## Status at pause
- **HEAD on origin:** `6037596` (post-tag commit; the tag itself - **HEAD on origin:** `59424a3` (post-Android-runbook commit).
points at this commit).
- **Working tree:** modified — `CHANGELOG.md` and - **Working tree:** modified — `CHANGELOG.md` and
`SESSION_HANDOFF.md` carry the v0.19.0 promotion + this refresh, `SESSION_HANDOFF.md` carry the v0.20-candidates promotion + this
ready to commit. refresh, ready to commit. `artwork/` remains untracked.
- **Build:** `cargo clippy --workspace --all-targets -- -D warnings` - **Build:** `cargo clippy --workspace --all-targets -- -D warnings`
clean (verified this session). clean (verified this session).
- **Tests:** **1170 passing / 0 failing** across the workspace - **Tests:** **1170 passing / 0 failing** across the workspace
(verified this session). One known flake remains: (verified this session). The previously-flaky
`solitaire_engine::sync_plugin::tests::pull_failure_sets_error_status` `pull_failure_sets_error_status` is fixed; no known flakes remain.
occasionally fails when cargo-test parallelism starves the - **Tags on origin:** `v0.9.0` through `v0.19.0`.
`AsyncComputeTaskPool` within the test's 5-update budget. Same
shape as the auto-save flake before v0.19.0's hardening; could be
fixed similarly with a wall-clock-bounded loop.
- **Tags on origin:** `v0.9.0` through `v0.18.0` (v0.19.0 ready to
push once committed).
## Where we are ## Where we are
v0.18.0's resume-prompt menu (AD) is closed: v0.19.0's "Possible next-round candidates" list shipped 3 of 4:
- ~~**A — Tag v0.18.0:**~~ shipped at `bfcd05f`. - ~~**`pull_failure_sets_error_status` flake fix:**~~ shipped at
- ~~**B — Solver-on-`AsyncComputeTaskPool` for the H-key hint:**~~ `67c150b`.
shipped at `3e11e9e`. - ~~**Settings UI for smart-default-size opt-out:**~~ shipped at
- **C — Desktop packaging:** still gated on artwork + signing `e1b8766`.
certs. Icon export PNGs (11 sizes, 161024 px) sit in - ~~**Persistent share link URL on selector caption:**~~ shipped at
`artwork/` from the v0.18-era export; not yet wired into the `9b065e5` (as a "Shareable" badge on the Latest-win caption —
Bevy window or assembled into `.icns` / `.ico`. App icon is the Prev/Next selector chips don't have a live spawn site yet,
the first natural step. so the badge attaches to the existing single-replay caption).
- ~~**D — Persistent share link:**~~ shipped at `42d90b1`. - **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.
The Rusty Pixel theme arc is documented as a sub-history but Two new threads opened that weren't on any prior punch list:
not part of v0.19.0's content:
| Commit | Status | - **F3 FPS / frame-time overlay** (`690e1d2`). `DiagnosticsHudPlugin`
|---|---| wraps `FrameTimeDiagnosticsPlugin`; F3 toggles a top-right
| `de47511` PNG-format thumbnail support | reverted | readout. Hidden by default; primarily a developer affordance.
| `17e3112` `pixel_art: bool` field + nearest-sampling opt-in | reverted | - **Android build target** (`fb8b2ac` + `59424a3`).
| `21ec03b` bundle Rusty Pixel as `embedded://` theme | reverted | `solitaire_app` is now a bin + cdylib hybrid. `cargo apk build`
| `aad8bb9` / `e41def8` / `0b3140a` reverts | landed | produces a 54 MB APK with full assets. Five gating points
resolved (split, manifest, bevy feature, arboard target-gate,
The arc remains in commit history for archaeology but the keyring target-gate). What's *not* yet verified: APK launch on
codebase reaches v0.19.0's HEAD identical to where it would be if AVD/phone, `dirs::data_dir()` Android behaviour for the
the arc had never landed. persistence/sync layer.
### Design direction (unchanged) ### Design direction (unchanged)
@@ -67,105 +66,131 @@ the arc had never landed.
`github.com/funman300/Rusty_Solitaire` is the canonical repo. `github.com/funman300/Rusty_Solitaire` is the canonical repo.
Always push there. Always push there.
## v0.19.0 (2026-05-06) ## v0.20 candidates ([Unreleased] in CHANGELOG)
| Area | Commits | What landed | | Area | Commit | What landed |
|---|---|---| |---|---|---|
| Async H-key hint | `3e11e9e` | New `pending_hint.rs` module: `PendingHintTask` resource, `poll_pending_hint_task` + `drop_pending_hint_on_state_change` systems, cancel-on-replace, stale-state guard via `move_count_at_spawn`. Removes the last synchronous solver hot path. | | 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. |
| Persistent share URLs | `42d90b1` | `Replay.share_url: Option<String>` with `#[serde(default)]`. `poll_replay_upload_result` writes into `replays[0].share_url` + persists. Stats Copy button reads from selected replay. `LastSharedReplayUrl` deleted. | | 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. |
| Auto-save flake fix | `91b7605` | `test_app` clears `PendingRestoredGame(None)` after plugin build; test re-arms the timer in a bounded loop. No production-code change. | | 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). |
| Wayland support | `b57db01` | Adds `wayland` to Bevy features. winit prefers Wayland when `WAYLAND_DISPLAY` is set, falls back to X11. Native Wayland surface instead of XWayland frame. | | Help: M / P / Win-Summary-Enter | `35516d3` | Three rows added to F1 Help → Overlays. Closes coverage drift on post-v0.18 keys. |
| Smart default window size | `b57db01` | New `apply_smart_default_window_size` Update system queries `PrimaryMonitor` and resizes the window to ~70 % of monitor's logical size on the first frame. Skipped when saved geometry was applied. | | 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`. |
| Win-celebration cleanup | `55c235b` | Drops the duplicate "You Win" toast that rendered behind the WinSummary modal. Cards-fly-off cascade kept; toast removed. | | 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. |
| Double-click reject animation | `d7ffb16` | Single-card double-clicks with no destination now play the same shake + sound as multi-card stack misses. Both priorities' failure paths converge on one `MoveRejectedEvent` write. | | Android runbook | `59424a3` | Debian 13 toolchain install, `cargo apk build` invocation, post-sign panic workaround, wired-vs-stubbed table. Fresh-clone runnable. |
| Double-click animation dedup | `6037596` | Drops the redundant `StateChangedEvent` write in `end_drag`'s uncommitted-drag branch; previously raced an in-flight CardAnim and restarted the slide visibly. |
## Open punch list ## Open punch list
### Carried forward ### Carried forward from v0.19.0
- **Desktop packaging** per `ARCHITECTURE.md §17`. Eleven icon - **App icon round.** `Window::icon` not yet wired; no `.icns` /
PNG sizes (16, 24, 32, 48, 64, 96, 128, 192, 256, 512, 1024) `.ico` / Linux hicolor PNG hierarchy. The 11-size icon export
exported via `artwork/Icon Export.html` sit in `artwork/` the v0.19 handoff referenced is *not* currently in
pending wiring. Pending: actual Bevy window-icon hookup, `artwork/` — re-running `artwork/Icon Export.html` is the
macOS `.icns` assembly via `iconutil`, Windows `.ico` via prerequisite. Half-day task once the PNGs are back in place.
`magick convert`, Linux hicolor PNG hierarchy install, No cert dependency.
AppImage recipe, macOS notarisation cert, Windows
Authenticode cert.
### Possible next-round candidates ### New — Phase Android (opened by `fb8b2ac` + `59424a3`)
- **App icon round** — wire the icon into the Bevy window via - **APK launch verification on AVD / device.** `adb install` then
`Window::icon`, generate `.icns` and `.ico` from the existing `adb logcat` against the bevy_test AVD. Shakes out any
PNGs. Half-day task; doesn't depend on signing certs. Bevy/winit Android-specific runtime bugs not caught by the
- **`pull_failure_sets_error_status` flake fix** — same pattern build alone.
as the auto-save flake. Wall-clock-bounded loop instead of - **`dirs::data_dir()` Android port.** Persistence (settings,
fixed 5-update budget. ~10 lines. stats, achievements, replays, progress) all route through this
- **Settings UI for "open at this size on launch"** — once the function. Android sandboxing usually demands `getFilesDir()` via
smart-default-size system is shipping, expose a checkbox to JNI. Until verified, the APK may launch but fail to persist
*disable* it (player who specifically wants 1280×800 every anything across cold starts.
time). Trivial. - **JNI ClipboardManager bridge.** Replaces the Android stub for
- **Persistent share link URL on selector caption** — surface the Stats "Copy share link" toast. `arboard` doesn't ship an
whether the currently-selected replay has a `share_url` Android backend, so this is a small custom JNI call.
populated (e.g. "Replay 3 / 8 \u{2022} Shareable") so players - **Android Keystore for credentials.** `keyring` is target-gated
know which entries the Copy button can copy. 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) ### Process notes (from this round)
- **Async port template (worked again):** the H-key port - **Async-test starvation pattern (resolved twice now).**
followed `d489e7a`'s `PendingNewGameSeed` shape one-to-one Auto-save flake (v0.19) and pull-failure flake
and the second async port required no new infrastructure. (v0.20-candidates) shared the same root cause: a fixed
Future async ports (e.g. moving `try_solve_with_first_move`'s N-update budget for an `AsyncComputeTaskPool` task to surface
full-search variant, if it ever surfaces in the picker UI) its result, which starves under cargo-test parallelism. The
should follow the same shape. wall-clock-bounded loop pattern (`std::thread::yield_now()`
- **Rusty Pixel reverted cleanly:** `git revert` of three between pumps, deadline = `Instant::now() + Duration::from_secs(5)`)
contiguous feature commits produced a clean three-revert is the canonical fix. Future async-test work should reach for
sequence with no manual conflict resolution. Bisect remains this shape on the first commit, not after a flake materialises.
fast over the full v0.19.0 history because the reverts are - **Bin → lib + thin shim refactor.** The `solitaire_app` split
individual commits, not a squash. for cargo-apk is a textbook cdylib-as-NativeActivity pattern.
- **Defensive event writes pattern:** the Worth knowing as a reusable shape for any future Bevy-on-mobile
`auto_save_writes_after_30_seconds` flake AND the project: keep `main.rs` to ≤10 lines that delegate to
`end_drag` double-animation bug shared a root cause: `pub fn run`, put all setup in `lib.rs`, and let the build
defensive `MessageWriter` writes that originally covered an system pick which artifact (`bin` or `cdylib`) it needs.
edge case which no longer holds, but became load-bearing - **Target-gating defensive defaults.** Three of v0.20-candidates'
once another system started paying attention to the event. Android-arc commits had to disable a default-on dependency
Worth a periodic pass: any event write that doesn't (`arboard`, `keyring`, `keyring-core`) for the new target.
correspond to a real state change is a candidate for When a future contributor adds a desktop-implicit dependency,
removal. reaching for `[target.'cfg(not(target_os = "android"))'.dependencies]`
preemptively is cheaper than rediscovering the gating during
the next platform port.
## Resume prompt ## Resume prompt
``` ```
You are a senior Rust + Bevy developer working on Solitaire Quest. You are a senior Rust + Bevy developer working on Solitaire Quest.
Working directory: <Rusty_Solitaire clone path on this machine>. Working directory: <Rusty_Solitaire clone path on this machine>.
Branch: master. v0.19.0 just shipped. The next natural item is Branch: master. v0.19.0 is tagged on origin; seven commits sit on
desktop-packaging follow-through, starting with the app icon. top opening the v0.20 cycle (3 punch-list closes + a perf tool +
the Android build target).
State: HEAD at 6037596 + the v0.19.0 docs commit on top (this State: HEAD at 59424a3 + the v0.20-candidates docs commit on top
session). Tag v0.19.0 points at the docs commit. (this session). Working tree may carry the doc updates if not yet
committed.
READ FIRST (in order, before doing anything): READ FIRST (in order, before doing anything):
1. SESSION_HANDOFF.md — this file 1. SESSION_HANDOFF.md — this file
2. CHANGELOG.md — [Unreleased] is empty; [0.19.0] just landed 2. CHANGELOG.md — [Unreleased] holds the v0.20 draft
3. CLAUDE.md — unified-3.0 rule set 3. CLAUDE.md — unified-3.0 rule set
4. CLAUDE_SPEC.md — formal architecture spec 4. CLAUDE_SPEC.md — formal architecture spec
5. ARCHITECTURE.md — crate responsibilities + data flow 5. ARCHITECTURE.md — crate responsibilities + data flow
6. ~/.claude/projects/<this-project>/memory/MEMORY.md 6. docs/android/* — Android setup + build runbook (59424a3)
7. ~/.claude/projects/<this-project>/memory/MEMORY.md
— saved feedback / project context — saved feedback / project context
(machine-local; may be missing on a (machine-local; may be missing on a
fresh machine) fresh machine)
DECISION TO ASK THE PLAYER FIRST: DECISION TO ASK THE PLAYER FIRST:
A. App icon — wire artwork/icon-{size}.png into Bevy's A. APK launch verification — `adb install` + `adb logcat` on
Window::icon, generate .icns + .ico, drop into Linux bevy_test AVD or a physical x86_64 device. Shakes out
hicolor hierarchy. Half-day task. No cert dependency. runtime bugs the build can't catch.
B. Desktop packaging continued — AppImage recipe, .desktop B. Phase-Android persistence — port dirs::data_dir() through a
file, install scripts. Larger task; unlocks distro JNI getFilesDir() bridge so the APK can survive a cold
packaging. No cert dependency. start. Largest unblocked Android piece.
C. macOS / Windows signing cert acquisition — needs user C. App icon — re-run artwork/Icon Export.html, then wire
action; agent can't drive. Window::icon + generate .icns / .ico. Half-day task. No
D. `pull_failure_sets_error_status` flake fix — small, well- cert dependency.
scoped. Same pattern as the v0.19.0 auto-save flake fix. 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: WORKFLOW NOTES:
- Use the system git config (already correct). - Use the system git config (already correct).
@@ -173,8 +198,8 @@ WORKFLOW NOTES:
"Quat" not "Rhys" (saved feedback memory). "Quat" not "Rhys" (saved feedback memory).
- Sub-agents stage + verify only; orchestrator commits. - Sub-agents stage + verify only; orchestrator commits.
- Every commit must pass build / clippy / test before pushing. - Every commit must pass build / clippy / test before pushing.
- Push to GitHub (origin) — gh auth setup-git is already - Push to GitHub (origin) — gh auth setup-git wired on
wired on this machine. primary dev box; verify on laptop before first push.
OPEN AT THE START: ask which of AD. Don't pick unilaterally. OPEN AT THE START: ask which of AD. Don't pick unilaterally.
``` ```