Repository navigation
fix: keep arXiv preprints apart from unlinked published records - #61
Merged
Merged
Conversation
The disk survivor check rejected a preprint/published pair only when both records carried different arXiv ids. The merge strips eprint fields from every published record, so that guard never fired, and the pair fell through to a 0.55 title threshold meant for retitled preprints. A forced refresh therefore let the published SugarCrepe++ record (10.52202/079017-0571, arXiv 2406.11171) replace the VISLA Benchmark preprint (arXiv 2404.16365) at a title score of 0.713, deleting a separate paper from Milios, Oore and Sajjad. Enrichment accepted the same pair through its composite gate, because a Crossref candidate carries no arXiv id either. An arXiv id on one side only now counts as unknown identity. Without equal ids, the disk preprint-pair, composite and relaxed-preprint paths need the near-exact file title threshold, and the enrichment composite gate stays closed.
Collaborator
Author
|
Refresh replay on
|
gabrielspadon
added a commit
that referenced
this pull request
Oct 25, 2026
…62) ## Summary Two pairs of different papers by the same team were scored as one work, both on disk and in enrichment, so a refresh with slightly different metadata could delete one of each pair: - Bodorik: `Liu2021-BlockchainPrivacy` vs `Liu2022-AutomatingSmart` - Matwin: `Ferreira2022-SemiSupervised` vs `Ferreira2022-SemiSupervisedGeometric` ## Root cause `compute_dedup_score` gives 0.25 for author overlap and 0.10 for the same year, or 0.05 for one year apart (`citeforge/text_utils.py:654-664`). A co-authored pair from one year therefore starts at 0.30 to 0.35 of the 0.60 threshold with no title evidence at all. - Liu: title 0.654 × 0.40 = 0.262, plus authors 0.25, year 0.05 and venue 0.08, gives 0.641. - Ferreira: 0.262 + 0.25 + 0.10 gives 0.612. The composite paths only required a title score of 0.55 to 0.6 before the composite could decide. In enrichment the floor was 0.35. ## Fix `_titles_agree` (`citeforge/identity.py:106`) accepts titles that score at least `SIM_TITLE_SIM_MIN` (0.8), or where one normalized title occurs whole inside the other, because Scholar truncates long titles from both ends. When neither record carries an arXiv id, the following now require it: - the disk preprint-pair, same-key, composite and relaxed-preprint paths (`:250-255`); - the enrichment composite gate (`:208`). Equal arXiv ids, the one-sided arXiv rule from #61, and DOI, DOI-version, external-id, high-title and truncated-title matches are unchanged. ## Effect on the committed corpus Every same-directory pair evaluated under `DISK_SURVIVOR` before and after: three pairs flip from "same work" to "distinct". - Bodorik Liu 2021/2022 and Matwin Ferreira 2022. These are distinct papers and are now kept. - Orji, `D2025-DevelopingInteractive.bib` (medRxiv `10.1101/2025.10.07.25337102`) vs `Etienne2025-DevelopingInteractive.bib` (JMIR Human Factors `10.2196/86283`). It is the same author list, retitled, at a title score of 0.773. Crossref has no relation between the two DOIs, so the preprint is now kept instead of removed as superseded. Reilly's Porcino2022 pair is unchanged: both files are kept. ## Verification - `pytest -m 'not live' --cov=citeforge --cov=main --cov-fail-under=68` on Python 3.12, macOS: 2083 passed, 2 skipped (the documented cutover contracts), 7 deselected, coverage 84.14%. `ruff check` and `mypy` are clean. - `test_shared_authors_and_year_never_merge_different_titles` uses the committed Liu and Ferreira records. On `main` both cases fail, with one file left on disk. Both pass with the fix, and enrichment also rejects both pairs. - `TestStrongAuthorDedupGate::test_same_authors_moderate_title_sim_matches` still passes. Alhasani 2025 scores 0.737, and its Scholar title is a both-ends truncation of the published one. - Enrichment-context verdicts on every same-directory corpus pair: `main` accepts 11 pairs and this branch accepts 2. Besides Liu, Ferreira and Orji, `main` also accepted six pairs of different Neethirajan papers at title scores of 0.48 to 0.53, with a preprint/published split opening the gate. The 2 that remain are prefix truncations (`TRUNCATED_TITLE`). - Refresh replay on `main` plus this change: the real `run_all` over a copy of the committed corpus, with live Crossref, arXiv, OpenAlex and DOI enrichment of shared-DOI records (Scholar and Gemini not used), then `finalize_run`. 9 authors were forced, 0 DOI conflicts remained, and finalization completed with 3691 files and 1105 in a2i2. Against the committed corpus, 0 of 58 directories changed file count or publication set. Liu, Ferreira, Porcino, Orji and VISLA are all present.
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
The identity check treated the published SugarCrepe++ record (10.52202/079017-0571, arXiv 2406.11171) and the VISLA Benchmark preprint (10.48550/arxiv.2404.16365) as one work. They matched at a title score of 0.713. During the refresh replay this deleted VISLA from Milios, Oore, Sajjad and a2i2.
Root cause
_disk_identityrejected a preprint/published pair only when both records carried arXiv ids that differed (citeforge/identity.py, the preprint-pair branch).merge_utilsstripseprintandarchiveprefixfrom every record that has a published DOI, so a published record on disk never carries an arXiv id and the guard could not fire. The pair then fell through toSIM_PREPRINT_TITLE_THRESHOLD(0.55), which exists for retitled preprints._enrichment_identityhad the same gap in its composite gate: a Crossref candidate carries no arXiv id either, and VISLA vs SugarCrepe++ scored COMPOSITE True.Fix
If only one record carries an arXiv id, that now counts as unknown identity rather than agreement. Unless both records carry the same arXiv id, the disk preprint-pair, composite and relaxed-preprint paths require
SIM_FILE_DUPLICATE_THRESHOLD(0.95), and the enrichment composite gate stays closed. Identical-title twins, DOI matches, DOI versions, equal arXiv ids, external ids and truncated titles are unchanged.Effect on the committed corpus
I evaluated every same-directory pair under
DISK_SURVIVORbefore and after the change. Five pairs flip from "same work" to "distinct":Lowe2023-ZeroShot.bib(2023 workshop paper) vsLowe2024-EmpiricalStudy.bib(arXiv 2406.02465, TMLR 2026). These are distinct titles and are now kept.Porcino2022-DesignXR.bib(arXiv 2208.14842, abbreviated title) vsPorcino2022-DesignExtended.bib(10.1007/978-3-031-20212-4_9). This is likely the same paper, but neither an arXiv DOI nor a Crossref relation links them, so the preprint is kept rather than removed as superseded.Verification
pytest -m 'not live' --cov=citeforge --cov=main --cov-fail-under=68on Python 3.12, macOS: 2080 passed, 2 skipped (the documented cutover contracts intests/test_workflow_contracts.py), 7 deselected, coverage 84.13%.ruff check citeforge/ tests/ main.pyandmypy citeforge/ main.pyare clean.test_published_record_never_absorbs_a_distinct_arxiv_preprintuses the committed VISLA and SugarCrepe++ records. Both directions fail onmain: the incoming published record replaces VISLA, and an incoming VISLA is refused. Both pass with this change.test_enrichment_never_adopts_a_distinct_work_as_the_published_versionfails onmainwith COMPOSITE True and passes with this change.The refresh replay on
mainplus #60 and this change is reported in a comment below.