# How /understand-diff Performs Impact Analysis for Code Changes

> Understand how the /understand-diff endpoint performs impact analysis for code changes. It maps diffs to knowledge graphs to identify affected components and generate risk reports.

- Repository: [Yuxiang Lin/Understand-Anything](https://github.com/Lum1104/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-06-06

---

**The `/understand-diff` endpoint analyzes Git diffs by mapping changed files to knowledge graph nodes, propagating one-hop relationships to identify affected components, and generating a risk-aware markdown report based on complexity metrics and architectural cross-dependencies.**

The Understand-Anything repository provides a semantic code analysis system that transforms raw Git diffs into structured impact assessments. By traversing a persisted knowledge graph stored in [`.understand-anything/knowledge-graph.json`](https://github.com/Lum1104/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json), the system reveals hidden dependencies and architectural risks that traditional diff tools cannot detect.

## Three-Phase Impact Analysis Architecture

The impact analysis operates through three tightly coupled phases implemented in [`understand-anything-plugin/src/diff-analyzer.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/understand-anything-plugin/src/diff-analyzer.ts). Each phase progressively expands the scope of detected changes to surface ripple effects across the codebase.

### Phase 1: Mapping Changed Files to Graph Nodes

The algorithm begins by correlating files from `git diff … --name-only` with **GraphNode** entities in the knowledge graph. In `buildDiffContext` (lines 31–41), the system iterates over `changedFiles` and compares each path against the `filePath` field of every node. Matching node IDs are recorded as **changed nodes**, while files without corresponding graph entries are flagged as *unmapped* for manual review.

### Phase 2: Propagating One-Hop Relationships

Next, the system executes edge traversal (lines 57–69) to capture immediate dependencies. The algorithm scans all **GraphEdge** records, marking any edge where the *source* **or** *target* matches a changed node as **impacted**. The opposite endpoint of each impacted edge is added to the **affected nodes** set, unless it is already a changed node. This implementation also handles `contains` relationships specifically, ensuring that child entities of changed files are included in the changed set before propagation begins.

### Phase 3: Deriving Higher-Level Impact and Risk Assessment

Finally, the system aggregates impacted node IDs to determine affected **layers** (lines 74–77). The `formatDiffAnalysis` function (starting at line 90) generates a markdown report containing changed components, affected components, impacted edges, and affected architectural layers. The risk assessment logic (lines 58–94) evaluates four critical factors:

- **Node complexity**: Flags changes to nodes marked `complex` versus `simple`
- **Cross-layer impact**: Detects when changes span multiple architectural layers
- **Blast radius**: Alerts when downstream affected nodes exceed five components
- **Unmapped files**: Notes files present in the diff but absent from the knowledge graph

## Core Algorithm Implementation

The following TypeScript excerpt from [`src/diff-analyzer.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/src/diff-analyzer.ts) demonstrates the exact logic used to build the diff context:

```typescript
// 1️⃣ Identify changed nodes
for (const file of changedFiles) {
  let mapped = false;
  for (const node of nodes) {
    if (node.filePath === file) {
      changedNodeIds.add(node.id);
      mapped = true;
    }
  }
  if (!mapped) unmappedFiles.push(file);
}

// 2️⃣ Include "contains" children of changed file nodes
for (const edge of edges) {
  if (edge.type === "contains" && changedNodeIds.has(edge.source)) {
    changedNodeIds.add(edge.target);
  }
}

// 3️⃣ 1-hop propagation → affected nodes & impacted edges
for (const edge of edges) {
  const sourceChanged = changedNodeIds.has(edge.source);
  const targetChanged = changedNodeIds.has(edge.target);
  if (sourceChanged || targetChanged) {
    impactedEdges.push(edge);
    if (sourceChanged && !changedNodeIds.has(edge.target)) affectedNodeIds.add(edge.target);
    if (targetChanged && !changedNodeIds.has(edge.source)) affectedNodeIds.add(edge.source);
  }
}

// 4️⃣ Determine impacted layers
const allImpactedIds = new Set([...changedNodeIds, ...affectedNodeIds]);
const affectedLayers = layers.filter(layer =>
  layer.nodeIds.some(id => allImpactedIds.has(id))
);

```

## Using the /understand-diff Skill

Developers can invoke impact analysis through two primary interfaces: direct library consumption or Claude Code integration.

### Direct Library Usage

For programmatic access in Node.js environments, import `buildDiffContext` and `formatDiffAnalysis` from the skill package:

```typescript
import { readFile } from "fs/promises";
import { buildDiffContext, formatDiffAnalysis } from "@understand-anything/skill";

// Load the persisted knowledge graph
const graphJson = await readFile("./.understand-anything/knowledge-graph.json", "utf-8");
const graph = JSON.parse(graphJson);

// Example list of changed files from a CI job
const changedFiles = [
  "src/api/userController.ts",
  "src/models/User.ts",
];

// Build the diff context and format a markdown report
const diffCtx = buildDiffContext(graph, changedFiles);
const report = formatDiffAnalysis(diffCtx);

console.log(report);

```

### Claude Code Integration

When used as a Claude Code skill, the system executes autonomously:

1. Verify presence of [`.understand-anything/knowledge-graph.json`](https://github.com/Lum1104/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json)
2. Execute `git diff … --name-only` to obtain changed files
3. Call `buildDiffContext(graph, changedFiles)` to traverse the graph
4. Generate markdown via `formatDiffAnalysis` and write [`diff-overlay.json`](https://github.com/Lum1104/Understand-Anything/blob/main/diff-overlay.json) for dashboard visualization

Invoke the skill using the command:

```bash
/understand-diff

```

The resulting **diff overlay** file enables the Understand-Anything dashboard to visualize changed ↔ affected component relationships directly on the interactive graph.

## Summary

- **`buildDiffContext`** in [`src/diff-analyzer.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/src/diff-analyzer.ts) drives the three-phase analysis: file-to-node mapping, one-hop edge propagation, and layer aggregation.
- **Impact detection** identifies both direct changes and downstream affected nodes by traversing `source` and `target` relationships in the graph edge set.
- **Risk assessment** automatically flags high-complexity components, cross-layer dependencies, wide blast radii (≥5 affected nodes), and unmapped files.
- **Output artifacts** include a structured markdown report for human review and [`diff-overlay.json`](https://github.com/Lum1104/Understand-Anything/blob/main/diff-overlay.json) for graphical dashboard visualization.
- **Integration options** include direct Node.js library imports or autonomous execution via Claude Code agents.

## Frequently Asked Questions

### How does /understand-diff handle files not present in the knowledge graph?

Files returned by `git diff` that lack corresponding `GraphNode` entries are collected in an `unmappedFiles` array and reported in the final analysis. According to the risk assessment logic in `formatDiffAnalysis`, unmapped files trigger a specific warning flag, indicating potential blind spots in the architectural model that may require manual review or graph regeneration.

### What constitutes a "high risk" assessment in the generated report?

The risk assessment algorithm flags high risk when changes exhibit any of four characteristics: modification of nodes marked with `complex` status, impact spanning multiple architectural layers, a downstream blast radius affecting five or more nodes, or the presence of unmapped changed files. Changes meeting none of these criteria receive a **low-risk** classification.

### Can the analysis detect transitive dependencies beyond one hop?

The current implementation in [`src/diff-analyzer.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/src/diff-analyzer.ts) performs strictly one-hop propagation from changed nodes to direct neighbors. While the algorithm captures immediate relationships through `contains` edges and standard dependencies, multi-hop transitive chains require iterative execution or graph preprocessing outside the current `buildDiffContext` implementation.

### Where is the impact analysis output stored for dashboard visualization?

After `formatDiffAnalysis` generates the markdown report, the skill writes a **diff overlay** to [`.understand-anything/diff-overlay.json`](https://github.com/Lum1104/Understand-Anything/blob/main/.understand-anything/diff-overlay.json). This JSON file contains the changed node IDs, affected node IDs, and impacted edge definitions that the Understand-Anything dashboard consumes to highlight affected components in the knowledge graph visualization.