Season 0 is TVDB's catch-all for specials/recaps/shorts and often a tie-in
movie already tracked as its own separate media_item (verified live:
Chainsaw Man's season 0 included a movie already present as its own entry).
Monitoring these by default means the library never actually "completes"
and inflates the missing-episode count with content nobody asked to
acquire as an episode. Regular seasons are unaffected.
Plain /episodes/default returns names in the show's original airing
language — for a lot of anime that's Japanese with no English name at all,
which is what was ending up embedded in generated filenames. TVDB carries
real crowd-sourced English translations at /episodes/default/eng (same
numbering/air-date fields, just a better name) — try that first and only
fall back to the original-language endpoint if a show has no English data.
TVDB has no English episode title at all for some shows (entire seasons of
otherwise-English-titled shows came back Japanese-only) — using it verbatim
put unreadable-to-most-tooling script into an otherwise Latin-script library.
Falls back to the no-title filename shape instead.
"S01E01v2" (a fixed re-release of an episode) glued the version marker
directly onto the episode number with no separator, so the word-boundary
check after the digits never matched and the whole file fell through as
unparsed. Verified live: some shows had zero episode files linked because
every release happened to be a v2.
qBittorrent's newer WebUI API returns 204 (not 200 "Ok.") on login success,
and a JSON success/failure summary (not plain "Ok."/"Fails." text) from
torrents/add — both broke against the currently deployed version. Also had
scan_tv_root move already-tracked episode files into their Season NN
subfolder instead of just recording wherever they already sat on disk.
breadarr has no .forgejo/workflows at all (no mirror, release, or
package workflow) and no PKGBUILD, and it isn't listed in
bread-ecosystem's registry/bread-ecosystem.toml, so gen-index.sh would
never pick it up even if a release workflow existed. The bakery.toml
here was pure dead metadata.
Not wiring up a release workflow instead: breadarr isn't in the
registry and its distribution channel (bakery, pacman, both, neither)
hasn't actually been decided, so adding one here would be inventing
a channel commitment I have no signal for. If/when breadarr is ready
to ship, follow docs/release-channels.md in bread-ecosystem to add it
properly (bakery.toml + registry entry + release.yml, or a PKGBUILD +
package.yml, or both).
expand_home() fell through to PathBuf::from(input) — the literal,
unexpanded "~/..." string — whenever the HOME env var itself wasn't set,
same bug class as breadclip-core/breadpad-shared/breadmon (found during
this pass's own crate-migration sweep, in a different shape here: the bug
was in this crate's own tilde-expansion helper rather than a
dirs::xxx().unwrap_or_else() chain). Fixed via bread_utils::xdg::home_dir,
which resolves a real home directory before ever needing to fall back.
Builds and tests clean: 205 passed, 1 pre-existing network-dependent test
ignored, 0 failed.
OrtEmbedder's tokenize -> tensor build -> mean-pool -> L2-normalize
pipeline was near-byte-identical to breadmill's own OrtEmbedder (same
truncation, same actual_seq.min(mask.len()) padding guard, same 1e-10
epsilon) — now both share bread_onnx::embedding::EmbeddingSession (path
dependency for now, see the TODO in breadarrd/Cargo.toml). This crate
stays CPU-only (Provider::Cpu), matching its existing documented rationale.
ensure_model's reqwest-based download function is replaced with
bread_onnx::download::ensure_file (sync/ureq, matching breadmill's own
downloader and this workspace's bakery convention) dispatched via
spawn_blocking from this async context.
Builds and tests clean across the whole breadarr workspace: 205 passed, 1
pre-existing network-dependent test ignored, 0 failed.
Both import_one and import_season_pack_file deleted the existing
episode_file row and unlinked the on-disk file *before* link_or_copy_file
placed the new one. If the link/copy (or the free-space check) then
failed, the original content and its DB row were already gone with
nothing to fall back to.
Now the stale file is renamed to a sibling (freeing dest for the
hardlink fast path, same as before) and the DB row is left alone. Only
after the replacement is confirmed on disk are the file and the
old row cleaned up; any failure in between restores the original file
before returning the error.