Repository navigation
Series: one series per spelling, numbers from titles, paged and searchable Series page - #123
Merged
Merged
Conversation
…hable Series page
Series names that differ only in case, accents, punctuation or spacing are
one series everywhere: the aggregate (named by its matched books' spelling),
every series filter (admin list, player /books and /series/books), the series
ordering and the next book. A book with a series and no position takes the one
its title gives ("He Who Fights with Monsters 4: ..."); books indexed before
get it once at start.
The admin Series page pages its cards (numbered, in the URL), finds a series by
name or author, loads each card's books by its own series filter, and Back
returns to the same page, search and scroll position.
A series swap takes another spelling of a listed series for it (server and the console's draft, one sameSeries helper). The title-position pass runs in the background and finds books whose snapshot or path title numbers them; titles in decomposed form read too. Spellings skip the more_series lists where no caller uses them, and the next book reads them only for numbered series.
This was referenced Oct 12, 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.
Fixes the Library > Series page reported on 2026-10-12. "He Who Fights with Monsters" showed as three cards ("WIth", "With" and "with"), and the matched card listed as missing books that sat on the other two. The page also lacked numbered paging and search, and Back returned to the top of the first batch.
Docs: KodeStar/audiosilo-docs#123.
What step 1 found
data/series/he-who-fights-with-monsters.jsonon main is one series with 13 works at positions 1-13, no duplicates. The only other series with that key is the German translation (translation_of), which the series rules already leave out.catalog.Seriesgrouped by the exact series string.seriesFilter,seriesOrderKeys,numberedSeriesMembersand the console'sgroupSeriesPageswere all exact too.series_index0 and no ASIN, and their titles carry the number ("He Who Fights with Monsters 4: A LitRPG Adventure ..."). Even on one card they couldn't be placed.match_runs2) found the right work for every one of them at score 91. Books 2-5, 7, 8 and 10 were held for review because the runner-up, an adjacent volume, scored 86: under the 10-point lead rule. The review items were never applied. Sopkg/match/matchrundidn't fail; metaserve separates adjacent volumes by only 5 points even with the number in the title (follow-up for audiosilo-meta'sworks/matchscoring)./libraries/{id}/series,/series/booksand/books?series=share the same catalog code, so the server fix covers it. audiosilo-frontend never groups series client-side, and its series page already falls back to a loose key (inSeries->looseKey), so no frontend PR is needed.The fix
One series, any spelling (server).
seriesKey(match.SeriesKey, the key the rails already use: case, accents, punctuation and spacing aside; a name with no letter or number is its own key) groups everywhere:catalog.Seriesmerges counts, positions, lengths and authors. The name is the spelling the matched books use most, else the one most books use, ties alphabetical.Catalog.spellingsreads the index's spellings (the distinct(library_id, series)ofidx_books_seriesin order, plus more_series names when memberships are on). These feed IN lists, an OR'd FTS phrase prefilter, literal order keys, the next-book query andpositionIn.SeriesListandnormalizeMoreSerieskeep a series once however a list spells it again.sameSeries).Cost. About 20 ms over 50,000 books across all libraries, 9 ms in one.
/series/booksreads spellings once per batch.Wire. The JSON is unchanged (CROSS-REPO §15). Shipped players just see fewer, fuller series. Their
/books?series=<name>(no memberships) now returns every spelling's books, which is what they need for a merged entry.A position from the title.
bookLayers.scannedFieldsgives a book with a series and no position the number its title gives (metadata.PositionInTitle). It's deliberately narrow:It's in the resolve step, not the console, so the players and
/nextbenefit too. Books indexed earlier get it fromCatalog.PlaceByTitles, which the launcher runs once per database, in the background (server_statetitle_positions). On the real data it placed 25 books, all correct. A first draft read "Dork Diaries 1-12" as #1; that's now a golden negative case.Series page (admin-ui).
Pagerinsrc/components/andpagerItemsinsrc/lib/pager.ts, 24 cards a page.SearchBox, now shared insrc/components/.pageandqare in the URL. A library switch resets the page.scrollRestoration: trueon the router, so Back/Forward restore scroll and a new visit opens at the top.MembersCarddid), so a jump to page 9 asks for page 9's series only.groupSeriesPagesand the series-sorted walk are gone.Verified in a real browser
Run against a scratch copy of
audiosilo-server/data(two books given a "WIth" override, to have three spellings), headless Chromium:?library=5&page=3with the same scroll position (scrollY 3244 and card top 509, before and after). A search also survived opening a book and Back./libraries/5/seriesreturns one entry with positions 1-13./series/booksreturns all 13 books for "WIth" and for lower-case./books?series=without memberships returns all 13 too./nextfrom Demo mode #2 ("With") gives Integration #3 ("WIth").Not driven: the web player's own Series screen. The API it reads was checked instead.
Gates
go build ./... && go vet ./... && go test -race ./... && golangci-lint runall pass.scripts/build-admin.shpasses, 679 tests.internal/backupTestStartRunsAtOncefailed once under machine load and passed 3/3 on its own; this change doesn't touch backups./simplifyand/code-review xhigh --fixboth ran. Fixes applied include the swap-by-spelling regression, the title pass missing match-retitled books, startup blocking, decomposed (NFD) titles, and wasted more_series scans.Follow-ups, not in this PR
series_keycolumn (migration + backfill) would replace the per-request spellings read with a seek. Worth it if more series paths come.works/match: adjacent volumes score within 5 points even with the volume number in the title, so whole numbered series land in review.