Recommendation batch: You-might-like fallback + taste 2b + observability #96
Reference in New Issue
Block a user
Delete Branch "dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Server + web. Three CI-green commits since v2026.06.11.
You-might-like fallback broadened (#790)
The artists row showed only a couple of tiles because the fallback drew from
explicit artist-likes only. Broaden both fallbacks to entities you've shown
affinity for — artist fallback = explicit artist-likes ∪ artists of liked
albums ∪ artists of liked tracks; album fallback = liked albums ∪ albums of
liked tracks. Read-side, fills immediately.
Taste phase 2b — taste_overlap candidate arm (#796)
A 6th arm to the candidate union: in-library tracks by the user's top
positively-weighted taste-profile artists enter the pool (weight > 0,
deterministic order, pool-inclusion only — TasteMatch scores the fit). For-You
/ radio use it; You-might-like sets it to 0 (it wants NOT-engaged artists).
Taste phase 4 — recommendation observability (#796)
GET /api/me/recommendation-metrics: per-source plays / skips / skip-rate /
avg-completion so you can see which surfaces land and tune the taste weights. A
"Recommendation metrics" card on the Settings page renders it. (For-You /
Discover / mixes; You-might-like plays aren't source-tagged yet.)
Deferred: phase 3 (context) — design-heavy, payoff concentrated in radio; do it
later if the metrics show radio needs help.
🤖 Generated with Claude Code
The fallback pulled artists only from explicit artist-likes (general_likes_artists), but most users like albums and tracks far more than artists — so the artists row still came up thin (a couple of tiles) even with a rich library, while the albums row filled fine. Broaden both fallbacks to "entities you've shown affinity for": - artist fallback = explicit artist-likes ∪ artists of liked albums ∪ artists of liked tracks. - album fallback = explicit album-likes ∪ albums of liked tracks. New dedicated queries (ListYouMightLike{Artist,Album}FallbackForUser) replace the narrow Rediscover-fallback reuse; same projection so the Go layer still converts directly. (Aliased + fully-qualified the UNION arms — sqlc merges UNION scopes, so unqualified user_id was ambiguous across the three like tables.) Test: 12 liked TRACKS by distinct artists, no artist-likes → the artist row now fills from their artists (was empty before). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Per-source play outcomes so the operator can see whether each recommendation surface is landing and tune the now-operator-tunable taste weights. Server: - query RecommendationSourceMetricsForUser: groups the user's play_events by source (system-playlist surface), reporting plays / skips / avg completion over a window; NULL-source (library/radio) plays excluded. - GET /api/me/recommendation-metrics?days=30 (default 30, capped 365) → {window_days, sources:[{source, plays, skips, skip_rate, avg_completion}]}. - handler test: 401 unauth; per-source aggregation + NULL-source exclusion + skip_rate / avg_completion math. Web: - lib/api/metrics.ts: query + friendly source labels. - settings page gains a "Recommendation metrics" card (table of surface / plays / skip rate / avg completion), with loading/error/empty states. - settings tests mock the new query (manual subscribe-store, hoisting-safe). Note: You-might-like plays aren't source-tagged (it's a Home row, not a system playlist), so this covers For-You / Discover / the mixes. Tagging YML plays would be a client follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>