fix(import): accept a same-work different-media-type pocket match for a completed download - #213
Open
jordanfelle wants to merge 4 commits into
Open
jordanfelle wants to merge 4 commits into
jordanfelle wants to merge 4 commits into
Conversation
…g context
Automatic download import blocked files that the Manual Import screen resolves
locally on sight ("No match in local library. Suggested author: X (hc:NNN)."
while GET /api/v1/manualimport returns a local editionId and no rejections).
The two paths differ in exactly one matching flag. ProcessFolder gates
path/filename evidence behind ShouldAllowTrackedDownloadPathFallback
(DownloadedBooksImportService.cs:1552), which requires a tracked download with
a resolved single author AND exactly one grabbed target book. A completed
download with no usable grabbed identity therefore matches with
DisablePathFallback=true, so HolyGrailEvaluation returns early for a file whose
embedded tags carry nothing searchable (FileMatchingService.cs:4328) and never
runs the supplemental path pass (FileMatchingService.cs:4426). The preview's
MatchingContextPresets.ForManualPreview() defaults allowPathFallback to true,
so the same file resolves. Everything else in the two contexts is identical,
and both build path tokens through the same BuildPathDerivedTags/SplitTokens
helpers, so underscored folder names ("Galileo_And_The_Solar_System") were
never the problem - underscores are already separators.
Fix: after the strict pass (and after the author-auto-add rematch), re-run
only the still-unmatched files with ForDownloaded(false, targetBookIds,
allowPathFallback: true) - flag-for-flag the preview's context minus provider
identification, which the second pass does not need. Rejected alternatives:
widening ShouldAllowTrackedDownloadPathFallback would also loosen the first
pass for files that did match on weaker evidence, and lowering thresholds was
out of the question. This keeps the strict pass authoritative and only adds a
fail-open retry where today's outcome is an unconditional block.
Trade-off: path evidence now reaches the library for downloads with no grabbed
identity, which is strictly more permissive than before. It is bounded by the
same guards the preview already relies on - the matcher's own smoke test and
author/title proofs are untouched, UsePathAsTagsFallback and Strict strictness
still disable it, the author restriction and grabbed target books carry over
(EnforceTrackedDownloadTargetBooks still rejects off-target matches), no author
is imported, and a multi-file leftover set resolving to more than one book is
discarded as ambiguous rather than guessed at.
Tests: new AutoImportLocalPreviewParityFixture reproduces the Galileo case
against FileMatchingService (strict context blocks, parity/preview contexts
match, near-miss folder name stays unmatched, same-title twin is decided by
author evidence) plus three DownloadedBooksImportService tests for the second
pass, the ambiguity discard, and the no-extra-pass case.
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 26, 2026
…ftover sets The parity pass also ran for a folder with no download client item, where nothing bounds the path evidence (no grabbed release, no author restriction) and no one reviews the result. It now only runs for a tracked download. A multi-file leftover set that matched only in part was imported for the matching files while the rest were rejected, leaving the edition partially filled so a later attempt to add the remainder failed with 'Edition already has files'. Path evidence is folder-level, so a genuine match covers every leftover file; a partial match is now discarded like an ambiguous one.
…download
EnforceTrackedDownloadTargetBooks rejected any match whose BookId differed from
a grabbed target book, which blocked audio downloads whose files correctly
resolve to the audiobook pocket of a work that was grabbed against its ebook
pocket ("grabbed for 'The Vines' (BookId 166297, work hc:514913), but import
matched 'The Vines' (BookId 290880, work hc:514913)"). RetargetSameWorkMatches-
ToGrabbedBook cannot help here: it deliberately requires identical MediaType,
because audio files must not be filed under the ebook row.
An off-target match is now accepted when all off-target files resolved to the
same book row (more than one stays an ambiguous multi-book rejection), that row
has the same author as exactly one grabbed target book, shares a canonical work
provider id with it (WorkIdMatcher.WorkProviderIdMatches, work-level ids only),
and its MediaType matches the media type of the files themselves. Different
works, different authors and one-sided work ids keep being rejected.
IsSameWorkMediaPocketMatch only compared the matched row's media type with the files, so for a multi-book grab (where RetargetSameWorkMatchesToGrabbedBook is skipped) a same-format sibling row of the grabbed work, for example another narrator's audiobook row, was accepted as a pocket. Require the grabbed target to have a different media type than the matched row.
jordanfelle
force-pushed
the
fix-same-work-media-type-pocket-match
branch
from
September 26, 2026 21:52
5e7aee6 to
761c62f
Compare
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 26, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 26, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 27, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 27, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 27, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 27, 2026
jordanfelle
added a commit
to jordanfelle/chaptarr
that referenced
this pull request
Sep 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on the parity-retry PR (
fix-auto-import-local-preview-parity); it is stacked on that branch.Problem
EnforceTrackedDownloadTargetBooksrejects any match whoseBookIddiffers from a grabbed target book. That blocks audio downloads whose files correctly resolve to the audiobook pocket of a work that was grabbed against its ebook pocket ("grabbed for 'The Vines' (BookId 166297, work hc:514913), but import matched 'The Vines' (BookId 290880, work hc:514913)").RetargetSameWorkMatchesToGrabbedBookcannot help: it deliberately requires identicalMediaType, because audio files must not be filed under the ebook row.Fix
An off-target match is accepted when all off-target files resolved to the same book row (more than one stays an ambiguous multi-book rejection), that row has the same author as exactly one grabbed target book, shares a canonical work provider id with it (
WorkIdMatcher.WorkProviderIdMatches, work-level ids only), and itsMediaTypematches the media type of the files. Different works, different authors and one-sided work ids keep being rejected.Verification
DownloadedBooksImportServicetests for each accepted/rejected combination.The rule requires the grabbed target to have a different media type than the matched row: a same-format sibling row (for example another narrator's audiobook) is handled by the existing retarget step and is not accepted here, including in multi-book grabs.
DownloadedBooksImportServiceFixture: a same-media-type sibling in a multi-book grab is rejected (fails without the fix), and a different-media pocket is still accepted in a multi-book grab (3,034 core tests pass).