[Atlas] Cross-artifact relationship-graph view (A cites B debates C) done

← Atlas
D3 force graph rooted at any artifact, expanding artifact_links N hops; shortest-path between artifacts; saved-view artifact.

Completion Notes

Auto-completed by supervisor after successful deploy to main

Git Commits (2)

Squash merge: orchestra/task/b4e04fba-triage-50-failed-tool-calls-by-skill-and (95 commits) (#1011)2026-04-27
[Atlas] Cross-artifact relationship-graph view (A cites B debates C) [task:66bdea91-0996-4c4f-95d1-080373aef901] (#939)2026-04-27
Spec File

Effort: thorough

Goal

The 688K-edge knowledge graph is exposed at /graph (site/graph.html)
but only over canonical entities (genes, diseases). The richer artifact_links table (which captures relationships like cites, synthesizes, derived_from, debates, supersedes, responds_to) is invisible to users.

Build a "relationship graph" viewer rooted at any artifact id that
expands its full N-hop neighborhood across artifact_links, so users
can trace "this hypothesis was synthesized by that brief, which cites
this paper, which is debated in this session, which answered this
open question". Today there's no way to see this lineage.

Acceptance Criteria

☐ New route GET /relationship-graph/{artifact_id} in api.py.
Optional query params: depth (default 2, max 4),
link_types (csv filter, default all), direction
(out / in / both, default both).
☐ Backed by /api/relationship-graph/{artifact_id}.json returning
{nodes: [{id, type, title, score, ...}], edges: [{src, dst,
type, created_at}]}
. Bounded: hard cap of 200 nodes per
response, BFS truncates with a truncated_at_node_count flag.
☐ Rendered via D3 force-directed graph in
site/relationship-graph.html, link-type colored, node-shape
by artifact_type. Click on node = navigate to that artifact's
page. Hover = tooltip with title + composite_score + 1-line
summary.
☐ Path-finding: ?to=<other_artifact_id> returns shortest path
(BFS) between two artifacts as a highlighted subgraph.
☐ Saved-view: a "save as artifact" button registers the current
view (root + depth + filters) as a relationship_view artifact
so it can be cited in briefs and embedded in dashboards.
☐ Pytest fixture seeds an 8-node graph with mixed link types and
asserts depth=2 returns the right neighborhood, depth=4
returns the right truncated set, and shortest-path returns the
expected 3-edge path.
☐ Human acceptance: open
/relationship-graph/<top-AD-hypothesis-id>?depth=3 and
verify ≥10 nodes appear with at least 3 distinct link types
represented.

Approach

  • Audit artifact_links schema and the existing link types in use
  • (SELECT DISTINCT link_type FROM artifact_links).
  • BFS implementation in
  • scidex/atlas/relationship_graph.py — recursive CTE in PG with
    depth limit + node-count cap; return ordered by hop distance.
  • D3 force-directed view in site/relationship-graph.html reusing
  • the styling from site/graph.html. New file, no edit to
    site/graph.html.
  • Saved-view artifact: register via artifact_registry with
  • metadata {root, depth, link_types, direction, snapshot_node_ids}.
  • Path-find: standard bidirectional BFS via second recursive CTE.
  • Dependencies

    • e352460b-2d76 — view_spec_json DSL (only used for embedded
    rendering of saved views).
    • Existing artifact_links table.

    Work Log

    2026-04-27 — Implementation complete [task:66bdea91-0996-4c4f-95d1-080373aef901]

    Approach taken:

    • Audited artifact_links: 20 valid link types in chk_link_type constraint; 3.4M rows dominated by see_also, related, mentions. Notable semantic types: cites (224), derives_from (11K), supports (1.5K).
    • BFS implemented in Python (not recursive CTE) for predictable node-count cap: scidex/atlas/relationship_graph.py with get_neighborhood() and find_shortest_path().
    • Added relationship_view to ARTIFACT_TYPES in artifact_registry.py.
    • Three API routes added to api.py:
    - GET /relationship-graph/{artifact_id} — HTML page, injects ROOT_ARTIFACT_ID
    - GET /api/relationship-graph/{artifact_id}.json — JSON BFS/path response
    - POST /api/relationship-graph/save-view — register view as artifact
    • site/relationship-graph.html: SVG D3 force-directed graph; link-type colored; node-shape by type (diamond=hypothesis, square=analysis/notebook/dataset, circle=default); click→artifact page; hover tooltip; depth/direction/link-type controls; shortest-path highlighted in gold.
    • 9 pytest tests in tests/atlas/test_relationship_graph.py — all pass.
    Human acceptance verified:
    • depth=3 from top AD hypothesis (hypothesis-h-var-de1677a080) returns 200 nodes (truncated), 12 distinct link types — well above the ≥10 nodes / ≥3 types threshold.

    Sibling Tasks in Quest (Atlas) ↗