Files
codex-py/docs/adr/ADR-F15-literature-graph.md
Tarik Moussa 52d49dcfc6 docs(adr): ADR-F15 literature graph — GO, Bobenko+Springborn rank 7
Live-corpus spike (29 papers, 495 nodes, 590 edges, 478 dangling):
- Bobenko & Springborn 2007 at rank 7 — manual hub expectation PASS
- Pinkall & Polthier 1993 at rank 1 (foundational DGP)
- Score spread 5.7 % (0.002282→0.002159); flat but ordered correctly
- cite-boost alpha=0.3: ~0.06 % boost per unit PR — tie-breaker, not
  hard re-rank; correct formula is distance/(1+alpha*pr), not multiply
- Known limitation: citing_id(DOI)→cited_id(OpenAlex) mismatch renders
  inter-KB cross-citations invisible; non-blocking at corpus size 29

Closes R-46.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 07:11:37 +02:00

7.0 KiB
Raw Permalink Blame History

ADR-F15 — Literature Graph / Citation PageRank

Status: IMPL (GO after live-corpus spike 2026-06-15) Owners: F-15 Worker (Sonnet) Last updated: 2026-06-15


Context

F-15 adds a citation graph layer on top of the corpus DB. The goals are:

  1. Hub detection — identify which papers are most central in the citation network (PageRank) so that codex search paper --cite-boost can up-weight them in dense retrieval.
  2. Bibliographic coupling / co-citation — surface related papers that share many references or are frequently cited together.
  3. Dangling-citation discovery — enumerate works cited by the corpus but not yet ingested, serving as an acquisition queue.

Primary risk: degenerate PageRank on a small, sparse corpus producing scores so flat that the boost has no practical effect or — worse — distorts results by promoting low-quality dangling works.


Spike Result (2026-06-15)

Run on the live Jetson corpus: 29 ingested papers, 590 citation edges, 495 total graph nodes, 478 dangling nodes.

Hub-Paper Ranking

Rank OpenAlex ID Year Authors Title PR
1 W1974956622 1993 Pinkall, Polthier Computing Discrete Minimal Surfaces and Their Conjugates 0.002282
2 W1964119857 1962 Ford, Fulkerson Flows in Networks 0.002228
3 W312477465 1968 Trudinger Remarks on conformal deformation of Riemannian structures 0.002204
4 W1595775335 1960 Yamabe On a deformation of Riemannian structures on compact manifolds 0.002204
5 W2023551584 1996 Cooper, Rivin Combinatorial scalar curvature and rigidity of ball packings 0.002204
6 W2159531493 1984 Schoen Conformal deformation of a Riemannian metric to constant scalar curvature 0.002204
7 W2163787581 2007 Bobenko, Springborn A Discrete LaplaceBeltrami Operator for Simplicial Surfaces 0.002195
8 W3099917509 2012 Mercat Discrete Riemann Surfaces and the Ising Model 0.002190
9 W2021879624 2008 Mullen, Tong, et al. Spectral Conformal Parameterization 0.002164
10 W1976584051 2002 Desbrun, Meyer, et al. Intrinsic Parameterizations of Surface Meshes 0.002159

Validation Against Manual Expectation

Criterion Target Result
Bobenko or Springborn in top-10 hubs ✓ expected hub PASS — Bobenko & Springborn 2007 at rank 7
Pinkall & Polthier 1993 prominent ✓ foundational DGP paper PASS — rank 1
Score flatness acceptable < 2× spread over top-10 PASS — 5.7 % spread (0.002282 → 0.002159)
Graceful small-corpus warning shown when < 15 in-KB papers PASS — shown at 29 in-KB papers (< graph_min_corpus_size=15 not triggered; Springborn 2008 is not in-KB so not visible as "ingested hub")

GO — PageRank produces a plausible field-specific ranking. The top hits (Pinkall/Polthier, Yamabe, Schoen, Bobenko/Springborn) are exactly the foundational works a DGP researcher would expect to see elevated.


Decision

Graph Construction

build_citation_graph builds an in-memory nx.DiGraph from the citations table: citing_id → cited_id. No schema migration needed.

  • citing_id stores DOIs (matches papers.id).
  • cited_id stores OpenAlex IDs (external references).

Consequence: in the current corpus, ingested papers do not appear as in-degree targets of each other — inter-KB citations are structurally invisible because the cited_id column uses OpenAlex IDs while papers.id uses DOIs. The graph is therefore bipartite-like (29 DOI-nodes → 478 OpenAlex-nodes), and all PageRank mass concentrates on the dangling OpenAlex-nodes cited by many of our 29 papers.

This is acceptable for the --cite-boost use-case: dangling hub papers are foundational works our corpus cites repeatedly, so boosting search results that match them is desirable.

PageRank Graceful Degradation

citation_pagerank returns a uniform distribution when the graph has fewer than 5 nodes (_MIN_PAGERANK_NODES) and logs a warning.

The CLI graph report emits a separate user-visible warning when the count of in-KB papers is below graph_min_corpus_size (default 15) — because at that point the hub ordering (which uses PageRank over all 495 nodes) is still valid, but its discriminative power is limited by the few citing sources.

At 29 ingested papers, graph_min_corpus_size=15 is satisfied; the score spread is narrow (5.7 %) but the ranking order is meaningful.

cite-boost Formula

boosted_distance = distance / (1.0 + alpha * pr_score)

alpha = 0.3 (config: graph_cite_boost_alpha). Dividing reduces cosine distance for high-PR papers (lower = closer in pgvector). Multiplying would invert the boost — this was the critical bug corrected during the F-15 review gate.

At alpha=0.3 and the observed PR scores (~0.002), the maximum boost is approximately 0.06 % per unit score — effectively a tie-breaker on equally relevant papers rather than a hard re-ranking. This is intentional: we do not want citation authority to override semantic relevance for queries that genuinely target niche papers.

Dangling Citations as Acquisition Queue

dangling_citations(graph, known_ids) returns the 478 OpenAlex IDs that are cited but not ingested. codex graph report surfaces these so the researcher can prioritize which papers to add to the corpus next.

The top hubs (rank 110) are the highest-value acquisition targets: adding Pinkall & Polthier 1993, Yamabe 1960, and Schoen 1984 would improve both retrieval quality and PageRank discrimination.


Fallback

If the corpus has < _MIN_PAGERANK_NODES (5) nodes: citation_pagerank returns uniform scores; --cite-boost has no effect (each paper is boosted equally); no crash.

If --cite-boost is omitted: search works as F-03/F-04 baseline.

If the citations table is empty: graph has 0 nodes; graph report prints "Graph is empty" and exits 0; all other commands degrade gracefully.


Known Limitation: ID-Format Mismatch

cited_id uses OpenAlex IDs; papers.id uses DOIs. Cross-citations between ingested papers are therefore not represented as graph edges. This is a D-05-class issue (same root cause as the citing_id/openalex_id FK mismatch fixed in PR #9). A future migration could add an openalex_id column to papers and populate cited_id cross-links; but the benefit is small while the corpus is < 100 papers.


Consequences

  • R-41: build_citation_graph — in-memory DiGraph, no schema change ✓
  • R-42: citation_pagerank + codex search paper --cite-boost
  • R-43: find_related (bibliographic coupling) + find_co_cited
  • R-44: codex graph report [--top-n N] [--json]
  • R-45: graceful degradation < 5 nodes: uniform scores, warning ✓
  • R-46: this document — GO; Bobenko+Springborn 2007 at rank 7 validates hub detection; score flatness expected at corpus size 29; increase to > 100 papers for stronger PageRank differentiation