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

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, 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 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 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. This function implements the decision tree that determines the update mode.

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:

understand --full

Run the classifier to automatically select the update mode:

understand

Programmatic Access

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

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 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. 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, 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.

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 →