Large batch. Two umbrellas + play-event correctness + CI. CI green on dev; the pre-PR cross-cutting consistency audit found no blocking issues (route↔client contracts, removed-handler cleanup, sqlc/drift sync, two-bucket migration, refreshable web-flag vs Flutter-derived parity all verified).
S1: /healthz reachability offlineProvider (smoke-safe; no connectivity coupling).
S2: single 5GB capBytes → independent Liked + Rolling 5GB caps; bucket = liked-ness; storage-only dedup (never filters playback); orphan-partial accounting so the rolling cap truly bounds disk; liked-protective eviction. Explicit Download removed.
S3: two cap selectors + per-bucket usage meters.
S4: offline disables system-playlist play; always-present Shuffle all (online GET /api/library/shuffle; offline cache-union); offline Home tiles "Recently played" / "Liked".
CI
Debug APK gated to main only (dev runs ~3min not ~10); runner image republished with the Android SDK baked in (the ~7-min per-run download is gone); Dockerfile shard-hardened for reliable future pushes.
Device-check checklist (post-merge, on a real build)
S2 (highest risk — deletes cached files): lower the Liked cap and the Rolling cap; confirm each evicts only its own bucket and liked tracks survive rolling pressure; two usage meters update.
Airplane mode: Library "Shuffle all" plays the cached union; Home shows "Recently played"/"Liked" tiles that play from cache; system-playlist tile play is disabled.
Online: "Shuffle all" hits /api/library/shuffle; offlineProvider flips after ~3 failed /healthz probes and recovers on reconnect.
The five new mixes populate sensibly on a built library; "Refreshed …" subtitle shows.
Play a multi-track queue to completion: rows show was_skipped=false (not the old false-skip); offline plays replay on reconnect with correct timestamps.
Large batch. Two umbrellas + play-event correctness + CI. CI green on `dev`; the pre-PR cross-cutting consistency audit found no blocking issues (route↔client contracts, removed-handler cleanup, sqlc/drift sync, two-bucket migration, `refreshable` web-flag vs Flutter-derived parity all verified).
## #411 — System playlists v2
- Snapshot/shuffle behavior: For-You no longer force-refreshes on play; shuffle-on-play default; For-You expanded to 100; sample-history rotation dedup (server-side `play_events.source` + rotation state).
- Generalized per-tile refresh affordance (web kebab + Flutter); detail-screen Regenerate for system playlists.
- Play-event reporting fixed: in-queue track end classified ended-vs-skipped (was poisoning recommendation skip-ratios) **and** offline replay capture so cached-track plays aren't lost.
- R1→R3 kind-registry refactor: generic `/api/playlists/system/{kind}/{refresh,shuffle}`; adding a mix = one query + one registry entry.
- Five new mixes: Deep Cuts, Rediscover, New for you, On This Day, First Listens.
- "Refreshed …" freshness subtitle on system tiles.
- "Not for me" intentionally **dropped** (likes + skips are the only feedback signals).
## #427 — Offline cache rework
- S1: `/healthz` reachability `offlineProvider` (smoke-safe; no connectivity coupling).
- S2: single 5GB `capBytes` → independent **Liked + Rolling** 5GB caps; bucket = liked-ness; storage-only dedup (never filters playback); orphan-partial accounting so the rolling cap truly bounds disk; liked-protective eviction. **Explicit Download removed.**
- S3: two cap selectors + per-bucket usage meters.
- S4: offline disables system-playlist play; always-present **Shuffle all** (online `GET /api/library/shuffle`; offline cache-union); offline Home tiles "Recently played" / "Liked".
## CI
- Debug APK gated to `main` only (dev runs ~3min not ~10); runner image republished with the Android SDK baked in (the ~7-min per-run download is gone); Dockerfile shard-hardened for reliable future pushes.
## Device-check checklist (post-merge, on a real build)
- [ ] **S2 (highest risk — deletes cached files):** lower the Liked cap and the Rolling cap; confirm each evicts only its own bucket and **liked tracks survive rolling pressure**; two usage meters update.
- [ ] Airplane mode: Library "Shuffle all" plays the cached union; Home shows "Recently played"/"Liked" tiles that play from cache; system-playlist tile play is disabled.
- [ ] Online: "Shuffle all" hits `/api/library/shuffle`; `offlineProvider` flips after ~3 failed `/healthz` probes and recovers on reconnect.
- [ ] The five new mixes populate sensibly on a built library; "Refreshed …" subtitle shows.
- [ ] Play a multi-track queue to completion: rows show `was_skipped=false` (not the old false-skip); offline plays replay on reconnect with correct timestamps.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Large batch. Two umbrellas + play-event correctness + CI. CI green on
dev; the pre-PR cross-cutting consistency audit found no blocking issues (route↔client contracts, removed-handler cleanup, sqlc/drift sync, two-bucket migration,refreshableweb-flag vs Flutter-derived parity all verified).#411 — System playlists v2
play_events.source+ rotation state)./api/playlists/system/{kind}/{refresh,shuffle}; adding a mix = one query + one registry entry.#427 — Offline cache rework
/healthzreachabilityofflineProvider(smoke-safe; no connectivity coupling).capBytes→ independent Liked + Rolling 5GB caps; bucket = liked-ness; storage-only dedup (never filters playback); orphan-partial accounting so the rolling cap truly bounds disk; liked-protective eviction. Explicit Download removed.GET /api/library/shuffle; offline cache-union); offline Home tiles "Recently played" / "Liked".CI
mainonly (dev runs ~3min not ~10); runner image republished with the Android SDK baked in (the ~7-min per-run download is gone); Dockerfile shard-hardened for reliable future pushes.Device-check checklist (post-merge, on a real build)
/api/library/shuffle;offlineProviderflips after ~3 failed/healthzprobes and recovers on reconnect.was_skipped=false(not the old false-skip); offline plays replay on reconnect with correct timestamps.🤖 Generated with Claude Code