fix(pubs): carry open-access metadata through the discovery review queue - #26
Merged
Merged
Conversation
A paper promoted from the OpenAlex discovery queue landed on /references with no "Open access" badge and no citation count, until the nightly by-DOI enrichment job happened to re-fetch it. The search response already carries `open_access.oa_status` and `cited_by_count` — the wire type even parsed them — but `Candidate` dropped both, `pubs.publication_candidate` had nowhere to put them, and `promote_candidate`'s INSERT omitted them. Carry them end to end (discovery job and the public "suggest a paper" form), and gap-fill rather than overwrite when promotion reuses an existing publication. Two related defects on the same path: - Publications with an OpenAlex id but no DOI were unreachable by enrichment — the work-list is `WHERE doi IS NOT NULL`, and a candidate is promoted on its OpenAlex id alone. Adds `work_by_id` and a second pass over those rows. - OpenAlex returns `doi` as a resolver URL, stored verbatim. That rendered the reference list's link as https://doi.org/https://doi.org/... and made `exists_by_doi` miss, so a paper already in the catalog could be queued a second time from the public form. Ingest now normalizes to bare form and mig 0073 backfills what is stored (30 publications, 5,934 candidates in dev). `upsert_candidate` takes a `NewCandidate` struct — the positional list was at seven arguments and this would have made nine. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
A paper promoted from the OpenAlex discovery queue lands on
/referenceswith no Open access badge and no citation count, until the nightly by-DOI enrichment job happens to re-fetch it. In dev the un-badged rows are exactly the recently-promoted ones.Root cause
The search response already carries
open_access.oa_statusandcited_by_count— the wireWorktype even parsed them — butCandidatedropped both,pubs.publication_candidatehad nowhere to put them, andpromote_candidate's INSERT omitted them. So a promoted publication starts withopen_access_status = NULL, which the list template maps to "no badge".Now carried end to end, from both the discovery job and the public "suggest a paper" form. When promotion reuses an existing publication it gap-fills only — a row the curators already own is never overwritten.
Two related defects on the same path
Publications with an OpenAlex id but no DOI were unreachable by enrichment. The work-list is
WHERE doi IS NOT NULL, but a candidate is promoted on its OpenAlex id alone, so those rows keep NULL citations/OA forever. Addswork_by_idand a second enrichment pass. Confirmed against live OpenAlex on the dev row that hit this (W7111817982: no DOI,oa_status: green).DOIs from discovery were stored as resolver URLs. OpenAlex returns
https://doi.org/10.xand it was stored verbatim, so the reference list renderedhref="https://doi.org/https://doi.org/10.x"(broken link), andexists_by_doicouldn't match the bare DOI the public form normalizes — meaning a paper already in the catalog could be queued a second time. Ingest now normalizes;normalize_doimoves todu-externaland is shared with the submit form.Migration 0073
Adds
cited_by_count/open_access_statustopubs.publication_candidateand backfills URL-form DOIs to bare form in both tables.publication.doiis UNIQUE, so the publication update skips any row whose bare form is already taken by another publication — a pre-existing duplicate pair survives un-normalized instead of aborting the migration. Dev and cutover both had zero such collisions; worth re-checking on prod after deploy.Applied to dev: 30 publications and 5,934 candidates normalized, 0 URL-form rows left.
Notes
upsert_candidatenow takes aNewCandidatestruct — the positional list was at seven arguments and this would have made nine.publication-updaterun to backfill (requiresOPENALEX_MAILTO); new promotions carry the badge at accept time.Test
cargo test --workspaceagainst a fresh empty database: 54 binaries, 239 tests, 0 failures.cargo clippy --workspace -- -D warningsclean. New coverage: candidate keeps OA/citations through promotion (live-DB test), DOI normalization, and the search-payload parse.🤖 Generated with Claude Code