How Impact Radius Analysis Works in CRG: BFS Graph Traversal Explained

Impact radius analysis in CRG (Code-Review-Graph) uses a bidirectional breadth-first search (BFS) over a SQLite graph database to find all code entities affected by file changes, with a default depth of 2 hops.

The impact radius feature—also called blast radius in the codebase—determines which parts of your codebase are at risk when specific files change. This article explains the complete implementation in the tirth8205/code-review-graph repository, from graph storage to the VS Code user interface.

Graph Storage Architecture

The foundation of impact radius analysis is a SQLite database populated by the Python backend. This database contains two core tables:

  • nodes – code entities (files, classes, functions, methods) with unique qualified_name identifiers and source file references
  • edges – relationships including CALLS, IMPORTS_FROM, DEPENDS_ON, and others

Each node's qualified_name serves as the canonical identifier used throughout the traversal algorithm.

The SqliteReader Class: Database Access Layer

The VS Code extension accesses this database through SqliteReader in src/backend/sqlite.ts. This TypeScript class wraps the better-sqlite3 library and provides typed query helpers for graph operations.

The impact radius implementation lives in SqliteReader.getImpactRadius (lines 40–81 in src/backend/sqlite.ts).

Impact Radius Algorithm: Step-by-Step

The algorithm follows three distinct phases:

Seed Collection

The method receives an array of changed file paths. For each file, it gathers all nodes belonging to that file and builds a seed set of their qualified_name values.

const seeds = new Set<string>();
for (const f of changedFiles) {
  for (const node of this.getNodesByFile(f)) {
    seeds.add(node.qualifiedName);
  }
}

BFS Traversal

Starting from the seed set, the algorithm performs a bidirectional BFS up to a configurable maxDepth (default: 2). For each node in the current frontier:

  • Forward traversal: fetches outgoing edges via getEdgesBySource to find "who does this node affect?"
  • Backward traversal: fetches incoming edges via getEdgesByTarget to find "who depends on this node?"
const visited = new Set<string>();
let frontier = new Set(seeds);
const impacted = new Set<string>();
let depth = 0;

while (frontier.size > 0 && depth < maxDepth) {
  const nextFrontier = new Set<string>();
  for (const qn of frontier) {
    visited.add(qn);
    // forward edges
    for (const e of this.getEdgesBySource(qn)) {
      if (!visited.has(e.targetQualified)) {
        nextFrontier.add(e.targetQualified);
        impacted.add(e.targetQualified);
      }
    }
    // reverse edges
    for (const e of this.getEdgesByTarget(qn)) {
      if (!visited.has(e.sourceQualified)) {
        nextFrontier.add(e.sourceQualified);
        impacted.add(e.sourceQualified);
      }
    }
  }
  frontier = nextFrontier;
  depth++;
}

The bidirectional approach ensures both downstream and upstream dependencies are captured.

Result Materialization

After BFS completion, the method:

  1. Resolves seed and impacted qualified_name values to full GraphNode objects
  2. Gathers distinct impacted file paths
  3. Extracts all edges connecting involved nodes via getEdgesAmong

The final ImpactRadius object contains:

  • changedNodes – entities directly in changed files
  • impactedNodes – entities reached via the BFS
  • impactedFiles – distinct files containing impacted nodes
  • edges – all relationships among involved nodes

This mirrors the Python implementation GraphStore.get_impact_radius for cross-language consistency.

User-Facing Command Integration

The codeReviewGraph.showBlastRadius command in src/features/blastRadius.ts (lines 17–68) provides the UI entry point:

// src/features/blastRadius.ts – command registration
vscode.commands.registerCommand('codeReviewGraph.showBlastRadius', async () => {
  const editor = vscode.window.activeTextEditor;
  if (!editor) return;

  // Resolve innermost node at cursor, fallback to file
  let targetNode = await reader.getNodeAtCursor(editor.document, position);
  const targetFiles = targetNode 
    ? [targetNode.filePath] 
    : [editor.document.fileName];

  // Read user-configured depth
  const depth = config.get<number>('blastRadiusDepth', 2);

  // Execute impact radius analysis
  const radius = reader.getImpactRadius(targetFiles, depth);

  // Populate tree view
  treeProvider.setImpactRadius(radius);
});

The command:

  • Obtains the active editor's file and cursor position
  • Resolves the innermost node via reader.getNodeAtCursor
  • Falls back to file-level analysis if no specific node is found
  • Reads codeReviewGraph.blastRadiusDepth from user configuration
  • Feeds results into BlastRadiusTreeProvider for visualization

Programmatic Usage Examples

From Another Extension Feature

import { SqliteReader } from '../backend/sqlite';

const reader = await SqliteReader.create(dbPath);

const changed = ['/src/utils/fileHelper.ts', '/src/api/userService.ts'];
const radius = reader.getImpactRadius(changed, 3);

console.log('Changed nodes:', radius.changedNodes.length);
console.log('Impacted nodes:', radius.impactedNodes.length);
console.log('Impacted files:', radius.impactedFiles);

Invoking the VS Code Command

vscode.commands.executeCommand('codeReviewGraph.showBlastRadius');

Key Files Reference

File Purpose URL
src/backend/sqlite.ts SqliteReader class with getImpactRadius BFS implementation source
src/features/blastRadius.ts Command registration and cursor-to-target resolution source
src/views/treeView.ts BlastRadiusTreeProvider UI component source
src/features/cursorResolver.ts Helper for finding nodes at cursor position source

Summary

  • Impact radius analysis uses bidirectional BFS with configurable depth (default: 2) to find affected code
  • The algorithm operates on SQLite graph data with nodes and edges tables
  • SqliteReader.getImpactRadius in src/backend/sqlite.ts contains the core traversal logic
  • Both forward and reverse edges are traversed to capture complete dependency chains
  • The VS Code command integrates cursor resolution, user configuration, and tree view visualization

Frequently Asked Questions

What is impact radius in CRG?

Impact radius—also called blast radius—is a code analysis feature that identifies which parts of a codebase are affected when specific files change. It answers "what else might break?" by traversing dependency relationships in both directions through a graph representation of your code.

How does the BFS traversal handle cycles in the dependency graph?

The algorithm uses a visited Set to track already-processed qualified_name values. Before adding any node to the next frontier, it checks visited.has() to prevent infinite loops and redundant processing. This ensures termination even with circular dependencies.

Can I configure how far the impact radius search travels?

Yes. The maxDepth parameter controls BFS iterations (default: 2). Users can set codeReviewGraph.blastRadiusDepth in VS Code settings. Deeper searches find more distant relationships but increase computation time and result noise.

Why does the algorithm traverse edges in both directions?

Bidirectional traversal captures both "this node calls/uses others" (outgoing edges) and "other nodes call/depend on this" (incoming edges). This is essential for complete impact analysis—outgoing edges show what your changes might break; incoming edges show what external code depends on your changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →