# How the Change Classifier Determines Full vs Incremental Updates in Egonex-AI Understand-Anything

> Discover how the Egonex-AI change classifier uses file fingerprint comparisons and graph staleness checks to intelligently choose between full or incremental updates for optimal performance.

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

---

**The change classifier compares file fingerprints against stored hashes and checks graph staleness to decide between a full graph rebuild or an incremental update.**

The change classifier is the decision-making engine within the **Understand-Anything** framework that optimizes knowledge graph synchronization. Located in the core package of the **Egonex-AI** repository, this module analyzes file changes to determine whether the system can perform a lightweight incremental update or must execute a complete graph reconstruction.

## Core Components of the Classification Pipeline

The change classifier relies on three supporting modules to make accurate decisions. Each component handles a specific aspect of change detection.

### Fingerprint Module

The **fingerprint** module, implemented in [`understand-anything-plugin/packages/core/src/fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/core/src/fingerprint.ts), computes a deterministic hash for every source file. When the content of a file changes, its fingerprint hash changes. The classifier compares these new hashes against the hashes stored in the previous graph metadata to detect material content changes.

### Staleness Detector

The **staleness detector** in [`understand-anything-plugin/packages/core/src/staleness.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/core/src/staleness.ts) checks whether the persisted graph is out-of-date with respect to the current repository state. If the schema version changed, a plugin was added or removed, or the fingerprint map is missing, the detector flags the graph as stale. A stale graph forces an immediate full rebuild regardless of file changes.

### Ignore Filter

The **ignore filter** defined in [`understand-anything-plugin/packages/core/src/ignore-filter.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/core/src/ignore-filter.ts) filters out files that never affect the knowledge graph. Generated assets, lockfiles, and other non-source files are discarded before the classifier evaluates changes. This prevents irrelevant modifications from triggering unnecessary full rebuilds.

## Classification Logic Flow

The classification process follows a strict four-step pipeline when a `/understand` run starts.

1. **Collect changed files** – The launcher queries Git for files that differ from the last successful run using `git diff --name-only`.
2. **Apply ignore rules** – Each changed path passes through the ignore filter. Files matching ignore patterns are removed from consideration.
3. **Compute fingerprints** – For every remaining file, the fingerprint module generates a content hash and compares it against the stored hash in the persisted graph metadata.
4. **Evaluate conditions** – The classifier checks staleness flags and fingerprint differences to return either `"full"` or `"incremental"`.

## Implementation in classifyUpdate

The core logic resides in the exported `classifyUpdate` function within [`understand-anything-plugin/packages/core/src/change-classifier.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/core/src/change-classifier.ts). This function implements the decision tree that determines the update mode.

```typescript
export function classifyUpdate(changedFiles: string[]): "full" | "incremental" {
  // 1️⃣ Remove ignored paths
  const relevant = changedFiles.filter(f => !ignoreFilter.matches(f));

  // 2️⃣ If nothing relevant changed → incremental
  if (relevant.length === 0) return "incremental";

  // 3️⃣ Staleness shortcut – a stale persisted graph forces a full rebuild
  if (isStale()) return "full";

  // 4️⃣ Compare fingerprints
  const anyFingerprintChanged = relevant.some(f => {
    const newHash = fingerprint.compute(f);
    const oldHash = persistedGraph.fingerprints?.[f];
    return newHash !== oldHash;
  });

  return anyFingerprintChanged ? "full" : "incremental";
}

```

The function first filters the input array through `ignoreFilter.matches()`, then checks for staleness via `isStale()`. Finally, it iterates through relevant files, calling `fingerprint.compute()` for each and comparing against `persistedGraph.fingerprints`.

## Decision Matrix

The change classifier evaluates conditions in priority order to determine the update type.

- **No non-ignored changes** – Returns **Incremental** when the filtered change set is empty, indicating the existing graph remains valid.
- **Staleness flag set** – Returns **Full** when `isStale()` detects schema version changes, plugin modifications, or missing fingerprint maps.
- **Fingerprint mismatch** – Returns **Full** when any relevant file’s computed hash differs from the stored hash in `persistedGraph.fingerprints`.
- **Identical fingerprints** – Returns **Incremental** when changed files produce identical hashes, indicating only metadata like timestamps changed.

## Practical Usage Examples

You can interact with the change classifier through the CLI or programmatically via the core package API.

### CLI Commands

Force a full rebuild regardless of changes:

```bash
understand --full

```

Run the classifier to automatically select the update mode:

```bash
understand

```

### Programmatic Access

Import the classifier in custom plugins or scripts to determine update strategy dynamically:

```typescript
import { classifyUpdate } from "@understand-anything/core/change-classifier";
import { getChangedFiles } from "@understand-anything/core/git-utils";

async function maybeUpdate() {
  const changed = await getChangedFiles();          // e.g. ["src/app.ts", "package.json"]
  const mode = classifyUpdate(changed);
  if (mode === "full") {
    await runFullGraphBuild();
  } else {
    await runIncrementalUpdate(changed);
  }
}

```

This pattern allows external tools to leverage the same optimization logic used by the core engine.

## Summary

- The **change classifier** in [`change-classifier.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/change-classifier.ts) orchestrates the decision between full and incremental updates.
- **Fingerprint comparison** detects material content changes by hashing files and comparing against persisted metadata.
- **Staleness detection** forces full rebuilds when schema versions or plugin configurations change.
- The **ignore filter** prevents irrelevant files from triggering expensive rebuilds.
- The `classifyUpdate` function returns `"full"` or `"incremental"` based on a prioritized evaluation of these conditions.

## Frequently Asked Questions

### What triggers a full rebuild in the change classifier?

A full rebuild triggers when the staleness detector finds schema version mismatches, missing plugins, or corrupted fingerprint maps. Additionally, if any non-ignored file produces a fingerprint hash that differs from the stored value, the classifier selects a full update.

### How does the fingerprint module determine if content changed?

The fingerprint module reads file content and computes a deterministic hash using the implementation in [`fingerprint.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/fingerprint.ts). When the computed hash for a file path differs from the hash stored in `persistedGraph.fingerprints`, the classifier recognizes the file as materially modified.

### Can I force a full update regardless of the classifier's decision?

Yes. Pass the `--full` flag to the CLI command to bypass the change classifier entirely. Programmatically, you can skip the `classifyUpdate` call and invoke `runFullGraphBuild()` directly when you need guaranteed complete reconstruction.

### What happens if the persisted graph is stale?

When `isStale()` returns true in [`staleness.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/staleness.ts), the classifier immediately returns `"full"` without evaluating fingerprints. This safeguard ensures structural changes like new language plugins or schema upgrades cannot leave the graph in an inconsistent state.