Help us shape the future of Go! Take the 2026 Go Developer Survey

graph

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 20, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MemoryRootID is the single root node for the memory layer.
	MemoryRootID = "memory:root:ancora"

	// Cross-layer canonical-key target prefixes used on memory reference edges.
	// Targets in these namespaces do NOT get a corresponding memory-layer node —
	// they are pointers out of the memory graph.
	RefRepoFile      = "repo:file:"
	RefRepoSymbol    = "repo:symbol:"
	RefWorkspaceRepo = "workspace:repo:"
	RefMemoryObs     = "memory:observation:"
	RefMemoryConcept = "memory:concept:"
)
View Source
const (
	MemoryRelContains    = "contains"    // root -> workspace, workspace -> visibility
	MemoryRelBelongsTo   = "belongs_to"  // observation -> workspace/organization
	MemoryRelScopedTo    = "scoped_to"   // observation -> visibility
	MemoryRelMentions    = "mentions"    // observation -> workspace:repo (cross-layer)
	MemoryRelRelatedTo   = "related_to"  // observation -> observation
	MemoryRelDefines     = "defines"     // observation -> concept
	MemoryRelReferences  = "references"  // observation -> external artifact
	MemoryRelDocuments   = "documents"   // architecture/discovery obs -> code
	MemoryRelDecidesOn   = "decides_on"  // decision obs -> code
	MemoryRelConstrains  = "constrains"  // bugfix obs -> code
	MemoryRelExemplifies = "exemplifies" // pattern obs -> code
)

Memory edge relations.

View Source
const (
	MemoryEvidenceObservation = "observation"
	MemoryEvidenceReference   = "observation-reference"
	MemoryEvidenceStructural  = "memory-structure"
)

Evidence type tags specific to the memory layer.

View Source
const (
	// Workspace edge relations.
	WorkspaceRelExposes   = "exposes"    // repo -> service
	WorkspaceRelHosts     = "hosts"      // repo -> package
	WorkspaceRelOwns      = "owns"       // repo -> domain
	WorkspaceRelDependsOn = "depends_on" // repo -> repo
)

Variables

View Source
var ErrGraphLocked = errors.New("graph is locked by another process (daemon running?); stop the daemon first")

ErrGraphLocked is returned when another process holds the graph lock.

Functions

func BindMemoryReferenceEdge added in v1.4.0

func BindMemoryReferenceEdge(edge types.Edge, liveNodes []types.Node) types.Edge

BindMemoryReferenceEdge binds a single memory reference edge against the current graph state.

func BindMemoryReferences added in v1.4.0

func BindMemoryReferences(edges []types.Edge, liveNodes []types.Node) []types.Edge

BindMemoryReferences projects memory reference edges onto the current live code/workspace nodes. Current and redirected bindings are rewritten to point at the live node ID; stale and ambiguous references keep their original canonical target and carry queryable binder metadata instead.

func Canonicalize added in v1.4.0

func Canonicalize(nodes []types.Node, edges []types.Edge) ([]types.Node, []types.Edge)

Canonicalize removes duplicate node IDs and duplicate/orphaned edges while preserving the first occurrence order for stable graph exports.

func GodNodes

func GodNodes(g *Graph, topN int) []types.Node

GodNodes returns the topN nodes sorted by total degree (in + out). These are the most-connected concepts in the graph — architectural hubs.

func MemoryConceptID added in v1.4.0

func MemoryConceptID(c string) string

func MemoryObservationID added in v1.4.0

func MemoryObservationID(id int64) string

ID helpers for memory-layer nodes.

func MemoryOrganizationID added in v1.4.0

func MemoryOrganizationID(o string) string

func MemoryReferenceEdge added in v1.4.0

func MemoryReferenceEdge(src string, ref ResolvedMemoryReference, artifact string) types.Edge

MemoryReferenceEdge materializes a canonicalized memory reference edge.

func MemoryVisibilityID added in v1.4.0

func MemoryVisibilityID(v string) string

func MemoryWorkspaceID added in v1.4.0

func MemoryWorkspaceID(name string) string

func MergeContract added in v1.4.0

func MergeContract(
	repoNodes []types.Node, repoEdges []types.Edge,
	contractNodes []types.Node, contractEdges []types.Edge,
) ([]types.Node, []types.Edge)

MergeContract folds a contract-layer graph (nodes + edges) on top of a repo-layer graph while preserving the declared > derived invariant.

Guarantees:

  • Repo and contract nodes live side-by-side. Contract nodes keep their "contract:*" identity; they are never merged into repo-local entities.
  • When a derived edge and a declared edge claim the same (source, target, relation) triple, the derived edge is dropped — declared truth wins.
  • Duplicate declared edges are deduplicated on (source, target, relation) so ingesting the same artifact twice is idempotent.

This helper stays structural: it does not inspect evidence scores beyond the `layer` and `evidence_confidence` metadata that extractors stamp. That keeps the invariant easy to audit in tests and keeps the contract layer from quietly reaching into repo ranking logic.

func MergeMemory added in v1.4.0

func MergeMemory(
	baseNodes []types.Node, baseEdges []types.Edge,
	memNodes []types.Node, memEdges []types.Edge,
) ([]types.Node, []types.Edge)

MergeMemory folds the memory graph onto an existing repo+contract+workspace graph. Memory nodes keep their "memory:" identity; cross-layer reference edges target canonical keys that already exist elsewhere. Memory never overwrites repo/contract/workspace nodes.

func RunLeiden

func RunLeiden(g *Graph) (map[string]int, error)

RunLeiden runs Leiden community detection on the graph by delegating to the bundled Python script (scripts/leiden.py). Returns a map of node ID → community ID (0-indexed integers).

If Python or the script is unavailable, a clear error is returned (no panic). The script itself falls back to connected-components if graspologic is missing.

func SuggestedQuestions

func SuggestedQuestions(nodes []types.Node, edges []types.Edge) []string

SuggestedQuestions returns 4–5 question templates populated with the names of the top god nodes. These are questions the graph is uniquely positioned to answer through path-finding and community analysis.

func SurpriseEdges

func SurpriseEdges(g *Graph, topN int) []types.Edge

SurpriseEdges returns the topN edges that cross community boundaries, ranked by the product of the degrees of their endpoints (a proxy for betweenness centrality: high-degree nodes in different communities that are directly connected are architecturally "surprising").

func WorkspaceDomainID added in v1.4.0

func WorkspaceDomainID(name string) string

WorkspaceDomainID returns the canonical workspace ID for a domain tag.

func WorkspacePackageID added in v1.4.0

func WorkspacePackageID(name string) string

WorkspacePackageID returns the canonical workspace ID for a package.

func WorkspaceRepoID added in v1.4.0

func WorkspaceRepoID(name string) string

WorkspaceRepoID returns the canonical workspace ID for a repo.

func WorkspaceServiceID added in v1.4.0

func WorkspaceServiceID(name string) string

WorkspaceServiceID returns the canonical workspace ID for a service. The identity mirrors the contract-layer service so routing and contract views can share identity without a cross-layer join.

Types

type Graph

type Graph struct {
	Directed      *simple.DirectedGraph
	NodeIndex     map[string]int64     // node ID string → gonum int64 ID
	NodeByID      map[int64]types.Node // gonum int64 ID → types.Node
	ResolvedEdges []types.Edge         // only edges where both endpoints resolved
	Nodes         []types.Node
}

Graph wraps a gonum directed graph with auxiliary indexes for fast lookup.

func Build

func Build(nodes []types.Node, edges []types.Edge) (*Graph, error)

Build constructs a Graph from the provided nodes and edges.

Edge resolution:

  • e.Source must match a node ID exactly (it is always in "<file>:<name>" format).
  • e.Target is first tried as an exact ID, then as a bare label via labelIndex.

Only edges where BOTH endpoints resolve to known nodes are stored in ResolvedEdges and added to the gonum graph. Dangling edges (targeting stdlib/external symbols) are silently dropped — they add noise and break Obsidian graph view by creating isolated satellite dots.

func (*Graph) ApplyCommunities

func (g *Graph) ApplyCommunities(partition map[string]int) map[int][]string

ApplyCommunities writes community IDs back onto the graph's node metadata and populates the community → []nodeID index for report generation.

func (*Graph) Communities

func (g *Graph) Communities() map[int][]string

Communities returns a map of communityID → list of node IDs (empty until clustering is run).

func (*Graph) Degree

func (g *Graph) Degree(nodeID string) int

Degree returns the total degree (in + out) of the node with the given ID string.

func (*Graph) EdgeCount

func (g *Graph) EdgeCount() int

EdgeCount returns the number of resolved edges in the graph.

func (*Graph) NodeCount

func (g *Graph) NodeCount() int

NodeCount returns the number of nodes in the graph.

func (*Graph) ToTypes

func (g *Graph) ToTypes() *types.Graph

ToTypes converts this internal Graph to the types.Graph for serialisation. Only resolved edges are exported — dangling references are excluded.

type GraphLock added in v1.3.0

type GraphLock struct {
	// contains filtered or unexported fields
}

GraphLock holds an exclusive advisory lock on ~/.vela/graph.lock so the daemon and vela extract cannot write graph.json concurrently.

func AcquireGraphLock added in v1.3.0

func AcquireGraphLock(lockPath string) (*GraphLock, error)

AcquireGraphLock opens the lock file and acquires a non-blocking exclusive lock. Returns ErrGraphLocked if another process already holds the lock.

func (*GraphLock) Release added in v1.3.0

func (l *GraphLock) Release()

Release unlocks and closes the lock file. Safe to call on a nil receiver.

type HealthMetrics added in v1.2.0

type HealthMetrics struct {
	Path        string `json:"path"`
	GeneratedAt string `json:"generated_at,omitempty"`

	// Size
	Nodes int `json:"nodes"`
	Edges int `json:"edges"`

	// Coverage — breakdowns
	NodesByKind     map[string]int `json:"nodes_by_kind"`
	EdgesByRelation map[string]int `json:"edges_by_relation"`

	// Quality / resolution
	BrokenEdges    int     `json:"broken_edges"`
	SelfLoops      int     `json:"self_loops"`
	DuplicateEdges int     `json:"duplicate_edges"`
	ResolutionRate float64 `json:"resolution_rate"` // 0..1

	// Confidence
	ConfidenceDist map[string]int `json:"confidence_dist"`
	ExtractedRate  float64        `json:"extracted_rate"` // 0..1

	// Degree
	AvgDegree     float64 `json:"avg_degree"`
	MedianDegree  int     `json:"median_degree"`
	P95Degree     int     `json:"p95_degree"`
	MaxDegree     int     `json:"max_degree"`
	IsolatedNodes int     `json:"isolated_nodes"`
	HubNodes      int     `json:"hub_nodes"`  // total degree >= 10
	LeafNodes     int     `json:"leaf_nodes"` // total degree == 1
	ConnectedPct  int     `json:"connected_pct"`

	// Communities
	Communities          int     `json:"communities"`
	LargestCommunitySize int     `json:"largest_community_size"`
	SingletonCommunities int     `json:"singleton_communities"`
	Modularity           float64 `json:"modularity"`

	// Top nodes (length fixed via TopN when loading)
	TopByOutDegree []NodeRank `json:"top_by_out_degree"`
}

HealthMetrics is the full set of graph-health signals computed from an on-disk graph.json. It is the single source of truth consumed by both `vela bench` and the TUI Graph Status screen.

func LoadHealthMetrics added in v1.2.0

func LoadHealthMetrics(path string, topN int) (HealthMetrics, error)

LoadHealthMetrics reads graph.json at path and computes every signal. topN controls the length of TopByOutDegree (5 is a reasonable default).

type MemoryGraph added in v1.4.0

type MemoryGraph struct {
	Nodes []types.Node
	Edges []types.Edge
}

MemoryGraph is the derived memory-layer graph. Nodes and Edges are exposed for persistence alongside the repo + contract + workspace graphs.

func BuildMemory added in v1.4.0

func BuildMemory(obs []ancora.Observation, opts MemoryOptions) *MemoryGraph

BuildMemory materializes the memory-layer graph from a slice of Ancora observations. It is intentionally independent of the repo extraction path: the memory graph can be rebuilt from Ancora alone without re-parsing code.

Emitted structure:

  • memory:root:ancora — single root
  • memory:workspace:<ws>, memory:visibility:<v>, memory:organization:<o> — scope nodes aggregated from the observations actually present
  • memory:observation:<ancora_id> — one node per observation
  • memory:concept:<name> — one node per concept reference target

Emitted edges:

  • structural: root->workspace (contains), workspace->visibility (contains)
  • binding: observation->workspace (belongs_to), observation->visibility (scoped_to), observation->organization (belongs_to)
  • cross-memory: observation->observation (related_to), observation->concept (defines)
  • cross-layer reference edges to repo files/symbols or workspace repos, with canonical "<layer>:<kind>:<key>" targets and a verification state so the identity resolver can later rebind stale references.

Every node and edge is stamped with layer=memory plus evidence_type and evidence_confidence so ranking and explainability stay consistent across layers.

type MemoryOptions added in v1.4.0

type MemoryOptions struct {
	// KnownRepos is the set of workspace-layer repo names the caller already
	// knows about. Case-insensitive. When an observation's workspace matches
	// one of these, a cross-layer "mentions" edge to workspace:repo:<name>
	// is emitted in addition to the memory-internal workspace binding.
	KnownRepos []string
}

MemoryOptions carries optional resolution hints that let the memory graph point at other layers by canonical reference. Memory never synthesizes repo, contract, or workspace nodes — it only emits reference edges when a known target exists.

type MemoryReferenceBinding added in v1.4.0

type MemoryReferenceBinding struct {
	State       types.VerificationState
	BoundTarget string
	Suggestions []string
	Evidence    string
}

MemoryReferenceBinding captures the live binding state for a memory reference. The original reference target is preserved separately so history does not get silently rewritten when code moves.

type NodeRank added in v1.2.0

type NodeRank struct {
	ID     string `json:"id"`
	Label  string `json:"label"`
	File   string `json:"file,omitempty"`
	Kind   string `json:"kind,omitempty"`
	OutDeg int    `json:"out_degree"`
	InDeg  int    `json:"in_degree"`
}

NodeRank is a compact row used in metric leaderboards (top-N by degree).

type RepoOverrides added in v1.4.0

type RepoOverrides struct {
	Domains      []string
	Packages     []string
	Dependencies []string // other repo names this repo depends on
}

RepoOverrides carries declarative routing hints the caller wants to stamp onto a repo that cannot be derived from the merged graph alone (domain tags from repo config, declared dependencies from manifests, language packages, etc.). All fields are optional.

type RepoRouteHit added in v1.4.0

type RepoRouteHit struct {
	Repo    string
	Score   float64
	Reasons []string
}

RepoRouteHit is one ranked repo candidate returned by SelectRepos. Reasons explains why the repo matched so the orchestrator can surface provenance.

type ResolvedMemoryReference added in v1.4.0

type ResolvedMemoryReference struct {
	Target       string
	Relation     string
	Confidence   types.Confidence
	Verification types.VerificationState
	CrossLayer   bool
}

ResolvedMemoryReference is the canonicalized form of a raw observation reference. It keeps memory provenance explicit without folding memory into repo/workspace truth.

func ResolveMemoryReference added in v1.4.0

func ResolveMemoryReference(refType, target, obsType string, opts MemoryOptions) (ResolvedMemoryReference, bool)

ResolveMemoryReference canonicalizes a raw observation reference into a layer-aware target plus relation metadata.

type WorkspaceGraph added in v1.4.0

type WorkspaceGraph struct {
	Nodes []types.Node
	Edges []types.Edge
	// contains filtered or unexported fields
}

WorkspaceGraph is the routing-only derived graph. It exposes its nodes and edges for persistence alongside the repo+contract graph, plus the indexes needed for SelectRepos.

func BuildWorkspace added in v1.4.0

func BuildWorkspace(nodes []types.Node, edges []types.Edge, overrides map[string]RepoOverrides) *WorkspaceGraph

BuildWorkspace derives a workspace graph from the merged repo+contract graph plus optional per-repo overrides. Inputs follow the same shape that MergeContract produces.

Derivation rules (lightweight by design):

  • one workspace:repo node per project node
  • one workspace:service node per contract:service node
  • repo -> service ("exposes") edges inferred from contract "declared_in" edges (declared evidence flows through unchanged)
  • repo -> package ("hosts"), repo -> domain ("owns"), repo -> repo ("depends_on") edges from the caller-supplied overrides

BuildWorkspace is idempotent: running it twice on the same inputs produces the same output. It makes no attempt to mine code structure — packages, domains, and dependencies must come from declared sources (overrides) to keep routing trustworthy.

func LoadWorkspace added in v1.4.0

func LoadWorkspace(nodes []types.Node, edges []types.Edge) *WorkspaceGraph

LoadWorkspace rebuilds routing indexes from persisted workspace-layer nodes and edges already present in a merged graph.

func (*WorkspaceGraph) Repos added in v1.4.0

func (w *WorkspaceGraph) Repos() []string

Repos returns the repo names known to the workspace graph, sorted.

func (*WorkspaceGraph) ReposExposing added in v1.4.0

func (w *WorkspaceGraph) ReposExposing(service string) []string

ReposExposing returns the repo names that expose a given service.

func (*WorkspaceGraph) SelectRepos added in v1.4.0

func (w *WorkspaceGraph) SelectRepos(tokens []string, limit int) []RepoRouteHit

SelectRepos ranks repos against a set of query tokens. Matching is case-insensitive and token-wise. The returned slice is sorted by descending score; limit<=0 returns all non-zero hits.

Scoring is intentionally coarse — the workspace layer is a prefilter, not a ranker. Declared evidence (service name matches) outranks derived hints (domain/package tags) so contract truth flows through routing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL