Repository navigation
fix(series): skip split edition parts of owned books and apply metadata profile filters to series fill (#3048, #2208) - #3109
Merged
Conversation
…ries fill (#3048, #2208) Fill and the wanted sweep skip a stored book that is a split edition part of a whole already in the library, using the same two signal rule as #2915. A new series endpoint unmonitors those parts. Series fill now screens the books it creates and re queues through the author's metadata profile, and two admin endpoints preview and unmonitor wanted books a profile filter turned on later would have kept out. Nothing is deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fJcCVbNnKsmj2MAAMwWj9 Signed-off-by: vavallee <vavallee@protonmail.com>
…and profile filters (#3048, #2208) Series page marks split edition parts, leaves them out of the missing count, offers a one click unmonitor and reports what a fill skipped. Drops the profile level retroactive endpoints from the first commit: per author Reconcile catalogue (#2247) already applies every filter to stored rows. Adds the db test for the covered split part query, docs and changelog fragments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fJcCVbNnKsmj2MAAMwWj9 Signed-off-by: vavallee <vavallee@protonmail.com>
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
…nting hand monitored books as skipped (#2208) Review follow up. Hardcover series entries carry no language, so a profile with unknown languages set to fail rejected every book of an add all whenever OpenLibrary was primary. A blank language now passes during a fill, and a failed language evidence lookup passes too, the same unknown passes rule MinPages and SkipMissingISBN use. Only a definitive "not allowed" rejects. The re-queue loop now screens only unmonitored stored rows. A monitored book is already being sought, often because it was added by hand, so it is queued as before and no longer reported as skipped on every fill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fJcCVbNnKsmj2MAAMwWj9 Signed-off-by: vavallee <vavallee@protonmail.com>
…anted-series-filters Signed-off-by: vavallee <vavallee@protonmail.com>
vavallee
marked this pull request as ready for review
October 8, 2026 03:56
vavallee
enabled auto-merge (squash)
October 8, 2026 03:56
10 tasks done
gchahcg
pushed a commit
to gchahcg/bindery
that referenced
this pull request
Oct 10, 2026
…avallee#2524) vavallee#3109 landed on main while this was open and introduced its own copy of the same two-signal rule (seriesmatch.SplitEditionPartOf, db.ListCoveredSplitEditionParts) for rows already stored, asking whichever PR landed second to line up with the other. - splitEditionWhole now calls seriesmatch.SplitEditionPartOf instead of the separate IntegerFloorPosition/SplitPartOf pair, which are removed; HasPartMarker/StripPartMarker keep their own tests but now share split_edition.go's splitEditionMarkerRe instead of a second copy of the same regex. - The eligibility gate ListCoveredSplitEditionParts applies to a stored whole (not excluded, imported or monitored) now gates a Present row's eligibility to cover a catalogue-diff part too, via a new eligibleSplitEditionWhole helper cross-referenced from both sides of the SQL/Go boundary, with a test for each half of the gate (excluded, wanted-and-unmonitored, wanted-and-monitored). - Merged the wiki's two split-edition paragraphs into one and dropped the em dashes. Review feedback from vavallee. Signed-off-by: gch ahcg <gchahcg@proton.me>
Open
5 of 6 tasks
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.
Closes #3048
Closes #2208
#3048: split edition parts filled before #2915 stay Wanted
Root cause. Fill's re-queue loop (
ListBooksInSeriesinFill) marks every non imported series book wanted and monitored, and the scheduled sweep searches every monitored wanted book. Neither knows about split editions, so the "The Way of Kings, Part 1/2" rows a pre #2915 fill created go back on Wanted on every fill and get searched.Fix.
seriesmatch.SplitEditionPartOf: the fix(series): count split editions of an owned book as covered, not missing (#2524) #2915 two signal rule for stored rows. The position is fractional under the whole's integer position, and the title is the whole's title plus aPart Nmarker. A subtitle after the marker is ignored.BookRepo.ListCoveredSplitEditionParts: SQL self join onseries_books, with the rule applied in Go. A part counts as covered when it is not imported and its whole is imported or monitored, not excluded, and has the same owner (null safe), so one user's library never changes another user's sweep.wantedSearchQueueskips them in the sweep. Rows are left exactly as they are.POST /series/{id}/split-parts/unmonitor(admin) unmonitors them in one click. Nothing is deleted and imported books are never touched.GET /seriesand/series/{id}carrysplitEditionPartBookIds, and the series card badges those rows, leaves them out of the missing count, and shows Unmonitor N split parts when any are still monitored.Coordination with #2915. #2915 is still open (changes requested), so this PR doesn't reuse its helpers. The rule lives in a new file,
internal/seriesmatch/split_edition.go, with distinct names (SplitEditionPartOf, a privatesplitEditionMarkerRe/fractionalFloor). It doesn't touchmatch.go,importer/volume.go,buildHardcoverDiffor the diff response type. Both PRs can merge in either order with no textual or compile conflict. Once both are in,SplitEditionPartOfcan be collapsed onto #2915'sIntegerFloorPosition+SplitPartOfin a small follow up. There is one deliberate difference: #2915 treats any Present row as the whole. Here the whole has to be imported or monitored, because a wanted, unmonitored whole means nothing is being sought and the parts may be what the user wants.For whichever of #2915 and this PR lands second:
splitEditionWholeto the same status gate: the whole must be imported or monitored, and not excluded. Otherwise the diff and Fill/sweep disagree about the same rows.seriesmatch/split_edition.go(splitEditionMarkerRe) and fix(series): count split editions of an owned book as covered, not missing (#2524) #2915'spartMarkerReinmatch.goare the same pattern. CollapseSplitEditionPartOfontoIntegerFloorPosition+SplitPartOf.docs/Hardcover-Series-Wiki.md: both PRs add a split edition paragraph (fix(series): count split editions of an owned book as covered, not missing (#2524) #2915 after the box set rule, this one in Missing-Book Fill). Merge them into one paragraph covering the diff's Covered section and the Fill/sweep skip.#2208: metadata profile filters and series fill
Already fixed, part 1 (retroactive). #2247 (
7917b7ec, 2026-09-04, "feat(author): add safe catalogue reconciliation (#2208)") added More → Reconcile catalogue…. It applies every profile filter to stored rows, with a preview and the provider lookups that needs. This PR doesn't duplicate it. The docs now point to it from the filter description.Root cause, part 2.
ensureHardcoverCatalogBooknever consulted a metadata profile, and Fill's re-queue loop re-monitored stored rows the profile rejects (which also undid any hand unmonitoring).Fix.
SeriesHandler.WithMetadataProfiles, wired inmain.go.catalogBookProfileFilter. That covers SkipPartBooks, SkipMissingDate, MinEditionCount (unknown passes), the language allow list (a rejection is rechecked against the provider's edition evidence, as the sync does; a blank language passes whatever the unknown language setting says, because Hardcover series entries carry none and it is resolved later; a failed evidence lookup also passes), and MinPages/SkipMissingISBN via an edition lookup made only when one of them is on (a failed lookup enforces nothing). A brand new author is screened before the author row is created. Books already in the library are linked regardless, matching the sync's "existing books are maintained" rule.skippedByProfile. There's no stored signal for "added by hand", and a monitored row is being sought by the sweep anyway.skippedByProfileandskippedSplitParts, and the series card says what was skipped.Fail before evidence
Run on
origin/mainsource with the new tests applied. Forinternal/api, a test only shim gave the two new entry points (WithMetadataProfiles,UnmonitorSplitEditionParts) no op bodies so the tests compile against main's behaviour:Review follow up (
1c0bf1c0), run against the previous branch head:TestSplitEditionPartOf,TestListCoveredSplitEditionPartsand the SeriesPage vitest case cover new code that doesn't exist on main.Checks
gofmt -l .,go vet ./...golangci-lintv2.11.4 on touched packages: 0 issuesgo test -p 2oninternal/api,internal/db,internal/scheduler,internal/seriesmatch,internal/models,cmd/binderycd web && npm ci && npm run lint && npm run typecheck && npx vitest run && npm run build(lint shows only the existing warnings)docs/Hardcover-Series-Wiki.md,docs/User-Guide-Wiki.md,docs/API.mdchangelog.d/3048-split-edition-parts.md,changelog.d/2208-series-fill-profile-filters.md🤖 Generated with Claude Code
https://claude.ai/code/session_016fJcCVbNnKsmj2MAAMwWj9