Skip to content

feat(method-citations): gate bibliographies for fabricated references - #138

Merged
sajor2000 merged 1 commit into
mainfrom
feat/reference-integrity-gate
Oct 19, 2026
Merged

sajor2000 merged 1 commit into
mainfrom
feat/reference-integrity-gate

Conversation

@sajor2000

@sajor2000 sajor2000 commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

What

Closes the reference-integrity gap from the MedSci Skills competitive audit (gap #2, docs/audits/2026-10-19-medsci-skills-competitive-audit.md): the plugin could build citations but could not catch fabricated ones. method-citations now ships scripts/verify_references.py, a deterministic audit that parses an existing bibliography (BibTeX, RIS, delimited, or a plain numbered list), resolves every DOI via CrossRef then OpenAlex and every PMID via PubMed, and classifies each entry:

Verdict Meaning
OK identifier resolves; claimed title/year/first author match
MISMATCH identifier resolves but a claimed field differs; the record's true values travel in the report
UNVERIFIED no identifier, or no record fetched; carried into the ledger, never a silent OK
FABRICATED DOI/PMID registered nowhere; the audit exits 2 and blocks delivery

Design decisions

  • Free text is compared by identifier only. A numbered list parsed from running prose carries a guessed title and year; marking it MISMATCH would flag the parser, not the author. fields_trustworthy marks the distinction, and the resolved record is attached for a human to compare.
  • Offline seam for tests. --lookup-cache records and reuses lookups; --offline classifies from a populated cache, so the test suite never reaches the network. classify also accepts --entries/--lookups files directly.
  • Zero title overlap is a MISMATCH, not a skip. Smoke-testing caught that a 0.0 similarity was skipped as a falsy value; the gate is now on both sides having tokens.

Regression coverage

tests/verify-references.test.ts pins the bugs found while smoke-testing: DOIs containing parentheses (legitimate in registered DOIs, e.g. 10.1016/S0140-6736(19)30001-1), bracketed [1]/[2] numbering splits, and the zero-overlap title report. Verified live before committing: a real DOI resolves OK, a fabricated one is caught FABRICATED with exit 2.

Repo surfaces

  • plugins/methodsmith/skills/method-citations/ — the script; SKILL.md documents the audit as step 4 of the evidence workflow with the anchored SKILL_DIR invocation and a python-probe fallback row in failure handling.
  • evals/methodsmith/skill-creator/method-citations/ — eval 3 gains the integrity-gate expectation; one should-trigger query now covers fabricated-reference detection (eval and trigger counts stay at 3 and 10/10 per the skill-creator contract).
  • plugins/methodsmith/README.md — the /method-citations row mentions the bibliography gate.

Validation

  • bun test — 1729 tests, 0 fail (includes frontmatter, portability, displayed-counts, skill-creator-evals, description-fingerprints contracts)
  • bunx tsc --noEmit — clean
  • bun run release:validate — in sync, 55 agents / 67 skills
  • Add verify_references.py to parse and audit BibTeX, RIS, delimited, and numbered-list bibliographies.
  • Resolve DOIs through CrossRef and OpenAlex, and PMIDs through PubMed. Classify entries as OK, MISMATCH, UNVERIFIED, or FABRICATED.
  • Add cached and offline lookup options. Fabricated references cause exit code 2; mismatches cause exit code 2 with --strict.
  • Update the method-citations workflow, evals, and plugin README to include the bibliography integrity gate.
  • Add tests for parsing, classification, offline behavior, and CLI results.
Author Lines added Lines removed
JC Rojas 923 2

Add scripts/verify_references.py, a deterministic reference-integrity
audit for existing bibliographies. It parses BibTeX, RIS, delimited, and
numbered free-text reference lists, resolves every DOI via CrossRef then
OpenAlex and every PMID via PubMed, then classifies each entry:

- OK: identifier resolves and claimed title/year/author match
- MISMATCH: identifier resolves but a claimed field differs
- UNVERIFIED: no identifier or no record fetched
- FABRICATED: DOI/PMID registered nowhere; the audit exits 2

Free-text entries carry guessed titles and years, so only their identifier
is compared and the resolved record is attached for a human to check (the
fields_trustworthy flag marks the distinction). --lookup-cache records and
reuses lookups across runs; --offline classifies from a populated cache
with no network, which is also how the tests run.

Regression coverage pins the parsing bugs found while smoke-testing:
DOIs containing parentheses, bracketed numbering splits, and zero title
overlap reported as a MISMATCH instead of skipped as a falsy similarity.

SKILL.md documents the audit as step 4 of the evidence workflow with the
anchored script invocation and a python-fallback row in failure handling.
The method-citations eval set gains the integrity-gate expectation, and
the plugin README row and one trigger query cover the new capability.
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: d2e0dd8f-9b81-4153-b2a0-2048b3bdc2d1
📥 Commits

Reviewing files that changed from the base of the PR and between dbd3d1d and 15198b5.

📒 Files selected for processing: 6
  • evals/methodsmith/skill-creator/method-citations/evals.json
  • evals/methodsmith/skill-creator/method-citations/trigger-evals.json
  • plugins/methodsmith/README.md
  • plugins/methodsmith/skills/method-citations/SKILL.md
  • plugins/methodsmith/skills/method-citations/scripts/verify_references.py
  • tests/verify-references.test.ts
+-----------------------------------------------------------+
| Patterns mean 'I have run out of language.' - Rich Hickey |
+-----------------------------------------------------------+
  \
   \     /)/)
        ( '')
        /  |
      o(___)
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@sajor2000
sajor2000 merged commit 3b3781f into main Oct 19, 2026
2 of 3 checks passed
@sajor2000
sajor2000 deleted the feat/reference-integrity-gate branch October 19, 2026 19:29
@github-actions github-actions Bot mentioned this pull request Oct 19, 2026
sajor2000 added a commit that referenced this pull request Oct 21, 2026
Close the journal-selection half of audit gap #5 with a new skill that
matches a finished manuscript or abstract to candidate journals:

- builds a 5-8 candidate pool from each journal's own aims-and-scope page
  read via web tools, never from memory or a third-party summary;
- gathers scope-fit evidence by searching PubMed restricted to each
  candidate journal for similar recent studies (count and recency);
- runs a legitimacy screen verifying each candidate's indexing claims
  against the NLM Catalog or DOAJ, flagging unverifiable claims, copycat
  names, and APC-only venues instead of silently dropping or accepting
  them;
- applies the author's must-haves (indexing, access policy and fees,
  review speed) as hard filters, ranks with every cell sourced or marked
  unknown, and recommends a target plus two backups, leaving the choice
  to the author.

Sourcing rules are the core discipline: no impact factor, acceptance
rate, turnaround, or APC from memory; every metric carries a source URL
and date or is marked unknown. Egress mirrors the other research skills:
searches carry study topics, designs, and journal names only.

The listing budget rises from 11,500 to 11,700 for the 68th skill
(11,686 total, the same ~172-char average per skill), and every
displayed count surface (READMEs, website, brand SVG) moves 67 -> 68.
Eval sets follow the skill-creator contract (3 evals, 10/10 triggers).
The audit doc records gap closures: #2 (PR #138), #4 (PR #140), and the
journal-selection half of #5, with the ICMJE COI half left open as a
decision. Description fingerprints regenerated from history.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant