Files
bookorbit/server/test/e2e/metadata-lock
neon 1199e3cdd4 fix(metadata): stop one book record being assembled from several books
Field rules resolve each field from whichever provider ranks first for it, and nothing ever
compared candidates to one another. A provider that matched the wrong book still won every field
it led on, so a single record could carry a title from one book, a cover from a second and a
subtitle from a third. The stock defaults make that the ordinary case rather than an unlucky one,
since cover leads with Amazon while title and subtitle lead with Goodreads.

Relevance scoring is what let those wrong matches in. A candidate survived on any score above
zero, and token overlap counted stopwords, so "The Girl on the Train" scored against a query for
"The Hobbit" on the strength of a shared "the". Substring matching ignored word boundaries as
well, which is how "Ubik" matched "Rubik Cube Solutions". Drop stopwords from the query side,
require a majority of the words that remain, match whole words only, and give the surviving floor
a name.

Then hold every candidate to an anchor before field rules ever see it. The anchor is the edition
confirmed by the book's own ISBN when there is one, otherwise the candidate the query supports
most strongly, with the title rule breaking ties because that is where the reader declares which
provider decides identity. Agreement admits subtitle extensions, reordered words and translated
editions, and rejects on a contradicting author, which is the only signal that separates a book
from a companion volume that extends its title. Reject solely on positive evidence: a candidate
with no title, or with no author to compare against, keeps the benefit of the doubt, and a lone
provider is never second-guessed. Rejected candidates no longer contribute their provider ids
either, which would otherwise pin the wrong book for every later refresh.

Normalizing titles to [a-z0-9] emptied every title written in Japanese, Chinese, Russian or
Greek. That scored two providers reporting an identical title as a disagreement, which under the
new anchor would drop all but one of them in those libraries, and it had already denied the
relevance gate any way to score them at all. Decompose instead, strip nonspacing marks so Soseki
matches Sōseki, and keep letters of any script.

Two sets of fixtures described different books per provider while testing something else
entirely, field-rule precedence and metadata locking, and now describe one book so that they
still test what they were written for.

Closes #1023
2026-08-18 19:30:13 +00:00
..