feat(mixes): tiered rebuilds for New for you + First listens (rule #131)
Both mixes move from a single hard eligibility rule to the tiered ladder, with their tier stamped onto playlist_tracks.pick_kind via the #1270 provenance pipeline. New for you (#1267) — consume on play, degrade by stepping back: - "Consumed" = any track attempted >=30s; played albums leave the mix at the next build instead of crowding it until the calendar window expires. - Tier 1: unconsumed albums added <30d by direct-affinity artists. Tier 2: unconsumed affinity albums from the wider 30-90d window — added while you weren't looking. Tier 3: any unconsumed album added <90d, newest first. First listens (#1268) — track-level "attempted" threshold: - A 2-second accidental brush no longer disqualifies a whole album; "attempted" is duration_played_ms >= 30000 per track. - Tier 1: albums with zero attempted tracks. Tier 2: barely-attempted albums (<=25% of tracks reached 30s), minus the attempted tracks themselves. The artist-affinity ordering signal also moves to the >=30s definition so skip-only contact doesn't read as trust. Producer plumbing: fetch adapters map the tier column onto pick kinds, finishMix propagates PickKind into the persisted candidates, and rotateForDay now rotates within contiguous same-pick-kind blocks so daily rotation can't hoist tier-3 filler above tier-1's exact fits (untiered pools are one block — original behavior). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TsF3cNoKrqCYsU78cXC8U6
This commit is contained in:
@@ -169,6 +169,21 @@ func pickKindForSeedTier(tier int32) string {
|
||||
}
|
||||
}
|
||||
|
||||
// pickKindForMixTier maps a tiered mix query's 1-based tier column
|
||||
// (numbered to match rule #131's ladder directly) onto the pick-kind
|
||||
// vocabulary. Distinct from pickKindForSeedTier, whose 0-based tiers
|
||||
// count fallback steps of the seed pool rather than eligibility rungs.
|
||||
func pickKindForMixTier(tier int32) string {
|
||||
switch tier {
|
||||
case 1:
|
||||
return pickKindTier1
|
||||
case 2:
|
||||
return pickKindTier2
|
||||
default:
|
||||
return pickKindTier3
|
||||
}
|
||||
}
|
||||
|
||||
const systemMixLength = 25
|
||||
|
||||
// systemMixWeights are the fixed scoring weights used by the cron worker.
|
||||
|
||||
Reference in New Issue
Block a user