7226dab9ff
The 2-week metrics review found Discover beating the manual baseline on skip rate — which for a discovery surface means it plays it safe. On a single-user server it's effectively dormant + crude-random, and the per-user taste profile (taste_profile_tags, #796) went unused (#1254 gap). Add a fourth Discover candidate bucket, ListTasteUnheardTracksForDiscover: unheard / non-liked / non-quarantined tracks ranked by summed taste-tag weight over tracks.genre (split like the radio tag_overlap arm), md5 tiebreak. Its picks are stamped pick_kind = 'taste_unheard' (migration 0041 widens the CHECK on playlist_tracks + play_events, rule #36). Rebalance the slot allocation 40/30/30 → taste_unheard 35 / dormant 30 / cross_user 20 / random 15, and lead the interleave with taste_unheard so a track shared with another bucket keeps the taste stamp and the targeted-novelty arm stays measurable. Metrics label "Taste-matched" + order entry added to the single server-side pickKindLabels map, so web and Android surface the new breakdown row with no client change. Cold start (empty taste_profile_tags) yields an empty taste bucket that redistributes to the survivors, so Discover still fills. Scribe #1488. Companion review outcomes: Songs-like starvation already fixed (#1255); For You v2 ratified as-is (fresh-injection cost disproven). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.4 KiB
SQL
33 lines
1.4 KiB
SQL
-- Discover taste-targeted novelty bucket (milestone #127, Scribe #1252/#1488).
|
|
--
|
|
-- The 2-week metrics review found Discover beating the manual baseline on
|
|
-- skip rate — which for a discovery surface means it is playing it safe:
|
|
-- on a single-user server it is effectively dormant + crude-random, and
|
|
-- the per-user taste profile (n_tags, #796) went unused. This adds a
|
|
-- fourth Discover candidate bucket that ranks unheard tracks by the
|
|
-- user's taste-profile tag weights ("novelty that fits your vibe"), so
|
|
-- its picks need a new pick_kind provenance value.
|
|
--
|
|
-- Postgres CHECK whitelists can't be altered in place: DROP + re-ADD with
|
|
-- the expanded list, in the same migration (family rule — new CHECK-enum
|
|
-- value needs a same-change migration).
|
|
ALTER TABLE playlist_tracks
|
|
DROP CONSTRAINT playlist_tracks_pick_kind_check;
|
|
ALTER TABLE playlist_tracks
|
|
ADD CONSTRAINT playlist_tracks_pick_kind_check
|
|
CHECK (pick_kind IN (
|
|
'taste', 'fresh',
|
|
'dormant', 'cross_user', 'random', 'taste_unheard',
|
|
'tier1', 'tier2', 'tier3'
|
|
));
|
|
|
|
ALTER TABLE play_events
|
|
DROP CONSTRAINT play_events_pick_kind_check;
|
|
ALTER TABLE play_events
|
|
ADD CONSTRAINT play_events_pick_kind_check
|
|
CHECK (pick_kind IN (
|
|
'taste', 'fresh',
|
|
'dormant', 'cross_user', 'random', 'taste_unheard',
|
|
'tier1', 'tier2', 'tier3'
|
|
));
|