Scheduler reliability + Dispatcharr live_proxy compatibility + issue #18
Fixes
- #18 — Video format suffixes append instead of replace. Quality tags no longer stack (
Channel [HD] [FHD]). Any recognized trailing[TAG](configured ∪ UHD/FHD/HD/SD/Unknown) is stripped before re-appending the freshly detected format. - Dispatcharr
ts_proxy→live_proxyrename.ChannelServiceimport tries the newlive_proxypath first and falls back to legacyts_proxy, so the plugin works on both current and next-release Dispatcharr. The dead-streamStreamimport was corrected toapps.channels.models(the oldapps.proxy.ts_proxy.modelspath never existed and silently disabled that cleanup). - Scheduler stale-lock after container restart. The cross-process lock file now carries a container boot token (boot_id + PID 1 starttime); a lock from a previous container is reclaimed unconditionally instead of trusting a recycled PID. Fixes the scheduler wedging permanently after a restart.
- Duplicate cron fire. A re-entrant lifecycle lock makes scheduler stop+create+assign atomic, and the loop self-evicts if superseded — no more two threads firing the same minute.
- Stale-resume scope hijack. Pending-resume state is discarded (fresh load) on settings drift or an elapsed window, and dead pending state is cleared on restart.
All changes QA-reviewed; scheduler fixes verified working in production.