with_status drops its seasons slice for the same reason as
derive_series_status; tv_by_series no longer loads seasons at all.
Offline query data regenerated.
derive_series_status identified specials by looking the episode's
season up in a parallel seasons slice, so a caller passing an
incomplete slice silently reverted to pre-#118 behaviour. The season
number now rides on each episode and the slice is gone.
COMPLETE before the season tag was weak junk, so it stayed in
the title and exact-title matching failed silently (#135). It
now closes the boundary wherever it lands.
S01-S01 produced no claim because the dash-range branch required
last > season; a degenerate range is one season's pack, matching
the rule match_episode lifted.
Own route beside library and queues. Roots edit kind, audience, path
and their policy; policies get a form over the real fields — size
bands as number inputs, score and source weights as numbers,
resolution preference and audio/HDR rules as validated lists. Delete
arms before firing; a 409 from a referenced policy or occupied root
surfaces its message.
Policies and roots were editable only via SQL inside the container.
Full CRUD over both, validated against the vocabulary the policy
engine knows — unknown resolutions or sources answer 422 naming the
field, malformed JSON answers 422, deleting a referenced policy or an
occupied root answers 409. Closes#116 (API half).
GET .../releases returned the stored score column, frozen at
search time. Policy tuning never reached an existing deck. Recompute
from parsed/size/seeders against the current policy and re-sort by
bucket then score; the stored column stays for the daemon's grab-time
winner pick.
Closes#114
MovieCommand::Search loaded the movie through the gap filter, so an
available movie fell out and the search was a silent no-op. Split the
lane: a gap still searches and grabs, anything already satisfied
refreshes the release deck (DESIGN.md 9.3) without grabbing, and a
blocked movie still refuses.
Closes#115