How Code-Review-Graph Detects Execution Flows from Entry Points
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, 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) 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:
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 targetsnodes_by_qnandnodes_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:
- Initializes a deque for BFS queue management
- Expands each node's outgoing
CALLSedges using the preloadedcalls_outmapping - Tracks visited nodes to prevent cycle-induced infinite loops
- Respects the
max_depthparameter to limit search scope - 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:
# 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:
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.pycombines 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()andincremental_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.
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 →