How Blast Radius Analysis Works in code-review-graph: A Deep Dive into the SQLite-Powered Graph Algorithm
Blast radius analysis in code-review-graph measures the scope of a code change by performing a weighted breadth-first search through a SQLite knowledge graph, calculating impact scores based on edge types and depth decay to identify all affected nodes within a configurable hop limit.
The code-review-graph repository provides a sophisticated blast radius analysis tool that quantifies how far-reaching a code change might be by traversing relationships between code entities. This analysis helps developers and reviewers understand the potential risk and scope of modifications before they reach production. At its core, the system uses a custom SQLite-based graph traversal algorithm to compute precise impact scores for every affected node.
Core Components of the Blast Radius Engine
The Public Interface: get_impact_radius
Located in code_review_graph/tools/query.py, the get_impact_radius function serves as the primary entry point for blast radius analysis. It accepts either an explicit list of changed files or automatically discovers them via git diff, then coordinates with the graph store to compute and format the results. This wrapper builds human-readable summaries including counts of changed nodes, impacted nodes, additional affected files, and generates risk ratings (low/medium/high) when using detail_level="minimal".
The Graph Engine: get_impact_radius_sql
The heavy lifting occurs in code_review_graph/graph.py within the GraphStore.get_impact_radius_sql method (starting at line 742). This implementation performs the actual graph traversal using temporary SQLite tables and a frontier-based expansion algorithm. It seeds the search with nodes from changed files, then iteratively expands the frontier while maintaining best-known scores for each node, ensuring the query remains efficient even on cyclic graphs.
Step-by-Step Algorithm Execution
1. Seed Preparation and Edge Weight Configuration
The algorithm begins by identifying all nodes residing in the changed files through self.get_nodes_by_file and storing their qualified names in the _impact_seeds temporary table (lines 996-1000 in graph.py). Simultaneously, it loads the IMPACT_EDGE_WEIGHTS mapping from code_review_graph/constants.py (lines 421-429) into the _impact_weights table, assigning specific weights to relationship types such as CALLS or IMPORTS_FROM.
2. Frontier Initialization
Two critical temporary tables are created: _impact_best tracks the highest impact score for each node, while _impact_frontier contains nodes awaiting expansion in the current iteration. Both tables are initialized with the seed nodes at a score of 1.0 (lines 511-518).
3. Iterative Weighted Expansion
For each depth iteration up to max_depth, the algorithm joins the current frontier with the edges table in both directions to generate candidates. Each candidate receives a score calculated as score = parent_score × edge_weight × depth_decay, where IMPACT_DEPTH_DECAY reduces the score as distance from the source increases (lines 585-618). Only candidates exceeding both the node's current best score and the global IMPACT_SCORE_FLOOR threshold survive and become the next frontier (loop at lines 886-904).
4. Result Extraction and Truncation Detection
After the BFS completes, the system selects the top max_nodes + 1 rows from _impact_best—the extra row serves solely to detect if results were truncated. It joins these results back to the nodes table to retrieve full entity data, filtering out seed nodes and internal "verilog-kind" nodes (lines 909-923).
Practical Implementation Examples
Command-Line Usage
The simplest way to run blast radius analysis is through the CLI:
# Analyze the blast radius of changes in the current branch
crg impact
This command maps to code_review_graph/main.py in the get_impact_radius_tool function, which internally invokes the full analysis pipeline.
Python API Integration
For programmatic access, import the query tool directly:
from code_review_graph.tools.query import get_impact_radius
# Generate a detailed report for the last commit
report = get_impact_radius(
changed_files=None, # Auto-detect via git diff
max_depth=2,
max_results=500,
detail_level="standard"
)
print(report["summary"])
# Output example:
# Blast radius for 3 changed file(s):
# - 5 nodes directly changed
# - 27 nodes impacted (within 2 hops)
# - 4 additional files affected
Direct Graph Store Access
Advanced users can interact with the underlying GraphStore class:
from code_review_graph.graph import GraphStore
store = GraphStore("/tmp/crg.db")
changed_files = ["src/foo/bar.py", "src/baz/qux.ts"]
impact = store.get_impact_radius_sql(
changed_files,
max_depth=3,
max_nodes=200
)
print(f"Impacted nodes: {len(impact['impacted_nodes'])}")
Configuration Constants and Tuning
Edge Weights and Scoring Parameters
The behavior of blast radius analysis is controlled by constants defined in code_review_graph/constants.py:
- IMPACT_EDGE_WEIGHTS: Dictionary mapping relationship types (e.g.,
CALLS,IMPORTS_FROM) to multipliers that amplify or reduce the propagation of impact scores - IMPACT_DEPTH_DECAY: Factor applied at each hop to simulate diminishing influence as distance from the change increases
- IMPACT_SCORE_FLOOR: Minimum threshold below which nodes are excluded from results, preventing infinite expansion through weak connections
Summary
- Blast radius analysis in code-review-graph uses a custom SQLite-based BFS algorithm to measure code change impact through relationship traversal.
- The
get_impact_radiusfunction incode_review_graph/tools/query.pyprovides the public API, whileget_impact_radius_sqlincode_review_graph/graph.pyhandles the low-level graph computation. - The algorithm employs weighted scoring (
parent_score × edge_weight × depth_decay) with configurable thresholds to ensure relevant results while maintaining linear performance on cyclic graphs. - Results include counts of changed nodes, impacted nodes, affected files, and risk ratings to guide code review prioritization.
Frequently Asked Questions
How does code-review-graph prevent infinite loops during blast radius analysis?
The algorithm uses the _impact_best temporary table to track the highest score achieved for each node, only updating the frontier when a new path yields a strictly better score. Combined with the IMPACT_SCORE_FLOOR threshold and max_depth limit, this ensures termination even when encountering cyclic dependencies in the graph.
What determines the impact score of a node in the blast radius calculation?
According to the source code in code_review_graph/graph.py, each node's impact score is calculated as the product of three factors: the parent node's score, the specific edge weight from IMPACT_EDGE_WEIGHTS based on relationship type, and the IMPACT_DEPTH_DECAY factor. This multiplication ensures that influence diminishes appropriately with both relationship strength and graph distance.
Can I customize which types of relationships affect the blast radius?
Yes, by modifying the IMPACT_EDGE_WEIGHTS dictionary in code_review_graph/constants.py (lines 421-429), you can adjust how different edge types (such as CALLS, IMPORTS_FROM, or INHERITS_FROM) contribute to the score. Setting a weight to 0.0 effectively excludes that relationship type from the analysis.
What is the difference between max_depth and max_nodes in the blast radius API?
The max_depth parameter controls how many hops the algorithm performs from the seed nodes, limiting the search radius in the graph, while max_nodes caps the total number of results returned after scoring. The system actually fetches max_nodes + 1 internally to detect when truncation occurs, allowing it to report whether additional impacted nodes exist beyond the returned set.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →