# How Egonex-AI Understand-Anything Handles Incremental Updates with Fingerprint-Based Change Detection

> Egonex-AI Understand-Anything intelligently handles incremental updates with fingerprint-based change detection, minimizing overhead by classifying file changes and updating only what's necessary.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-06-13

---

**Understand-Anything minimizes computational overhead by classifying file changes into NONE, COSMETIC, or STRUCTURAL categories using SHA-256 hashes and tree-sitter structural signatures, updating only the affected portions of the knowledge graph.**

The Egonex-AI/Understand-Anything repository implements a sophisticated **fingerprint-based change detection** system to enable efficient incremental updates. By creating detailed **FileFingerprint** objects for each source file, the system distinguishes between cosmetic code modifications and structural changes that require knowledge graph recomputation.

## Building the Fingerprint Store

The `buildFingerprintStore` function in [`fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/fingerprint.ts) generates a complete fingerprint catalog for the project. It walks every file, invokes the language-specific `registry.analyzeFile` parser, and creates a comprehensive fingerprint record.

```ts
// Definition of the fingerprint type – see
// fingerprint.ts#L9-L38
export interface FileFingerprint {
  filePath: string;
  contentHash: string;
  functions: FunctionFingerprint[];
  classes:   ClassFingerprint[];
  imports:   ImportFingerprint[];
  exports:   string[];
  totalLines: number;
  hasStructuralAnalysis: boolean;
}

```

Files without tree-sitter support receive a **hash-only fingerprint** and are treated conservatively as potentially STRUCTURAL changes. The resulting JSON map is written to [`fingerprints.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/fingerprints.json) and versioned with the current git commit hash.

```ts
// Build the store – see
// fingerprint.ts#L53-L84
export function buildFingerprintStore(
  projectDir: string,
  filePaths: string[],
  registry: PluginRegistry,
  gitCommitHash: string,
): FingerprintStore { … }

```

## Detecting Changes with compareFingerprints

On subsequent runs, `analyzeChanges` re-fingerprints only files reported by the VCS as modified. Each file pair is processed through `compareFingerprints` to determine the change severity.

```ts
// Compare two fingerprints – see
// fingerprint.ts#L31-L46
export function compareFingerprints(oldFp: FileFingerprint, newFp: FileFingerprint): FileChangeResult { … }

```

The comparison follows a three-tier classification system:

- **NONE** – The SHA-256 content hash matches exactly, requiring no processing.
- **COSMETIC** – The hash differs but all structural signatures (function signatures, class members, import/export lists) remain identical, indicating only internal logic changed.
- **STRUCTURAL** – Any structural signature differs, or structural analysis is unavailable, necessitating a full knowledge graph recomputation for that file.

The function also produces a human-readable `details` array (e.g., "new function: foo", "imports changed") that downstream agents use for enriched reporting.

## Aggregating Results for Incremental Processing

The `analyzeChanges` function aggregates per-file results into a `ChangeAnalysis` object, categorizing files as new, deleted, unchanged, cosmetically changed, or structurally changed.

```ts
// High-level change analysis – see
// fingerprint.ts#L94-L108
export function analyzeChanges(
  projectDir: string,
  changedFiles: string[],
  existingStore: FingerprintStore,
  registry: PluginRegistry,
): ChangeAnalysis { … }

```

This categorization drives the **incremental graph builder**: only files flagged as STRUCTURAL trigger node and edge updates, while COSMETIC files retain their existing graph representation. This selective recomputation dramatically reduces CPU and I/O for large codebases.

## Implementation Details and Code Examples

The following example demonstrates generating a fingerprint store and analyzing changes after a git operation:

```ts
import { 
  buildFingerprintStore,
  analyzeChanges,
  readFileSync,
  writeFileSync,
} from '@understand-anything/core';

// 1️⃣ Generate a fingerprint store for the whole project
const allFiles = await globby(['**/*.{ts,js,tsx,jsx,py,go,rs}']);
const registry = await import('@understand-anything/core/src/plugins/registry.js');
const store = buildFingerprintStore('/my/project', allFiles, registry, 'HEAD');

// Persist for later runs
writeFileSync('fingerprints.json', JSON.stringify(store));

// 2️⃣ Later – after git reports changed files
const changed = ['src/utils.ts', 'README.md']; // from `git diff --name-only`
const previousStore = JSON.parse(readFileSync('fingerprints.json', 'utf-8'));

const analysis = analyzeChanges('/my/project', changed, previousStore, registry);

// Use the analysis to trigger incremental graph updates
for (const file of analysis.structurallyChangedFiles) {
  console.log(`⚙️ Re-process structural change in ${file}`);
}
for (const file of analysis.cosmeticOnlyFiles) {
  console.log(`✨ Cosmetic change only – graph unchanged for ${file}`);
}

```

### Key Source Files

- **[`fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/fingerprint.ts)**: Contains core data structures and algorithms including `extractFileFingerprint`, `compareFingerprints`, `buildFingerprintStore`, and `analyzeChanges`.
- **[`types.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/types.ts)**: Defines shared type definitions used by the fingerprint module, such as `StructuralAnalysis`.
- **[`registry.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/registry.ts)**: Supplies language-specific tree-sitter parsers for structural analysis via the plugin registry.
- **[`staleness.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/staleness.ts)**: Implements higher-level logic determining when the knowledge graph requires updates based on fingerprint analysis.
- **[`change-classifier.test.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/change-classifier.test.ts)**: Test suite confirming correct classification of NONE, COSMETIC, and STRUCTURAL changes.

## Summary

- **FileFingerprint** objects capture SHA-256 content hashes and tree-sitter structural signatures (functions, classes, imports, exports) for every source file.
- The **`compareFingerprints`** function classifies changes into **NONE**, **COSMETIC**, or **STRUCTURAL** categories, enabling precise incremental updates.
- Files without tree-sitter support fall back to hash-only comparison and are treated conservatively as structural changes.
- The **`analyzeChanges`** pipeline processes only VCS-reported modified files, minimizing I/O and CPU usage for large repositories.
- This architecture ensures the knowledge graph updates only when actual structural dependencies change, not when code formatting or internal logic shifts.

## Frequently Asked Questions

### How does the system handle files in languages without tree-sitter support?

Files without available tree-sitter parsers receive a **hash-only fingerprint** where `hasStructuralAnalysis` is set to false. According to the conservative fallback strategy implemented in `buildFingerprintStore`, these files are automatically classified as **STRUCTURAL** changes if their content hash differs, ensuring correctness by forcing a full recomputation when the system cannot determine the actual structural impact.

### What is the performance benefit of cosmetic change detection?

By distinguishing **COSMETIC** changes (internal logic modifications) from **STRUCTURAL** changes (API modifications), the system avoids unnecessary knowledge graph rebuilds. When `compareFingerprints` detects a COSMETIC change, the existing graph nodes and edges remain valid, reducing CPU usage and I/O operations to only the files requiring actual structural updates.

### How does the fingerprint store persist across runs?

The `buildFingerprintStore` function generates a JSON-serializable `FingerprintStore` object that maps file paths to their `FileFingerprint` records. This store is typically written to [`fingerprints.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/fingerprints.json) alongside a git commit hash for versioning. On subsequent runs, `analyzeChanges` loads this persisted store and compares it against fresh fingerprints of only the changed files reported by the VCS.

### Why use SHA-256 instead of simpler hash functions?

SHA-256 provides cryptographic collision resistance that ensures two different file contents will virtually never produce the same hash. This guarantees that the **NONE** classification in `compareFingerprints` is absolutely reliable, preventing the incremental update system from missing actual content changes that could affect the knowledge graph's accuracy.