Batch of four features, all CI-green on dev head (8f29cc74). Cross-platform features (#371, #369) landed on server + web + native together.
UPnP / Sonos — graceful recovery (Android)
Idle-revert: after 5 minutes paused on a UPnP/Sonos route, the output reverts to the phone speaker — so a stale Sonos selection can't make a later "tap play" silently do nothing.
Play-intent recovery: a play() that fails its SOAP (dead/stale renderer) now reverts to phone and honors the tap (resumes locally) instead of swallowing it.
Fail-fast: transport SOAP gets a 2 s connect timeout (vs the shared 10 s) so the revert feels instant rather than a long stall.
fsnotify watcher: new/changed files are picked up within seconds (debounced, recursive), scanning just the affected paths and enriching their cover art inline (local instant, remote rate-limited) — "drop a file → it appears with art in seconds."
Scheduler retired: the configurable scan scheduler (scan_schedule table, GET/PATCH endpoints, web admin card) is removed in favor of the watcher + startup delta walk + a fixed 12 h safety-net walk. Migration 0033 drops the table.
Artist detail — discovery (server, web, native)
Similar artists strip (in-library, ranked by similarity score) and per-user top tracks panel on the artist page, on both clients. New /api/artists/{id}/similar + /top-tracks endpoints.
Requests — live progress auto-poll (web, native)
Native RequestsViewModel now polls while a request is mid-ingest (silent reloads, paused when nothing's in-flight) for parity with the web auto-poll, and the SSE-driven refresh updates in place instead of flashing a spinner. Web discover submit invalidates the requests query so a new request shows immediately. (The notifications-inbox half was deferred.)
Batch of four features, all CI-green on `dev` head (`8f29cc74`). Cross-platform features (#371, #369) landed on server + web + native together.
## UPnP / Sonos — graceful recovery (Android)
- **Idle-revert:** after 5 minutes paused on a UPnP/Sonos route, the output reverts to the phone speaker — so a stale Sonos selection can't make a later "tap play" silently do nothing.
- **Play-intent recovery:** a `play()` that fails its SOAP (dead/stale renderer) now reverts to phone **and** honors the tap (resumes locally) instead of swallowing it.
- **Fail-fast:** transport SOAP gets a 2 s connect timeout (vs the shared 10 s) so the revert feels instant rather than a long stall.
## Library — filesystem watcher + scheduler retirement (server, web)
- **fsnotify watcher:** new/changed files are picked up within seconds (debounced, recursive), scanning just the affected paths and enriching their cover art inline (local instant, remote rate-limited) — "drop a file → it appears with art in seconds."
- **Scheduler retired:** the configurable scan scheduler (`scan_schedule` table, GET/PATCH endpoints, web admin card) is removed in favor of the watcher + startup delta walk + a fixed 12 h safety-net walk. Migration 0033 drops the table.
## Artist detail — discovery (server, web, native)
- **Similar artists** strip (in-library, ranked by similarity score) and **per-user top tracks** panel on the artist page, on both clients. New `/api/artists/{id}/similar` + `/top-tracks` endpoints.
## Requests — live progress auto-poll (web, native)
- Native `RequestsViewModel` now polls while a request is mid-ingest (silent reloads, paused when nothing's in-flight) for parity with the web auto-poll, and the SSE-driven refresh updates in place instead of flashing a spinner. Web discover submit invalidates the requests query so a new request shows immediately. (The notifications-inbox half was deferred.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add Scanner.ScanFiles (watcher-driven targeted scan returning changed album
IDs) and a recursive fsnotify Watcher that debounces filesystem events and
enriches just the affected albums inline. Pure classifyEvent/drainPending
seams unit-tested; ScanFiles covered in the scanner integration test.
Wire the fsnotify watcher and a fixed 12h safety-net delta walk in main;
remove the configurable scan scheduler (scheduler.go, scan_schedule table via
migration 0033, GET/PATCH /api/admin/scan/schedule, and the server/api
plumbing). Manual scan + scan status are unchanged.
GET /api/artists/{id}/similar — in-library artists ranked by similarity
score (deduped across sources), ArtistRef list with cover + album count.
GET /api/artists/{id}/top-tracks — current user's most-played tracks for
the artist (skips excluded, quarantine filtered).
Native RequestsViewModel gains poll-while-approved (silent reloads, paused
when nothing in-flight) for parity with the web auto-poll, and the SSE
collector now reloads silently instead of flashing the loading spinner.
Web discover submit invalidates qk.myRequests() so a new request appears
on /requests immediately.
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.
Batch of four features, all CI-green on
devhead (8f29cc74). Cross-platform features (#371, #369) landed on server + web + native together.UPnP / Sonos — graceful recovery (Android)
play()that fails its SOAP (dead/stale renderer) now reverts to phone and honors the tap (resumes locally) instead of swallowing it.Library — filesystem watcher + scheduler retirement (server, web)
scan_scheduletable, GET/PATCH endpoints, web admin card) is removed in favor of the watcher + startup delta walk + a fixed 12 h safety-net walk. Migration 0033 drops the table.Artist detail — discovery (server, web, native)
/api/artists/{id}/similar+/top-tracksendpoints.Requests — live progress auto-poll (web, native)
RequestsViewModelnow polls while a request is mid-ingest (silent reloads, paused when nothing's in-flight) for parity with the web auto-poll, and the SSE-driven refresh updates in place instead of flashing a spinner. Web discover submit invalidates the requests query so a new request shows immediately. (The notifications-inbox half was deferred.)🤖 Generated with Claude Code
GET /api/artists/{id}/similar — in-library artists ranked by similarity score (deduped across sources), ArtistRef list with cover + album count. GET /api/artists/{id}/top-tracks — current user's most-played tracks for the artist (skips excluded, quarantine filtered).