Commit Graph

26 Commits

Author SHA1 Message Date
Miguel Palhas 917aa4fa76 feat: scale size bands by episode runtime
Implements #209 per §5.5 as amended by #208: a band's floor and target
are rates against a 45-minute reference runtime, scaled by the series'
minutes per episode. A missing or zero runtime applies the bands
unscaled, and movies are never scaled. The runtime is stored on the
series row (new migration), filled on add and by the metadata refresh,
which never blanks a known value against TMDB's frequently-empty
episode_run_time. Composes with #210: allow_below_floor waives against
the scaled floor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 22:45:55 +01:00
Miguel Palhas 1e03873209 feat(web): name the season deck's real state
An empty season deck was three truths wearing one message, and the one
it chose to blame was wrong: a season on the per-episode lane sat on
"sweeping indexers…" for the full wait and then blamed a backoff for a
pack search that was never going to run.

`GET /api/series/{id}/seasons/{n}/pack-state` says which lane the
season takes and why, from `season_grab_reason` in arr-core, plus the
failed-pack tally and when #181's window reopens. Seasons gain
`last_pack_search_at`, written only by a season-scoped sweep, so a
pack search that ran and found nothing is a settled answer rather than
a pending one.

The deck then says the true thing in each case, and a season held off
the pack lane by a failure offers the retry that waives its window.

Refs #182
2026-08-24 20:14:48 +01:00
Miguel Palhas a3897df0ab fix(db): keep migration checksums stable
ci / web (push) Successful in 38s
ci / rust (push) Successful in 1m4s
e2e / e2e (push) Successful in 1m14s
Issue #155 removed the sqlx 0.8 rebuild workarounds by editing migrations
0007, 0014 and 0021 in place. Editing an applied migration changes its
checksum, and `migrate()` refuses to run when one no longer matches what
`_sqlx_migrations` recorded, so the daemon exited on startup against any
database that had already applied them — production included.

The sqlx 0.9 bump is the fix and survives: a new migration can carry
`-- no-transaction` so `PRAGMA foreign_keys = OFF` holds and a table
rebuild stops cascade-deleting its children. Only the retroactive cleanup
of migrations that already ran is reverted, along with #153's
`CHECK (title <> '')`, which rode on the 0021 edit and needs a migration
of its own rather than a rewrite of history.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:14:42 +01:00
Miguel Palhas 93a3485c50 fix(db): drop 0.8 rebuild workarounds, enforce title
With sqlx 0.9 honouring `-- no-transaction`, 0007 loses its
movie_releases_backup stash like 0014 did, and 0021 gains
the CHECK (title <> '') that #153 abandoned because the 0.8
migrator could not run a rebuild with foreign keys off. The
rebuild test now enters at migration 6 so the child links
ride through all three rebuilds, and a new test proves the
'' -> 'TBA' backfill and the rejection of new empty titles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:39:22 +01:00
Miguel Palhas ef4722e1dd fix(db): bump sqlx to 0.9, honour no-transaction
sqlx-sqlite 0.8 ignored Migration.no_tx and wrapped every
migration in a transaction, where PRAGMA foreign_keys = OFF
is a no-op — so any table rebuild cascade-deleted children.
0.9 honours `-- no-transaction`, so 0014 drops its
movie_releases_backup / episode_releases_backup workaround
and runs the plain rebuild recipe with foreign keys off.
A migration test rebuilds both parents from a pre-0014
database and asserts the child link rows survive.

Closes #155

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:10:53 +01:00
Miguel Palhas 8478c0f8a9 feat(db): store poster, backdrop and rating on titles
§9.6 keeps rich detail out of the database except for the three fields
pure-SQL views need. Adds poster_path, backdrop_path and vote_average to
movies and series, written by the daily metadata refresh in both lanes
and filled at add time from the TMDB response the create flows already
fetch.
2026-08-23 22:12:05 +01:00
Miguel Palhas 0ed0791fd4 fix(db): backfill empty episode titles to TBA 2026-08-23 20:55:16 +01:00
Miguel Palhas 943f18cdf5 feat(db): add seasons.vanished conflict flag 2026-08-23 19:34:55 +01:00
Miguel Palhas 3bcc612f9a feat(db): flag episodes that vanish upstream 2026-08-23 17:59:41 +01:00
Miguel Palhas 808145d73b feat(db): stamp series metadata refresh time 2026-08-23 17:45:09 +01:00
Miguel Palhas 42a0895975 feat(db): season_releases table and season policy loader 2026-08-23 16:49:42 +01:00
Miguel Palhas 46de061e68 feat(db): nullable unique series.tvdb_id 2026-08-23 16:32:25 +01:00
Miguel Palhas a5b3680746 feat(core): rank resolutions in the score
ci / web (push) Successful in 42s
e2e / e2e (push) Successful in 1m13s
ci / rust (push) Successful in 1m18s
`resolution_pref` only gated eligibility, so every release was scored
against its own resolution's size band and a 23 GB 4K lost to an
at-target 1080p. Each step up the list is now worth `resolution_step`
points, seeded at 300: five gibibytes of 4K overshoot, so a 4K up to
27 GB wins and a bloated one still does not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:01:24 +01:00
Miguel Palhas 54b3ea8a4d fix(daemon): park vanished grabs instead of re-grabbing
ci / web (push) Successful in 42s
ci / rust (push) Successful in 1m22s
e2e / e2e (push) Successful in 1m39s
Overrides #86: removing a torrent by hand in Transmission is human
intent, not a gap to refill. Clear `wanted` and mark the target
`parked` (a new movies/episodes state) rather than reopening it as
`missing`, so neither targeted search nor RSS matching pick it back
up. Blacklist stays untouched, since the release never failed policy.

Closes #108
2026-08-23 09:13:37 +01:00
naps62-yolo 02d99ae558 feat: match RSS results by IMDb id (#99)
ci / web (push) Successful in 28s
e2e / e2e (push) Successful in 53s
ci / rust (push) Successful in 2m15s
2026-08-23 02:44:42 +01:00
Miguel Palhas 3082568171 fix(db): renumber colliding 0011 migration to 0012
ci / web (push) Successful in 45s
e2e / e2e (push) Successful in 1m2s
ci / rust (push) Successful in 2m59s
PRs #97 and #98 each added a migration numbered 0011; merged together
sqlx hits UNIQUE on _sqlx_migrations.version.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 02:33:23 +01:00
naps62-yolo bc2da22ea5 fix: reopen the gap for a grab whose torrent vanished (#98)
ci / web (push) Successful in 55s
ci / rust (push) Failing after 3m50s
e2e / e2e (push) Failing after 1m32s
2026-08-23 02:31:50 +01:00
naps62-yolo 55ae44fa7b fix(db): scale TV size bands to episode size (#97)
ci / web (push) Successful in 57s
e2e / e2e (push) Successful in 2m31s
ci / rust (push) Successful in 5m9s
2026-08-23 02:31:44 +01:00
naps62-yolo 9f812fac11 feat: season-pack vs per-episode grab selection (#94)
ci / web (push) Successful in 24s
e2e / e2e (push) Successful in 54s
ci / rust (push) Successful in 2m11s
2026-08-23 01:40:53 +01:00
naps62-yolo e01505bd53 Targeted-search backoff and release-date gating (#90)
ci / web (push) Successful in 25s
e2e / e2e (push) Successful in 46s
ci / rust (push) Successful in 2m9s
2026-08-23 00:42:13 +01:00
naps62-yolo 62aba6315c feat(db): align movie state with canonical MediaState (#85)
ci / web (push) Successful in 29s
e2e / e2e (push) Successful in 47s
ci / rust (push) Successful in 2m59s
2026-08-22 23:21:09 +01:00
naps62-yolo d3cea8693b feat(api): series, season and episode endpoints (#81)
ci / web (push) Successful in 26s
e2e / e2e (push) Successful in 47s
ci / rust (push) Successful in 2m39s
2026-08-22 23:02:34 +01:00
naps62-yolo ac6ed8b798 feat(db): add series, season and episode model (#71)
ci / rust (push) Successful in 1m36s
ci / web (push) Successful in 34s
e2e / e2e (push) Successful in 1m41s
2026-08-22 22:04:27 +01:00
naps62-yolo 29d6831c83 feat(core): score by distance from target size (#63)
ci / web (push) Successful in 48s
ci / rust (push) Successful in 1m13s
e2e / e2e (push) Successful in 1m15s
2026-08-22 21:15:26 +01:00
naps62-yolo 99ac79373d feat(api): add movie CRUD API (#56)
ci / web (push) Successful in 8s
e2e / e2e (push) Successful in 1m21s
ci / rust (push) Successful in 3m53s
2026-08-22 20:40:31 +01:00
naps62-yolo 84777169d0 feat(db): SQLite schema and movie migrations (#48)
ci / web (push) Successful in 7s
ci / rust (push) Successful in 35s
e2e / e2e (push) Successful in 47s
2026-08-22 19:36:39 +01:00