soulsync/core/video
BoulderBadgeDad 21e1944784 video scan: only FULL resets enrichment; incremental/deep preserve it
A scan wrote server-provided fields straight over the row, so an incremental/deep
re-read wiped the TMDB-backfilled 'status' (Plex returns it blank) — clearing the
airing watchlist. Now matches the intended model: incremental (add recent) and deep
(coverage + prune) PRESERVE enrichment-owned fields the server left blank; only a FULL
scan clobbers them (an explicit reset / fresh start).

- _resilient_upsert gains preserve_enrichment (default True): on a conflict UPDATE,
  enrichment-owned columns (per _ENRICH_META_COLS: status/network/ratings/air dates/…)
  take the server value only when non-blank, else keep what's stored. A real server
  value still wins.
- upsert_movie/upsert_show_tree thread the flag; scanner passes preserve=(mode!='full').

Tests: preserve-on-blank, server-value-wins, full-resets, and the scanner picking the
right mode. 88 DB + 18 scanner tests + isolation green.
2026-06-20 15:06:44 -07:00
..
enrichment video scan: harden library scope + pause ALL enrichers during any scan 2026-06-20 13:24:57 -07:00
__init__.py video side: library scanner (server = source of truth) + scan API 2026-06-13 23:13:50 -07:00
download_config.py video downloads: reword download_config docstring (a wrapped line started with 'from the music side' — tripped the core/video no-music-import guard, a test false positive) 2026-06-19 00:25:57 -07:00
download_events.py video automations: post-download scan chain (parity with music's batch→scan→update) 2026-06-20 14:47:00 -07:00
download_monitor.py video automations: post-download scan chain (parity with music's batch→scan→update) 2026-06-20 14:47:00 -07:00
download_pipeline.py video downloads pipeline: data + pure logic foundation 2026-06-19 14:50:27 -07:00
mock_search.py video search: each source returns its own results (was identical) 2026-06-19 13:56:04 -07:00
quality_eval.py video search: evaluate/rank pipeline + mock indexer + /downloads/search 2026-06-19 13:39:09 -07:00
quality_profile.py video quality profile: loose resolution cutoff + movie/episode size split 2026-06-19 10:40:53 -07:00
release_parse.py video search: scene/p2p release-title parser (Sonarr-style) 2026-06-19 13:28:37 -07:00
retry.py video downloads Phase C: auto-retry + alternate-query requery 2026-06-19 17:12:44 -07:00
scanner.py video scan: only FULL resets enrichment; incremental/deep preserve it 2026-06-20 15:06:44 -07:00
slskd_download.py video downloads Phase A: cancelled state, cancel/retry, monitor robustness 2026-06-19 15:31:51 -07:00
slskd_search.py video search: poll the FULL slskd timeout (~60s) + explain audio-only results 2026-06-19 16:55:53 -07:00
sources.py video scan: harden library scope + pause ALL enrichers during any scan 2026-06-20 13:24:57 -07:00
youtube.py Playlist/channel extraction: stop pinning a static user_agent for yt-dlp 2026-06-17 22:21:12 -07:00
youtube_enrichment.py Remember each channel: cache the video catalog + metadata (instant re-open) 2026-06-17 18:08:04 -07:00
youtube_quality.py video downloads: separate YouTube quality profile (yt-dlp) 2026-06-19 10:45:38 -07:00