97 lines
5.7 KiB
Markdown
97 lines
5.7 KiB
Markdown
# Session — 07 July 2026
|
||
|
||
## Scaffolded: v2 Recommendation Engine — code complete, not yet deployed (Systems A–E + Phase 4)
|
||
|
||
All six axioms encoded as running code. Every claim is evidence, not fact.
|
||
MusicBrainz is the structural spine, not truth. Conflicts coexist in the graph.
|
||
|
||
### Files created (8 new)
|
||
|
||
| File | Lines | System |
|
||
|---|---|---|
|
||
| `backend/src/services/generators.service.ts` | 446 | **C** — 8 candidate generators |
|
||
| `backend/src/services/session-director.service.ts` | 761 | **D** — Session planner + fatigue + arcs |
|
||
| `backend/src/services/discovery.service.ts` | 297 | **E** — Graph walks + probation lifecycle |
|
||
| `backend/src/services/image-enrichment.service.ts` | 105 | **Phase 4** — Image candidate pipeline |
|
||
| `workers/src/mb-spine-writer.ts` | 136 | **A** — MB artist-credit → claims writer (wired into enrichment.service.ts) |
|
||
| `backend/src/routes/graph.routes.ts` | 152 | Graph API (claims, fusion, sources, evidence) |
|
||
| `backend/src/routes/v2.routes.ts` | 130 | v2 vibe endpoints (start, next, feedback, state) |
|
||
| `backend/src/routes/discovery.routes.ts` | 103 | Discovery + image API endpoints |
|
||
|
||
### Files modified (3)
|
||
|
||
| File | Changes |
|
||
|---|---|
|
||
| `backend/src/db/schema.sql` | +187 lines: 9 new tables + 2 ALTER TABLE + indexes |
|
||
| `backend/src/services/db.service.ts` | +700 lines: 6 migrations, 12 new methods, 6 interfaces, evidence wiring in recordPlay/recordSkip/recordFeedback/dislikeTrack, listener-behavior writer in recordPlay |
|
||
| `backend/src/app.ts` | +4 lines: imports + registrations for v2 + discovery routes |
|
||
|
||
### System-by-system
|
||
|
||
**System A — Knowledge Graph (probabilistic fusion)**
|
||
- `source_trust` table: configurable trust weights (mb=0.90, tag=0.30, listener_behavior=0.40)
|
||
- `claims` table: graph spine, unique on (subject, pred, object, source, user_id)
|
||
- `claim_fusion` view: weighted vote SUM(trust × confidence × recency)
|
||
- `track_artists_v2` / `album_artists_v2`: compatibility views over fusion
|
||
- `recording_mbid` on tracks: structural spine anchor
|
||
- Methods: upsertClaim, upsertClaims, getClaimsBySubject, getFusedValue, getFusedTrackArtists
|
||
- Backfill migration `20260707_backfill_claims`: existing track_artists → claims (tag), artist_similar → same_scene_as (lastfm)
|
||
|
||
**System B — Listener Model**
|
||
- `evidence` table: append-only signal stream
|
||
- `listener_beliefs` table: per-profile beliefs with decay
|
||
- Every play/skip/feedback writes evidence rows automatically
|
||
- Methods: recordEvidence, recordEvidenceBatch, getListenerBeliefs, updateListenerBelief
|
||
|
||
**System C — Candidate Generators (8 generators)**
|
||
- `comfortGenerator`: longterm affinity > 0.5 artists
|
||
- `adjacentGenerator`: 2-hop graph walks from seed artist
|
||
- `discoveryGenerator`: unfamiliar artists via same_scene_as from trusted artists, gated by novelty_tolerance
|
||
- `deepDiveGenerator`: obsession album deep cuts in album order
|
||
- `revivalGenerator`: stale high-affinity artists (>90d untouched)
|
||
- `experimentalGenerator`: random unfamiliar genres
|
||
- `contextualGenerator`: context-tagged preferences
|
||
- `noveltyGenerator`: recent releases (≤60d) via same_scene_as/same_label_as/produced edges from trusted artists
|
||
- All candidates carry non-empty `ClaimEdge[]` explanations (graph paths)
|
||
|
||
**System D — Session Director (runs alongside v1; getNextVibeChunk not yet deleted)**
|
||
- `buildState`: energy from last 5 plays, novelty_hunger from discovery profile, session age
|
||
- `computeFatigue`: exponential decay per dimension (track/7d-30d, artist/24h-8h, genre/24h-8h, language/2h-1h)
|
||
- `getBudgets`: reads diversity_budgets, calculates spend from recent history
|
||
- `pickArc`/`getArcSlots`: energy+novelty-based arc templates (comfort/discovery/energetic/late-night)
|
||
- `rankCandidates`: multi-objective weighted sum (enjoyment, fatigue, diversity, entropy, repetition)
|
||
- `detectAntiLoop`: Herfindahl-Hirschman Index + fatigue threshold
|
||
- `buildPlan`/`replan`: full orchestration loop with slot filling
|
||
- 27KB of planner logic
|
||
|
||
**System E — Acquisition Pipeline**
|
||
- `walkGraphForDiscovery`: walks same_scene_as/featured_on edges to artists not in library
|
||
- `evalCandidates`: fused relevance + novelty tolerance + diversity check → acquire/retire
|
||
- `evalProbation`/`sweepProbation`: evidence-based retain/retire lifecycle
|
||
- `runMetaLearning`: discovery source retention analysis
|
||
- `discovery_candidates` + `probation_status` columns
|
||
|
||
**Phase 4 — Image Candidates**
|
||
- `fetchImagesForArtist`/`fetchImagesForAlbum`: write candidate rows per source
|
||
- `selectBestImage`: source-priority-tiered selection, updates image_path/artwork_id
|
||
- `image_candidates` table with source/verified tracking
|
||
|
||
### Evidence wiring (every interaction)
|
||
- recordPlay → playback_completed (longterm +0.10) + replay_within_24h if applicable + alias_of/same_scene_as behavior claims
|
||
- recordSkip → skip_quick (negative -0.20)
|
||
- recordFeedback(promoted) → add_to_favorites (longterm +0.60)
|
||
- recordFeedback(disliked) → hidden (negative -0.60)
|
||
- dislikeTrack → hidden (negative -0.60)
|
||
|
||
### Verification
|
||
- `npx tsc --noEmit` — 0 errors
|
||
- `npx vitest run` — 30/30 pass (mocked shape checks, not DB-state)
|
||
- No git repo — changes uncommitted
|
||
- NOT deployed: live backend container is pre-v2; `/api/v2/*` and `/api/graph/*` return 404; DB has zero v2 tables. See `docs/architecture/v2-fix-plan.md` for the fix + deploy plan.
|
||
|
||
### Next
|
||
- Execute `docs/architecture/v2-fix-plan.md` (MV refresh, decay job, bug fixes, deploy)
|
||
- After deploy + verify: wire the v2 endpoint into the frontend Vibe page (replace v1 vibeService calls)
|
||
- Build yt-dlp worker for System E acquisition (download candidates)
|
||
- After v2 is verified in production: delete v1 CTE (`getNextVibeChunk`), `vibe.routes.ts`, `feedback` table, `artist_similar` table per the doc's "Retiring v1" list
|