关于 verify-refs
verify-refs 是用于审计论文和参考文献的技能,可检查虚构、信息不符及重复条目,适合准备或审阅学术论文的研究者。它记录证据和状态,但不会修改参考文献文件。
主要功能
- 01对照索引核验参考文献信息
- 02分类标记 OK、MISMATCH、FABRICATED 和 UNVERIFIED
- 03报告重复标识符和审计计数
- 04根据本地全文检查引文主张
- 05生成结构化 JSON 审计报告
适用场景
- 01投稿前审计参考文献
- 02查找作者或标识符不符
- 03对照已下载论文核查引文主张
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aperivue/ medsci-skills --skill verify-refs安装后在 Claude Code 中输入/verify-refs确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
skill.ymlreferences/claim_evidence_workflow.mdmanual_checkpoint_guide.mdscripts/_claim_evidence.py_quote_match.pycheck_claim_fidelity.pyverify_cli.shverify_refs.pyscripts/claim_fidelity_challenge/verify.shscripts/claim_fidelity_challenge/fixture/manuscript_numbered.mdmanuscript_shortsource.mdmanuscript_supported.mdmanuscript_unsupported.mdrefs.bibscripts/claim_fidelity_challenge/fixture/fulltext/10.1000_synthetic.oversight.md10.1000_synthetic.stub.mdtests/test_audit_source_path.shtest_author_normalization.shtest_bib_entry_headers.shtest_bib_last_field.shtest_bibtex_et_al.shtest_claim_evidence.pytest_corporate_author.shtest_doi_not_registered.shtest_fabricated_author.shtest_identifier_title.shtest_markdown_reference_heading.shtest_openalex_tier.shtests/fixtures/corporate_author.bibpagination_placeholder.bib详细介绍
核验参考文献(仅审计)
审计现有稿件或参考文献目录,查找伪造或不匹配的参考文献。本技能绝不会写入 references/ 或 manuscript/_src/refs.bib:更正须通过 /lit-sync(Zotero → Better BibTeX → refs.bib)进行,而 /manage-project 的 scripts/validate_project_contract.py 会将此处写入的任何 references/* 文件标记为偏差。本技能不会检索文献(/search-lit),也绝不会用看似合理的替代项替换缺失或有误的引文——替换须通过 /search-lit 或由用户完成。
输入
- 稿件或参考文献目录:
.md、.docx、.bib、.txt或.tsv。 - 可选的项目根目录。默认值:当前工作目录。
- 可选标志:
--offline(提取并分类,不调用 API)、--timeout N(HTTP 超时秒数)、--strict、--no-openalex。
对于包含 pandoc [@bibkey] 引文的 Markdown 稿件,请先检查引文键(/manage-refs 的 check_citation_keys.py,或使用你的参考文献管理器)。该检查可发现键名错误的引文;verify_refs.py 可发现伪造的元数据。
确定性脚本
请运行随附脚本,不要凭记忆核验引文:
python "${CLAUDE_SKILL_DIR}/scripts/verify_refs.py" manuscript/manuscript.md --project-root .
如需在钩子中使用或快速手动运行,请使用包装脚本:
"${CLAUDE_SKILL_DIR}/scripts/verify_cli.sh" manuscript/manuscript.md --offline
手动提交前严格运行:
"${CLAUDE_SKILL_DIR}/scripts/verify_cli.sh" manuscript/index.qmd --strict
--strict 禁止与 --offline 同时使用,并且只要有任何一行状态为 UNVERIFIED,就会以非零状态码退出。何时运行以及如何处理各状态,请参阅 references/manual_checkpoint_guide.md。
查询顺序为 PubMed(PMID)→ CrossRef(DOI;如果 CrossRef 返回 404,则查询 doi.org 的句柄注册库)→ OpenAlex,最后进行 PubMed 标题搜索。每一行状态为 OK 的记录都有 DOI、PMID、CrossRef 或 PubMed 标题证据作为依据;查询失败会记为 UNVERIFIED,绝不会被悄然判定为通过。无论在哪个索引中,只有返回的标题与所引标题匹配时,标题搜索才算有效(使用相同的词元相似度检查),因此仅仅搜索到某个条目,不能让虚构标题获得 OK。
OpenAlex 层级。 它可找回 PubMed 和 CrossRef 未收录的会议论文及无 DOI 引文(在医学 AI 稿件中常见的 NeurIPS / ICLR / ACL),且仅在尚未获取作者列表时调用。它优先通过 DOI 解析,否则会在词元相似度检查的保护下搜索标题,因此虚构标题无法获得 OK。OpenAlex 不区分姓氏和名字,因此只能用于检查文献是否存在,以及宽松地检查第一作者是否在作者名单中——绝不用于严格的位置或作者数量 MISMATCH 判断;这些判断仍由 PubMed efetch / CrossRef 负责。OpenAlex 未能找到结果时,状态为 UNVERIFIED,绝不会是 FABRICATED。--no-openalex 会将核验范围限制为 PubMed + CrossRef。
输出约定(v1.3.0)
qc/reference_audit.json(schema_version 4)是唯一输出;此技能是该文件的唯一写入者,
且不会写入 TSV 或 library.bib。
records[]:每条参考文献对应的status、note、evidence、cited_authors[]/actual_authors[]、cited_author_count/actual_author_count。status为以下之一:OK:查询确认了这篇作品(通过 DOI、PMID 或通过相似度校验的标题搜索),且作者一致。MISMATCH:作品存在,但引文有误:作者不同(Gate 4),或 DOI/PMID 不存在,但查询仍找到了该作品(note = "wrong identifier…")。FABRICATED:所引标识符不存在,且没有找到其他关于该作品的结果(详情如下)。UNVERIFIED:没有确认或证伪(查询失败、DOI 仅由其他注册机构持有但没有任何索引确认、没有标识符且标题未匹配、PubMed 仅匹配到标题但无法比较作者或作者不同(note = "title_only: …"),或使用了--offline)。
counts和duplicate_findings[](Gate 5)。submission_safe:不存在FABRICATED或MISMATCH,且duplicate_findings为空。fully_verified还要求不存在UNVERIFIED。submission_safe允许存在UNVERIFIED条目,因为离线运行会产生这些条目;投稿前,请逐一处理(手动确认并说明确认方式,或移除引文)——不要把UNVERIFIED参考文献当作已核查的内容提交。source_sha256和audited_ref_ids:记录已审计的内容。后续读者会将它们与当前 bib 进行比较;bib 一旦变更,审计结果就会过期。
工作流
- 确认输入文件和项目根目录。
- 运行
scripts/verify_refs.py。 - 阅读
qc/reference_audit.json。所有判定均以该文件为准;切勿自行将某条记录标记为OK。 - 首先报告所有
FABRICATED和MISMATCH条目(来自records[])。 - 报告所有
duplicate_findings[]条目(逐字重复的 PMID/DOI——必须重新编号引文)。 - 如果仍有
UNVERIFIED条目,将其列为人工核查项,且不要称稿件完全符合投稿要求。无论每条记录的状态如何,都要检查其note:pagination_placeholder(e000–e000/in press/TBD/forthcoming)表示投稿前必须解决该引文;/self-reviewPhase 2.5c 会判定其中是否有任何一项属于 P0 阻碍。 - 如果用户需要易读的表格,请在聊天中根据
records[]汇总——不要写入 TSV。
质量门槛
- 门槛 1:如果任何一行标记为
FABRICATED,则停止提交。 - 门槛 2:接受
UNVERIFIED引用前,必须征得用户确认。 - 门槛 3:任何引用编辑后都必须重新运行。
- 门槛 4(完整作者交叉核对):存在 PMID 时,权威作者列表取自 PubMed
efetch.fcgi(XML)——由于 CrossRef 对名字的可靠性不足,优先采用此来源——CrossRef 和 PubMed esummary 作为后备来源。对于 BibTeX 输入,逐项比较每个被引用的姓氏,并比较引用和来源中的作者人数;规范化大小写、变音符号、连字符与空格,以及姓名中的虚词(“von”、“van”、“de”)后进行比较;一个姓名可以是另一个姓名的完整单词(“Garcia” / “Garcia-Lopez”),但不能只是子字符串(“Li” / “Williams”)。如果某行的 DOI/PMID 可以解析,但任一位置的作者或作者人数不一致,则标记为MISMATCH:第一作者的note = "first-author hallucination suspected",第 2 至第 N 作者或作者人数的note = "non-first-author hallucination or count mismatch"。第一作者正确并不能证明其余作者列表正确。纯文本 / TSV 输入以及无法可靠解析的列表,降级为仅检查第一作者(如果第一作者信息也为空,则跳过)。仅匹配到 PubMed 标题时,只有在将匹配记录的 esummary 作者与引用作者进行比较且一致时,状态才为OK;否则保持UNVERIFIED。声明了截断的情况——BibTeX 中的and others,或_audit_truncated = <N>字段——若作者人数少于来源记录,则记为备注;引用的作者人数多于来源记录时,始终标记。 - 门槛 5:参考文献列表中逐字相同的 PMID 或规范化后的 DOI 重复项,属于
duplicate_findings[]中的 MAJOR 发现;submission_safe == true要求该列表为空。 - 门槛 6:原始条目仍包含
e000–e000、in press、TBD或forthcoming的引用,标记为UNVERIFIED,并设置note = "pagination_placeholder"。verify-refs 不依赖稿件内容,只负责标记;/self-reviewPhase 2.5c 会在拿到稿件后判断该引用是否对方法或核心结论至关重要,进而决定是否构成 P0 阻塞项。
引用元数据混淆不等于伪造。 DOI 后缀中的数字看起来像文章编号、但与文章编号不同(例如 DOI 尾部为 "77196",文章编号为 26068),属于表面差异。如果标识符可以解析且作者匹配,不要将该行报告为伪造:脚本仅会在标识符不存在时返回 FABRICATED——PubMed 中没有该 PMID 的记录,或者 CrossRef 对 DOI 返回 404,且 doi.org 的句柄注册库(涵盖所有注册机构:CrossRef、DataCite、mEDRA、JaLC)报告未找到——并且没有其他查询途径找到该作品时才会如此。CrossRef 返回 404 后,DOI 的判定如下:
| doi.org 句柄注册库 | 其他查询是否找到该作品 | 状态 |
|---|---|---|
| 未找到 | 否 | FABRICATED |
| 未找到 | 是(标题搜索通过相似度检查) | MISMATCH — 引用了真实论文,但 DOI 错误 |
| 已找到(在其他机构注册) | 否 / 是 | UNVERIFIED / OK |
| 查询失败(网络、5xx、意外回复) | 否 / 是 | UNVERIFIED / OK |
格式不正确的 DOI 字段(例如占位符 n/a)不会发送给 doi.org,并保持 UNVERIFIED。doi.org 未找到的旧式 SICI DOI(10.1002/(SICI)…)也保持 UNVERIFIED,因为提取时很容易截断其中的标点。真实标识符若作者不匹配,则标记为 MISMATCH(门槛 4)。
主张忠实度——来源是否确实如你所说?
verify_refs.py 回答的是参考文献是否真实以及属于谁,而不是引用它的句子是否准确描述了它。scripts/check_claim_fidelity.py 会检查那些有可核实答案的主张,对照已下载并转换的全文进行核查(/fulltext-retrieval 会生成完全相同的目录结构;此脚本不会抓取任何内容):
python3 "${CLAUDE_SKILL_DIR}/scripts/check_claim_fidelity.py" \
--manuscript manuscript/manuscript.md \
--fulltext-dir fulltext/ --bib manuscript/_src/refs.bib \
--out qc/claim_fidelity.json --strict
| 判定 | 严重性 | 触发条件 |
|---|---|---|
CITED_QUOTE_ABSENT | major | 归于某来源的引文,在该来源的任何阅读顺序中都不存在。 |
CITED_QUOTE_UNRESOLVED | prompt | 引文仅有一两个词缺失便能匹配——这是提取不干净的迹象,而非伪造。请检查,不要妄下结论。 |
ATTRIBUTION_UNSUPPORTED | prompt | 归于某来源的主张中,没有任何内容词以任何形式出现在该来源中。改述通常至少会保留来源中的一个术语。 |
ORDINAL_CLAIM_UNSUPPORTED | prompt | 例如“报告了三种策略 [12]”,来源虽然讨论了该名词,却从未在其附近提及这个数量。 |
只有引文判定会导致 --strict 失败;其他判定只是提示你去阅读来源,因为改述是合理的。请阅读“未检查”行:磁盘上没有全文的引用会被报告为未解决;提取文本只有摘要的来源会被报告为过短,无法判断。没有提示意味着“没有发现可核实的问题”,而不是“一切都正确”。
已知限制:如果引文中的所有词都按顺序出现在来源中,且中间夹有来源文本中的其他词(INTERLEAVED),就会被视为已验证,因此遗漏了“not”等来源词的引文不会触发任何发现;对于任何改变否定词或限定语的引文,都要重新阅读。
句子级来源证据表
qc/claim_fidelity.json 还包含 evidence_rows:每个已识别的正文句子/引用组合对应一行,其中包含稿件坐标、来源文本和 PDF 哈希、建议性检索身份,以及由评估者填写的比较结果;即使书目信息状态为 OK 且没有触发探查,该结果也会以 not_assessed 开始。
python3 "${CLAUDE_SKILL_DIR}/scripts/check_claim_fidelity.py" \
--manuscript manuscript/manuscript.md --bib manuscript/_src/refs.bib \
--fulltext-dir fulltext/ --retrieval-report pdfs/retrieval_report.json \
--reference-audit qc/reference_audit.json \
--out qc/claim_fidelity.json --evidence-table qc/claim_fidelity.md
只有在检查过实际来源后,才填写页码、摘录、指标/单位/分母、研究对象、方向和具名评估;数字相同或措辞匹配并不能证明来源支持该主张。请记录评估者是否使用了 AI 辅助,绝不要将 AI 生成的评估描述为人工批准。使用 --reviewed-report qc/claim_fidelity.json 重新运行,以保留批注;输入发生变化时,旧评估将变为未解决状态。Markdown 表格是派生视图,并非第二个可编辑的证据存储。填写或沿用评估前,请阅读 references/claim_evidence_workflow.md。