feat: enrich bare imports + remember the unresolvable#6
Merged
Conversation
Watch-imports arrive with no Hardcover id and the server never auto-enriches them, so a frequent sweep submits a REPLACE_MISSING refresh to seed them. New colophon/enrich.py + the `enrich` subcommand (dry-run unless --apply, precondition-gated like every other write). The sweep now has memory (new store.enrich_state table): a book that never seeds (no/odd ISBN, self-pub edition Hardcover lacks) is marked stuck after COLOPHON_ENRICH_STUCK_AFTER failed sweeps (default 6), dropped from the sweep so it stops being re-poked every cycle, and surfaced once in the maintain digest with a UI deep-link (COLOPHON_BOOKSTORE_URL, route /book/<id>) for the human to delete or keep. maintain marks a book reported only after a successful email on an --apply run. Replaces the memory-less external enrich loop that re-refreshed the same unmatchable books every 30 minutes indefinitely. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vidaks
added a commit
that referenced
this pull request
Jul 9, 2026
Watch-imports arrive with no Hardcover id and the server never auto-enriches them, so a frequent sweep submits a REPLACE_MISSING refresh to seed them. New colophon/enrich.py + the `enrich` subcommand (dry-run unless --apply, precondition-gated like every other write). The sweep now has memory (new store.enrich_state table): a book that never seeds (no/odd ISBN, self-pub edition Hardcover lacks) is marked stuck after COLOPHON_ENRICH_STUCK_AFTER failed sweeps (default 6), dropped from the sweep so it stops being re-poked every cycle, and surfaced once in the maintain digest with a UI deep-link (COLOPHON_BOOKSTORE_URL, route /book/<id>) for the human to delete or keep. maintain marks a book reported only after a successful email on an --apply run. Replaces the memory-less external enrich loop that re-refreshed the same unmatchable books every 30 minutes indefinitely.
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.
Problem
Bare watch-imports land with no Hardcover id and grimmory never auto-enriches them, so an external every-30-min sweep re-submitted a
REPLACE_MISSINGrefresh for every un-seeded book. Books that can never match (no/odd ISBN, self-pub/KDP editions Hardcover lacks) stayed un-seeded forever, so the sweep re-poked the same handful indefinitely — tens of metadata refreshes a day on days with zero new books, and no way for the operator to learn which books were hopeless.Change
Move enrichment into colophon and give it memory.
colophon/enrich.py+colophon enrich— read the un-seeded set, submit aREPLACE_MISSINGrefresh, precondition-gated like every other write (the prior bash loop wrote blind). Dry-run unless--apply.store.enrich_state— each sweep records observations; a book that never seeds is marked stuck afterCOLOPHON_ENRICH_STUCK_AFTERfailed sweeps (default 6 ≈ 3h at the 30-min cadence), dropped from the sweep (the churn stops), and surfaced once in themaintaindigest. Seeded/deleted books are pruned.COLOPHON_BOOKSTORE_URL, route/book/<id>, Authelia-gated). No destructive link in email — deletion is the operator's click-through to the UI button.maintainmarks a book reported only after a successful email on an--applyrun; silence thereafter = keep.Safety
moveFilesToLibraryPattern=false+saveToOriginalFile=false) now guards the enrich refresh.Test plan
tests/test_enrich.py(14 cases): counting, stuck threshold, pruning, report-once, dry-run/apply refresh, precondition-abort, URL build, digest render. Stdlibunittest, network-free.compileallclean.🤖 Generated with Claude Code