Source-text capture for a node — signature, body slice, preceding doc-comment,
and byte range into the original file. Filled during pass 1 from the
tree-sitter node’s byte range; cheap (no extra parsing).
LLD annotations added during pass-2 analysis. All fields are optional because
pass 2 runs asynchronously — nodes are queryable before annotations arrive.
Find import cycles via Tarjan’s SCC over EdgeKind::Imports edges.
Returns one Vec<String> (node IDs) per cycle; cycles of size 1 (self-loops)
are excluded.
Count inbound Calls edges per destination node id.
Shared by gitcortex-mcp (centrality/clustering/tour) and gitcortex-viz
so both surfaces always use the same algorithm and cannot drift.