Commit Graph

13 Commits

Author SHA1 Message Date
Jonathan e04c1c9795 feat(discover): also seed discovery from owned-album artists
Discovery seeded only from followed artists. Now it also seeds from artists
you own albums by (LibraryItem.artistMbid, captured since the MBID own-state
work) but don't follow — so your library shapes suggestions, not just your
follows.

- New DiscoverySeed throttle table (migration add_discovery_seed) mirroring
  WatchedArtist.lastDiscoveredAt, so each library-derived seed is swept once
  per interval (WatchedArtist seeds keep their own throttle).
- _seed_artists merges both seed sources least-recently-swept first, capped at
  chunk_size; run_discovery stamps the right throttle per seed and evicts
  contributions from seeds that are neither followed nor owned.
- Artists you already have (followed OR owned) are excluded from the suggestion
  candidates — discovery surfaces only genuinely new artists.
- discover.seedFromLibrary config (default true) + a Discovery settings toggle.

NOTE: existing LibraryItem rows have null artistMbid (populated on new
import/scan), so a re-scan is needed before old albums seed discovery.
worker 236, web 187 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:39:52 +02:00
Jonathan a47d37a787 feat(discover): show why each item is suggested
Each suggestion now carries the followed artists (seeds) that surfaced it,
from DiscoverySeedContribution joined to the current watched roster (an
unfollowed seed drops out), highest-scoring seed first. /discover renders
"Similar to Arctic Monkeys, Coldplay +2" under each artist and album row —
both kinds key off the candidate's artistMbid, so an album inherits its
artist's seeds. web 187 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 22:07:05 +02:00
Jonathan c9905937cc feat(discover): suggest full albums only (filter singles/EPs)
Discovery's "Suggested albums" surfaced singles and EPs because
_derive_albums filtered with is_core_release (Album/Single/EP). Add a
discovery-only _album_kind_ok gate that, when discover.albumsOnly (new
config, default true), requires primary_type == "Album" with no secondary
types. is_core_release is untouched — the monitor/scan still use it.

Exposed discover.albumsOnly in the discover config route + a Discovery
settings toggle. Worker + web tests added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 20:37:28 +02:00
Jonathan 938b8f32f9 feat(web): surface Discover freshness ("last discovered N ago") + true in-progress
/discover felt "stale until I hit Discover now": it showed the result string but
never WHEN the sweep last ran, and "Discovering…" ended the moment the worker
claimed the request (requested→false) rather than when the sweep finished.

- /api/discover/run GET now also returns `inProgress` (discover.inProgress) and
  `lastRunAt` (the discover.result Config row's updatedAt = last completion).
- The client treats requested||inProgress as "running", so "Discovering…"
  persists for the whole sweep, and polls until both clear before refreshing.
- The tool row shows "Last discovered {N ago} · {result}", a sweeping message
  while running, and a clear "Not yet run" empty state.

web 151 tests (inProgress + lastRunAt asserted), tsc + build clean. No worker
change (signals already written); NOT a page cache (would worsen staleness).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 11:47:58 +02:00
Jonathan bbe1616ed2 fix(web): harden config PATCH allowlists against prototype-chain keys
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:06:49 +02:00
Jonathan fd0bb6aaa0 feat(web): surface discover.listenBrainzUrl; swap maxSeeds->chunkSize in Discovery tab 2026-07-13 00:33:49 +02:00
Jonathan 9f2b115721 feat(preview): POST /api/discover/want (want a release-group by metadata)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 01:42:49 +02:00
Jonathan 46164c9eab feat(preview): GET /api/discover/preview/[mbid] annotated discography
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 01:39:35 +02:00
Jonathan 10262f053a feat(discovery): GET/PATCH /api/discover/config
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 00:41:13 +02:00
Jonathan c7aeab5176 feat(discovery): POST /api/discover/[id] follow/want/dismiss actions
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 00:38:06 +02:00
Jonathan bf868829d8 feat(discovery): GET /api/discover/search interactive seed search
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 00:34:28 +02:00
Jonathan be59862dfc feat(discovery): POST/GET /api/discover/run trigger + status
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 00:32:01 +02:00
Jonathan f750b815d2 feat(discovery): GET /api/discover feed
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 00:29:28 +02:00