# Recommendation & Vibe Specification This document defines the logic for the "Vibe" engine, moving from simple similarity to a continuous, evolving listening experience. ## 1. The "Vibe" Concept The "Vibe" is an infinite, stateful listening session. Unlike a static playlist, it is a **Rolling Window** that evolves based on user interaction. ## 2. Scoring Logic When generating a sequence, every candidate track is assigned a score. $$Score = (W_{genre} \cdot S_{genre}) + (W_{artist} \cdot S_{artist}) + (W_{random} \cdot R)$$ ### **Scoring Components** * **$S_{genre}$ (Genre Match):** * Uses hierarchical weights (e.g., `Deep House` (1.0) $\rightarrow$ `House` (0.8) $\rightarrow$ `Electronic` (0.5)). * Calculated as the highest weight match between candidate and "Center Track." * **$S_{artist}$ (Artist Similarity):** * A binary or weighted score based on whether the artist is in the user's "Liked" list or frequent listening history. * **$R$ (Randomness/Exploration):** * A jitter factor to ensure the queue doesn't feel repetitive. ## 3. The Rolling Window Algorithm The backend does not return a fixed list. It returns a **Sequence Chunk**. ### **Step-by-Step Generation** 1. **Identify the Center:** Find the `last_successfully_played_track_id`. 2. **Candidate Selection:** * **Local Pool (80%):** Tracks from the user's library similar to the center track. * **Probation Pool (20%):** Tracks from the `recommendation_batch` that have `probation=1`. 3. **Constraint Application (Batch Rules):** * **Diversity Check:** No more than 1 track from the same artist per chunk. * **Genre Cap:** No more than 2 tracks from the same genre per chunk. 4. **Chunking:** Return a sequence of $N$ tracks (e.g., 20). ## 4. The "Vibe" Session Lifecycle A "Vibe" is represented by a `recommendation_batch` record. | State | Description | | :--- | :--- | | **ACTIVE** | The user is currently listening. The stream is being generated. | | **RESOLVED** | The session has ended naturally or timed out. | | **FAILED** | The session was interrupted by a critical error or manual reset. | ### **Transition Logic** * **Start:** User clicks "Start Vibe" $\rightarrow$ Create `ACTIVE` batch. * **Progress:** User listens $\rightarrow$ Update `last_interaction_at` in the batch. * **Termination:** * **Natural:** User exits the app $\rightarrow$ Session marked `RESOLVED` after 24h. * **Manual:** User ends session $\rightarrow$ Mark `RESOLVED` immediately. * **Timeout:** No interaction for 24h $\rightarrow$ Mark `RESOLVED`. ## 5. Success/Failure Feedback Loop The engine learns from the `feedback` table: * **`action = 'promoted'`:** (High Score) Increase weight of this genre/artist in future seeds. * **`action = 'disliked'`:** (Negative Signal) Decrease weight of this genre/artist. * **`action = 'skipped'`:** (Transient Negative) Do not adjust long-term weights, but avoid this specific track in the current session window.