From medsci-project
Audits manuscript references against PubMed/CrossRef to detect fabricated or mismatched citations. Run before journal submission.
How this skill is triggered — by the user, by Claude, or both
Slash command
/medsci-project:verify-refsinheritThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You help a medical researcher prevent reference hallucinations before submission.
You help a medical researcher prevent reference hallucinations before submission.
This skill audits an existing manuscript or bibliography. It does not write
to references/ or manuscript/_src/refs.bib. It does not discover new
literature; use /search-lit for discovery and /lit-sync for bib management.
.docx manuscripts inherited from
coauthors or external editors./sync-submission freezes a journal package..md, .docx, .bib, .txt, or .tsv.--offline: extract and classify references without API verification.--timeout N: HTTP timeout seconds.For markdown manuscripts using pandoc [@bibkey] citations, validate citation
keys first to catch undefined/unused keys before this audit. If you also use the
companion manage-refs skill, run its check_citation_keys.py for this;
otherwise use your reference manager's citation-key check.
Then run verify_refs.py against the .bib to validate each entry against
PubMed/CrossRef. The two checks are complementary: a citation-key check catches
mis-keyed cites; verify_refs.py catches fabricated metadata.
Run the bundled script rather than verifying citations by memory:
python "${CLAUDE_SKILL_DIR}/scripts/verify_refs.py" manuscript/manuscript.md --project-root .
For hooks or quick manual runs, use the wrapper:
"${CLAUDE_SKILL_DIR}/scripts/verify_cli.sh" manuscript/manuscript.md --offline
Manual pre-submission strict run (Phase 1A.5):
"${CLAUDE_SKILL_DIR}/scripts/verify_cli.sh" manuscript/index.qmd --strict
--strict forbids --offline and exits non-zero on any UNVERIFIED row.
Full checkpoint protocol: references/manual_checkpoint_guide.md.
The script uses DOI, PMID, CrossRef, and PubMed E-utilities where available. If
network verification fails, it records UNVERIFIED rather than silently passing.
| Artifact | Path | Purpose |
|---|---|---|
| Audit JSON | qc/reference_audit.json | Sole output — row-level status (OK/MISMATCH/UNVERIFIED/FABRICATED), counts, cited_authors[]/actual_authors[], duplicate_findings[], submission-safe flag, full records |
v1.2.0 (2026-05) adds duplicate_findings[] to the audit JSON. Verbatim PMID or DOI duplicates within the reference list are flagged as MAJOR findings (resolves /peer-review Phase 2A P7). DOI normalization strips https://doi.org/, http://dx.doi.org/, doi: prefixes plus trailing slashes before comparison so https://doi.org/10.x/abc/ and 10.x/abc collapse to one key. Both submission_safe and fully_verified now require duplicate_findings to be empty.
v1.3.0 (2026-05) extends the author cross-check from first-author-only to the full author list and bumps schema_version to 4. For BibTeX inputs, every cited author family name is compared index-by-index against the authoritative source, and the cited-vs-source author counts are compared. PubMed efetch.fcgi (XML full record) is the truth source when a PMID is present — it is authoritative for given/family names where CrossRef is not (a documented case where CrossRef returned a wrong given name that PubMed efetch corrected). Records now carry cited_authors[], actual_authors[], cited_author_count, and actual_author_count. Motivation: a real AI-assisted manuscript registered a reference with a correct first author but seven of ten fabricated co-author names, and the first-author-only check passed it. Plain-text / TSV inputs, which cannot be parsed into a confident full list, degrade gracefully to the first-author check.
Removed in Phase 1A.2 (per docs/artifact_contract.md):
references/verified_references.tsv — record-level details now live inside reference_audit.json under records[].references/library.bib — never this skill's concern. /search-lit produces candidates; /lit-sync (via Better BibTeX) writes manuscript/_src/refs.bib.Sole-writer enforcement: scripts/validate_project_contract.py will flag any references/* file written by this skill as drift.
scripts/verify_refs.py.qc/reference_audit.json.FABRICATED and MISMATCH rows first (from records[]).duplicate_findings[] entries (verbatim PMID/DOI duplicates — cite renumbering required).UNVERIFIED rows remain, list them as manual checks and do not call the
manuscript fully submission-safe. Rows with note = "pagination_placeholder"
(e000–e000 / in press / TBD / forthcoming) need the citation resolved
before submission; /self-review Phase 2.5c decides whether any is a P0 blocker.records[] in chat — do not write a TSV.FABRICATED.UNVERIFIED references.MISMATCH. First-author mismatches get
note = "first-author hallucination suspected"; #2..#N family or count
mismatches get note = "non-first-author hallucination or count mismatch".
This catches the LLM failure mode where a real DOI is paired with invented
author names anywhere in the list, not just the lead author. Intentional CSL
et-al truncation (cited fewer than source) can be silenced per-entry with a
BibTeX _audit_truncated = <N> field.duplicate_findings[]. submission_safe == true requires the list to be
empty. Resolves /peer-review Phase 2A P7.e000–e000, in press, TBD, or forthcoming
is not yet a fully citable record. Each is marked UNVERIFIED with
note = "pagination_placeholder" (a would-be VERIFIED record is downgraded; a
worse status is left unchanged). verify-refs is manuscript-agnostic and does not
judge centrality — it only flags. The escalation call (is this a method- or
headline-load-bearing citation, hence a P0 submission blocker?) is made by
/self-review Phase 2.5c, which has the manuscript in hand.Classification note — citation-metadata confusion is not fabrication. Digits
in a DOI suffix sometimes look like a journal article number but differ from the
real one (e.g., a DOI tail "77196" against article number 26068, or a "60466-1"
suffix against article 6274). This is cosmetic metadata confusion, not a
fabricated reference: do not record such rows as FABRICATED when the DOI/PMID
resolves and the authors match. A genuine FABRICATED verdict requires a
non-resolving identifier or an author cross-check failure (Gate 4), not a
mismatch between a DOI suffix and an article number.
Driven by two actual incidents. First (Gate 4 origin): a manuscript had a
reference cited with a plausible lead author but the correct DOI for an entirely
different author's whitepaper. Pre-patch verify-refs marked it OK because the
DOI resolved; post-patch it is MISMATCH. Second (v1.3.0 extension): an
AI-assembled .bib registered a reference with the correct first author but
seven of ten fabricated co-author names — the first-author-only check passed it,
and it would have shipped to reviewers. The full-author cross-check catches it.
efetch.fcgi (XML) when a
PMID is present, falling back to CrossRef (DOI) and then PubMed esummary.
efetch is preferred because CrossRef is unreliable for given names.cited_authors[],
balanced-brace aware, LaTeX-accent tolerant) and compared family-by-family and
by total count against actual_authors[]._audit_truncated = <N> to downgrade the count mismatch to a note./search-lit or user approval./lit-sync after this audit.UNVERIFIED and keep it visible.npx claudepluginhub aperivue/medsci-skills --plugin medsci-projectVerifies every citation in a manuscript by fetching cited works to detect ghost papers, wrong IDs, inverted claims, and dead links. Includes optional fix mode for bib corrections and claim rewrites.
Audits citations and source claims in academic manuscripts. Verifies whether cited papers support attributed claims and checks quantitative claims.
Verifies academic citations against CrossRef and OpenAlex, detects fabricated or wrong entries, and writes audit trail to a project summary table.