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.