How to Merge Subdomain Knowledge Graphs into a Main Graph in Understand-Anything

Use the mergeGraphUpdate utility from packages/core/src/staleness.ts to merge subdomain knowledge graphs by identifying changed file paths, filtering out stale nodes and edges, and appending the new subgraph data.

Understand-Anything constructs comprehensive knowledge graphs that model code, configuration, and documentation relationships across software projects. When analyzing large codebases split across multiple subdomains—such as microservices, libraries, or documentation sets—you generate independent subgraphs that must be unified into a single coherent graph. The core utility mergeGraphUpdate implements an idempotent replacement strategy that simplifies this consolidation.

How the Merge Algorithm Works

The mergeGraphUpdate function in packages/core/src/staleness.ts performs a five-step reconciliation process that treats incoming subdomain data as an update to specific file paths.

1. Identify Changed File Paths

The function first collects the IDs of nodes associated with files that have changed or belong to the incoming subdomain. It reads the node.filePath property from the existing graph and builds a removedNodeIds set (lines 61–68).

2. Filter Retained Nodes

It then partitions the existing graph, keeping only nodes whose IDs are not in the removal set. This retainedNodes array represents the portion of the main graph that remains valid (lines 70–73).

3. Prune Orphaned Edges

Any edges whose source or target node was discarded are removed. The retainedEdges array filters out relationships that reference nodes in removedNodeIds (lines 75–78).

4. Append New Subgraph Data

The function constructs the merged graph by spreading the retained data and the new subdomain data:

nodes: [...retainedNodes, ...newNodes],
edges: [...retainedEdges, ...newEdges]

This operation occurs at lines 87–89 in the source file.

5. Refresh Project Metadata

Finally, the function updates the project section of the graph object, including fields like gitCommitHash and analyzedAt, ensuring the unified graph reflects the latest analysis state (lines 81–86).

The result is a fresh KnowledgeGraph object containing the unified view of all domains.

Implementing Subdomain Graph Merging

When working with multiple subgraphs, wrap the core utility in a helper that extracts file paths and aggregates nodes and edges.

Bulk Merge Helper Function

import { mergeGraphUpdate } from "@understand-anything/core";
import type { KnowledgeGraph } from "@understand-anything/core";

/**
 * Merge several subdomain graphs into the main graph.
 *
 * @param mainGraph   The existing full-project graph (may be empty on first run).
 * @param subGraphs   Array of subdomain graphs produced by separate analyses.
 * @param newCommit   The git commit hash after all analyses.
 * @returns           A merged KnowledgeGraph ready for dashboard rendering.
 */
export function mergeSubDomainGraphs(
  mainGraph: KnowledgeGraph,
  subGraphs: KnowledgeGraph[],
  newCommit: string,
): KnowledgeGraph {
  // Collect every node-file path from all sub-graphs – these are the "changed" paths.
  const changedFilePaths = subGraphs
    .flatMap((g) => g.nodes)
    .filter((n) => n.filePath !== undefined)
    .map((n) => n.filePath!);

  // Gather all nodes/edges that we want to add.
  const newNodes = subGraphs.flatMap((g) => g.nodes);
  const newEdges = subGraphs.flatMap((g) => g.edges);

  // Merge into the current main graph.
  return mergeGraphUpdate(
    mainGraph,
    changedFilePaths,
    newNodes,
    newEdges,
    newCommit,
  );
}

CLI Integration Script

For automation in build pipelines or CLI tools, load existing graphs, merge them, and persist the result:

#!/usr/bin/env node
import { readFileSync, writeFileSync } from "fs";
import { mergeSubDomainGraphs } from "./merge-helper.js";
import { loadGraph } from "@understand-anything/core/persistence";

// 1️⃣ Load the existing main graph (or start with an empty one)
let mainGraph = {};
try {
  mainGraph = JSON.parse(readFileSync("./.understand-anything/knowledge-graph.json"));
} catch {
  console.log("No existing graph – starting fresh.");
}

// 2️⃣ Load subdomain graphs generated elsewhere
const subA = JSON.parse(readFileSync("./sub-a/knowledge-graph.json"));
const subB = JSON.parse(readFileSync("./sub-b/knowledge-graph.json"));

// 3️⃣ Merge them
const merged = mergeSubDomainGraphs(mainGraph, [subA, subB], "HEAD");

// 4️⃣ Persist the updated graph
writeFileSync("./.understand-anything/knowledge-graph.json", JSON.stringify(merged, null, 2));
console.log("✅ Merged sub-domains into the main knowledge graph.");

Key Source Files in the Merge Pipeline

The following files define the data structures, implement the merge logic, and handle persistence:

Summary

  • Use mergeGraphUpdate in packages/core/src/staleness.ts as the canonical way to merge subdomain knowledge graphs.
  • The algorithm operates by file-path-based replacement, removing nodes associated with changed files before appending new data.
  • Retained nodes and edges persist across merges, ensuring incremental updates do not destroy unrelated graph data.
  • The function returns a complete KnowledgeGraph object suitable for immediate persistence via the core persistence layer.
  • Repeated calls to the merge utility allow you to build a unified graph spanning the entire codebase from independent subdomain analyses.

Frequently Asked Questions

What is the primary function used to merge knowledge graphs in Understand-Anything?

The primary function is mergeGraphUpdate exported from packages/core/src/staleness.ts. It accepts the current main graph, an array of changed file paths, new nodes and edges from the subdomain, and a git commit hash, returning a merged KnowledgeGraph object.

How does the merge handle stale or outdated nodes?

The function builds a removedNodeIds set containing all node IDs associated with the changed file paths. It filters the existing graph to create retainedNodes and retainedEdges arrays that exclude these IDs, effectively pruning stale data before appending the new subgraph.

Can I merge multiple subdomain graphs in a single operation?

Yes. Aggregate all nodes and edges from your subdomain graphs into single arrays and collect all unique file paths. Pass these to mergeGraphUpdate (or a wrapper like mergeSubDomainGraphs) to replace all specified paths in one atomic operation.

Where is the merged graph stored for the dashboard to access?

The merged graph is typically written to knowledge-graph.json in the .understand-anything directory via the persistence layer (packages/core/src/persistence/index.ts). The dashboard's store (packages/dashboard/src/store.ts) reads this file to render the unified visualization and provide context to chat agents.

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 →