[Atlas] Per-claim citation freshness audit + auto-bibliography done

← Multi-Source Literature Search
Audit every claim/citation pair, flag >5yr-old refs with replacement suggestions; bibliography export; freshness heatmap.

Completion Notes

Auto-completed by supervisor after successful deploy to main

Git Commits (2)

Squash merge: orchestra/task/a4c450f7-biomni-analysis-parity-port-15-use-cases (87 commits) (#717)2026-04-27
[Atlas] Per-claim citation freshness audit + auto-bibliography [task:080fc7ac-8430-4524-93c4-f0671d8d0a21] (#693)2026-04-27
Spec File

Goal

Audit every claim/citation pair across the 310+ hypotheses and 17 K wiki
pages, flag claims supported by references older than 5 years, and generate a
per-hypothesis bibliography that lists all supporting + contradicting papers
with freshness scores. Tie into the multi-provider ranker so the auditor can
suggest fresher replacement citations.

Why this matters

Old citations are a quiet credibility drain: a hypothesis claiming "TREM2
loss-of-function elevates Aβ" anchored only on a 2012 paper looks weak next
to one citing 2024 work. The audit makes staleness visible and actionable
(suggested fresh refs ready to swap in), and the bibliography feature gives
human researchers a publication-grade artifact to export.

Acceptance Criteria

☐ Migration claim_citation_freshness(claim_id, citation_pmid_or_doi,
pub_year, age_years, freshness_score, replacement_suggestions_json,
audited_at)
.
scripts/audit_citation_freshness.py walks claims and
wiki_page_refs; computes freshness_score = exp(-age_years*ln2/5).
☐ When age_years > 5, calls parallel_rank() with the claim text
filtered to last-3-year window; stores up to 3 suggested replacements.
☐ New endpoint /api/hypothesis/<id>/bibliography returns BibTeX +
JSON-LD.
/hypothesis/<id> page adds a "Citations" tab with a freshness
heatmap (red <0.3, amber 0.3-0.6, green >0.6) and one-click "swap
to suggested" action that opens a curation review.
☐ Aggregate metric on /atlas/quality: median_citation_freshness
tracked over time.
☐ Auditor runs scidex-citation-freshness.timer weekly Sunday 05:00.

Approach

  • Pull pub years from papers table where present; fall back to Crossref
  • published-print lookup.
  • Replacement search uses the parallel ranker scoped to recent window.
  • BibTeX export reuses existing rocrate_export.py helpers.
  • Dependencies

    • q-mslit-parallel-ranker.
    • Existing papers, claims, wiki_page_refs tables.

    Work Log

    2026-04-27 — task:080fc7ac (claude-sonnet-4-6)

    Implemented all acceptance criteria. Notes on spec vs actual:

    • parallel_rank() does not exist in the codebase; used paper_cache.search_papers() for replacement suggestions (same effect, same data providers).
    • wiki_page_refs table does not exist; auditor walks hypothesis_papers (12,677 rows across 310+ hypotheses). Wiki refs may be added to a future pass once that table is added.
    • hypothesis_id is used as the per-claim grouping key (1 hypothesis → N papers) since claims in this context are hypothesis-scoped.
    • Freshness metric added to /api/atlas/stats JSON and the Atlas HTML page stat grid.
    Files created/modified:

    FileChange
    migrations/add_claim_citation_freshness.pyNew table: claim_citation_freshness with 3 indices
    scripts/audit_citation_freshness.pyFull auditor: batch walk, freshness formula, replacement search, upsert
    api.pyBibliography endpoint /api/hypothesis/{id}/bibliography (BibTeX + JSON-LD); Citations tab on hypothesis detail page (freshness heatmap, swap suggestions, export link); median_citation_freshness in /api/atlas/stats and Atlas HTML page
    scidex-citation-freshness.serviceSystemd one-shot service
    scidex-citation-freshness.timerWeekly Sunday 05:00 timer
    Test run: python scripts/audit_citation_freshness.py --limit 50
    • 37 hypothesis-paper pairs audited; 5 stale (>5 yr); 27 rows inserted.
    • DB: mean_freshness=0.8189, median_freshness=1.0 (skewed high — recent papers dominate).
    Acceptance criteria status:
    ☑ Migration claim_citation_freshness table — applied and verified.
    scripts/audit_citation_freshness.py — walks hypothesis_papers; computes freshness_score = exp(-age*ln2/5).
    ☑ When age_years > 5, calls paper_cache.search_papers() (acts as parallel ranker); stores up to 3 replacements.
    /api/hypothesis/<id>/bibliography — BibTeX + JSON-LD, includes freshness_score per paper.
    /hypothesis/<id> "Citations" tab — freshness heatmap (red/amber/green), swap suggestions, export button.
    ☑ Atlas median_citation_freshness — in /api/atlas/stats JSON and Atlas page stat card.
    scidex-citation-freshness.timer — weekly Sunday 05:00 via Persistent=true.

    Sibling Tasks in Quest (Multi-Source Literature Search) ↗