Recommendation engine and browse UI #10

Manually merged
marvin8 merged 7 commits from feat/issue-5-phase-1d-recommendations into main 2026-10-10 06:38:11 +00:00
Collaborator

Phase 1d (Closes #5): the spike's round-2 engine ported to services/engine.py behind a worker recommend job, plus the zero-JS browse UI.

Engine — seeds = ledger items rated ≥ 8; per-seed TMDB recommendations + similar fan-out (page 1); vote_count ≥ 100 floor; seen/dismissed/Jellyfin-library exclusion (library best-effort); score = adjacency × clip((bayes/6)², 0.3, 2.0) with m=300, C=6.0; movie-only franchise cap of 2 per belongs_to_collection (TMDB TV has no collection field, so shows rely on the ≥ 2-distinct-seed rule); genre-affinity /discover (top-3 ledger genres, release-date cap, bayes-sorted); seeded wildcards from the discovery mid-tier. Note: discovery fetches 3 pages per type to build the wildcard pool but stores the top 20 per discovery list. Recompute replaces the user's rows wholesale; an empty ledger genre distribution skips discovery with a warning.

Browse UI — /, /movies, /shows (20/page, paginated), /discover, /item/{id} (lazy TMDB enrichment with graceful degradation, seeds shown as "Because you rated X"), /library/unrated, /actions/{rate,hide,seen,refresh} (rate handles the rate+watched / rate+hide combos), /theme cookie override with prefers-color-scheme default. Zero JavaScript anywhere.

Also rides: owner folds for the WuMing max_diff_lines bump and the nox 3.15 matrix; migration 3 (recommendations).

Verification: 305 tests, uv run nox 9/9 sessions green at every commit; real-ledger smoke over the imported Trakt data (130 seeds — spike-identical, franchise cap, TV multi-seed, scores to 1e-9, byte-identical replay). Whole-branch review and all four unit reviews APPROVED; fix wave applied.

Closes #5

Phase 1d (Closes #5): the spike's round-2 engine ported to `services/engine.py` behind a worker `recommend` job, plus the zero-JS browse UI. **Engine** — seeds = ledger items rated ≥ 8; per-seed TMDB `recommendations` + `similar` fan-out (page 1); `vote_count ≥ 100` floor; seen/dismissed/Jellyfin-library exclusion (library best-effort); `score = adjacency × clip((bayes/6)², 0.3, 2.0)` with m=300, C=6.0; movie-only franchise cap of 2 per `belongs_to_collection` (TMDB TV has no collection field, so shows rely on the ≥ 2-distinct-seed rule); genre-affinity `/discover` (top-3 ledger genres, release-date cap, bayes-sorted); seeded wildcards from the discovery mid-tier. Note: discovery fetches 3 pages per type to build the wildcard pool but stores the top 20 per discovery list. Recompute replaces the user's rows wholesale; an empty ledger genre distribution skips discovery with a warning. **Browse UI** — `/`, `/movies`, `/shows` (20/page, paginated), `/discover`, `/item/{id}` (lazy TMDB enrichment with graceful degradation, seeds shown as "Because you rated X"), `/library/unrated`, `/actions/{rate,hide,seen,refresh}` (rate handles the rate+watched / rate+hide combos), `/theme` cookie override with `prefers-color-scheme` default. Zero JavaScript anywhere. **Also rides:** owner folds for the WuMing `max_diff_lines` bump and the nox 3.15 matrix; migration 3 (`recommendations`). **Verification:** 305 tests, `uv run nox` 9/9 sessions green at every commit; real-ledger smoke over the imported Trakt data (130 seeds — spike-identical, franchise cap, TV multi-seed, scores to 1e-9, byte-identical replay). Whole-branch review and all four unit reviews APPROVED; fix wave applied. Closes #5
🐛 fix: phase 1d review findings
All checks were successful
/ pr-review (pull_request) Successful in 5s
/ gitleaks (pull_request) Successful in 16s
/ checks (pull_request) Successful in 3m29s
/ container (pull_request) Has been skipped
/ publish-container (pull_request) Has been skipped
/ deploy-docs (pull_request) Has been skipped
5038a55046

This PR is too large to review automatically (6263 lines; limit is 5000). Please consider splitting it into smaller PRs.

This PR is too large to review automatically (6263 lines; limit is 5000). Please consider splitting it into smaller PRs.
marvin8 approved these changes 2026-10-10 06:37:15 +00:00
marvin8 manually merged commit e939d3cec9 into main 2026-10-10 06:38:11 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
marvin8/xique!10
No description provided.