The Python surface gained enough this week that three different builds
were installed on two machines all calling themselves 0.1.0: moria had
read_colophon through merge_colophon, mirkwood had a partial from the
middle of the afternoon, and PyPI had neither. A version that does not
move is a version nobody can depend on, which is how book-pipeline ended
up running a wheel scp'd into place by hand.
New since 0.1.0: colophon --shelf and catena.shelve, which file a book's
printed Library of Congress headings onto a closed list; catena
.read_colophon; catena.fetch_identifier, the registers in process; and
catena.colophon_prompt / merge_colophon, the question about what the
pages did not settle and the reply folded back in.
A catalogue's worst records are the ones whose file says nothing true about
itself: a PDF titled `Untitled` by an author called `Oxford`, which is a
publisher, from a filename that was never anything but a filename. What
those books do have is pages. The title page carries the title as the
publisher set it; the copyright page carries the imprint, the year, the
ISBN, and in most English books since the 1970s the cataloguing block, which
is a catalogue record a librarian already made, subject headings and all.
So this reads the pages. Every field names the page it came from, and a book
that printed nothing comes back empty with its fields in `unsettled` rather
than filled with something plausible — an extraction that starts at chapter
one has no front matter in it, and saying so is the answer.
Two pages look like a title page and are not, and both are how a catalogue
comes to name the wrong book. A series advertisement lists other titles in
the shape a title page uses, over as many as four pages with only the first
announcing itself. A translation's cataloguing block prints the original
title in brackets above the real one. Both are found and refused.
Three things the pages give that no file does: the subject headings a
librarian assigned, an ISBN that exists only in print — which turns a book
with no identifier into one `bibfetch` can look up — and a title in the case
the publisher meant, because a half title prints unbroken what the title
page breaks across two lines and sets in capitals.
`--prompt` and `--merge` are citefind's: a question about exactly the fields
the pages left unsettled, composed here and answered wherever the caller
keeps a model, with the advertising taken out of what the model is shown.
A field a model answered is marked `model`, so a record always says which of
it was read and which was inferred.
Measured against 600 books of the home corpus: the cataloguing block
answered for 21% of them and agreed with the catalogue 89% of the time, most
of the residue being the catalogue's error rather than this one's. Title
pages answered for another 41%. The remaining 38% print nothing readable,
and are what the prompt is for.
The harness compared these tools against the code they replaced — Python
imported from book-pipeline, podcast-pipeline and knowledge-mcp, and
JavaScript copied out of the podcast media server and indexer, each pinned to
a commit. All of it has since been deleted, so the live half cannot run and
the golden half pins answers against a source nobody can consult.
What was worth keeping was never the comparison. `KNOWN.md` argued, at
length, why a dozen of these tools deliberately do something a reader would
not expect: why pdfgutter measures the crop box throughout, why avplan finds
the encoder rather than reading one out of the environment, why mdscrub will
not manufacture a page boundary. Those arguments are about this code and
stand on their own, so they are now `docs/decisions.md`, rewritten to say
what each tool does and why rather than what it does differently.
Binding coverage is unaffected: the bindings carry 24 tests of their own, a
node smoke test against the built package, and a typecheck.
book-pipeline had its own copy of bibclean's author recovery. Bound on all
four surfaces so it can stop.
Checked against that Python over all 5,385 books in the library: 5,375
identical. On the other ten the Python had taken a translator, an illustrator
or the publisher off a copyright line — Sally-Ann Spencer for *The Dwarves*,
Thomas Nelson for a table of contents, C. S. Lewis for a book about Tolkien —
and bibclean either finds the real author in the Library of Congress block or
says nothing. Every one of the ten was read by hand.
Cuts a reference list into entries — at the note numbers where there are any,
at the layout where there are not — and reads each as far as its punctuation
allows. Fields that would not parse are named in `unsettled` rather than
guessed at, and `--prompt` asks a model about exactly those and no others.
Over 202 real reference sections from the corpus: 8,566 references, 95% with
a title, 82% with a year, 46% settling every field with no model involved.
A title is refused where the entry was never divided, so no record reports
its own text back as the work it cites.
`ibid.` is flagged and left alone — it points at a work, and the entry does
not say which. A rule of dashes is filled in, because the style defines it as
the author above.
chunkmd gains `note_starts` and `cites_something`: recognising a page of
notes and splitting one are the same knowledge, and two copies of that
pattern would drift.