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

> Merge subdomain knowledge graphs into one unified graph using the merge-subdomain-graphs.py script in Understand Anything. Deduplicate and create a single knowledge graph JSON file for analysis.

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

---

**To merge subdomain knowledge graphs in Understand-Anything, run the [`merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-subdomain-graphs.py) script, which discovers all `*knowledge-graph*.json` files in `.understand-anything/`, deduplicates nodes and edges by ID and weight, and writes a unified [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json) ready for analysis.**

The *Understand-Anything* repository stores codebase analysis results as **knowledge-graph** JSON files inside the hidden folder `.understand-anything/`. When a project splits into multiple subdomains—such as [`frontend-knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/frontend-knowledge-graph.json) and [`backend-knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/backend-knowledge-graph.json)—each generates its own graph file. The tool provides [`merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-subdomain-graphs.py), a Python utility that discovers, loads, and merges these subdomain graphs into a single coherent view.

## Understanding the Subdomain Graph Structure

Before merging, the system generates individual graph files for each analyzed subdomain. These files follow the same schema as the main knowledge graph but contain isolated slices of the project structure. According to the source code in [`core/src/analyzer/graph-builder.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/core/src/analyzer/graph-builder.ts), each subdomain graph includes nodes, edges, layers, and tours specific to that domain's analysis run.

The merge utility expects these files to reside in the `.understand-anything/` directory at your project root. By convention, subdomain graphs use the naming pattern `*knowledge-graph*.json`, while the central unified graph is named exactly [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json).

## Step-by-Step Merge Process

The merge process implemented in [`understand-anything-plugin/skills/understand/merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/skills/understand/merge-subdomain-graphs.py) follows a strict architectural pipeline to ensure data integrity and consistency.

### Discovery Phase

The script begins by scanning the `.understand-anything/` directory for any files matching the glob pattern `*knowledge-graph*.json` while explicitly excluding the central [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json) (lines 55‑60). This prevents the script from treating the existing merged output as an input source.

### Base Loading Strategy

If a central [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json) already exists, the script loads it first and places it at the front of the processing list (lines 84‑91). This ordering ensures that during conflict resolution, later subdomain data can override the base configuration, following the **last-write-wins** pattern for node definitions.

### Node Deduplication by ID

Nodes are indexed by their unique `id` field. When duplicate IDs exist across subgraphs, the later occurrence wins, and a per-node-type counter tracks how many duplicates were removed (lines 64‑76). This deduplication prevents entity proliferation while preserving the most recent metadata from subdomain analyses.

### Edge Deduplication by Weight

Edges are keyed by the tuple `(source, target, type)`. The algorithm keeps the edge with the **higher weight** value and discards duplicates, again maintaining counters for reporting purposes (lines 77‑89). Additionally, the script validates edge references and drops any edges pointing to nodes that no longer exist after node deduplication, logging these removals for transparency (lines 91‑99).

### Layer Merging

Layers with identical `id` values are merged by computing the union of their `nodeIds` arrays (lines 106‑126). The process strips dangling references to nodes that were removed during deduplication, ensuring layer definitions remain valid and consistent with the final node set.

### Tour Consolidation

Tour steps from all subgraphs are concatenated into a single sequence. Steps sharing the same `title` are merged by uniting their `nodeIds` and retaining the longer `description` text (lines 127‑146). Similar to layer processing, any tour step references to nodes that no longer exist are removed to maintain graph integrity (lines 148‑156).

### Project Metadata Aggregation

Language, framework, description, and timestamp fields from each subgraph are combined into the unified output. The algorithm avoids duplicate entries and specifically selects the newest `analyzedAt` timestamp to represent the project's last analysis time (lines 158‑182).

### Report Generation

After processing, the script generates a human-readable report listing input sizes, fixes performed (duplicate nodes/edges removed, dangling references dropped), and any unfixable issues (lines 183‑199). This report is printed to `stderr`, allowing the JSON output to remain clean for piping or file redirection while still informing the user of merge operations.

### Final Output

The merged graph is written back to [`.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json) (lines 300‑304), completing the unification process.

## Running the Merge Script

You can invoke the merge utility either from the command line or programmatically within Python workflows.

### Command Line Execution

From your project root, execute the script directly:

```bash
python ./understand-anything-plugin/skills/understand/merge-subdomain-graphs.py $PROJECT_ROOT

```

The script accepts the project root path as its argument and automatically discovers all relevant subgraph files within the `.understand-anything/` subdirectory.

### Programmatic Integration

For custom workflows, import the core functions and handle the merge logic directly:

```python
from pathlib import Path
from understand_anything_plugin.skills.understand.merge_subdomain_graphs import (
    load_graph,
    merge_graphs,
)
import json

project_root = Path("/path/to/project")
ua_dir = project_root / ".understand-anything"

# Discover subdomain graphs (same glob pattern used by the script)

graph_files = sorted(p for p in ua_dir.glob("*knowledge-graph*.json")
                    if p.name != "knowledge-graph.json")

graphs = [load_graph(p) for p in graph_files if load_graph(p) is not None]

# Optionally load the existing central graph as base

base_path = ua_dir / "knowledge-graph.json"
if base_path.is_file():
    base = load_graph(base_path)
    if base:
        graphs.insert(0, base)

merged_graph, report = merge_graphs(graphs)

# Write the merged graph back to disk

output_path = ua_dir / "knowledge-graph.json"
output_path.write_text(
    json.dumps(merged_graph, indent=2, ensure_ascii=False), encoding="utf-8"
)

# Print the merge report

for line in report:
    print(line)

```

## Embedding Merges in Automated Workflows

The [`SKILL.md`](https://github.com/Egonex-AI/Understand-Anything/blob/main/SKILL.md) documentation (lines 159‑164) instructs automated agents to invoke the merge script after completing subdomain scans. You can embed this step into your CI/CD pipelines or analysis workflows:

> “If any subdomain graphs exist, run the merge script bundled with this skill: `python <SKILL_DIR>/merge-subdomain-graphs.py $PROJECT_ROOT`”

This ensures that whenever subdomains are analyzed—whether [`frontend-knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/frontend-knowledge-graph.json) or [`backend-knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/backend-knowledge-graph.json)—the unified view stays synchronized without manual intervention. The design also makes the merge **idempotent**: re-running the script after a previous merge simply re-discovers any new subdomain files and updates the central graph accordingly.

## Summary

- **Discovery**: The script scans `.understand-anything/` for `*knowledge-graph*.json` files, excluding the central [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json).
- **Deduplication**: Nodes merge by ID (last occurrence wins), while edges merge by `(source, target, type)` tuple keeping the highest weight.
- **Consistency**: Layers and tours merge by ID, stripping dangling references and unifying node lists.
- **Metadata**: Project properties combine with the newest `analyzedAt` timestamp preserved.
- **Reporting**: A detailed report prints to `stderr`, while clean JSON outputs to [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json).
- **Idempotency**: The script safely re-runs to incorporate new subdomain analyses without duplicating data.

## Frequently Asked Questions

### What happens if I run the merge script multiple times?

The merge process is **idempotent**. Re-running [`merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-subdomain-graphs.py) after a previous merge simply re-scans the `.understand-anything/` directory, discovers any new subdomain graphs, and merges them with the existing central graph. Because the script reprocesses all inputs from scratch and re-applies deduplication rules, you will not accumulate duplicate data across multiple runs.

### How does the script resolve conflicts between subdomain graphs?

For **nodes**, the script uses a last-write-wins strategy where the later occurrence of a duplicate ID overrides earlier definitions (lines 64‑76). For **edges**, which are keyed by `(source, target, type)`, the edge with the **higher weight** value is retained while lower-weight duplicates are discarded (lines 77‑89). This ensures that the most refined or recent analysis data takes precedence in the unified graph.

### Can the merge utility handle batch analysis results?

Yes. While [`merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-subdomain-graphs.py) handles standard subdomain unification, the repository also includes [`merge-batch-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-batch-graphs.py) for deeper pipelines that process multiple batch analysis results. Both utilities follow similar architectural patterns but target different analysis granularities within the Understand-Anything ecosystem.

### Where does the merge report go, and what information does it contain?

The script generates a human-readable report that lists: the size of each input graph, the number of duplicate nodes and edges removed, the count of dangling references dropped, and any unfixable issues encountered during processing. According to lines 183‑199 in [`merge-subdomain-graphs.py`](https://github.com/Egonex-AI/Understand-Anything/blob/main/merge-subdomain-graphs.py), this report is printed to `stderr`, allowing the valid JSON output to stream to `stdout` or a file without contamination from log messages.