How /understand-diff Performs Impact Analysis on Code Changes: A Graph-Based Approach
/understand-diff executes deterministic impact analysis by mapping git diff output onto a knowledge graph, propagating changes through dependency edges, and surfacing architectural risks via blast-radius detection.
The /understand-diff command in the Egonex-AI/Understand-Anything repository transforms code reviews into data-driven assessments. Instead of relying on simple text searches, it queries the project's semantic knowledge graph—a structured representation of files, functions, classes, and their relationships—to calculate exactly which components change and which components depend on them.
The Core Algorithm in diff-analyzer.ts
The impact analysis engine resides in src/diff-analyzer.ts and follows a deterministic, multi-phase pipeline. The function buildDiffContext orchestrates the process, accepting a knowledge graph and a list of changed file paths, then returning a structured DiffContext object containing changed nodes, affected neighbors, and architectural layers.
Step 1: Mapping Changed Files to Graph Nodes
The analysis begins by correlating file system changes with graph entities. The algorithm iterates over graph.nodes and matches each node's filePath property against the incoming list of changed paths.
- Nodes with matching paths are added to
changedNodeIds - Files without corresponding nodes are tracked in
unmappedFiles(lines 31-42)
This mapping establishes the foundation for all downstream impact calculations.
Step 2: Including Child Components via Contains Edges
Code changes affect not just files but their internal constituents. The algorithm traverses all edges of type contains (where a file node is the source) and adds the target child nodes—functions, classes, or methods—to changedNodeIds (lines 44-49).
This ensures that modifying src/service.ts marks both the file node and its internal service functions as changed, creating granular impact visibility.
Step 3: One-Hop Impact Propagation
The engine identifies affected components by scanning the graph for dependency relationships. It examines every edge in the graph:
- If an edge connects to any
changedNodeIds(either source or target), it is added toimpactedEdges - The opposite endpoint of each impacted edge—if not already in the changed set—is added to
affectedNodeIds(lines 57-69)
This one-hop propagation captures the immediate blast radius: every component that directly imports, calls, or inherits from the changed code.
Step 4: Resolving Affected Architectural Layers
Architectural context emerges by intersecting changed nodes with the graph's layer definitions. The algorithm unites changedNodeIds and affectedNodeIds into allImpactedIds, then filters the layers array to retain only those layers whose nodeIds intersect this set (lines 74-77).
The result reveals whether changes span multiple architectural tiers—such as leaking from the Data Layer into the Service Layer—flagging potential architectural violations.
Step 5: Risk Assessment and Report Generation
The formatDiffAnalysis function consumes the DiffContext and emits a structured markdown report (lines 58-94). The report includes:
- Changed components: Name, type, summary, file path, and complexity metrics
- Affected components: One-hop neighbors downstream of changes
- Affected layers: Architectural tiers touched by the modification
- Impacted relationships: Raw dependency edges for traceability
- Unmapped files: Changed paths absent from the knowledge graph
- Risk assessment: Automated flags for high-complexity changes, cross-layer impacts, wide blast radii, or incomplete graph coverage
Implementation Code Example
The following TypeScript demonstrates how to programmatically invoke the analysis engine:
import { buildDiffContext, formatDiffAnalysis } from "./diff-analyzer.js";
import type { KnowledgeGraph } from "@understand-anything/core";
// Load the knowledge graph generated by /understand
const graph: KnowledgeGraph = await import(
"./.understand-anything/knowledge-graph.json"
);
// Collect changed files from git diff or PR data
const changedFiles = ["src/service.ts", "src/db.ts"];
// Build the diff context with full impact analysis
const ctx = buildDiffContext(graph, changedFiles);
// Generate markdown report for LLM consumption or CI output
const markdown = formatDiffAnalysis(ctx);
console.log(markdown);
Executing this code produces a markdown document with sections for changed components, affected dependencies, architectural layers, and risk indicators based on the actual graph topology.
Integration with the Understand-Anything Agent
The skill specification in skills/understand-diff/SKILL.md orchestrates the agent's execution of impact analysis. The workflow follows these operational steps:
- Obtain diff list: Execute
git diff ... --name-onlyor parse PR data to extract changed paths - Query the graph: Grep the knowledge-graph JSON for nodes matching changed file paths
- Identify edges: Grep for one-hop edges connecting to changed nodes
- Resolve layers: Filter architectural layers containing affected nodes
- Assemble analysis: Call
formatDiffAnalysisand optionally write a diff-overlay JSON for dashboard visualization
This deterministic pipeline ensures consistent results whether running locally, in CI pipelines, or via the Understand-Anything dashboard.
Summary
- Graph-based mapping correlates file system changes with semantic nodes in
src/diff-analyzer.ts - Child inclusion via
containsedges ensures functions and classes within changed files are fully analyzed - One-hop propagation calculates the immediate blast radius by traversing dependency edges
- Layer resolution detects cross-layer architectural impacts by filtering the
layersarray against affected node IDs - Structured output via
formatDiffAnalysisprovides markdown reports with embedded risk assessments for automated consumption
Frequently Asked Questions
What is the difference between changed and affected components in /understand-diff?
Changed components are nodes explicitly modified in the git diff—their file paths match the input list or they are children (functions, classes) contained within changed files via contains edges. Affected components are nodes identified through one-hop dependency analysis—these are upstream callers or downstream dependencies that interact with changed code but were not themselves modified.
How does /understand-diff handle files not present in the knowledge graph?
Files without corresponding nodes in the graph are tracked separately in the unmappedFiles array. According to lines 31-42 in diff-analyzer.ts, these files are excluded from impact propagation but flagged in the final risk assessment, alerting reviewers that the analysis may be incomplete for certain changes.
What types of relationships trigger impact propagation?
The algorithm considers all edge types when calculating one-hop impact, not just imports or calls. If any relationship exists between a changed node and another node—whether dependency, inheritance, composition, or reference—that relationship is added to impactedEdges and the connected node is marked as affected.
Can /understand-diff be integrated into CI pipelines?
Yes. The skill is designed for automation. By invoking buildDiffContext and formatDiffAnalysis programmatically, CI systems can generate impact reports for every pull request. The optional diff-overlay JSON output enables dashboard visualization of blast radius and architectural risk gates before code merges.
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 →