# How CRG Identifies Execution Paths and Flows: Static Call Graph Analysis

> Learn how CRG identifies execution paths and flows by statically parsing code into ASTs, resolving call edges, and storing call chains in a queryable SQLite database.

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

---

**CRG identifies execution paths and flows by statically parsing source code into abstract syntax trees, resolving function call edges, and materializing complete call chains into a queryable SQLite database with calculated depth metrics.**

The `tirth8205/code-review-graph` repository implements a multi-language static analysis engine that maps execution paths and flows without runtime instrumentation. By walking ASTs and recording caller-callee relationships, CRG constructs a persistent flow graph that enables precise impact analysis and automated code review workflows.

## Static Tracing: Mapping the Call Graph

CRG begins execution path discovery through **static tracing**, a process that traverses source files to identify every reachable function call. The entry point for this analysis is the `trace_flows` function in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py), which orchestrates the AST parsing and edge resolution logic [lines 285-306](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py#L285-L306).

For each source file, CRG uses language-specific parsers to resolve imports and attribute accesses, converting raw syntax into structured call edges. When repositories evolve, the `incremental_trace_flows` function [lines 459-473](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py#L459-L473) retraces only modified files, merging new edges with existing flows to maintain an up-to-date call graph without full reanalysis.

## Flow Representation and Graph Construction

Once edges are collected, CRG materializes them into **flow records** using the `FlowAdjacency` model defined in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) [lines 156-165](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py#L156-L165). Each flow represents a complete execution path from an entry point through its deepest call chain.

The system calculates **depth** as the longest call-chain length from the entry point, classifies the **kind** of entry point (e.g., `Function`, `Class`), and stores an ordered list of **steps** representing caller-to-callee transitions. This structured representation enables precise querying of specific execution scenarios and dependency chains.

## Persistence and Query Interface

CRG persists discovered flows to an embedded SQLite database via the `store_flows` function, ensuring **atomic transactions** that roll back completely on failure [as tested in [`tests/test_transactions.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_transactions.py) lines 63-81](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_transactions.py#L63-L81). The flows are stored in a dedicated `flows` table with indexed columns for rapid retrieval.

The repository exposes these capabilities through MCP-tool wrappers including `list_flows`, `get_flow`, and `get_affected_flows_func`, which are validated in [`tests/test_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_tools.py) [lines 1062-1190](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_tools.py#L1062-L1190). These utilities provide both programmatic Python APIs and CLI commands for inspecting execution paths.

## Practical Examples: Tracing and Querying Execution Flows

Generate and inspect execution paths using the CRG CLI:

```bash

# Trace all flows in the current repository

code-review-graph trace-flows

# List flows sorted by call depth, limiting to 10 results

code-review-graph list-flows --sort-by depth --limit 10

# Retrieve a specific flow with source code context

code-review-graph get-flow --name handle_request --include-source

# Identify affected flows after modifying specific files

code-review-graph get-affected-flows --changed-files auth.py

```

For programmatic access, import the MCP tools directly:

```python
from code_review_graph.tools import list_flows, get_flow, get_affected_flows_func

# Query top-level execution paths

flows = list_flows(repo_root=".", sort_by="depth", limit=5)

# Retrieve detailed flow with source snippets

flow = get_flow(flow_name="handle_request", repo_root=".", include_source=True)

# Analyze impact of file changes

affected = get_affected_flows_func(changed_files=["auth.py"], repo_root=".")

```

## Summary

- **Static AST Parsing**: CRG uses `trace_flows` in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py) to walk source trees and resolve static call edges without runtime execution.
- **Incremental Updates**: The `incremental_trace_flows` function retraces only changed files, enabling efficient updates to the execution path graph.
- **Structured Storage**: Flow records stored via `store_flows` include depth metrics, entry-point classification, and ordered step sequences in an atomic SQLite transaction.
- **Multi-Interface Access**: Execution paths are queryable through both CLI commands and Python MCP tools like `get_flow` and `get_affected_flows_func`.

## Frequently Asked Questions

### How does CRG handle incremental updates when source files change?

CRG implements incremental analysis through the `incremental_trace_flows` function in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py) [lines 459-473](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py#L459-L473). This function identifies modified files since the last trace, re-parses only those ASTs, and merges the resulting call edges with the existing flow graph, avoiding costly full-repository rescans.

### What specific data is stored for each identified execution flow?

Each flow record contains a unique identifier, the **depth** (maximum call-chain length from entry), the **kind** of entry point (Function, Class, etc.), and an ordered list of **steps** representing caller-to-callee pairs. These fields are defined in the `FlowAdjacency` model within [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) [lines 156-165](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py#L156-L165).

### How does CRG ensure database consistency during flow storage?

The `store_flows` function wraps all INSERT operations in a SQLite transaction. If any part of the storage operation fails, the entire transaction rolls back, leaving the database in a consistent state. This atomic behavior is verified in [`tests/test_transactions.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_transactions.py) [lines 63-81](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_transactions.py#L63-L81).

### Can CRG trace execution paths across multiple programming languages?

Yes, CRG supports multi-language analysis through language-specific parsers that resolve static imports and attribute accesses for Python, Java, Rust, and other languages. The tracing engine abstracts these differences to produce a unified call graph representation regardless of source language.