# How Code-Review-Graph Detects Execution Flows from Entry Points

> Discover how code-review-graph detects execution flows from entry points. Learn about call analysis, decorator detection, BFS tracing, and flow criticality scoring.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-07-25

---

**The code-review-graph detects execution flows by first identifying entry points through incoming call analysis, framework decorator detection, and naming conventions, then tracing reachable code via breadth-first search while scoring each flow's criticality based on file spread, security sensitivity, and test coverage gaps.**

The `tirth8205/code-review-graph` repository implements a sophisticated static analysis engine that maps how execution propagates through a codebase starting from entry points. Understanding how the graph detects these execution flows is essential for prioritizing code reviews and identifying high-risk change surfaces. All flow detection logic resides in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py), which coordinates entry point discovery, traversal algorithms, and criticality scoring.

## Detecting Entry Points in the Graph

The `detect_entry_points()` function (lines 64-78 in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py)) identifies functions capable of initiating program execution through three complementary detection strategies. Test files are automatically filtered out unless `include_tests=True` is passed, utilizing the `_is_test_file()` helper (lines 54-61).

### Root Function Detection

The primary mechanism identifies **root functions** that have no incoming `CALLS` edges. The algorithm builds a set called `called_qnames` containing every qualified name that appears as a call target via `store.get_all_call_targets`. Any node whose qualified name is absent from this set qualifies as an entry point:

```python
if node.qualified_name not in called_qnames:
    # Identified as entry point

```

This detection occurs at lines 99-100 and catches true roots like `main()` functions or unreferenced handlers.

### Framework Decorator Recognition

The helper `_has_framework_decorator()` (lines 29-40) scans each node's `extra["decorators"]` metadata against `_FRAMEWORK_DECORATOR_PATTERNS`. These regex patterns recognize decorators from Flask, FastAPI, Click, Django, Spring, and other common frameworks that designate entry handlers.

### Conventional Naming Patterns

The `_matches_entry_name()` function (lines 43-51) tests node names against `_ENTRY_NAME_PATTERNS` (e.g., `main`, `test_`, `on_`, `handler`) and language-specific patterns stored in `_LANGUAGE_ENTRY_NAME_PATTERNS`. This captures Angular lifecycle hooks, event handlers, and conventional startup routines that might not have decorators or be true roots.

## Tracing Execution Flows via BFS

Once entry points are identified, `trace_flows()` (lines 84-98) initiates a forward traversal to map all reachable execution paths. This process employs a configurable breadth-first search with a default `max_depth` of 15 to prevent runaway traversal.

### Building the Flow Adjacency Structure

Before traversal begins, the system loads an in-memory adjacency structure via `store.load_flow_adjacency()`. This caches:
- `calls_out`: A dictionary mapping qualified names to their reachable call targets
- `nodes_by_qn` and `nodes_by_id`: Fast lookup tables for node metadata

This preprocessing eliminates repeated database queries during the BFS phase.

### Breadth-First Search Implementation

For each entry point, `_trace_single_flow()` (lines 22-63) executes the traversal:

1. Initializes a deque for BFS queue management
2. Expands each node's outgoing `CALLS` edges using the preloaded `calls_out` mapping
3. Tracks visited nodes to prevent cycle-induced infinite loops
4. Respects the `max_depth` parameter to limit search scope
5. Assembles a flow dictionary containing ordered node IDs, depth metrics, distinct file paths visited, and file count

Trivial flows containing single nodes with no outgoing calls are discarded (`if len(path_ids) < 2: return None`). The final list of flows is sorted by criticality score in descending order.

## Scoring Flow Criticality

The `compute_criticality()` function (lines 24-92) evaluates each discovered flow across five weighted dimensions:

| Dimension | Measurement | Weight |
|-----------|-------------|--------|
| **File Spread** | Normalized distinct file count: `min((file_count-1)/4, 1)` | 0.30 |
| **External Calls** | Ratio of calls to nodes outside the graph, capped at 1.0 | 0.20 |
| **Security Sensitivity** | Proportion of nodes matching `_SECURITY_KEYWORDS` | 0.25 |
| **Test Coverage Gap** | `1 - coverage_ratio` for nodes lacking `TESTED_BY` edges | 0.15 |
| **Traversal Depth** | Normalized BFS depth: `min(depth/10, 1)` | 0.10 |

The weighted sum is rounded to four decimal places and stored as `flow["criticality"]`, enabling prioritization of flows that cross multiple files, touch security-sensitive code, or lack test coverage.

## Practical Usage Examples

The public API exposes two primary functions for flow analysis:

```python

# Example: Analyze the three most critical execution flows

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

store = GraphStore("/path/to/.codegraph.db")

# Retrieve flows with default depth 15, excluding test entry points

flows = trace_flows(store, max_depth=15, include_tests=False)

# Display top-3 critical flows

for flow in flows[:3]:
    print(
        f"Flow {flow['name']} (criticality={flow['criticality']}) "
        f"spans {flow['file_count']} files at depth {flow['depth']}"
    )

```

For incremental analysis after file changes:

```python
from code_review_graph.flows import incremental_trace_flows

changed_files = ["src/app.py", "src/routes/user.py"]
updated_count = incremental_trace_flows(store, changed_files=changed_files)
print(f"Re-traced {updated_count} affected execution flows")

```

## Summary

- **Entry point detection** in [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py) combines root analysis (no incoming calls), framework decorator scanning, and naming convention matching to identify program starting points.
- **Execution tracing** utilizes a breadth-first search with cycle detection and configurable depth limits, operating on preloaded adjacency data for performance.
- **Criticality scoring** weights file spread (30%), security keywords (25%), external calls (20%), test gaps (15%), and traversal depth (10%) to rank flows by review priority.
- The `trace_flows()` and `incremental_trace_flows()` APIs provide both full-repository and change-based analysis capabilities.

## Frequently Asked Questions

### What qualifies as an entry point in code-review-graph?

An entry point is any function that satisfies at least one of three criteria: it has no incoming `CALLS` edges (a true root), it carries a recognized framework decorator (Flask, FastAPI, Django, etc.), or its name matches conventional patterns like `main`, `test_`, `on_`, or `handler`. The `detect_entry_points()` function evaluates all three conditions while optionally filtering out test files.

### How does the BFS traversal avoid infinite loops?

The `_trace_single_flow()` function maintains a visited set during traversal. Before expanding any node's outgoing edges, the algorithm checks if the target has already been processed. This prevents cycles in the call graph from causing infinite recursion, while the configurable `max_depth` parameter (default 15) provides an additional safeguard against runaway searches in deeply connected graphs.

### What factors determine a flow's criticality score?

The criticality algorithm weighs five factors: the number of distinct files touched (file spread), calls to external nodes not present in the graph, presence of security-sensitive keywords in function names, the proportion of nodes lacking test coverage, and the maximum traversal depth. File spread carries the highest weight (0.30), followed by security sensitivity (0.25), making cross-file security flows the highest priority for review.

### Can the graph include test files as entry points?

Yes, by passing `include_tests=True` to `trace_flows()` or `detect_entry_points()`. By default, the `_is_test_file()` helper filters out test files to focus analysis on production code paths. When enabled, test functions matching entry patterns (like `test_` prefixes) are treated as valid starting points for execution flow analysis, useful for understanding test coverage and fixture initialization chains.