bibcheck — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited bibcheck (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Audit-only sister skill to /cite. Given a .bib file, spawn one subagent per entry to verify the entry against canonical sources (DOI metadata, Semantic Scholar, OpenAlex, arXiv, Zotero). Report PASS / WARN / FAIL per entry with a one-line diagnostic, group by severity, and write a dated report plus a corrected.bib the user can review and merge themselves. Never overwrites the source .bib.
Why per-entry parallelism. One agent asked to audit 80 entries in a single pass drifts: early entries get careful treatment, late entries get pattern-matched. Spawning one subagent per entry gives each citation a full attention budget and removes the late-batch quality cliff. This mirrors the structure of /seven-pass-review (parallel lenses) and /audit-reproducibility (per-claim checking).
The LLM-fabrication concern. Hallucinated citations have a recognizable signature: plausible author names + plausible title + a DOI that 404s + no Semantic Scholar / OpenAlex / arXiv match anywhere. /bibcheck is built to surface exactly this pattern.
.bib actually exists.$0 — path to a .bib. If omitted, Glob the cwd for references.bib, refs.bib, bibliography.bib, then any *.bib. Overleaf projects typically live under <OVERLEAF_ROOT>/<PROJECT_SUBDIR>/. If multiple .bib files exist, grep the main .tex for \bibliography{} / \addbibresource{} to pick the right one; ask the user if still ambiguous..bib.^@\w+\{ boundaries. Capture entry type (article, book, incollection, misc, inproceedings, unpublished), citation key, and every field = {value} pair (handle braced and quoted forms, escaped braces, multi-line values).<bib_dir>/bibcheck_<YYYYMMDD_HHMM>/ with subfolders entries/ (one file per entry for subagent input) and reports/ (one JSON per entry for subagent output).For each well-formed entry, launch a Task subagent with a focused prompt: "Verify this single BibTeX entry against canonical sources. Return JSON with verdict and per-field findings." Cap concurrent subagents at 8 (--max-parallel if the user passes it). Each subagent runs the per-entry checks below and writes one JSON file to reports/<citekey>.json. Lower the cap if rate-limited; raise it for very large bibliographies.
In order, stopping early once verdict is determined:
doi field:mcp__semantic-scholar__get_paper_details(paper_id="DOI:<doi>"). On hit, compare title / author surnames / year / venue / volume / issue / pages against the entry. Discrepancies → field-level WARN; outright mismatches → FAIL.WebFetch("https://api.crossref.org/works/<doi>") for Crossref ground truth.eprint = {2403.12345}, archivePrefix = {arXiv}, or note = {arXiv:...}):mcp__arxiv__get_abstract(paper_id="<id>") to confirm existence and pull canonical metadata.mcp__semantic-scholar__search_papers(query="<title>")) — if so, emit a WARN suggesting the published @article entry instead of the preprint @misc.mcp__semantic-scholar__search_papers(query="<title>", limit=5). Fuzzy-match against the entry's title (case-insensitive, normalize punctuation, accept ≥ 0.85 cosine on token-set). On a confident hit, compare authors / year / venue. On no plausible match, also try mcp__openalex__openalex_search_entities(entity_type="works", query="<title>") as a second opinion.doi is present but DOI doesn't resolve in S2 OR Crossref, AND (b) title search returns no fuzzy match in S2 OR OpenAlex OR arXiv → FAIL with diagnostic fabricated? — DOI does not resolve and no metadata source recognises the title. This is the LLM-hallucination signal.Pena vs. Peña), missing tussenvoegsels (Van Den Bulte vs. van den Bulte) → WARN.& others or missing trailing authors) → WARN.eprint/archivePrefix=arXiv present and entry year matches arXiv-submission year → WARN ("entry cites preprint year <y1>; published version is <y2>"). Do not auto-FAIL — citing the preprint year is a legitimate choice.<y1>, canonical says <y2>").journal against canonical name from S2 / OpenAlex. Marketing-relevant cases worth WARNing on:J. Mark. Res. vs. Journal of Marketing Research, Mark. Sci. vs. Marketing Science, Mgmt. Sci. vs. Management Science, Quant. Mark. Econ. vs. Quantitative Marketing and Economics.booktitle on @inproceedings (ICML, NeurIPS, KDD — full names).lastname2024Word), call mcp__zotero__zotero_search_items(query="<title>", qmode="titleCreatorYear", limit=3). If a Zotero hit exists with a different DOI than the entry, WARN. The Zotero MCP is read-only — never attempt to write back; surfacing the mismatch is sufficient.Each subagent emits:
{
"citekey": "smith2024paper",
"verdict": "PASS | WARN | FAIL",
"diagnostic": "one-line summary",
"field_findings": [
{"field": "year", "status": "FAIL", "entry_value": "2023", "canonical_value": "2024", "source": "doi.org/10.1287/mksc.2024.0123"}
],
"canonical_source": "doi | s2 | openalex | arxiv | none",
"suggested_replacement": "<full corrected BibTeX entry, or null if PASS / unfixable>"
}Read every JSON in reports/. Bucket entries by verdict: FAIL > WARN > PASS. Within each bucket, sort by citekey alphabetically (stable, easy to diff across runs).
Write <bib_dir>/bibcheck_<YYYYMMDD_HHMM>/bibcheck_report.md:
# Bibliography Audit: <bib filename>
**Date:** YYYY-MM-DD HH:MM
**Source:** <full path to .bib>
**Entries audited:** N (parsed) / M (malformed, skipped)
## Summary
| Verdict | Count |
|---|---|
| PASS | a |
| WARN | b |
| FAIL | c |
| Possibly fabricated | d (subset of FAIL)|
## FAIL (blockers — verify before submission)
| Citekey | Diagnostic | Canonical source |
|---|---|---|
| smith2023paper | year mismatch: entry 2023, canonical 2024 | doi.org/10.1287/mksc.2024.0123 |
| jones2024nope | fabricated? DOI 404s, no S2/OpenAlex/arXiv match | none |
## WARN (style / preprint-vs-published / minor field drift)
| Citekey | Diagnostic |
|---|---|
## PASS
<one-line per entry>
## Per-entry detail
<expandable section with the JSON for each FAIL and WARN>
## Next steps
1. Review each FAIL row. Open `corrected.bib` for suggested replacements.
2. Diff `corrected.bib` against the source `.bib` (`git diff --no-index`).
3. After review, move `corrected.bib` into place yourself — this skill does not overwrite the source.Also write <bib_dir>/bibcheck_<YYYYMMDD_HHMM>/corrected.bib: a full copy of the source .bib with FAIL/WARN entries replaced by their suggested_replacement (preserving every PASS entry untouched, preserving comments and entry order). Entries with no confident correction are kept as-is and tagged with a leading % bibcheck:FAIL — <diagnostic> comment line.
Files written to <bib_dir>/bibcheck_<YYYYMMDD_HHMM>/:
input.bib # verbatim copy of source for provenance
entries/<key>.bib # one parsed entry per file (subagent inputs)
reports/<key>.json # one verdict per file (subagent outputs)
bibcheck_report.md # consolidated human-readable report
corrected.bib # drop-in candidate replacement (user reviews + merges)| Skill | Direction | Mutates .bib? | Talks to Zotero? |
|---|---|---|---|
/cite | adds ONE entry from a DOI/arXiv/title identifier | yes (appends) | yes (read + write via Web API) |
/bibcheck | audits ALL entries in an existing .bib | no (writes a separate corrected.bib) | read-only via MCP for cross-check |
If /bibcheck finds an entry that should be replaced and the user wants to do that via /cite, hand off the DOI / arXiv ID to /cite rather than mutating the .bib here.
Bibliographies over ~60 entries with --max-parallel 8 can take several minutes. Use Bash run_in_background: true for the dispatch loop and stream subagent completion via Monitor. Do not block on a single slow MCP call — set a 30-second per-entry timeout and emit a WARN: lookup_timeout rather than hanging.
--max-parallel 2. If still failing, surface the error to the user rather than silently marking everything FAIL..bib may be a non-English-titled set or a niche venue not indexed by S2/OpenAlex. Flag and ask the user to point at a sample entry known to be correct, then recalibrate./cite. If an entry should be replaced, write the suggestion to corrected.bib; do not POST to Zotero./review-paper literature-fidelity check; /bibcheck only verifies the entry's metadata matches a real paper.corrected.bib, even if the user's style preference differs./cite — adds individual entries; complementary forward direction./litreview — finds papers to cite; pair before /cite and /bibcheck./audit-reproducibility — same per-claim subagent-fanout structure, applied to numeric claims rather than citations./review-paper / /seven-pass-review — broader manuscript reviews; the citation-pass in those skills delegates here.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.