How /understand-diff Performs Impact Analysis on Code Changes in Understand-Anything

The /understand-diff skill analyzes code changes by mapping git diffs to a knowledge graph, propagating impacts through one-hop relationships, and generating a structured markdown report with risk assessments.

The /understand-diff command in the Egonex-AI/Understand-Anything repository provides deterministic, graph-driven impact analysis by comparing changed files against the project's knowledge graph. This built-in skill transforms raw git diffs into actionable intelligence, identifying not just what changed, but which architectural components and dependencies are affected downstream.

Understanding the Knowledge Graph Foundation

At the core of the analysis lies the KnowledgeGraph data structure generated by the /understand command. This graph contains nodes representing files, functions, classes, and architectural layers, connected by edges that encode relationships like contains (parent-child) and dependencies.

When /understand-diff executes, it loads this graph from .understand-anything/knowledge-graph.json and passes it to the buildDiffContext function in understand-anything-plugin/src/diff-analyzer.ts.

Step-by-Step Impact Analysis Process

Mapping Changed Files to Graph Nodes

The analysis begins by obtaining the list of changed file paths—typically via git diff … --name-only or a PR diff. The buildDiffContext function iterates over graph.nodes and matches node.filePath against each changed path.

Matched node IDs are stored in changedNodeIds, while files lacking corresponding nodes populate unmappedFiles (lines 31-42 in diff-analyzer.ts). This separation ensures the system tracks both known components and new or untracked files.

Including Child Components via Containment Edges

Code changes affect not just files, but the functions and classes within them. The algorithm scans all edges of type contains where the source node is a changed file. For each match, the child node (target) is added to changedNodeIds (lines 44-49).

This step ensures that internal components—such as individual functions in a modified file—are flagged as changed alongside their parent containers.

One-Hop Impact Propagation

After identifying directly changed nodes, the system calculates blast radius by examining graph connectivity. The algorithm scans all edges in the graph; if an edge touches a changed node (as either source or target), it is added to impactedEdges.

The opposite endpoint of each such edge—provided it is not already a changed node—is added to affectedNodeIds (lines 57-69). This yields the affected components: everything one hop away from the modified code, representing direct dependencies and dependents.

Resolving Architectural Layers

To provide architectural context, the system unifies all changed and affected node IDs into allImpactedIds. It then filters the layers array, keeping only those layers whose nodeIds intersect with this impacted set (lines 74-77).

The result identifies which architectural layers—such as Service Layer or Data Layer—are touched by the change, enabling reviewers to assess cross-layer impacts.

Generating the Risk Assessment Report

The formatDiffAnalysis function consumes the populated DiffContext and emits a structured markdown report. This report includes:

  • Changed components: Name, type, summary, file path, and complexity
  • Affected components: One-hop neighbors and dependencies
  • Affected layers: Architectural context
  • Impacted relationships: Raw edges for detailed inspection
  • Unmapped files: New files not yet in the knowledge graph
  • Risk assessment: Flags for high-complexity changes, cross-layer impact, wide blast radius, and unmapped files

The skill specification in understand-anything-plugin/skills/understand-diff/SKILL.md orchestrates these steps, guiding the agent to grep the graph JSON for matching nodes and edges, then assemble the final analysis.

Implementation Example

Here is a complete example of invoking the impact analysis programmatically:

import { buildDiffContext, formatDiffAnalysis } from "./diff-analyzer.js";
import type { KnowledgeGraph } from "@understand-anything/core";

// 1️⃣ Load the knowledge graph generated by /understand
const graph: KnowledgeGraph = await import(
  "./.understand-anything/knowledge-graph.json"
);

// 2️⃣ Collect changed files (example for a PR)
const changedFiles = ["src/service.ts", "src/db.ts"];

// 3️⃣ Build the diff context
const ctx = buildDiffContext(graph, changedFiles);

// 4️⃣ Render a markdown report
const markdown = formatDiffAnalysis(ctx);
console.log(markdown);

Executing this code produces a markdown document structured as follows:


# Diff Analysis: test-project

## Changed Components

- **service.ts** (file) — Service
  - File: `src/service.ts`
  - Complexity: complex
...

## Affected Components

- **routes.ts** (file) — Routes
- **db.ts** (file) — Database
...

## Affected Layers

- **Service Layer**: Business logic
- **Data Layer**: Database
...

## Risk Assessment

- **High complexity**: 1 complex component changed: service.ts
- **Cross-layer impact**: Changes span 2 architectural layers
- **Wide blast radius**: 2 components affected downstream

Summary

  • Graph-based mapping: /understand-diff matches changed files to nodes in graph.nodes, storing results in changedNodeIds while tracking unmappedFiles for new components.
  • Containment traversal: Edges of type contains ensure child components (functions, classes) are included alongside parent files.
  • One-hop propagation: The algorithm identifies affected components by finding edges touching changed nodes, populating affectedNodeIds with direct dependencies.
  • Layer resolution: The system filters architectural layers by intersecting allImpactedIds with layer node sets.
  • Risk assessment: formatDiffAnalysis generates structured markdown highlighting complexity, cross-layer impacts, and unmapped files.

Frequently Asked Questions

What file types does /understand-diff analyze?

The skill analyzes any file path returned by the git diff command. It attempts to map these paths to nodes in the knowledge graph; files without corresponding nodes are tracked in unmappedFiles rather than ignored, ensuring visibility into new or untracked components.

How does the algorithm determine which components are "affected"?

Components are flagged as affected through one-hop impact propagation. When an edge connects to a changed node, the opposite endpoint is added to affectedNodeIds if not already marked as changed. This captures direct dependencies and callers without over-propagating through the entire graph.

Where is the impact analysis logic implemented?

The core logic resides in understand-anything-plugin/src/diff-analyzer.ts, specifically within the buildDiffContext and formatDiffAnalysis functions. The skill orchestration is defined in understand-anything-plugin/skills/understand-diff/SKILL.md, while src/__tests__/diff-analyzer.test.ts validates the mapping and propagation logic.

Can /understand-diff detect cross-layer architectural impacts?

Yes. By unifying changedNodeIds and affectedNodeIds into allImpactedIds and filtering the layers array, the system identifies exactly which architectural layers contain impacted nodes. This enables the risk assessment to flag cross-layer impacts that might violate architectural boundaries.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →