fix(bib): dedup paper.bib (2 dup keys + 17 redundant) + add dedup aud… #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Citation Audit | |
| # Enforces CLAUDE.md §10 "zero-hallucination" red line. Two gates: | |
| # | |
| # 1. tools/audit_citations.py — every arXiv / NBER / DOI reference in | |
| # src/ and docs/ must match primary-source metadata (authors / year / | |
| # title). Fails on MISMATCH or UNRESOLVED under --strict. | |
| # | |
| # 2. tools/audit_bib_duplicates.py — paper.bib must have no duplicate | |
| # bib keys (biblatex error), no duplicate DOIs, no duplicate arXiv | |
| # ids (same paper under two keys = citation drift). Fails on any | |
| # duplicate under --strict. | |
| # | |
| # Both audit reports are uploaded as artifacts so reviewers can see the | |
| # full verdict. | |
| # | |
| # Security: no untrusted PR inputs flow into `run:` commands — only the | |
| # repo's own scripts under tools/ are executed. | |
| on: | |
| pull_request: | |
| branches: [ main ] | |
| paths: | |
| - 'src/**' | |
| - 'docs/**' | |
| - 'paper.bib' | |
| - 'paper.md' | |
| - 'tools/audit_citations.py' | |
| - 'tools/audit_bib_duplicates.py' | |
| - '.github/workflows/citation-audit.yml' | |
| push: | |
| branches: [ main ] | |
| paths: | |
| - 'src/**' | |
| - 'docs/**' | |
| - 'paper.bib' | |
| - 'paper.md' | |
| - 'tools/audit_citations.py' | |
| - 'tools/audit_bib_duplicates.py' | |
| - '.github/workflows/citation-audit.yml' | |
| workflow_dispatch: | |
| concurrency: | |
| group: citation-audit-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| audit: | |
| name: Audit arXiv / NBER / DOI citations | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python 3.13 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.13' | |
| - name: Install certifi | |
| run: python -m pip install --quiet certifi | |
| - name: Run paper.bib duplicate auditor (strict) | |
| id: bib_audit | |
| # Gate 1: runs first because it's cheap (stdlib only, no network) | |
| # and a broken bibliography invalidates downstream citation checks. | |
| run: python tools/audit_bib_duplicates.py --strict | |
| - name: Run citation auditor (strict) | |
| id: citation_audit | |
| # Gate 2: live verification against arXiv / NBER / Crossref. | |
| # --strict: unresolved IDs fail alongside mismatches, so a typo | |
| # that breaks primary-source lookup is caught early. | |
| run: python tools/audit_citations.py --strict --out audit_report.md | |
| - name: Upload citation audit report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: citation-audit-report | |
| path: audit_report.md | |
| retention-days: 30 | |
| - name: Summarise to GitHub step summary | |
| if: always() | |
| run: | | |
| { | |
| echo "### Citation Audit" | |
| echo "" | |
| if [ -f audit_report.md ]; then | |
| sed -n '3p' audit_report.md | |
| fi | |
| echo "" | |
| echo "Full citation report is attached as the \`citation-audit-report\` artifact." | |
| } >> "$GITHUB_STEP_SUMMARY" |