# How Execution Flows Are Traced Through the Call Graph in code-review-graph

> Discover how code-review-graph traces execution flows using a knowledge graph and breadth-first search to generate linear paths with criticality scores.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: internals
- Published: 2026-07-20

---

**The code-review-graph package traces execution flows by detecting entry points in a SQLite-backed knowledge graph and performing a breadth-first search (BFS) over CALLS edges to generate linear execution paths with criticality scores.**

The `code-review-graph` repository builds a static analysis toolchain that maps codebase structure into a queryable graph. Understanding how execution flows are traced through the call graph enables developers to identify critical paths, analyze test coverage, and prioritize code review efforts.

## Detecting Entry Points in the Call Graph

The `detect_entry_points` function in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py) (lines 64-81) identifies functions that can initiate program execution. It evaluates every `Function` and `Test` node against three distinct criteria to determine if it qualifies as an entry point.

### True Root Functions

Functions with **no inbound CALLS edges**—meaning nothing else in the codebase invokes them—are flagged as potential entry points. The implementation queries `store.get_all_call_targets()` at line 179 to build a set of called qualified names, then filters for nodes absent from that set.

### Framework-Specific Decorators

The analyzer scans for framework decorators using regex patterns defined in `_FRAMEWORK_DECORATOR_PATTERNS` (lines 26-71). When a node's `extra["decorators"]` field matches patterns for Flask (`@app.get`), Click (`@click.command`), Spring (`@GetMapping`), or similar frameworks, the `_has_framework_decorator` helper (line 29) marks it as an entry point.

### Conventional Entry Names

Functions matching naming conventions in `_ENTRY_NAME_PATTERNS` (lines 73-84) are automatically classified as entry points. These patterns include common names like `main`, `handle_*`, and `lambda_handler`, evaluated by the `_matches_entry_name` function (line 44).

## Loading the Flow Adjacency Structure

To avoid expensive SQLite lookups during traversal, `GraphStore.load_flow_adjacency` in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) (lines 1493-1527) materializes the graph into a `FlowAdjacency` dataclass. This in-memory structure contains:

- `nodes_by_qn`: Maps qualified names to `GraphNode` objects
- `nodes_by_id`: Maps node IDs to `GraphNode` objects  
- `calls_out`: Dictionary mapping source qualified names to lists of target qualified names for CALLS edges
- `has_tested_by`: Set of qualified names with TESTED_BY edges for criticality calculations

## BFS Traversal of Execution Flows

With entry points identified and the adjacency structure loaded, the system traces execution flows using breadth-first search.

### Tracing Individual Execution Paths

The `_trace_single_flow` function (lines 222-260 in [`flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/flows.py)) implements a forward BFS starting from each entry point. It initializes a queue with the entry point's qualified name at depth 0, then iteratively processes each node by recording its ID and enqueueing unvisited callees from `calls_out`. The traversal respects a configurable `max_depth` parameter (default 15) and discards trivial flows containing fewer than two nodes.

### Criticality Scoring and Flow Assembly

For each valid flow, the system calculates a **criticality score** based on factors including test coverage (using the `has_tested_by` set) and flow depth. The resulting dictionary contains the ordered path of node IDs, distinct files touched, depth metrics, and the computed criticality value.

## Complete Execution Flow Pipeline

The `trace_flows` function (lines 284-316) orchestrates the complete process:

```python
def trace_flows(
    store: GraphStore,
    max_depth: int = 15,
    include_tests: bool = False,
) -> list[dict]:
    entry_points = detect_entry_points(store, include_tests=include_tests)
    adj = store.load_flow_adjacency()
    flows = []
    for ep in entry_points:
        flow = _trace_single_flow(adj, ep, max_depth)
        if flow:
            flows.append(flow)
    flows.sort(key=lambda f: f["criticality"], reverse=True)
    return flows

```

This pipeline first identifies entry points, loads the adjacency structure once, traces each entry point via BFS, and returns flows sorted by criticality.

## Practical Code Examples

### Tracing Production Flows

To analyze all production execution flows while excluding test-only entry points:

```python
from code_review_graph.graph import GraphStore
from code_review_graph.flows import trace_flows

store = GraphStore("my-repo-graph.db")
all_flows = trace_flows(store, max_depth=20, include_tests=False)

for flow in all_flows[:5]:
    print(f"Flow {flow['entry_point']} → depth {flow['depth']}")
    print("  nodes:", flow["path"])
    print("  criticality:", flow["criticality"])

```

### Incremental Re-tracing After Changes

When specific files change, `incremental_trace_flows` updates only affected flows without rebuilding the entire graph:

```python
from code_review_graph.flows import incremental_trace_flows

changed_files = ["src/services.py", "src/api/routes.py"]
re_traced = incremental_trace_flows(store, changed_files, max_depth=15)
print(f"Re-traced {re_traced} flows after modifications")

```

### Retrieving Detailed Flow Information

To access step-by-step details for a specific flow:

```python
from code_review_graph.flows import get_flow_by_id

flow_detail = get_flow_by_id(store, flow_id=42)
print("Flow name:", flow_detail["name"])
for step in flow_detail["steps"]:
    print(f"{step['qualified_name']} ({step['file']}:{step['line_start']}-{step['line_end']})")

```

## Summary

- **Entry point detection** combines static analysis of call targets, framework decorators, and naming conventions to identify flow origins in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py).
- **Flow adjacency loading** materializes the SQLite graph into RAM via `load_flow_adjacency` in [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) to enable fast traversal.
- **BFS traversal** in `_trace_single_flow` explores call relationships up to a configurable depth, filtering trivial flows and calculating criticality scores.
- The complete `trace_flows` pipeline returns execution paths sorted by criticality, enabling targeted code review and analysis.

## Frequently Asked Questions

### What constitutes an entry point in the code-review-graph system?

An entry point is any function identified by `detect_entry_points` that has no inbound CALLS edges, uses recognized framework decorators like `@app.get` or `@click.command`, or matches conventional naming patterns such as `main` or `lambda_handler`. These functions represent potential starting points for program execution.

### How does the system handle large codebases efficiently?

The system loads all nodes and CALLS edges into a `FlowAdjacency` structure in memory using `load_flow_adjacency`, eliminating repeated database queries during BFS traversal. This approach reduces the tracing of execution flows through the call graph to simple dictionary lookups.

### What is the default maximum depth for flow tracing and why?

The default `max_depth` is 15 levels, configured in the `trace_flows` and `_trace_single_flow` functions. This limit prevents infinite loops in recursive call patterns and ensures analysis completes in bounded time while still capturing meaningful execution contexts.

### How are execution flows prioritized in the output?

Flows are sorted by a **criticality score** computed during tracing. This score incorporates factors such as whether the flow includes tested code (via TESTED_BY edges) and the complexity of the call chain, with higher criticality flows appearing first in the returned list.