How Staleness Detection Determines When the Egonex-AI Knowledge Graph Needs Rebuilding
Staleness detection in Egonex-AI compares the current Git HEAD against the commit hash stored in the knowledge graph, triggering a rebuild only when git diff identifies changed files between these two points.
The Egonex-AI Understand-Anything engine maintains an incremental knowledge graph that tracks codebases over time. To avoid expensive full rebuilds, the system implements staleness detection that determines exactly when the underlying source has drifted from the stored analysis. This mechanism lives in the core package and leverages Git history to make precise, file-level decisions about graph validity.
How Staleness Detection Identifies Changed Files
Git Diff Execution
The detection starts in understand-anything-plugin/packages/core/src/staleness.ts with the getChangedFiles function (lines 13‑26). This utility executes a synchronous Git command via child_process.execFileSync to compare the stored commit hash against the current repository state.
const output = execFileSync('git',
['diff', `${lastCommitHash}..HEAD`, '--name-only'],
{ cwd: projectDir, encoding: "utf-8" });
The function parses the newline‑delimited output into an array of file paths. If Git fails—for instance, when the stored commit hash is unknown or the repository is corrupted—the function returns an empty array, conservatively treating the graph as up‑to‑date to prevent unnecessary rebuilds.
Staleness Evaluation Logic
The isStale function (lines 34‑42) consumes the changed file list to make a boolean determination. It calls getChangedFiles and evaluates whether the returned array contains any entries. When the array is non‑empty, the function returns stale: true alongside the list of changed files for downstream processing.
This design separates the detection concern from the action concern, allowing the pipeline to inspect exactly which files triggered the staleness flag before committing to a rebuild.
Rebuilding the Knowledge Graph After Stale Detection
When staleness is confirmed, the pipeline invokes mergeGraphUpdate (lines 54‑90) to surgically update the graph rather than regenerating it from scratch.
Selective Node and Edge Removal
The merge strategy operates on the principle of file-level invalidation:
- Node removal: All nodes whose
filePathproperty appears in the changed file set are discarded from the graph - Edge cleanup: Any edges connected to removed nodes—whether as source or target—are automatically stripped to maintain graph integrity
- Fresh data append: New nodes and edges from the current analysis are appended to the cleaned graph structure
This approach preserves analysis results for unchanged files while eliminating stale references to modified code.
Metadata Synchronization
After structural updates, mergeGraphUpdate updates the project metadata stored within the KnowledgeGraph object. It writes the new gitCommitHash (current HEAD) and refreshes the analyzedAt timestamp to reflect the analysis time, ensuring future staleness checks compare against the correct baseline.
Practical Implementation Examples
Checking Graph Freshness
The following pattern demonstrates how the main analysis pipeline uses isStale to gate rebuild operations:
import { isStale } from "@understand-anything/core";
async function maybeRebuild(projectDir: string, storedGraph: KnowledgeGraph) {
const { stale, changedFiles } = isStale(projectDir, storedGraph.project.gitCommitHash);
if (!stale) {
console.log("Graph is fresh – no rebuild needed.");
return storedGraph;
}
console.log("Detected changes:", changedFiles);
// Run a fresh analysis (omitted) → newNodes, newEdges, newCommitHash
// const { newNodes, newEdges, newCommitHash } = await runAnalysis(projectDir);
// return mergeGraphUpdate(storedGraph, changedFiles, newNodes, newEdges, newCommitHash);
}
Applying Incremental Updates
When changes are detected, the mergeGraphUpdate function reconciles the old graph with fresh analysis data:
import { mergeGraphUpdate } from "@understand-anything/core";
function updateGraph(
oldGraph: KnowledgeGraph,
changedFiles: string[],
freshNodes: GraphNode[],
freshEdges: GraphEdge[],
newCommitHash: string,
) {
return mergeGraphUpdate(
oldGraph,
changedFiles,
freshNodes,
freshEdges,
newCommitHash,
);
}
Unit Test Verification
The test suite in understand-anything-plugin/packages/core/src/__tests__/staleness.test.ts validates each branch of the logic, including Git output parsing and error handling:
import { isStale, getChangedFiles } from "../staleness.js";
test("isStale returns true when files changed", () => {
vi.mocked(execFileSync).mockReturnValue("src/index.ts\n");
expect(isStale("/project", "abc123")).toEqual({
stale: true,
changedFiles: ["src/index.ts"],
});
});
Summary
- Staleness detection relies on
git diff ${lastCommitHash}..HEAD --name-onlyto identify changed files between the stored analysis commit and the current repository state. - The
isStalefunction instaleness.ts(lines 34‑42) returns a boolean flag and the specific file list, enabling precise invalidation decisions. - When rebuilding is required,
mergeGraphUpdate(lines 54‑90) removes nodes and edges associated with changed files while preserving the rest of the graph structure. - The system updates
gitCommitHashandanalyzedAtmetadata after each successful rebuild to establish a new baseline for future comparisons. - Error handling in
getChangedFilesdefaults to "fresh" status if Git commands fail, preventing unnecessary rebuilds on repository errors.
Frequently Asked Questions
What triggers a knowledge graph rebuild in Egonex-AI?
A rebuild triggers when the isStale function detects that the Git commit hash stored in the knowledge graph differs from the current HEAD and git diff returns a non‑empty list of changed files. The system then removes nodes associated with those specific files and merges fresh analysis results.
How does the system handle Git command failures during staleness checks?
If execFileSync throws an error—for example, when the stored commit hash no longer exists in the repository—the getChangedFiles function catches the exception and returns an empty array. This conservative approach treats the graph as fresh, preventing unnecessary rebuilds when Git metadata is unavailable or corrupted.
What happens to graph edges when a file is marked as stale?
The mergeGraphUpdate function removes any edges where either the source or target node references a file path in the changed file set. This ensures the graph maintains referential integrity after nodes are removed, eliminating dangling connections to obsolete code entities.
Where is the staleness detection logic located in the codebase?
The core implementation resides in understand-anything-plugin/packages/core/src/staleness.ts, which exports getChangedFiles, isStale, and mergeGraphUpdate. Type definitions for KnowledgeGraph, GraphNode, and GraphEdge are imported from types.ts in the same directory, while comprehensive unit tests are located in __tests__/staleness.test.ts.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →