How to Merge Subdomain Knowledge Graphs into a Unified Graph in Understand-Anything
To merge subdomain knowledge graphs in Understand-Anything, run the 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 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 and backend-knowledge-graph.json—each generates its own graph file. The tool provides 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, 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.
Step-by-Step Merge Process
The merge process implemented in 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 (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 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 (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:
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:
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 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 or 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*.jsonfiles, excluding the centralknowledge-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
analyzedAttimestamp preserved. - Reporting: A detailed report prints to
stderr, while clean JSON outputs toknowledge-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 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 handles standard subdomain unification, the repository also includes 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, this report is printed to stderr, allowing the valid JSON output to stream to stdout or a file without contamination from log messages.
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 →