Tags give the ability to mark specific points in history as being important
-
v1.9.2
protected7059a578 · ·v1.9.2 — hygiene sweep + iPhone PWA safe-area (correcting v1.9.1, which was tagged on a stale local main and shipped the v1.9.0 tree; per policy the bad tag stays, this tag points at the intended hygiene merge, deliberately excluding the Stage 2 merge pending the Aug 5 data checkpoint)
-
v1.9.1
protected42df3a30 · ·v1.9.1 — hygiene sweep + iPhone PWA safe-area hardening Safe-area insets for viewport-fit=cover, defensive overflow containers, [WEB LOG] double-print removed, mark.log rotation, Seerr (type,title) keying + pagination hardening, SSL_BYPASS across all HTTP sessions, Plex shared-user timeout, dead-code sweep.
-
v1.9.0
protected42df3a30 · ·v1.9.0 — web auth (C5) and Stage 1: the DB is the web layer's single source of truth Session auth on every route and the log websocket, fail-closed without FERRET_WEB_PASSWORD. Dashboard renders the real deletion queue from cleanup.db with live countdowns, the deletion audit trail, incomplete-scan banner, and honest labels for matched-this-scan vs in-queue. Kills the in-memory cleanup_results dual state, unifies CLEANUP_DB_PATH resolution, adds busy_timeout, exclusion match feedback, stall re-alerting, and versioned static assets with cache headers.
-
v1.8.0
protected9b9cbf04 · ·v1.8.0 — Phase 0 deletion-safety fixes Ships the pre-Aug-18 items from the 2026-08-03 audit: degraded-scan guard for all three server types plus a scan-size drop check (C1), warning sends confirmed before marking sent with full chunked title lists (C2/H7), year in the flag key with an in-place migration (C3), resurrected flags start fresh countdowns (H2), pre-delete exclusion re-check (H3), fail-safe dry-run parsing (H4), provider-id contradiction veto and stall routing for year mismatches (H8/C4), empty-mount refusal (M3), and a per-cycle effective-config log line with per-key sources (H1).
-
v1.7.0
protected377b527f · ·v1.7.0 — settle deletions no *arr owns Deletions for items absent from Radarr/Sonarr no longer retry forever. Presence is probed with three states (present/absent/unknown); disk checking is opt-in via CLEANUP_MEDIA_PATH_MAP, so an unconfigured deployment never concludes a file is gone.
-
v1.6.1
protecteddcab0895 · ·v1.6.1 — the stuck-deletion alert stops repeating The alert shipped in v1.2.0 re-sent every cleanup cycle — hourly, indefinitely — and reported rows the scan no longer flags. 19 identical messages about one movie whose underlying metadata had already been corrected. Now fires once per item, and only for items the current scan actually flagged.
-
v1.6.0
protectedd6494fc6 · ·v1.6.0 — episode identity includes season/episode number Also the version prod gets pinned to, so that `dockerUpdateAll` stops shipping every main merge straight to production. The container was running :latest, which CI rebuilds on every merge, which made the tag gate meaningless for Ferret.
-
v1.5.0
protected666b92ab · ·v1.5.0 — deletions resolve by provider id, not by title The stuck "Falling" deletion was not Ferret being confused about a movie Radarr lacks — Radarr had it. Jellyfin had "Fallen (2006)" (tmdb 50126) catalogued under the title "Falling", so the Radarr lookup found nothing. And Radarr holds two films called "Fallen", so even the correct title would have been ambiguous. The resolver now tries tmdb, then imdb, then tvdb before falling back to title+year. Those ids were already collected for cross-server identity matching in v1.1.0; they just never reached the deletion path.
-
v1.4.0
protectedbd4704cd · ·v1.4.0 — sync stops un-marking watched episodes - The Jellyfin/Emby episode write path could reset a FINISHED episode to unwatched with a resume position, because the Series/Episodes queries lack the isPlayed=false filter the movie path has. Sync is additive; it never un-marks. - Series folders stopped matching across servers: path_suffix's two-component rule is right for episode files but a series folder's parent IS the library root, which is what differs between servers. Every show whose libraries are named differently synced no episodes at all. - Watch state was merged into the local picture before the write was known to have succeeded, so a failed write made the next server pair skip those items as "already synced". First test coverage for functions.py series handling, jellyfin_emby.py writes and main.py ordering — the files carrying all three. -
v1.3.0
protected42005b33 · ·v1.3.0 — the deletion guard now measures what it was supposed to Two more paths where the engine concluded "never watched" from data it never had, both data loss: - The guard compared collected data against CONNECTED servers, not configured ones. generate_server_connections returns the survivors of a connection failure, so an unreachable Plex produced "1/1 returned data — complete" and everything watched only on Plex became deletable. - Partial failures inside a server (a dropped shared user, a library that would not open) hid watch history while the scan still counted as complete. Cleanup thresholds are also validated now. CLEANUP_DELETE_AFTER_DAYS=0 meant flag and delete in the same scan; MAX_AGE=0 flagged the entire library. Both were accepted from the settings API while SLEEP_DURATION beside them was bounds-checked. -
v1.2.0
protected0e4954da · ·v1.2.0 — a stuck deletion stops being invisible An item that cannot be resolved to a single Radarr/Sonarr entry is refused, correctly, but was then refused again every hour forever with no counter, no alert and no dashboard surface. One movie sat eight days past its deletion date looking perfectly healthy. Failures are now counted per item with their reason, and escalate after three consecutive misses. The audit trail is written per deletion rather than batched, so a crash mid-batch can no longer leave media deleted with no record of it.
-
v1.1.0
protected5939c475 · ·v1.1.0 — the cleanup engine stops deleting media people have watched Six independent paths could answer "nobody watched this" when somebody had, and each ended in an irreversible file delete. - Cross-server identity: the merge keyed on the raw title string, so Plex's "Star Wars: The Mandalorian and Grogu" and Jellyfin's "The Mandalorian and Grogu" were two records — one holding every watch, one holding none. Now matched on tmdb/imdb/tvdb ids, which Jellyfin was already fetching and discarding. - Watched-with-no-play-date counted as never watched. - A missing Overseerr request date skipped the grace period entirely. - A lone *arr title match was accepted without comparing years, so the wrong film could be deleted. - "Requested & Unwatched Shows" could never fire ("tv" vs "show"). - Exclusions checked only one server's spelling, a config seed silently destroyed user-added protections, and legacy wildcards were dead rules. CLEANUP_EXCLUDE_CONTINUING was also a no-op for Plex shows: plexapi reports no status, so the engine now treats it as unknown and declines to delete a series it cannot confirm has ended.