Repository navigation
Conversation
build_bib_entry took the first 4 characters of the Zotero date field as
the year. Zotero stores dates free-form, so "June 2025" became {June},
"April 2026" became {Apri}, and "5/20/2017" became {5/20}. 15 entries in
one project bib were affected.
Replace the slice with year_from_date(), which pulls the first 19xx/20xx
match out of the string and returns "" when there is none.
Claude-Session: https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
Authoritative description of the feature: completeness model, the Crossref/DataCite/DBLP/OpenAlex/arXiv resolution pipeline, the matching tiers, field mappings, refs.bib splice and Zotero write-back. Claude-Session: https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
New `zobs augment` subcommand (argparse front end in cli.py; bare `zobs` still runs the sync). It finds entries missing what an IEEE citation needs, resolves canonical metadata, writes it into refs.bib and — when the API key allows — pushes the same fields back to Zotero. - augment.py — completeness model, interactive/--select/--json selection, plan_changes (fill blanks, repair malformed, respect --overwrite), refs.bib splice with no-match markers, Zotero update_item + 412 retry - metadata.py — Metadata model, adapters for Crossref / DataCite / arXiv / DBLP / OpenAlex, identifier-first resolution then a token_sort_ratio + author + year + key-term match (the key-term gate rejects e.g. a VUDDY hit for a MOVERY query) - cache.py — keyed on-disk response cache, ~0.34s request spacing, swallows all network errors so one dead source never aborts a run - sync.py — build_bib_entry now emits volume/issue/pages/publisher/ place when present and formats preprints as arXiv; shared generate_bib() deps: rapidfuzz, questionary. Spec: specs/augment-spec.md. Claude-Session: https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
- default --sources is now dblp,crossref,datacite,openalex,arxiv so the title search asks DBLP before Crossref (better coverage for USENIX / NDSS / S&P; Crossref title search produced false hits on short titles) - rewrite the README section in plain prose: drop the em dashes, the one-row variable table, and the "clears the bar" phrasing; spell out the DOI-vs-title-search order Claude-Session: https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
- README + .env.example: ZOBS_CONTACT_EMAIL is your own email address, optional, for the Crossref polite pool - tighten the README augment section prose - scrub em dashes from specs/augment-spec.md Claude-Session: https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
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.
Summary
Adds
zobs augment, a subcommand that fills in incompleterefs.bibentriesfrom bibliographic APIs, and fixes a year-parsing bug in
build_bib_entry.zobswith no subcommand still runs the sync unchanged.zobs augmentFinds entries missing what an IEEE citation needs (venue, year, pages, arXiv
id…), resolves canonical metadata from Crossref → DataCite → DBLP → OpenAlex
→ arXiv (identifier first, then a
token_sort_ratio+ first-author + year +key-term match), fills
refs.bibin place, and pushes the same fields back toZotero via
update_itemwhen the API key has write access.questionarychecklist (all incomplete pre-checked),or
--select KEYS, or--all.--jsonemits the candidate list forscripts / agents;
--dry-runshows the diff and writes nothing.--overwriteto force); repairs obviouslymalformed values (
year = "June") unless--no-repair.% zobs: no confident match — still missing {…}comment above them.MOVERY:/V1SCAN -must appear in a candidate title)rejects the false matches a bare fuzzy ratio would accept.
references/.zobs-cache/; requests spaced ~0.34s;a dead source never aborts a run.
New modules:
cli.py,augment.py,metadata.py,cache.py.New deps:
rapidfuzz,questionary. Design:specs/augment-spec.md.Year parsing fix
build_bib_entrytookdate[:4]as the year. Zotero dates are free-form, so"June 2025"became{June},"5/20/2017"became{5/20}. Replaced withyear_from_date(), which pulls the first19xx/20xxfrom the string. Alsotightened
build_bib_entryto emitvolume/issue/pages/publisher/placewhen present (needed so augment's pushed fields survive a re-sync) andto format preprints as
arXiv preprint arXiv:<id>.Behaviour change
The next
zobs syncafter this lands will surfacevolume/pages/publisherfields that were already in Zotero but not previously written, plus alignment
shifts on those entries.
Test plan
uv run pytest— 39 pass (new:test_augment.py,test_metadata.py)uv run black --check .— cleanof DOI and title search; false matches rejected by the key-term gate; blog
posts correctly marked no-match. No writes to Zotero during testing.
https://claude.ai/code/session_01GmjZkdNscHJ5g7DfkSVZXn
Closes #7
Closes #9