Understanding Edge Types and Weight Conventions in Lum1104/Understand-Anything's Knowledge Graph

Lum1104/Understand-Anything defines 35 edge types across eight semantic categories, with weights constrained to [0, 1] to represent relationship strength, where missing values default to 0.5 and out-of-range values are clamped to the nearest bound.

The knowledge graph at the heart of the Understand-Anything project transforms codebases into navigable networks of semantic relationships. To interpret these connections accurately, developers must grasp how edge types categorize relationships and how weights quantify their significance. This guide examines the edge taxonomy, weight semantics, and validation rules implemented in the Lum1104/Understand-Anything repository.

Edge Type Taxonomy in Understand-Anything's Knowledge Graph

The complete list of edge types lives in packages/core/src/types.ts, implemented as a TypeScript union type called EdgeType. These 35 distinct types are grouped into eight semantic categories that capture everything from code structure to domain knowledge.

The definition groups edges as follows:

// Edge types (35 total in 8 categories)
export type EdgeType =
  // Structural
  | "imports" | "exports" | "contains" | "inherits" | "implements"
  // Behavioral
  | "calls" | "subscribes" | "publishes" | "middleware"
  // Data flow
  | "reads_from" | "writes_to" | "transforms" | "validates"
  // Dependencies
  | "depends_on" | "tested_by" | "configures"
  // Semantic
  | "related" | "similar_to"
  // Infrastructure / Schema
  | "deploys" | "serves" | "provisions" | "triggers"
  // Schema / Data
  | "migrates" | "documents" | "routes" | "defines_schema"
  // Domain
  | "contains_flow" | "flow_step" | "cross_domain"
  // Knowledge
  | "cites" | "contradicts" | "builds_on" | "exemplifies"
  | "categorized_under" | "authored_by";

All edge type strings are validated by zod in packages/core/src/schema.ts within the EdgeTypeSchema. If an edge is missing a type, the validator auto-corrects it to "depends_on" and records an issue.

Structural and Behavioral Relationships

Structural edges model containment and inheritance hierarchies. The contains type indicates that a file or module encapsulates a function or class, while inherits and implements capture object-oriented relationships. Behavioral edges such as calls, subscribes, and publishes map runtime interactions like function invocations and event-driven communication patterns.

Data Flow and Dependencies

Data flow edges track how information moves through the system. The reads_from and writes_to types link functions to data sources, while transforms and validates indicate processing stages. Dependency edges like depends_on and tested_by express service relationships and testing coverage, often assigned higher weights to reflect critical path connections.

Semantic and Domain-Specific Connections

Higher-level relationships include related and similar_to for semantic similarity, cross_domain for boundary crossings in domain-driven design, and knowledge-graph primitives like cites and builds_on for documentation and research contexts. These edges typically carry lower weights (0.2–0.4) to indicate loose coupling compared to structural containment.

Edge Weight Conventions and Validation Rules

Every edge in the knowledge graph carries a weight: number field constrained to the closed interval [0, 1] as defined in GraphEdgeSchema within packages/core/src/schema.ts. The weight quantifies the strength or confidence of the relationship:

  • 0.0–0.2: Weak or optional relations (e.g., loose references or semantic similarity)
  • 0.3–0.6: Moderate confidence (common imports, typical function calls)
  • 0.7–1.0: Strong or deterministic relations (containment, direct calls, explicit dependencies)

Auto-Correction and Normalization

When deserializing a graph, the validation pipeline in packages/core/src/schema.ts enforces strict normalization rules:

  • Missing weight: Defaulted to 0.5 (mid-range) and recorded as an auto-corrected issue
  • String weight: Coerced to a number; invalid strings fall back to 0.5
  • Out-of-range values (e.g., -0.1 or 1.5): Clamped to the nearest bound (0 or 1) with an issue logged

These conventions guarantee that downstream consumers—such as the dashboard layout algorithms and LLM-driven explanations—always receive a numeric weight they can safely use for ranking or filtering.

Edge Directionality Semantics

Edges carry a direction field with three allowed values:

direction: "forward" | "backward" | "bidirectional"

During deserialization, the validator normalizes aliases such as "TO" to "forward". Forward edges point from source to target, backward edges represent the inverse relationship, and bidirectional edges render as two-way links in the UI. Directionality is critical for pathfinding algorithms and for correctly interpreting relationships like imports versus exports.

Practical Applications of Edge Weights

Edge weights influence multiple subsystems throughout the Understand-Anything codebase:

  • Layout algorithms: The dashboard's utils/layout.ts and utils/louvain.ts compute community detection and force-directed placement using weights to influence edge length—stronger edges draw nodes closer together
  • Explanation generation: src/explain-builder.ts filters and ranks edges by weight when assembling human-readable narratives, prioritizing high-confidence relationships (≥ 0.7)
  • Diff analysis: src/diff-analyzer.ts propagates changes through high-weight edges first, treating them as more impactful to the system's behavior

Working with GraphEdge in Code

The following examples demonstrate how to construct edges, handle validation, and utilize weights in custom algorithms.

Constructing a Type-Safe Edge

import { GraphEdge } from "@understand-anything/core";

const edge: GraphEdge = {
  source: "file:src/auth.ts",
  target: "function:src/auth.ts:login",
  type: "contains",          // structural containment
  direction: "forward",
  description: "auth file contains login function",
  weight: 1.0,               // strongest possible link
};

Validating Raw Input with Auto-Correction

import { validateKnowledgeGraph } from "@understand-anything/core";

const raw = {
  source: "file:src/service.ts",
  target: "file:src/db.ts",
  type: "reads_from",
  // direction omitted → defaults to "forward"
  // weight omitted → defaults to 0.5 (auto-corrected)
};

const { data, issues } = validateKnowledgeGraph({ 
  version: "1.0", 
  project: {/*…*/}, 
  nodes: [], 
  edges: [raw], 
  layers: [], 
  tour: [] 
});

console.log(data.edges[0].direction); // "forward"
console.log(data.edges[0].weight);    // 0.5
console.log(issues[0].message);       // edges[0]: missing "direction" — defaulted to "forward"

Using Weights in Layout Algorithms

import { GraphEdge } from "@understand-anything/core";

function computeEdgeLength(edge: GraphEdge): number {
  // Stronger edges are drawn shorter (more tightly) – inverse mapping
  const minLen = 30, maxLen = 200;
  return maxLen - edge.weight * (maxLen - minLen);
}

// Example usage:
const short = computeEdgeLength({ 
  weight: 1, 
  source: "", 
  target: "", 
  type: "contains", 
  direction: "forward" 
});
const long  = computeEdgeLength({ 
  weight: 0.2, 
  source: "", 
  target: "", 
  type: "related", 
  direction: "forward" 
});

console.log(short, long); // 30 170

Filtering by Confidence Threshold

import { GraphEdge } from "@understand-anything/core";

function topEdges(edges: GraphEdge[], threshold = 0.7) {
  return edges.filter(e => e.weight >= threshold);
}

const important = topEdges(sampleGraph.edges);
console.log(important.map(e => `${e.source} → ${e.target} (${e.weight})`));

Summary

  • 35 edge types in eight categories (structural, behavioral, data-flow, dependencies, semantic, infrastructure, schema, and knowledge) are defined in packages/core/src/types.ts
  • Weight values must fall within [0, 1], where higher values indicate stronger relationships; the system defaults missing weights to 0.5 and clamps out-of-range values
  • Validation occurs in packages/core/src/schema.ts using zod schemas that auto-correct missing types to "depends_on" and normalize direction strings
  • Directionality supports forward, backward, and bidirectional relationships, with normalization for legacy aliases
  • Downstream systems leverage weights for force-directed layout in utils/layout.ts, explanation ranking in explain-builder.ts, and impact analysis in diff-analyzer.ts

Frequently Asked Questions

What are the 35 edge types in Understand-Anything?

The 35 edge types span eight semantic categories defined in packages/core/src/types.ts. Structural types include imports, exports, contains, inherits, and implements. Behavioral types cover calls, subscribes, publishes, and middleware. Data flow is captured by reads_from, writes_to, transforms, and validates. Additional categories handle dependencies (depends_on, tested_by), infrastructure (deploys, serves), schema (defines_schema, migrates), domain logic (cross_domain, flow_step), and knowledge relationships (cites, builds_on).

How does Understand-Anything handle missing edge weights?

When an edge lacks a weight field, the validator in packages/core/src/schema.ts assigns a default value of 0.5 and logs an auto-correction issue. If the weight is provided as a string, the system attempts to coerce it to a number; invalid strings also fall back to 0.5. Values outside the [0, 1] range are clamped to the nearest valid bound (0 or 1) rather than rejected.

What is the difference between forward and bidirectional edges?

Forward edges represent relationships that flow from source to target, such as a file importing another module or a function calling another function. Bidirectional edges indicate mutual relationships where both nodes influence each other equally, such as two services in a circular dependency or semantically similar concepts. The UI renders forward edges as single arrows and bidirectional edges as double-headed links.

How are edge weights used in the dashboard layout?

The dashboard's layout engine in packages/dashboard/src/utils/layout.ts uses edge weights to compute force-directed graph distances. Higher weights (closer to 1.0) result in shorter edge lengths, pulling connected nodes tightly together. Lower weights allow greater separation. This visual encoding helps users immediately distinguish strong structural dependencies from weak semantic associations.

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 →