Skip to main content

Edge Types

Edges encode the relationships between nodes. They are the connective tissue that makes the graph more than a collection of lists.

The Seven Edge Types

The Spec Graph defines seven typed edge kinds. Each relationship is authored once as a forward declaration in the source node:

Edge TypeMeaningExample
containsGrouping/namespace relationshipFeature or layer contains its child nodes
depends_onMust be satisfied before this nodeA behavior depends on a decision being in place
constrainsNarrows implementation choices for the targetA policy limits how a behavior can be implemented
implementsThis node realizes part of the targetA behavior implements a domain concept
derived_fromGenerated or imported from target (pinned hash)A design token derived from an artifact
verified_byPoints to verification checksA behavior verified by a test strategy node
supersedesReplaces the target nodeA new decision supersedes an old one

Edge Direction

Edges are forward-only and stored in the source node's links field:

{
"id": "AUTH-01",
"type": "behavior",
"links": {
"implements": ["DOM-USER-01"],
"depends_on": ["DEC-AUTH-01"]
}
}

This means: "AUTH-01 implements DOM-USER-01" and "AUTH-01 depends on DEC-AUTH-01."

Inverse edges are computed by tooling, never stored. If AUTH-01 depends on DEC-AUTH-01, tooling derives that DEC-AUTH-01 is depended on by AUTH-01. This keeps the graph DRY — each relationship is declared once, on the node where it's most natural to author.

forward-only describes storage, not runtime traversal. Tooling materializes both outbound and inbound views in memory.

Edge Semantics

contains

Used by grouping nodes (feature, layer) to group their children. This is the primary organizational edge.

// In AUTH.json (feature)
"links": {
"contains": ["AUTH-01", "AUTH-02", "DEC-AUTH-01", "DOM-USER-01"]
}

depends_on

Establishes ordering requirements. If A depends on B, then B must be manifested (or at least understood) before A.

Critical rule: depends_on must be acyclic. Cycles in dependency edges are a validation error.

Layer-specific safety rule:

  • layer -> depends_on -> feature is invalid
  • feature -> depends_on -> layer is valid
  • layer -> depends_on -> layer is valid

This acyclicity requirement is specific to depends_on because manifestation order must be topologically sortable. Other edge types can be cyclic when that matches the domain model.

constrains

Narrows the implementation space of the target. A policy node might constrain a behavior node, meaning the behavior must be implemented within the policy's boundaries.

// In POL-PERF-01.json (policy)
"links": {
"constrains": ["AUTH-01", "AUTH-04"]
}

Constraint propagation through contains

To avoid edge explosion, constrains is interpreted with transitive propagation:

  1. If A constrains B and B contains C, then A implicitly constrains C (downward cascade).
  2. Propagation does not flow upward from child to parent.
  3. Direct constrains propagation does not flow over depends_on; dependency-based propagation is a separate layer-specific rule.
  4. If a node has multiple contains ancestors, inherited constraints are unioned.

implements

Links a concrete node to the abstract concept it realizes. Typically used by behavior nodes pointing to domain nodes:

// In AUTH-01.json (behavior)
"links": {
"implements": ["DOM-USER-01"]
}

derived_from

Indicates that this node was generated from or imported from another node, typically an artifact.

To make derivations reproducible, derived nodes should include pins entries that record the expected source hash at derivation time. Tooling can then detect when a derived node is stale (source hash changed) and trigger re-derivation.

verified_by

Points from a node to the node(s) that verify it. Useful when verification logic is complex enough to warrant its own node (e.g., an equivalence_contract or pipeline node).

supersedes

Marks a node as replacing another. The existence of this edge signals that the target node is deprecated. This supports evolution without losing history.

Validation Rules

  1. Referential integrity: every edge target must exist as a node in the graph
  2. No self-references: a node cannot have an edge to itself
  3. Acyclicity for depends_on: dependency chains must not form cycles
  4. Non-decorative: edges must affect planning, implementation, or verification — purely decorative edges are discouraged

Common Edge Patterns

Valid Non-depends_on Cycle

Non-dependency cycles are allowed by graph integrity checks. For example, this structural cycle is valid:

This can model a bidirectional relationship between a contract and domain rules. It is valid because neither edge is depends_on.

Invalid depends_on Cycle

Dependency cycles are rejected by graph integrity validation:

This is invalid because depends_on must be acyclic to preserve a deterministic manifestation order.

Behavior → Decision → Stack

A behavior depends on an architectural decision, which in turn depends on a technology choice.

Policy → Multiple Behaviors

A performance policy applies to multiple behaviors across features.

Grouping Node → Children

Features and layers both group related nodes regardless of type.