# How Does Incremental Analysis with Fingerprint-Based Change Detection Work in Understand Anything?

> Discover how Understand Anything uses fingerprint-based change detection for efficient incremental analysis. Avoid expensive re-analysis by intelligently tracking file changes.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: internals
- Published: 2026-06-12

---

**Understand Anything avoids re-scanning entire projects by storing SHA-256 fingerprints and structural signatures for each file, comparing them on subsequent runs to detect only meaningful changes and skip expensive LLM re-analysis when possible.**

The Egonex-AI/Understand-Anything repository implements a sophisticated incremental analysis system that eliminates redundant processing in large codebases. By combining cryptographic hashing with language-aware structural analysis, this fingerprint-based change detection mechanism determines exactly which files require re-processing and which can be safely ignored. The system operates through a three-stage pipeline that balances accuracy with performance.

## The Three-Stage Incremental Analysis Pipeline

### Stage 1: Fingerprint Generation with buildFingerprintStore

The process begins in [`packages/core/src/fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/fingerprint.ts) where the `buildFingerprintStore` function generates a comprehensive fingerprint for every source file. For each file, the system invokes the language-specific tree-sitter parser via the `PluginRegistry` to extract structural elements—function signatures, class definitions, imports, and exports—while simultaneously computing a SHA-256 **content hash** of the entire file.

The resulting `FingerprintStore` contains both the structural description and the content hash, persisted typically as [`.understand-anything/fingerprint.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/fingerprint.json). This dual-layer approach allows the system to distinguish between purely cosmetic whitespace changes and modifications that actually affect the knowledge graph.

### Stage 2: Change Detection via analyzeChanges and compareFingerprints

On subsequent runs, the engine receives a list of files from Git and executes `analyzeChanges` to recompute fingerprints for only those modified paths. The `compareFingerprints` function then categorizes each change into one of three levels:

- **NONE**: The SHA-256 content hash matches exactly, indicating no changes whatsoever.
- **COSMETIC**: The content hash differs, but structural signatures (functions, classes, imports/exports) remain identical—typically representing formatting or comment changes.
- **STRUCTURAL**: Any difference in signatures, missing structural analysis, new or deleted files, or changes to import/export statements that affect the dependency graph.

This analysis returns a `ChangeAnalysis` object that groups files by their change level, providing the granular data needed for intelligent update decisions.

### Stage 3: Update Classification with classifyUpdate

Located in [`packages/core/src/change-classifier.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/change-classifier.ts), the `classifyUpdate` routine transforms the raw `ChangeAnalysis` into actionable pipeline decisions. The function evaluates the scope and magnitude of changes to determine one of four update strategies:

- **SKIP**: Triggered when all changes are `NONE` or `COSMETIC`, requiring no re-analysis.
- **PARTIAL_UPDATE**: Used for structural changes confined to specific directories, limiting re-analysis to affected areas.
- **ARCHITECTURE_UPDATE**: Triggered by new or removed top-level directories, or when exceeding 10 structural changes.
- **FULL_UPDATE**: Reserved for massive refactorings (>30 structural changes or >50% of the project), necessitating a complete regeneration of the knowledge graph.

The returned `UpdateDecision` specifies exactly which files to re-analyze, whether to rebuild the architecture graph, and whether to regenerate the guided tour.

## Implementation Example: From Fingerprint to Update Decision

The following TypeScript implementation demonstrates the complete incremental analysis workflow:

```typescript
import { buildFingerprintStore, analyzeChanges } from "./fingerprint.js";
import { classifyUpdate } from "./change-classifier.js";
import { pluginRegistry } from "./plugins/registry.js";

// 1️⃣ First run – create a full fingerprint store
const allFiles = await glob("**/*.{ts,js,tsx,jsx}", { path: projectRoot });
const fingerprintStore = buildFingerprintStore(
  projectRoot,
  allFiles,
  pluginRegistry,
  gitCommitHash,
);

// Persist the store (e.g. .understand-anything/fingerprint.json)
// ---------------------------------------------------------------

// 2️⃣ Subsequent run – ask Git for changed paths
const changed = await getGitChangedFiles(); // ["src/utils.ts", "src/newFeature.ts"]

// 3️⃣ Detect what actually changed
const changeAnalysis = analyzeChanges(
  projectRoot,
  changed,
  fingerprintStore,
  pluginRegistry,
);

// 4️⃣ Decide the scope of the re‑analysis
const decision = classifyUpdate(
  changeAnalysis,
  allFiles.length,
  allFiles,
);

// 5️⃣ Feed the decision back to the core pipeline
if (decision.action !== "SKIP") {
  await reanalyzeFiles(decision.filesToReanalyze);
  if (decision.rerunArchitecture) await rebuildArchitectureGraph();
  if (decision.rerunTour) await regenerateTour();
}

```

This pipeline minimizes computational overhead by ensuring that only structurally modified files trigger expensive LLM-driven analysis, while cosmetic changes are processed instantly without re-building the knowledge graph.

## Summary

- **Fingerprint-based change detection** in Understand Anything combines SHA-256 content hashing with tree-sitter structural analysis to avoid redundant re-scanning.
- The `buildFingerprintStore` function in [`packages/core/src/fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/fingerprint.ts) creates dual-layer fingerprints capturing both content hashes and code signatures.
- **Change levels** (`NONE`, `COSMETIC`, `STRUCTURAL`) determined by `compareFingerprints` allow the system to distinguish between formatting changes and meaningful code modifications.
- **Update decisions** (`SKIP`, `PARTIAL_UPDATE`, `ARCHITECTURE_UPDATE`, `FULL_UPDATE`) generated by `classifyUpdate` in [`packages/core/src/change-classifier.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/change-classifier.ts) optimize pipeline execution based on change magnitude.
- Only files with structural changes trigger LLM re-analysis, dramatically improving performance on repeated runs of large projects.

## Frequently Asked Questions

### What is a fingerprint in Understand Anything?

A fingerprint is a persistent data structure created by the `extractFileFingerprint` function that contains two critical components: a SHA-256 content hash of the entire file source and a structural description of function signatures, class definitions, and import/export statements. These fingerprints are stored in the `FingerprintStore` and serve as the baseline for detecting changes between analysis runs.

### How does Understand Anything distinguish between cosmetic and structural changes?

The system uses `compareFingerprints` to perform a two-tier comparison. First, it checks the SHA-256 content hash; if matched, the change is `NONE`. If the hash differs, it compares the structural signatures extracted by tree-sitter parsers. Identical structures with different hashes result in a `COSMETIC` classification (formatting/comments), while any difference in signatures triggers a `STRUCTURAL` classification requiring re-analysis.

### When does the system trigger a full update versus a partial update?

According to the `classifyUpdate` implementation in [`packages/core/src/change-classifier.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/change-classifier.ts), a **FULL_UPDATE** occurs when there are more than 30 structural changes or when over 50% of the project files change structurally. A **PARTIAL_UPDATE** handles smaller structural changes confined to specific directories, while an **ARCHITECTURE_UPDATE** triggers for new or removed top-level directories or when exceeding 10 structural changes.

### Which tree-sitter parsers are used for fingerprint generation?

The `PluginRegistry` in [`packages/core/src/plugins/registry.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/plugins/registry.ts) provides the `analyzeFile` function that invokes language-specific tree-sitter parsers based on file extension. The `buildFingerprintStore` function passes each file through this registry to extract language-agnostic structural signatures (functions, classes, imports) regardless of whether the source is TypeScript, JavaScript, or other supported languages.