Documentation
¶
Index ¶
- Constants
- Variables
- func BindMemoryReferenceEdge(edge types.Edge, liveNodes []types.Node) types.Edge
- func BindMemoryReferences(edges []types.Edge, liveNodes []types.Node) []types.Edge
- func Canonicalize(nodes []types.Node, edges []types.Edge) ([]types.Node, []types.Edge)
- func GodNodes(g *Graph, topN int) []types.Node
- func MemoryConceptID(c string) string
- func MemoryObservationID(id int64) string
- func MemoryOrganizationID(o string) string
- func MemoryReferenceEdge(src string, ref ResolvedMemoryReference, artifact string) types.Edge
- func MemoryVisibilityID(v string) string
- func MemoryWorkspaceID(name string) string
- func MergeContract(repoNodes []types.Node, repoEdges []types.Edge, contractNodes []types.Node, ...) ([]types.Node, []types.Edge)
- func MergeMemory(baseNodes []types.Node, baseEdges []types.Edge, memNodes []types.Node, ...) ([]types.Node, []types.Edge)
- func RunLeiden(g *Graph) (map[string]int, error)
- func SuggestedQuestions(nodes []types.Node, edges []types.Edge) []string
- func SurpriseEdges(g *Graph, topN int) []types.Edge
- func WorkspaceDomainID(name string) string
- func WorkspacePackageID(name string) string
- func WorkspaceRepoID(name string) string
- func WorkspaceServiceID(name string) string
- type Graph
- type GraphLock
- type HealthMetrics
- type MemoryGraph
- type MemoryOptions
- type MemoryReferenceBinding
- type NodeRank
- type RepoOverrides
- type RepoRouteHit
- type ResolvedMemoryReference
- type WorkspaceGraph
Constants ¶
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:" )
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.
const ( MemoryEvidenceObservation = "observation" MemoryEvidenceReference = "observation-reference" MemoryEvidenceStructural = "memory-structure" )
Evidence type tags specific to the memory layer.
const ( // Workspace edge relations. WorkspaceRelExposes = "exposes" // repo -> service WorkspaceRelHosts = "hosts" // repo -> package WorkspaceRelOwns = "owns" // repo -> domain WorkspaceRelDependsOn = "depends_on" // repo -> repo )
Variables ¶
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
BindMemoryReferenceEdge binds a single memory reference edge against the current graph state.
func BindMemoryReferences ¶ added in v1.4.0
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
Canonicalize removes duplicate node IDs and duplicate/orphaned edges while preserving the first occurrence order for stable graph exports.
func GodNodes ¶
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 MemoryObservationID ¶ added in v1.4.0
ID helpers for memory-layer nodes.
func MemoryOrganizationID ¶ added in v1.4.0
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 MemoryWorkspaceID ¶ added in v1.4.0
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 ¶
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 ¶
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 ¶
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
WorkspaceDomainID returns the canonical workspace ID for a domain tag.
func WorkspacePackageID ¶ added in v1.4.0
WorkspacePackageID returns the canonical workspace ID for a package.
func WorkspaceRepoID ¶ added in v1.4.0
WorkspaceRepoID returns the canonical workspace ID for a repo.
func WorkspaceServiceID ¶ added in v1.4.0
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 ¶
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 ¶
ApplyCommunities writes community IDs back onto the graph's node metadata and populates the community → []nodeID index for report generation.
func (*Graph) Communities ¶
Communities returns a map of communityID → list of node IDs (empty until clustering is run).
func (*Graph) Degree ¶
Degree returns the total degree (in + out) of the node with the given ID string.
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
AcquireGraphLock opens the lock file and acquires a non-blocking exclusive lock. Returns ErrGraphLocked if another process already holds the lock.
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
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
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.