Skip to content

v6.13.0: Deterministic citation backfill (consolidated-footnotes recovery) #150

Description

@Number531

Status

Built + tested locally (29/29 + 114/114 ecosystem regression). Branch: feat/citation-synthesis-backfill. PR pending.

Problem

KG Phase 2 reads reports.content WHERE report_key='consolidated-footnotes' to produce citation nodes + CITES/SOURCED_FROM/REFERENCES edges. When citation-validator's output is truncated by Sonnet 4.6's 64K output token cap (observed on SpaceX-May 2026-05-16-1778951162), only the CITATION VALIDATION SUMMARY header persists — no footnote inventory. Phase 2 produces 0 citation nodes → ~1,100 lost edges (~80% of the SpaceX-vs-DigitalBridge KG disparity).

Solution

Transparent pre-step inside the existing /api/admin/sessions/:key/rebuild-kg endpoint (sibling to v6.12.0 entity synthesis). When detection heuristic identifies a truncated consolidated-footnotes, deterministically rebuild it from section-IV-* reports — zero LLM, zero new endpoints, zero schema changes.

Architecture — 4 deterministic stages

  1. Per-section miner with format auto-detection ([^N]: and N.); heading-anchored or last-15-KB fallback; sub-threshold fail-soft (<3 footnotes/section = no match)
  2. Global consolidator with provenance tags ([Original section: IV.X]) for Phase 2 SOURCED_FROM edge construction
  3. Canonical Format A emitter (Phase 2's strongest parse path) + regenerated summary header + citation-map.md sidecar
  4. Persistence: UPDATE reports.content + filesystem write + audit-backup INSERT into report_artifacts (ON CONFLICT DO NOTHING preserves original truncated state)

Detection — structural, not string-dependent

Trigger fires when:

  • Section files have ≥50 parseable footnotes (signal sufficient), AND
  • Consolidated has <30% of section footnote count

Independent of producer prompt header text / summary structure. Will not fire on healthy sessions (DigitalBridge regression-gated). Will not fire on intentionally small sessions.

Section-level truncation cross-check

detectSectionTruncation cross-checks narrative [^48] references against [^48]: definitions. >2 orphans = section file itself was truncated (e.g., memo-section-writer also hit 64K). Surfaced in audit payload + Prometheus gauge.

Observability — 3 Prometheus gauges

  • claude_citation_synthesis_fired_total{outcome="synthesized|skipped|failed"} — running counter; sustained "synthesized" = citation-validator producer regression
  • claude_citation_synthesis_footnotes_recovered{session_key} — last-value per session; healthy: 300-500
  • claude_citation_synthesis_section_orphan_refs{section} — section-level truncation signal

Files

Runtime:

  • src/utils/citationSynthesis.js (NEW, ~330 LoC)
  • src/utils/sdkMetrics.js (+3 gauges)
  • src/server/adminRouter.js (+70 LoC pre-step in /rebuild-kg, after v6.12.0 entities block)

Tests:

  • test/sdk/citation-synthesis.test.js (NEW, 29 tests, 9 groups)

Expected impact

Metric SpaceX-May Now Post-v6.13.0
consolidated-footnotes size 6.5 KB summary ~80-150 KB full inventory
Citation nodes 0 ~350-450
Total edges 409 ~1,500 (close to DigitalBridge baseline minus deal-shape)
citations_source in response "synthesized"
Session class Behavior
Pre-truncation legacy sessions (SpaceX-May, etc.) First /rebuild-kg synthesizes; subsequent rebuilds detect healthy state and skip
Healthy v6.11.0+ sessions (DigitalBridge, SpaceX-Apr) Detection returns false → no-op → citations_source: "native"
Future sessions where citation-validator truncates Synthesizer auto-fires, recovers the citation graph

Validation gauntlet (post-deploy)

  • Trigger /rebuild-kg for SpaceX session 2026-05-16-1778951162 → expect citations_source: "synthesized", citations_audit.total_footnotes ≥ 400
  • Confirm kg_nodes WHERE node_type='citation' count ≥ 350
  • Confirm total kg_edges ≥ 1,200
  • Confirm SELECT OCTET_LENGTH(content) FROM reports WHERE report_key='consolidated-footnotes' AND session_id=$1 ≥ 80 KB
  • Confirm report_artifacts has new row with category='audit', source='citation-backfill-pre-v6.13.0'
  • Regression gate: Trigger /rebuild-kg for DigitalBridge 2026-03-31-1774972751 → expect citations_source: "native", NO synthesis, KG counts unchanged (1,083/2,062)

Properties

  • Zero LLM dependency
  • Zero new endpoints (extends /rebuild-kg)
  • Zero frontend changes
  • Zero DB schema changes
  • Idempotent on re-run (UPDATE always; audit INSERT preserves original via ON CONFLICT)
  • Fail-soft throughout
  • Pre-state preserved indefinitely in report_artifacts

Risk

4/10 — one level higher than v6.12.0 because UPDATE on canonical reports.content. Offset by structural detection + DigitalBridge regression gate + audit backup.

Rollback

Revert adminRouter.js pre-step block (~70 LoC). citationSynthesis.js becomes dead code. ~5 min.

Related

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions