Skip to content

Ground book citations against Open Library / Internet Archive (read path, PRD-0009)#147

Draft
tieguy wants to merge 5 commits into
mainfrom
claude/openlibrary-read
Draft

Ground book citations against Open Library / Internet Archive (read path, PRD-0009)#147
tieguy wants to merge 5 commits into
mainfrom
claude/openlibrary-read

Conversation

@tieguy

@tieguy tieguy commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Book citations — a {{cite book}} with an ISBN but no url= — currently get
no verdict and no affordance: the verifier records them as skipped { NonUrlSource } because there is nothing to fetch. This adds a read-only path
that turns a book identifier into a grounded citation verdict:

  • Resolve the ISBN/OCLC/LCCN/OLID (pulled structurally from the cite
    template's data-mw) against Open Library's catalog — side-effect-free, no
    import-on-miss, no write endpoints touched.
  • Ground the claim in an Internet Archive full-text search-inside
    snippet when an exact-edition scan is available, feeding that snippet into the
    existing verification pipeline and anchoring the finding to a page-level deep
    link.
  • Report honest outcomes: a real not_supported when the text is searched and
    the claim isn't found, distinct from SourceUnavailable when no scan exists.

Everything here is read-only. The enrichment write lane (proposing edits
back to Open Library) is deliberately out of scope and lands separately as a
gated follow-up — this PR is independently mergeable without it.

Design: ADR-0024 (Open Library / Internet Archive read contract), implementing
PRD-0009 Layers 1–2. scripts/openlibrary-contract-smoke.sh is a manual
live-network smoke for the read endpoints.

Provenance / review notes

  • Revived from the orphaned claude/openlibrary-resolve branch (~90 commits
    behind); rebased onto current main.
  • The ADR is renumbered 0018 → 0024 to avoid a collision — 0018 is claimed
    in-flight by PR Docs: MCP citation write surface — agent proposes, human confirms (add path blocked on PRD-0012/ADR-0003 insertion) #106 (the citation write-surface / token seam), which is a
    different ADR. Main-side references to that 0018 are left untouched.
  • Rebase reconciled real drift where main's re-verify path (PRD-0014) and this
    book lane both extended shared structs/signatures in sp42-parsoid,
    sp42-citation, and sp42-mcp (both the bare-URL-repair and book-source maps
    survive; tally_stats threads book_resolutions).
  • Verified locally: cargo build/test/clippy --workspace green (the Tauri
    bundle step in ci-all can't run in this environment).

Draft — for review, not merge-ready.

claude and others added 5 commits July 11, 2026 22:35
…ce 1)

Draft ADR-0018, the Open Library / Internet Archive read contract spawned
by PRD-0009 (Q6a): identifier-gated resolution, a strictly side-effect-free
Books API catalog lookup (never the import-on-miss /isbn/{isbn}.json),
Read API exact-vs-similar scan availability, and the search-inside
grounding-source rules including the scoped ShortBody bypass.

Implement the first read-only slice:

- sp42-platform: BookIdentifier (ISBN checksum-validated, OCLC, LCCN
  LC-normalized, OLID canonicalized with author ids rejected) and
  BookSource; BlockRef carries book_sources alongside cited sources.
- sp42-parsoid: cite-template data-mw extraction now also reads
  isbn/oclc/lccn/ol params (and the cited page), independent of the
  url= gate, so a URL-less {{cite book}} finally yields something.
- sp42-citation extract: a url-less ref with a validated identifier is
  skipped as BookSource (with its identifiers) instead of blending into
  NonUrlSource; the page report prints those identifiers.
- sp42-citation openlibrary: pure build/parse pairs for the Books API
  catalog lookup and the Read API scan availability, partitioned so only
  exact-match scans can ever feed grounding.

Wiring resolution into the verify path and report is the next slice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012u5MVp3vAN44KhsVg3vroY
The page orchestrator now resolves every skipped book ref through the
side-effect-free Open Library lane (ADR-0018) and the report shows what
the catalog said, so a book citation prints a resolved record instead of
a bare identifier.

- sp42-citation openlibrary: resolve_book_source executor — tries a
  ref's identifiers in template order against the Books API, then checks
  Read API scan availability on the first hit. A clean miss is NotFound
  (never a create), a transport failure is LookupFailed (existence
  unknown), and an availability failure degrades to scan-unknown without
  losing the catalog hit. A recording-client test asserts the whole lane
  addresses only /api/books and /api/volumes/brief, never the
  import-on-miss /isbn/{isbn}.json path.
- verify_page: a bounded (<=3, REST politeness) resolution pass over the
  skipped refs' book sources; failures stay inside the books lane and
  never fail the page. Report gains book_resolutions plus
  books_resolved/books_not_found/book_lookups_failed stats, all
  serde-default so older reports still deserialize.
- Renderer: a Books section (resolved record with title/authors/record
  URL and an exact/similar_only/none/unknown scan label; distinct
  not_found vs lookup_failed lines) and a books lead tally.
- SkippedRef now carries its BookSource structures (identifiers + cited
  page) instead of a flattened identifier list, so resolution keeps
  per-template identifier order and the cited page for Layer 2.

Search-inside grounding (Layer 2) is the next slice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012u5MVp3vAN44KhsVg3vroY
Layer 2 of the book lane (ADR-0018 Decision 4): a resolved book citation
with an exact-edition scan now gets a real verdict instead of a skip.

- sp42-citation search_inside: the Internet Archive grounding source —
  item-metadata read for the designated search server (texts-only gate),
  BookReader full-text search build/parse (verbatim OCR snippets with
  highlight markers stripped, page numbers kept), conservative claim→query
  term selection, page-anchored deep links, and prepare_book_grounding
  mapping every degraded outcome onto the ADR-0007 split: no usable body
  (not a text item / no index) -> SourceUnavailable; an indexed scan
  searched with zero snippets -> not_supported, never SourceUnavailable.
  Cited page first, whole-book fallback, per PRD-0009 Q5.
- verify: FetchedSource gains a book_snippet provenance flag whose only
  effect is bypassing the generic ShortBody floor at the usability gate —
  arbitrary short web pages still short-circuit, an empty snippet stays
  unusable (covered by a three-way test). CitationFinding gains optional
  BookScanProvenance (ocaid, scanned vs cited page, refined note) and two
  no-model book outcomes for the unavailable/searched-empty cases.
- extract: a url-less ref with validated identifiers is now a BookUseSite
  (same sentence attach as URL refs, shared ordinal sequence) instead of
  an unconditional skip; only identifier-less refs skip at extract time.
- verify_page: the book pass resolves each site against Open Library,
  grounds resolved books through the snippet body and the model panel
  (resolved record as context-only metadata sidecar), degrades similar-
  only/no-scan books to an honest SourceUnavailable pointing at the OL
  record, and re-skips catalog misses with the refined BookSource reason.
  The scanned page the passage actually located on is recorded so
  pagination mismatches surface instead of causing false negatives.
- Renderer: finding lines show scan/scanned_page/cited_page/note; the
  Books section and stats are unchanged from slice 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012u5MVp3vAN44KhsVg3vroY
Manual, network-touching, never CI (ADR-0009 keeps tests on fixtures).
Walks the exact read chain verify-page uses — Books API catalog lookup,
Read API scan availability, archive.org item metadata, BookReader
search-inside — with read-only GETs and asserts precisely the response
fields the PRD-0009 parsers read. A pass means production still matches
the fixtures; a failure names the drifted contract and keeps the real
payload for fixture refresh. By construction it never touches the
import-on-miss /isbn/{isbn}.json path or any write endpoint.

Header notes that Open Library 403s datacenter IPs (observed from this
environment), so the smoke runs from a developer connection — the same
caveat applies to any future cloud-hosted SP42 deployment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012u5MVp3vAN44KhsVg3vroY
Rebased the PRD-0009 read/grounding slices onto current origin/main (~90
commits of drift). Renumber the read-contract ADR off contested 0018
(claimed by PR #106) to 0024. Reconcile struct/signature drift where main's
re-verify path (PRD-0014) and the book lane both extended shared types:
keep both parsoid maps (ref_bare + RefSources), thread book_resolutions
through tally_stats, and stamp book_sources/is_bare_url_ref/book_scan on the
merged struct literals.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants