ref-verify 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. ref_verify-1.3.0/PKG-INFO +499 -0
  2. ref_verify-1.3.0/README.md +488 -0
  3. {ref_verify-1.2.0 → ref_verify-1.3.0}/pyproject.toml +1 -1
  4. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/__init__.py +1 -1
  5. ref_verify-1.3.0/src/ref_verify/cache.py +90 -0
  6. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/claim_check.py +16 -0
  7. ref_verify-1.3.0/src/ref_verify/cli.py +474 -0
  8. ref_verify-1.3.0/src/ref_verify/crossref.py +210 -0
  9. ref_verify-1.3.0/src/ref_verify/doi_check.py +323 -0
  10. ref_verify-1.3.0/src/ref_verify/http.py +99 -0
  11. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/models.py +10 -1
  12. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/numeric_claim.py +49 -3
  13. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/openalex.py +16 -16
  14. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/pubmed.py +15 -26
  15. ref_verify-1.3.0/src/ref_verify/reference_parse.py +461 -0
  16. ref_verify-1.3.0/src/ref_verify/reference_resolve.py +433 -0
  17. ref_verify-1.3.0/src/ref_verify/report.py +318 -0
  18. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/semantic_scholar.py +26 -37
  19. ref_verify-1.3.0/src/ref_verify.egg-info/PKG-INFO +499 -0
  20. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify.egg-info/SOURCES.txt +10 -0
  21. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_abstract_sources.py +7 -6
  22. ref_verify-1.3.0/tests/test_benchmark_aggregate.py +76 -0
  23. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_cli.py +223 -1
  24. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_crossref.py +39 -0
  25. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_doi_check.py +87 -1
  26. ref_verify-1.3.0/tests/test_http_cache.py +388 -0
  27. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_numeric_claim.py +40 -0
  28. ref_verify-1.3.0/tests/test_reference_parse.py +210 -0
  29. ref_verify-1.3.0/tests/test_reference_resolve.py +815 -0
  30. ref_verify-1.3.0/tests/test_report.py +324 -0
  31. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_skill_docs.py +65 -6
  32. ref_verify-1.2.0/PKG-INFO +0 -313
  33. ref_verify-1.2.0/README.md +0 -302
  34. ref_verify-1.2.0/src/ref_verify/cli.py +0 -228
  35. ref_verify-1.2.0/src/ref_verify/crossref.py +0 -89
  36. ref_verify-1.2.0/src/ref_verify/doi_check.py +0 -191
  37. ref_verify-1.2.0/src/ref_verify.egg-info/PKG-INFO +0 -313
  38. {ref_verify-1.2.0 → ref_verify-1.3.0}/LICENSE +0 -0
  39. {ref_verify-1.2.0 → ref_verify-1.3.0}/setup.cfg +0 -0
  40. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/abstract_lookup.py +0 -0
  41. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify/batch.py +0 -0
  42. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify.egg-info/dependency_links.txt +0 -0
  43. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify.egg-info/entry_points.txt +0 -0
  44. {ref_verify-1.2.0 → ref_verify-1.3.0}/src/ref_verify.egg-info/top_level.txt +0 -0
  45. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_batch.py +0 -0
  46. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_claim_check.py +0 -0
  47. {ref_verify-1.2.0 → ref_verify-1.3.0}/tests/test_package_smoke.py +0 -0
@@ -0,0 +1,499 @@
1
+ Metadata-Version: 2.4
2
+ Name: ref-verify
3
+ Version: 1.3.0
4
+ Summary: Executable DOI and claim verification helpers for academic citations
5
+ Author: Moonweave Research
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
12
+ <div align="center">
13
+
14
+ <img src="https://raw.githubusercontent.com/Moonweave-Research/ref-verify/main/.github/assets/ref-verify-mark-512.png" alt="ref-verify mark" width="96">
15
+
16
+ </div>
17
+
18
+ # ref-verify
19
+
20
+ [English](https://github.com/Moonweave-Research/ref-verify/blob/main/README.md) | [한국어](https://github.com/Moonweave-Research/ref-verify/blob/main/README.ko.md)
21
+
22
+ **Stop citing papers that do not say what you think they say.**
23
+
24
+ `ref-verify` is an agent skill for citation verification. It helps Claude Code,
25
+ Cursor, Codex, and other skill-aware agents check references before they land in
26
+ your draft.
27
+
28
+ Use it when you want an agent to find papers, verify a DOI, check whether a paper
29
+ supports a specific claim, or audit references before submission. No server setup is required.
30
+
31
+ ---
32
+
33
+ ## Scorecard
34
+
35
+ <picture>
36
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Moonweave-Research/ref-verify/main/.github/assets/scorecard-dark.svg">
37
+ <img src="https://raw.githubusercontent.com/Moonweave-Research/ref-verify/main/.github/assets/scorecard-light.svg" alt="Bar chart of check-bib verdicts on 86 held-out references: real 80% passed cleanly, fabricated 96% flagged, retracted 100% caught, 0 of 10 unindexed references rejected." width="830">
38
+ </picture>
39
+
40
+ Held-out set: 86 references written and committed before the tool was run on them, with no paper
41
+ shared with the development set.
42
+
43
+ | What was measured (held-out set) | Result | n | 95% CI |
44
+ |---|---|---|---|
45
+ | Real papers passed cleanly | **80%** | 40 | 65–90% |
46
+ | Real papers sent for a manual check (WARN) | 20% | 40 | 10–35% |
47
+ | Real papers wrongly rejected | 0% | 40 | 0–9% |
48
+ | Fabricated references flagged (WARN or REJECT) | **96%** | 26 | 81–99% |
49
+ | Retracted papers caught as `PAPER_RETRACTED` | **100%** | 10 | 72–100% |
50
+ | Legitimate references missing from CrossRef that were rejected | 0 of 10 | 10 | 0–28% |
51
+
52
+ - Fabricated, by type: invented DOI 5/5 · no DOI 5/5 · DOI swap 4/4 · wrong author/year 4/5 · publicly reported cases 7/7.
53
+ - 7 of the 8 real papers that did not pass are cited in the physics/chemistry style that omits the
54
+ article title, which leaves nothing to compare against CrossRef.
55
+ - Time for all 86 references: 79 s on a cold cache (1.1 s median per reference), 0.1 s cached.
56
+
57
+ Development set (142 references, used while fixing the tool in
58
+ [#27](https://github.com/Moonweave-Research/ref-verify/pull/27), so these are in-sample scores): real
59
+ 66/66 passed (94–100%), fabricated 43/43 flagged, retracted 16/16 caught, 1 of
60
+ 17 unindexed references rejected.
61
+
62
+ Measured 2026-10-08 with ref-verify 1.2.2 (commit `01c7a37`) against live CrossRef, checking each set with
63
+ `check-bib` as BibTeX, RIS, and plain-text lists. Not measured: whether a paper supports a claim
64
+ (beyond a small numeric fixture), non-English literature beyond a few Korean items, and full text.
65
+ Every miss is listed per item in the results files ([held-out](https://github.com/Moonweave-Research/ref-verify/blob/main/benchmarks/results/2026-10-08-01c7a37-holdout-v1.json),
66
+ [development](https://github.com/Moonweave-Research/ref-verify/blob/main/benchmarks/results/2026-10-08-01c7a37-v1.json)); dataset, method, and how to rerun:
67
+ [benchmarks/README.md](https://github.com/Moonweave-Research/ref-verify/blob/main/benchmarks/README.md).
68
+
69
+ ---
70
+
71
+ ## Install the skill
72
+
73
+ ```bash
74
+ # requires npx (comes with Node.js)
75
+ npx skills add Moonweave-Research/ref-verify -g \
76
+ --skill ref-verify \
77
+ --agent claude-code cursor codex \
78
+ -y
79
+ ```
80
+
81
+ Works with **Claude Code, Cursor, Codex**, and any agent that supports the
82
+ `npx skills` ecosystem.
83
+
84
+ After installation, use it like a normal agent skill. You do not start a server and you do not configure MCP for this workflow. No MCP server is required for this workflow.
85
+
86
+ The skill includes its own copy of the CLI engine, and the agent runs it from the skill folder, so nothing else needs to be installed. Python 3.10 or newer must be available as `python3`.
87
+
88
+ For explicit agent tool-calling rules, see [AGENT_USAGE.md](https://github.com/Moonweave-Research/ref-verify/blob/main/AGENT_USAGE.md).
89
+
90
+ ---
91
+
92
+ ## Use it
93
+
94
+ Ask naturally:
95
+
96
+ ```text
97
+ verify these citations before I submit: [DOI list]
98
+ does this paper actually support the claim "actuation strain above 100%"?
99
+ find 3 papers supporting the claim that X, and verify each citation
100
+ check doi 10.1126/science.287.5454.836 against this title and year
101
+ audit all my references before submission
102
+ ```
103
+
104
+ `ref-verify` stays quiet for general topic questions, prose editing, APA/IEEE
105
+ formatting, and citation style questions.
106
+
107
+ ---
108
+
109
+ ## Check a whole reference list
110
+
111
+ Find references in a paper or thesis that do not exist (for example ones a
112
+ chatbot made up), whose DOI points to a different paper, or that were
113
+ retracted, in one run.
114
+
115
+ **With the agent:** after installing the skill, ask "check every reference in
116
+ references.bib with ref-verify".
117
+
118
+ **From a terminal:**
119
+
120
+ 1. Put the list in a file.
121
+ - Zotero: right-click the collection → Export Collection → BibTeX →
122
+ `references.bib` (EndNote and Mendeley export BibTeX or RIS).
123
+ - A Word or other manuscript: copy the reference list into a plain-text
124
+ editor and save it as `references.txt`. `[1]` or `1.` numbering and
125
+ wrapped lines are fine. `.docx` and `.pdf` files are not read directly.
126
+ 2. Install (Python 3.10 or newer):
127
+
128
+ ```bash
129
+ pipx install ref-verify
130
+ ```
131
+
132
+ With `uv`, skip the install:
133
+ `uvx ref-verify check-bib references.bib`.
134
+
135
+ 3. Run:
136
+
137
+ ```bash
138
+ ref-verify check-bib references.bib
139
+ ```
140
+
141
+ A first run takes about a second per reference (a little over two minutes
142
+ for 150, with a `Checking references: 37/150` counter). Running the same
143
+ list again takes seconds thanks to the cache. Prefixing
144
+ `REF_VERIFY_MAILTO=you@university.edu` uses CrossRef's polite pool and is
145
+ about three times faster.
146
+
147
+ Add `--report check.html` for a file to send to an advisor or co-author;
148
+ it opens in a browser with the items that need a look at the top.
149
+
150
+ **Reading the result**
151
+
152
+ | Result | Meaning | What to do |
153
+ |---|---|---|
154
+ | `PASS` | Title, first author, and year match the CrossRef record for the DOI (or the record found by search) | Nothing |
155
+ | `WARN` | Found, but something differs; the line below says what (year, author, the title of the paper the DOI really points to) | Compare that one with the source |
156
+ | `REJECT` | The DOI exists nowhere, points to a different paper, or the paper is retracted | Fix or drop the citation |
157
+ | `UNVERIFIED` | Could not be confirmed automatically; theses, local conference abstracts, some books, and DOIs registered outside CrossRef (arXiv, KISTI) often land here. It does not mean the reference is wrong | Check it yourself |
158
+
159
+ A made-up reference without a DOI can only show as `UNVERIFIED`, not `REJECT`,
160
+ so look each `UNVERIFIED` item up once (for example in Google Scholar).
161
+
162
+ ---
163
+
164
+ ## Optional CLI engine
165
+
166
+ The skill is the agent workflow. The Python CLI is the skill-level execution engine that the installed skill can call from a terminal.
167
+
168
+ The Python package is CLI-only. It does not install `SKILL.md`; install the agent skill from GitHub with `npx skills add` as shown above.
169
+
170
+ This is a skill/plugin-level workflow, not an MCP server. The CLI covers the
171
+ checks that are currently safe to automate directly:
172
+
173
+ - CrossRef metadata check: `ref-verify verify-doi`
174
+ - DOI-bound abstract claim check: `ref-verify check-claim`
175
+ - Batch DOI-bound claim checks: `ref-verify check-file`
176
+ - literal text claims
177
+ - subject-matched percentage claims such as efficiency, response rate, or actuation strain
178
+ - simple unit/count claims such as cycles, patients, voltage, temperature, and concentration
179
+ - CrossRef first, then DOI-bound OpenAlex, Semantic Scholar, and PubMed fallback when CrossRef has no abstract
180
+ - Reference-list check (BibTeX, RIS, plain text, Markdown): `ref-verify check-bib`
181
+ - JSON output for agent-readable routing
182
+ - Non-zero exit codes for `WARN`, `REJECT`, and `UNVERIFIABLE` results
183
+
184
+ Statistical metrics such as p-values, AUC/AUROC, F1 score, hazard ratio, odds ratio, and confidence intervals still use the manual skill protocol. DOI landing-page checks still use the skill protocol. The CLI rejects a DOI that CrossRef records as retracted (via its retraction notice); retraction banners CrossRef does not know about, Unpaywall, arXiv, and two-source existence checks remain in the `SKILL.md` protocol.
185
+
186
+ The CLI has zero third-party Python runtime dependencies, but it is not an
187
+ offline verifier. Functional checks require outbound HTTPS access to public
188
+ academic APIs such as CrossRef, OpenAlex, Semantic Scholar, and PubMed.
189
+
190
+ ### Cache
191
+
192
+ The CLI keeps API responses on disk for 7 days, so re-running a check does not
193
+ query CrossRef and the abstract sources again. A DOI that returned HTTP 404 is
194
+ kept for 1 day only, so a newly registered DOI is re-checked soon. Rate limits
195
+ (429) and server errors (5xx) are retried up to 3 times with backoff, honouring
196
+ `Retry-After` up to 10 s, and are never cached.
197
+
198
+ - Location: `$REF_VERIFY_CACHE_DIR`, else `$XDG_CACHE_HOME/ref-verify`, else `~/.cache/ref-verify`.
199
+ - Lifetime: `REF_VERIFY_CACHE_TTL_DAYS` (default `7`).
200
+ - Disable: `--no-cache` on any command, or `REF_VERIFY_NO_CACHE=1`. Delete the directory to clear it.
201
+
202
+ To run the CLI yourself, install it from PyPI:
203
+
204
+ ```bash
205
+ uvx ref-verify --help # run without installing (uv)
206
+ pipx install ref-verify # or install the `ref-verify` command
207
+ ```
208
+
209
+ Or install it from a local checkout:
210
+
211
+ ```bash
212
+ git clone https://github.com/Moonweave-Research/ref-verify.git
213
+ cd ref-verify
214
+ python3 -m pip install -e .
215
+ ```
216
+
217
+ Check whether the CLI is available:
218
+
219
+ ```bash
220
+ ref-verify --help
221
+ ```
222
+
223
+ If you are working from an uninstalled source checkout, use the module
224
+ entrypoint:
225
+
226
+ ```bash
227
+ PYTHONPATH=src python3 -m ref_verify.cli --help
228
+ ```
229
+
230
+ Run a DOI metadata check:
231
+
232
+ ```bash
233
+ ref-verify verify-doi 10.1126/science.287.5454.836 \
234
+ --title "High-Speed Electrically Actuated Elastomers with Strain Greater Than 100%" \
235
+ --first-author Pelrine \
236
+ --year 2000 \
237
+ --json
238
+ ```
239
+
240
+ Run a DOI-bound abstract claim check:
241
+
242
+ ```bash
243
+ ref-verify check-claim 10.1126/science.287.5454.836 \
244
+ --claim "actuation strain above 100%" \
245
+ --json
246
+ ```
247
+
248
+ By default, `check-claim` uses CrossRef first. If CrossRef has no abstract, it tries DOI-bound OpenAlex, Semantic Scholar, and PubMed fallback sources. Use `--source crossref`, `--source openalex`, `--source semantic-scholar`, or `--source pubmed` for source-specific debugging; explicit non-CrossRef source selection bypasses CrossRef.
249
+
250
+ Source-checkout equivalents:
251
+
252
+ ```bash
253
+ PYTHONPATH=src python3 -m ref_verify.cli verify-doi 10.1126/science.287.5454.836 \
254
+ --title "High-Speed Electrically Actuated Elastomers with Strain Greater Than 100%" \
255
+ --first-author Pelrine \
256
+ --year 2000 \
257
+ --json
258
+
259
+ PYTHONPATH=src python3 -m ref_verify.cli check-claim 10.1126/science.287.5454.836 \
260
+ --claim "actuation strain above 100%" \
261
+ --json
262
+ ```
263
+
264
+ For local development, run:
265
+
266
+ ```bash
267
+ PYTHONPATH=src python3 -m unittest discover -s tests -v
268
+ ```
269
+
270
+ Release safety checks also build the Python package, validate metadata, and
271
+ install the built wheel in a fresh virtualenv before publishing. Live checks
272
+ against public academic APIs are kept in a manual GitHub Actions workflow so
273
+ normal CI does not fail because an upstream API is temporarily unavailable.
274
+
275
+ ---
276
+
277
+ ## What it catches
278
+
279
+ | Problem | What happens without ref-verify |
280
+ |---|---|
281
+ | **Wrong DOI** | An agent lists a plausible DOI that resolves to a different paper |
282
+ | **Wrong authors** | A citation says "Smith et al. (2020)", but CrossRef shows one author |
283
+ | **Wrong year** | The paper was published in 2008, but the draft says 2011 |
284
+ | **Made-up content** | The draft says a paper shows a result that is not in the abstract |
285
+ | **Near-miss citation** | The right number appears, but in the wrong context |
286
+ | **Retracted paper** | The DOI is valid, but the paper was retracted |
287
+
288
+ ---
289
+
290
+ ## Scope — optional CLI versus manual audit
291
+
292
+ `ref-verify` is a conservative guard, not an oracle. It errs toward flagging: an
293
+ `ACCEPT` is high-confidence, and **anything else means "not auto-verifiable —
294
+ check it yourself", not "the citation is wrong."**
295
+
296
+ **The optional CLI verifies**
297
+
298
+ - DOI metadata: title, first-author surname, and year against CrossRef.
299
+ - Whether a DOI-bound **abstract** explicitly supports a specific numeric or
300
+ literal claim, quoted verbatim. If no abstract is reachable, it returns
301
+ `UNVERIFIABLE` rather than guessing.
302
+
303
+ **The optional CLI does not verify** (out of scope by design, not bugs)
304
+
305
+ - **Full-text, figure, table, or supplementary values** — abstract-only. A number
306
+ that appears only in the body stays `UNVERIFIABLE`.
307
+ - **Relational or qualitative claims** — proportionalities, mechanisms,
308
+ "broader/stronger than". Only value+unit and literal claims are checked.
309
+ - **Papers whose publisher withholds the abstract** — some titles expose no
310
+ abstract to CrossRef or OpenAlex. No abstract → `UNVERIFIABLE`, which reflects
311
+ reachability, not the claim.
312
+ - **Statistical metrics** (p-value, AUC/AUROC, F1, hazard/odds ratio, confidence
313
+ intervals) — handled by the manual skill protocol, not the CLI.
314
+ - **Paper quality, novelty, field consensus**, or whether the *full* paper
315
+ supports a broader statement.
316
+
317
+ The agent skill's manual Full Audit protocol goes beyond the optional CLI for
318
+ mechanism, implementation, and procedural claims. It requires a fetched
319
+ full-text passage at that source depth; when full text is unavailable, it
320
+ returns `WARN (ABSTRACT-ONLY)` instead of upgrading an abstract topic match to
321
+ `ACCEPT`.
322
+
323
+ **Reading a CLI verdict**
324
+
325
+ | Verdict | Meaning |
326
+ |---|---|
327
+ | `ACCEPT` | The fetched abstract explicitly supports the claim. High-confidence pass. |
328
+ | `WARN` / `PARTIAL` | An abstract was read but does not explicitly support the exact claim. Check the source. |
329
+ | `UNVERIFIABLE` | No abstract was reachable to check against. Not a judgment on the claim. |
330
+ | `REJECT` | DOI is dead, resolves to a different paper, contradicted, or retracted. |
331
+
332
+ ---
333
+
334
+ ## Modes
335
+
336
+ **Quick Screen** is for DOIs you already have. It uses CrossRef to compare the
337
+ provided DOI, title, first-author surname, and year.
338
+
339
+ ```bash
340
+ ref-verify verify-doi <doi> --title "<title>" --first-author <last-name> --year <year> --json
341
+ ```
342
+
343
+ `verify-doi` exits `0` only for `PASS`. `WARN` and `REJECT` return a non-zero
344
+ exit code, so weak or mismatched metadata cannot silently pass automation gates.
345
+
346
+ **Full Audit** is for literature search and final pre-submission review. The
347
+ skill fetches abstracts through CrossRef, OpenAlex, Semantic Scholar, Unpaywall,
348
+ arXiv, and PubMed where needed. For a topline claim, it checks the abstract; for
349
+ a mechanism, implementation, or procedural claim, it continues to a fetched
350
+ full-text passage before assigning support.
351
+
352
+ For a single DOI-backed claim, the CLI can run the abstract check:
353
+
354
+ ```bash
355
+ ref-verify check-claim <doi> --claim "<specific claim>" --json
356
+ ```
357
+
358
+ `check-claim` exits `0` only for `ACCEPT`. `WARN`, `PARTIAL`, and
359
+ `UNVERIFIABLE` return a non-zero exit code. JSON output includes
360
+ `abstract_source`, `source_attempts`, and `error_code` so agents can distinguish
361
+ missing abstracts, source failures, DOI mismatches, and ambiguous evidence.
362
+
363
+ Use `check-file` when a draft, literature note, or AI-agent output has many
364
+ DOI/claim pairs.
365
+
366
+ JSONL:
367
+
368
+ ```bash
369
+ ref-verify check-file claims.jsonl
370
+ ref-verify check-file claims.jsonl --json
371
+ ```
372
+
373
+ CSV:
374
+
375
+ ```bash
376
+ ref-verify check-file claims.csv
377
+ ```
378
+
379
+ Each row must include `doi` and `claim`. Optional fields are `id`, `source`,
380
+ and `note`. Rows are checked 4 at a time by default (`--workers N`); output keeps
381
+ the input order, and CrossRef and Semantic Scholar requests go one at a time
382
+ because their public APIs reject parallel requests. In a terminal, a
383
+ `Checking claims: N/M` counter on stderr shows progress (never with `--json`).
384
+ Ctrl-C stops the run; finished lookups stay cached, so rerunning resumes quickly. Batch mode reuses the same conservative `check-claim` engine:
385
+ `ACCEPT` means the abstract explicitly supports the numeric claim. `WARN`,
386
+ `PARTIAL`, `REJECT`, or `UNVERIFIABLE` means the claim should not be treated as
387
+ verified.
388
+
389
+ Current `check-claim` error codes:
390
+
391
+ - `CLAIM_SUPPORTED`: explicit abstract support found.
392
+ - `CLAIM_NOT_EXPLICIT`: an abstract was available, but the claim was not explicitly supported.
393
+ - `CLAIM_AMBIGUOUS`: numeric evidence or context exists, but binding is ambiguous.
394
+ - `NO_ABSTRACT`: attempted DOI-bound sources did not provide abstract text.
395
+ - `DOI_NOT_FOUND`: CrossRef has no record for the DOI (HTTP 404), or the selected source did not find a DOI-bound record. The JSON still carries a `verdict` of `REJECT`.
396
+ - `PAPER_RETRACTED`: CrossRef lists a retraction notice for the DOI; the claim is rejected before any abstract is read.
397
+ - `DOI_MISMATCH`: the primary or explicitly selected DOI-bound record did not match the requested DOI.
398
+ - `SOURCE_API_ERROR`, `SOURCE_TIMEOUT`, `SOURCE_RATE_LIMITED`, `SOURCE_UNSUPPORTED`: source lookup failed, timed out, was rate-limited, or could not be used.
399
+
400
+ Use `check-bib` when you have a reference list rather than DOI/claim pairs:
401
+
402
+ ```bash
403
+ ref-verify check-bib references.bib
404
+ ref-verify check-bib references.ris --json
405
+ ref-verify check-bib references.md --format txt
406
+ ```
407
+
408
+ It reads BibTeX, RIS, and plain-text or Markdown lists (one reference per
409
+ paragraph, per line, or per `[1]`/`1.`/`1)` item). A reference with a DOI is
410
+ compared with its CrossRef record like `verify-doi`; a plain-text reference
411
+ passes only when its text shows the CrossRef title and first author. A
412
+ reference without a DOI is looked up with CrossRef bibliographic search and
413
+ accepted only when the title matches and the year is within one. Matching
414
+ accepts the print or the online-first year, a title with or without its
415
+ subtitle or edition note, TeX math in BibTeX titles (`$\beta$` reads as β),
416
+ CrossRef's original-language title (for example the Korean title of
417
+ a *Polymer Korea* paper), and Hangul author names against CrossRef's
418
+ romanized ones (윤 → Yoon/Yun). When a DOI is unknown to CrossRef, doi.org is
419
+ asked which agency registered it, so arXiv, Zenodo, or KISTI DOIs are not
420
+ reported as dead. Search results that are about the paper rather than the
421
+ paper itself (peer-review reports, Faculty Opinions recommendations,
422
+ addenda and corrections) are skipped. The terminal output starts with a count line
423
+ (`19 references: 11 PASS, 2 WARN, 5 REJECT, 1 UNVERIFIED`), lists one row per
424
+ reference (citation key, or the start of the reference for a pasted list), puts
425
+ the reason under every row that is not `PASS`, and ends with a one-paragraph
426
+ legend. With `--json` it is an object with `summary` (`total`, `pass`, `warn`,
427
+ `reject`, `unverified`, `failed`; `warn` includes the `UNVERIFIED` rows) and
428
+ `results`. `check-bib` exits `0` only
429
+ when every reference is `PASS`.
430
+
431
+ `check-bib` error codes:
432
+
433
+ - `REFERENCE_RESOLVED`: the reference had no DOI; CrossRef search found a matching record, reported as `resolved_doi`. `WARN` when the year differs by one or the first author differs.
434
+ - `REFERENCE_UNMATCHED`: the reference had no DOI and no CrossRef record matched (`status: UNVERIFIED`, `verdict: WARN`). The tool could not confirm it automatically; that does not mean the reference is wrong. Verify it manually.
435
+ - `DOI_NOT_IN_CROSSREF`: the DOI is registered with another agency (DataCite for arXiv and Zenodo, KISTI, JaLC, ...), so its metadata was not compared (`status: UNVERIFIED`, `verdict: WARN`). Open the DOI to confirm it.
436
+ - `DOI_NOT_FOUND`: neither CrossRef nor doi.org knows the DOI (`REJECT`).
437
+ - `PAPER_RETRACTED`, `ROW_CHECK_ERROR`: as for `check-claim` and `check-file`. Other DOI-backed results carry `error_code: null`; read `verdict`, `mismatches`, and `reason`, which names what differs (for example `the year differs (reference: 2009; CrossRef: 2010)`). A plain-text reference whose DOI belongs to a paper it does not mention is `status: MISMATCH`, `verdict: WARN`, with that paper's title in `reason`.
438
+
439
+ To hand the result to a co-author or supervisor, add `--report` to `check-bib`
440
+ or `check-file`. The file extension picks the format:
441
+
442
+ ```bash
443
+ ref-verify check-bib references.bib --report report.html
444
+ ref-verify check-file claims.jsonl --report report.md
445
+ ```
446
+
447
+ The HTML file is self-contained (inline CSS, no scripts, no external resources
448
+ other than `https://doi.org/` links). It opens with counts that add up to the
449
+ total (one box per verdict as shown), a plain-language line on what each
450
+ verdict means and asks you to do, then a "Needs a look" table with every
451
+ non-passing reference or claim and a "Passed" table below it. Each row is
452
+ coloured (`PASS`/`ACCEPT` green, `WARN` amber, `REJECT` red, `UNVERIFIED`
453
+ grey) and shows the reason and evidence. `UNVERIFIED` marks a result the tool
454
+ could not confirm automatically; it is not a finding that the reference is
455
+ wrong. The Markdown file has the same content. A `--report` path whose folder
456
+ does not exist is rejected before any lookup, so a long run is never lost.
457
+ `--json` output is unchanged.
458
+
459
+ > Core rule: every content statement about a paper must come from a live-fetched
460
+ > source at the depth the claim requires — abstract for topline claims, full
461
+ > text for mechanism, implementation, or procedural claims. If the required
462
+ > source is inaccessible, say so. Do not fill the gap from memory.
463
+
464
+ ---
465
+
466
+ ## Examples
467
+
468
+ **Checking citations you already have**
469
+
470
+ ```text
471
+ User: "verify these 3 citations before I submit"
472
+
473
+ Shahinpoor & Kim (2001) 10.1088/0964-1726/10/4/327 - PASS
474
+ Bar-Cohen (2004) 10.1117/3.547465 - WARN (listed as author; CrossRef: editor)
475
+ Carpi et al. (2011) 10.1016/B978-0-08-047488-5.00001-0 - REJECT
476
+ ```
477
+
478
+ **Checking a specific claim**
479
+
480
+ ```text
481
+ User: "does the Pelrine 2000 paper actually say DEAs reach over 100% strain?"
482
+
483
+ CONTENT: Supported
484
+ "Actuated strains up to 117% were demonstrated with silicone elastomers,
485
+ and up to 215% with acrylic elastomers."
486
+ [Source: CrossRef raw JSON, not recalled from memory]
487
+ ```
488
+
489
+ **Near-miss citation**
490
+
491
+ A candidate paper may contain "500% strain", but the abstract can show that the
492
+ number is a pre-strain condition, not an actuation result. `ref-verify` reports
493
+ that as `WARN (PARTIAL)` instead of accepting the citation.
494
+
495
+ ---
496
+
497
+ ## Related
498
+
499
+ - [decision-kernel](https://github.com/Moonweave-Systems/decision-kernel) - evidence-gated decisions and drift/done checks for coding agents