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

> Discover how impact radius analysis works in CRG using bidirectional BFS on a graph database. Understand affected code entities with this in-depth explanation.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: deep-dive
- Published: 2026-08-10

---

**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](https://github.com/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`](https://github.com/tirth8205/code-review-graph/blob/main/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`](https://github.com/tirth8205/code-review-graph/blob/main/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.

```typescript
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?"

```typescript
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`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/blastRadius.ts) (lines 17–68) provides the UI entry point:

```typescript
// 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

```typescript
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

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

```

## Key Files Reference

| File | Purpose | URL |
|------|---------|-----|
| [`src/backend/sqlite.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/sqlite.ts) | `SqliteReader` class with `getImpactRadius` BFS implementation | [source](https://github.com/tirth8205/code-review-graph/blob/main/code-review-graph-vscode/src/backend/sqlite.ts) |
| [`src/features/blastRadius.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/blastRadius.ts) | Command registration and cursor-to-target resolution | [source](https://github.com/tirth8205/code-review-graph/blob/main/code-review-graph-vscode/src/features/blastRadius.ts) |
| [`src/views/treeView.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/views/treeView.ts) | `BlastRadiusTreeProvider` UI component | [source](https://github.com/tirth8205/code-review-graph/blob/main/code-review-graph-vscode/src/views/treeView.ts) |
| [`src/features/cursorResolver.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/cursorResolver.ts) | Helper for finding nodes at cursor position | [source](https://github.com/tirth8205/code-review-graph/blob/main/code-review-graph-vscode/src/features/cursorResolver.ts) |

## 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`](https://github.com/tirth8205/code-review-graph/blob/main/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.