Documentation
¶
Index ¶
- Constants
- Variables
- func CacheDir() (string, error)
- func CanonicalSectionNames() []string
- func IsSurfaceableCodeNode(label, filePath string) bool
- func KnownEdgeType(t string) bool
- func MaxADRLength() int
- func Now() string
- func OpenPathWithAutoRecovery(dbPath, name string) (*Store, RecoveryEvent, error)
- func ParseADRSections(content string) map[string]string
- func RenderADR(sections map[string]string) string
- func SkipsSidecarPath(project string) (string, error)
- func UnmarshalProps(data string) map[string]any
- func ValidateADRContent(content string) error
- func ValidateADRSectionKeys(sections map[string]string) error
- func WriteSkips(project string, files []SkippedFile) error
- type ADRecord
- type ArchitectureInfo
- type ClusterInfo
- type ConfigStore
- func (c *ConfigStore) All() (map[string]string, error)
- func (c *ConfigStore) Close() error
- func (c *ConfigStore) Delete(key string) error
- func (c *ConfigStore) Get(key, defaultVal string) string
- func (c *ConfigStore) GetBool(key string, defaultVal bool) bool
- func (c *ConfigStore) GetInt(key string, defaultVal int) int
- func (c *ConfigStore) Set(key, value string) error
- type CrossPkgBoundary
- type Edge
- type EdgeEndpoint
- type EdgeInfo
- type EdgeTypeInfo
- type EmbeddingResult
- type EntryPointInfo
- type FileHash
- type FileTreeEntry
- type HotspotFunction
- type ImpactSummary
- type LabelCount
- type LanguageCount
- type Node
- type NodeHop
- type PackageLayer
- type PackageSummary
- type PartialBatchInsertError
- type Project
- type ProjectInfo
- type Querier
- type QueryCache
- type RecoveryEvent
- type ReleaseFunc
- type RiskLevel
- type RouteInfo
- type SchemaInfo
- type SearchOutput
- type SearchParams
- type SearchResult
- type ServiceLink
- type SkippedFile
- type Store
- func (s *Store) AllEdges(project string) ([]*Edge, error)
- func (s *Store) AllNodes(project string) ([]*Node, error)
- func (s *Store) BFS(startNodeID int64, direction string, edgeTypes []string, ...) (*TraverseResult, error)
- func (s *Store) BFSNodes(startNodeID int64, direction string, edgeTypes []string, ...) (*TraverseResult, error)
- func (s *Store) BFSWithMinConfidence(startNodeID int64, direction string, edgeTypes []string, ...) (*TraverseResult, error)
- func (s *Store) BeginBulkWrite(ctx context.Context)
- func (s *Store) BulkInsertEdges(ctx context.Context, edges []*Edge) error
- func (s *Store) BulkInsertNodes(ctx context.Context, nodes []*Node) error
- func (s *Store) CallsConfidenceTierStats(project string) (map[string]int, error)
- func (s *Store) CallsResolutionStats(project string) (map[string]int, error)
- func (s *Store) CallsResolverRuleStats(project string) (map[string]int, error)
- func (s *Store) Checkpoint(ctx context.Context)
- func (s *Store) Close() error
- func (s *Store) CosineSearch(project string, queryVec []float32, limit int) ([]EmbeddingResult, error)
- func (s *Store) CountEdges(project string) (int, error)
- func (s *Store) CountEdgesByType(project, edgeType string) (int, error)
- func (s *Store) CountFileHashes(project string) (int, error)
- func (s *Store) CountNodes(project string) (int, error)
- func (s *Store) CreateUserIndexes(ctx context.Context) error
- func (s *Store) DB() *sql.DB
- func (s *Store) DBPath() string
- func (s *Store) DeleteADR(project string) error
- func (s *Store) DeleteEdgesBetweenFiles(project, edgeType string, srcFiles, tgtFiles []string) (int64, error)
- func (s *Store) DeleteEdgesByProject(project string) error
- func (s *Store) DeleteEdgesBySourceFile(project, filePath, edgeType string) error
- func (s *Store) DeleteEdgesByType(project, edgeType string) error
- func (s *Store) DeleteFileHash(project, relPath string) error
- func (s *Store) DeleteFileHashes(project string) error
- func (s *Store) DeleteNodesByFile(project, filePath string) error
- func (s *Store) DeleteNodesByLabel(project, label string) error
- func (s *Store) DeleteNodesByProject(project string) error
- func (s *Store) DeleteOrphanNodesByLabel(project, label string) error
- func (s *Store) DeleteProject(name string) error
- func (s *Store) DropUserIndexes(ctx context.Context) error
- func (s *Store) EdgeCountsByType(project string) (map[string]int, error)
- func (s *Store) EmbeddingCount(project string) (int, error)
- func (s *Store) EmbeddingModelCounts(project string) (map[string]int, error)
- func (s *Store) EndBulkWrite(ctx context.Context)
- func (s *Store) FindArchitectureDocs(project string) ([]string, error)
- func (s *Store) FindCallerFilesOfTargetsInFiles(project string, targetFilePaths, edgeTypes []string) ([]string, error)
- func (s *Store) FindEdgeEndpointsByTypes(project string, edgeTypes []string) ([]EdgeEndpoint, error)
- func (s *Store) FindEdgesBySource(sourceID int64) ([]*Edge, error)
- func (s *Store) FindEdgesBySourceAndType(sourceID int64, edgeType string) ([]*Edge, error)
- func (s *Store) FindEdgesBySourceIDs(sourceIDs []int64, edgeTypes []string) (map[int64][]*Edge, error)
- func (s *Store) FindEdgesByTarget(targetID int64) ([]*Edge, error)
- func (s *Store) FindEdgesByTargetAndType(targetID int64, edgeType string) ([]*Edge, error)
- func (s *Store) FindEdgesByTargetIDs(targetIDs []int64, edgeTypes []string) (map[int64][]*Edge, error)
- func (s *Store) FindEdgesByType(project, edgeType string) ([]*Edge, error)
- func (s *Store) FindEdgesByURLPath(project, pathSubstring string) ([]*Edge, error)
- func (s *Store) FindNodeByID(id int64) (*Node, error)
- func (s *Store) FindNodeByQN(project, qualifiedName string) (*Node, error)
- func (s *Store) FindNodeIDsByQNs(project string, qns []string) (map[string]int64, error)
- func (s *Store) FindNodeLabelsByQNs(project string, qns []string) (map[string]string, error)
- func (s *Store) FindNodeSeedCandidates(project string, exactNameTokens, qnTokens []string) ([]*Node, error)
- func (s *Store) FindNodesByFile(project, filePath string) ([]*Node, error)
- func (s *Store) FindNodesByFileOverlap(project, fileSuffix string, startLine, endLine int) ([]*Node, error)
- func (s *Store) FindNodesByIDs(ids []int64) (map[int64]*Node, error)
- func (s *Store) FindNodesByLabel(project, label string) ([]*Node, error)
- func (s *Store) FindNodesByName(project, name string) ([]*Node, error)
- func (s *Store) FindNodesByProperty(project, label, propKey, propValue string) ([]*Node, error)
- func (s *Store) FindNodesByQNSuffix(project, suffix string) ([]*Node, error)
- func (s *Store) FindSimilarNodes(project string, nodeID int64, limit int) ([]EmbeddingResult, error)
- func (s *Store) FormatVersionOf() (int, error)
- func (s *Store) GetADR(project string) (*ADRecord, error)
- func (s *Store) GetArchitecture(project string, aspects []string) (*ArchitectureInfo, error)
- func (s *Store) GetFileHashes(project string) (map[string]FileHash, error)
- func (s *Store) GetIncrementalsSinceFull(project string) (int, error)
- func (s *Store) GetIndexIdentity(project string) (*indexidentity.Record, error)
- func (s *Store) GetIndexProgress(name string) (phase string, pct int, detail string, err error)
- func (s *Store) GetProject(name string) (*Project, error)
- func (s *Store) GetSchema(project string) (*SchemaInfo, error)
- func (s *Store) IncrementIncrementalsSinceFull(project string) error
- func (s *Store) InsertEdge(e *Edge) (int64, error)
- func (s *Store) InsertEdgeBatch(edges []*Edge) error
- func (s *Store) InvalidateEmbeddingCache()
- func (s *Store) IterEmbeddedNodeIDs(project string) ([]int64, error)
- func (s *Store) ListFilesForProject(project string) ([]string, error)
- func (s *Store) ListProjects() ([]*Project, error)
- func (s *Store) LoadNodeIDMap(ctx context.Context, project string) (map[string]int64, error)
- func (s *Store) NodeDegree(nodeID int64) (inbound, outbound int)
- func (s *Store) NodeNeighborNames(nodeID int64, limit int) (callerNames, calleeNames []string)
- func (s *Store) Q() Querier
- func (s *Store) ReachableExcluding(startID, targetID int64, direction string, edgeTypes []string, maxDepth int, ...) (bool, error)
- func (s *Store) ResetIncrementalsSinceFull(project string) error
- func (s *Store) RewriteProject(ctx context.Context, oldName, newName, newRoot string) error
- func (s *Store) Search(params *SearchParams) (*SearchOutput, error)
- func (s *Store) SetEnrichmentVersion(name, version string) error
- func (s *Store) SetIndexIdentity(project string, identity *indexidentity.Envelope) error
- func (s *Store) SetIndexIdentityState(project, status, reason string) error
- func (s *Store) SetIndexProgress(name, phase string, pct int, detail string) error
- func (s *Store) SetNodeIntProperty(project, qualifiedName, key string, value int) (int64, error)
- func (s *Store) ShortestPath(startID, targetID int64, direction string, edgeTypes []string, maxDepth int) ([]int64, error)
- func (s *Store) SnapshotTo(path string) error
- func (s *Store) StoreADR(project, content string) error
- func (s *Store) UpdateADRSections(project string, sections map[string]string) (*ADRecord, error)
- func (s *Store) UpsertEmbedding(nodeID int64, model string, vec []float32) error
- func (s *Store) UpsertEmbeddingBatch(nodeIDs []int64, model string, vecs [][]float32) error
- func (s *Store) UpsertFileHash(project, relPath, sha256 string, mtimeNs, size int64) error
- func (s *Store) UpsertFileHashBatch(hashes []FileHash) error
- func (s *Store) UpsertNode(n *Node) (int64, error)
- func (s *Store) UpsertNodeBatch(nodes []*Node) (map[string]int64, error)
- func (s *Store) UpsertProject(name, rootPath string) error
- func (s *Store) WALSize() int64
- func (s *Store) WithLargeCache(ctx context.Context, fn func() error) error
- func (s *Store) WithTransaction(ctx context.Context, fn func(txStore *Store) error) error
- type StoreRouter
- func (r *StoreRouter) AcquireStore(project string) (*Store, ReleaseFunc, error)
- func (r *StoreRouter) AllStores() map[string]*Store
- func (r *StoreRouter) CloseAll()
- func (r *StoreRouter) DeleteProject(name string) error
- func (r *StoreRouter) Dir() string
- func (r *StoreRouter) ForProject(name string) (*Store, error)
- func (r *StoreRouter) HasProject(name string) bool
- func (r *StoreRouter) ListProjects() ([]*ProjectInfo, error)
- func (r *StoreRouter) OnDelete(fn func(name string))
- func (r *StoreRouter) StartEvictor(ctx context.Context)
- func (r *StoreRouter) UseStore(project string, fn func(*Store) error) error
- type TraverseResult
- type TypeCount
Constants ¶
const ( // ConfigAutoIndex controls whether the server auto-indexes on startup. // Default: false (off). Enable with: code-graph config set auto_index true ConfigAutoIndex = "auto_index" // ConfigReportSkipPrefix prefixes per-project sticky skip_report // preferences ("report.skip.<project>" = "true"/"false"), persisted by // handleIndexRepository when skip_report is explicitly provided and // inherited by calls that omit the argument. ConfigReportSkipPrefix = "report.skip." // ConfigGraphPrecisionTierPrefix stores the explicit per-project graph // precision choice ("heuristic" or "scip"). ConfigGraphSCIPPathPrefix // stores the corresponding compiler index path, and // ConfigGraphPrecisionStatusPrefix stores the last machine-readable ingest // outcome surfaced by index_status. ConfigGraphPrecisionTierPrefix = "graph.precision.tier." ConfigGraphSCIPPathPrefix = "graph.precision.scip_path." ConfigGraphPrecisionStatusPrefix = "graph.precision.status." // ConfigAutoIndexLimit is the max file count for auto-indexing new projects. // Default: 50000. Projects above this limit require explicit index_repository. ConfigAutoIndexLimit = "auto_index_limit" // ConfigMemLimit sets GOMEMLIMIT for the server process. // Accepts human-readable sizes: "2G", "512M", "4096M". // Default: empty (no limit). Applied on server startup. ConfigMemLimit = "mem_limit" )
Known config keys and their defaults.
const ( // Structure. EdgeContains = "CONTAINS" EdgeContainsFile = "CONTAINS_FILE" EdgeDefines = "DEFINES" EdgeDefinesMeth = "DEFINES_METHOD" EdgeDefinesField = "DEFINES_FIELD" EdgeMemberOf = "MEMBER_OF" EdgeParameterOf = "PARAMETER_OF" // Calls family. EdgeCalls = "CALLS" EdgeCallReference = "CALL_REFERENCE" EdgeCallsExternal = "CALLS_EXTERNAL" EdgeCallsPseudo = "CALLS_PSEUDO" EdgeIndirectCalls = "INDIRECT_CALLS" EdgeHTTPCalls = "HTTP_CALLS" EdgeAsyncCalls = "ASYNC_CALLS" EdgeHandles = "HANDLES" // Types and inheritance. EdgeImports = "IMPORTS" EdgeImplements = "IMPLEMENTS" EdgeInherits = "INHERITS" EdgeOverride = "OVERRIDE" EdgeUsesType = "USES_TYPE" EdgeUsage = "USAGE" EdgeDecorates = "DECORATES" // Data flow and errors. EdgeReads = "READS" EdgeWrites = "WRITES" EdgeThrows = "THROWS" EdgeRaises = "RAISES" // Tests. EdgeTests = "TESTS" EdgeTestsFile = "TESTS_FILE" // Configuration, infrastructure, and policy. EdgeConfigures = "CONFIGURES" EdgeDependsOn = "DEPENDS_ON" EdgeReadsEnv = "READS_ENV" EdgePolicyGates = "POLICY_GATES" EdgeRunsBinary = "RUNS_BINARY" // Messaging. EdgePublishesTo = "PUBLISHES_TO" EdgeSubscribesTo = "SUBSCRIBES_TO" EdgeQueries = "QUERIES" EdgeAnswers = "ANSWERS" // Derived. EdgeFileChangesWith = "FILE_CHANGES_WITH" EdgeSemanticallySimilarTo = "SEMANTICALLY_SIMILAR_TO" EdgeRationaleFor = "RATIONALE_FOR" )
Edge type constants. Every relationship kind the graph can hold is declared here once; passes emit edges with these constants, and EdgeTypes documents each one. A test in this package fails when production code introduces a new `Type: "LITERAL"` outside this table, so the schema stays enumerable for get_graph_schema, docs/edge-types.md, and downstream consumers.
const ( ConfidenceExtracted = "EXTRACTED" ConfidenceInferred = "INFERRED" ConfidenceAmbiguous = "AMBIGUOUS" )
Edge confidence tier. Stored in Edge.Properties["confidence_tier"]; the generated column `confidence_tier_gen` on the edges table (see store.go initSchema) surfaces this value as a first-class, indexable field so Cypher queries can filter with `WHERE r.confidence_tier = 'X'`. Absent properties default to EXTRACTED at the column level via COALESCE.
Note on naming: the property key is `confidence_tier` (not `confidence`) to avoid collision with the pre-existing numeric `confidence` property used by configlink_strategies.go for per-strategy heuristic scores. The tier is categorical; the legacy score is continuous.
EXTRACTED
Direct, source-proven relationship. The AST literally says the edge exists (a function call expression, an import statement, a class definition). This is the default for any edge whose creator does not set a confidence_tier property.
INFERRED
Relationship deduced via static reasoning beyond the raw AST: interface satisfaction by method-set matching, inherited methods across class hierarchies, an HTTP caller matched to a route handler, a test function matched to its production target via a naming heuristic. Still high-signal, but a grammar change or a refactor could invalidate it.
AMBIGUOUS
Relationship asserted via a fuzzy match that may be wrong. A config file whose values happen to match a variable name, a git file-coupling metric below a high-confidence threshold, a parameterized URL path that could match multiple routes. Useful for suggestion-surface tools; filter these out for automated blast-radius calculations.
const AutoRecoveryEnvVar = "CODE_GRAPH_AUTO_RECOVERY"
AutoRecoveryEnvVar is the env var name that opt-in for auto-recovery. Default behavior (env var unset) preserves the existing "structured error → operator decides" flow.
const FormatVersion = 1
FormatVersion is the on-disk index format this build reads and writes. It is stored in SQLite's user_version pragma. Bump it whenever a schema or semantic change makes databases written by this build unreadable by the previous release, and document the bump in docs/index-format.md.
const MinSupportedFormatVersion = 1
MinSupportedFormatVersion is the oldest format this build still opens. Databases below it must be rebuilt with index_repository.
Variables ¶
var EdgeTypes = func() []EdgeTypeInfo { t := []EdgeTypeInfo{ {EdgeContains, "structure", "Directory or Package", "Directory, Package, or File", "Filesystem and package containment produced by the structure pass."}, {EdgeContainsFile, "structure", "Directory", "File", "Direct file containment used for fast per-directory listings."}, {EdgeDefines, "structure", "File or Module", "Function, Class, or Variable", "A file or module defines a top-level symbol."}, {EdgeDefinesMeth, "structure", "Class, Struct, or Trait", "Method", "A type defines a method."}, {EdgeDefinesField, "structure", "Class or Struct", "Field", "A type defines a field."}, {EdgeMemberOf, "structure", "Symbol", "Community", "Louvain community membership computed after indexing."}, {EdgeParameterOf, "structure", "Parameter", "Function", "A parameter belongs to a function; used by data-flow reachability."}, {EdgeCalls, "calls", "Function", "Function", "A resolved call. Properties carry resolver rule, strategy, confidence, and, for SCIP-derived edges, the artifact digest."}, {EdgeCallsExternal, "calls", "Function", "External stub", "A call whose target lives outside the indexed repository."}, {EdgeCallsPseudo, "calls", "Function", "Pseudo target", "A call to a language construct modelled as a pseudo node (modal dispatch, builtins)."}, {EdgeIndirectCalls, "calls", "Function", "Function", "A call reached through a function value, callback, or dispatch table."}, {EdgeHTTPCalls, "calls", "Function", "Route handler", "A cross-service HTTP call matched to the handler that serves the route."}, {EdgeAsyncCalls, "calls", "Function", "Function", "A call across an async boundary (task spawn, message dispatch)."}, {EdgeHandles, "calls", "Route", "Function", "A route node is served by a handler function."}, {EdgeCallReference, "calls", "Function or Module", "Function or Method", "A callable referenced at a value site (assignment, collection literal, argument) that resolves to exactly one target; not an invocation. Aligned with upstream codebase-memory-mcp: CALL_REFERENCE is the proven-single-target counterpart of USAGE."}, {EdgeImports, "types", "Module or File", "Module", "An import statement, normalized for relative imports."}, {EdgeImplements, "types", "Type", "Interface or Trait", "A type implements an interface or trait."}, {EdgeInherits, "types", "Class", "Class", "Class inheritance."}, {EdgeOverride, "types", "Method", "Method", "A method overrides a parent or interface method."}, {EdgeUsesType, "types", "Function or Field", "Type", "A signature or field references a type."}, {EdgeUsage, "types", "Function or Module", "Variable, Constant, Type, or Function", "An identifier used at a value site where no unique callable target is proven (a non-callable symbol, or an ambiguous or fuzzy resolution). The unproven counterpart of CALL_REFERENCE."}, {EdgeDecorates, "types", "Decorator", "Function or Class", "A decorator or attribute applied to a definition."}, {EdgeReads, "dataflow", "Function", "Variable or Field", "A read of a variable or field."}, {EdgeWrites, "dataflow", "Function", "Variable or Field", "A write to a variable or field."}, {EdgeThrows, "dataflow", "Function", "Type", "A function throws an exception type (statically typed languages)."}, {EdgeRaises, "dataflow", "Function", "Type", "A function raises an exception type (Python)."}, {EdgeTests, "tests", "Test function", "Function", "A test exercises a production function."}, {EdgeTestsFile, "tests", "Test file", "File", "A test file covers a production file by convention."}, {EdgeConfigures, "config", "Config file or Service", "Service, Function, or Variable", "Configuration links a config artifact to the code it configures."}, {EdgeDependsOn, "config", "Package or Service", "Package or Service", "A declared dependency from a lockfile, manifest, or infrastructure module."}, {EdgeReadsEnv, "config", "Function", "EnvVar", "Code reads an environment variable."}, {EdgePolicyGates, "config", "Policy", "Function or Route", "An OPA policy gates the target."}, {EdgeRunsBinary, "config", "Service", "Binary", "A declared service runs a binary (Nix modules)."}, {EdgePublishesTo, "messaging", "Service or Function", "Topic", "Publishes to a topic (Zenoh, Nix service declarations)."}, {EdgeSubscribesTo, "messaging", "Service or Function", "Topic", "Subscribes to a topic."}, {EdgeQueries, "messaging", "Function", "Topic", "Issues a query on a topic (Zenoh)."}, {EdgeAnswers, "messaging", "Function", "Topic", "Answers queries on a topic (Zenoh queryable)."}, {EdgeFileChangesWith, "derived", "File", "File", "Co-change coupling mined from git history."}, {EdgeSemanticallySimilarTo, "derived", "Function", "Function", "Embedding cosine similarity above threshold (opt-in)."}, {EdgeRationaleFor, "derived", "Rationale", "Function or Class", "A WHY/SAFETY/NOTE annotation explains the target."}, } sort.Slice(t, func(i, j int) bool { return t[i].Type < t[j].Type }) return t }()
EdgeTypes is the documented table of every edge kind, sorted by type.
var ErrCorruptDatabase = errors.New("corrupt database")
ErrCorruptDatabase is a sentinel error type for Mode 4 (corrupt header). Provided for callers that want errors.Is matching instead of substring. Currently unused upstream; reserved for future migration.
var ErrIndexFormatTooNew = errors.New("index format is newer than this code-graph build")
ErrIndexFormatTooNew is returned when a database was written by a newer code-graph than the one opening it.
var ErrIndexFormatUnsupported = errors.New("index format is no longer supported")
ErrIndexFormatUnsupported is returned when a database's format is older than this build can read; the fix is to rebuild the index.
Functions ¶
func CacheDir ¶
CacheDir resolves the default cache directory (CODE_GRAPH_CACHE_DIR, then ~/.cache/code-graph, then the legacy location), creating it if needed.
func CanonicalSectionNames ¶
func CanonicalSectionNames() []string
CanonicalSectionNames returns the ordered list of canonical ADR section names.
func IsSurfaceableCodeNode ¶
IsSurfaceableCodeNode reports whether a node represents concrete, openable source code — i.e. a legitimate result for the localization, ranking, and security-surface tools. It excludes two node classes that otherwise pollute result lists with entries the caller cannot act on:
Community pseudo-nodes: Louvain cluster aggregates (label "Community", no file). BFS over MEMBER_OF edges reaches them, and rank/localize surfaced them directly (observed live 2026-07-04: code_localize returned a "Getwd_cluster" Community node).
External-dependency stubs: CALLS_EXTERNAL targets carry Function/Method labels but have no file_path (e.g. os.WriteFile, github.com/DeusData/.../Executor.Execute). They are not code in THIS repo, so they cannot be opened or investigated.
A legitimate first-party symbol always has a non-empty file_path, so the empty-file_path check captures external stubs, and the label check captures Community aggregates (which also happen to have no file). Module / File nodes with real paths are retained — they are surfaceable.
func KnownEdgeType ¶
KnownEdgeType reports whether t is a documented edge type.
func MaxADRLength ¶
func MaxADRLength() int
MaxADRLength returns the maximum allowed ADR length for use by tool handlers.
func OpenPathWithAutoRecovery ¶
func OpenPathWithAutoRecovery(dbPath, name string) (*Store, RecoveryEvent, error)
OpenPathWithAutoRecovery wraps OpenPath with optional auto-recovery for the three manual-recovery modes (Mode 4 corrupt header, Mode 5 orphan sidecar, Mode 7 BulkWrite crash). See bench/research/2026-05-10-corruption-recovery-classification.md for the safety analysis underlying this behavior.
Behavior:
- Default (CODE_GRAPH_AUTO_RECOVERY unset): identical to OpenPath. The structured error propagates; the operator decides recovery.
- Opt-in (CODE_GRAPH_AUTO_RECOVERY=1): when OpenPath returns an auto-feasible error shape, the function (a) removes the corrupt on-disk artifacts (.db, .db-wal, .db-shm), (b) re-runs OpenPath on the now-clean path, and (c) returns the fresh Store + RecoveryEvent identifying which mode was recovered. Caller must re-index from source — the returned Store is empty.
Auto-recovery is logged via slog.Warn so the operator sees what happened. Pass the project's `name` if known (used purely for logging — pass "" to skip).
Errors that do NOT match the three auto-feasible shapes propagate as-is regardless of the env var. Auto-recovery never fires for errors outside the documented feasibility set.
func ParseADRSections ¶
ParseADRSections splits ADR content by canonical section headers. Only canonical headers (PURPOSE, STACK, ARCHITECTURE, PATTERNS, TRADEOFFS, PHILOSOPHY) are recognized as split boundaries. Other ## headers within content are treated as literal text within the current section.
func RenderADR ¶
RenderADR joins sections into markdown with canonical sections first (in order), followed by any non-canonical sections alphabetically.
func SkipsSidecarPath ¶ added in v0.9.1
SkipsSidecarPath returns the sidecar path for a project database.
func UnmarshalProps ¶
UnmarshalProps deserializes JSON properties. Exported for use by cypher executor.
func ValidateADRContent ¶
ValidateADRContent checks that content contains all 6 canonical sections. Returns an error listing any missing sections.
func ValidateADRSectionKeys ¶
ValidateADRSectionKeys checks that all keys in the map are canonical section names. Returns an error listing any invalid keys.
func WriteSkips ¶ added in v0.9.1
func WriteSkips(project string, files []SkippedFile) error
WriteSkips replaces the project's skip sidecar. An empty list removes it so a clean reindex leaves no stale report behind.
Types ¶
type ADRecord ¶
type ADRecord struct {
Project string `json:"project"`
Content string `json:"content"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
ADRecord holds a stored Architecture Decision Record.
type ArchitectureInfo ¶
type ArchitectureInfo struct {
TotalNodes int `json:"total_nodes,omitempty"`
TotalEdges int `json:"total_edges,omitempty"`
NodeLabels []LabelCount `json:"node_labels,omitempty"`
EdgeTypes []TypeCount `json:"edge_types,omitempty"`
Languages []LanguageCount `json:"languages,omitempty"`
Packages []PackageSummary `json:"packages,omitempty"`
EntryPoints []EntryPointInfo `json:"entry_points,omitempty"`
Routes []RouteInfo `json:"routes,omitempty"`
Hotspots []HotspotFunction `json:"hotspots,omitempty"`
Boundaries []CrossPkgBoundary `json:"boundaries,omitempty"`
Services []ServiceLink `json:"services,omitempty"`
Layers []PackageLayer `json:"layers,omitempty"`
Clusters []ClusterInfo `json:"clusters,omitempty"`
FileTree []FileTreeEntry `json:"file_tree,omitempty"`
}
ArchitectureInfo holds the result of a codebase architecture analysis.
The summary fields (TotalNodes, TotalEdges, NodeLabels, EdgeTypes) populate when the caller requests the "summary" aspect (default since 2026-05-12). Detail aspects populate when requested individually or via "all".
type ClusterInfo ¶
type ClusterInfo struct {
ID int `json:"id"`
Label string `json:"label"`
Members int `json:"members"`
Cohesion float64 `json:"cohesion"`
TopNodes []string `json:"top_nodes"`
Packages []string `json:"packages"`
EdgeTypes []string `json:"edge_types"`
}
ClusterInfo describes a community detected by the Louvain algorithm.
type ConfigStore ¶
type ConfigStore struct {
// contains filtered or unexported fields
}
ConfigStore provides persistent key-value configuration backed by SQLite. Stored in _config.db in the cache directory (separate from per-project DBs).
func OpenConfig ¶
func OpenConfig() (*ConfigStore, error)
OpenConfig opens or creates the global config database.
func OpenConfigInDir ¶
func OpenConfigInDir(dir string) (*ConfigStore, error)
OpenConfigInDir opens the config database in a specific directory (for testing).
func (*ConfigStore) All ¶
func (c *ConfigStore) All() (map[string]string, error)
All returns all config key-value pairs.
func (*ConfigStore) Delete ¶
func (c *ConfigStore) Delete(key string) error
Delete removes a config key.
func (*ConfigStore) Get ¶
func (c *ConfigStore) Get(key, defaultVal string) string
Get returns the value for a key, or defaultVal if not set.
func (*ConfigStore) GetBool ¶
func (c *ConfigStore) GetBool(key string, defaultVal bool) bool
GetBool returns a boolean config value (stored as "true"/"false").
func (*ConfigStore) GetInt ¶
func (c *ConfigStore) GetInt(key string, defaultVal int) int
GetInt returns an integer config value.
func (*ConfigStore) Set ¶
func (c *ConfigStore) Set(key, value string) error
Set stores a key-value pair (upsert).
type CrossPkgBoundary ¶
type CrossPkgBoundary struct {
From string `json:"from"`
To string `json:"to"`
CallCount int `json:"call_count"`
}
CrossPkgBoundary represents cross-package call volume.
type Edge ¶
type Edge struct {
ID int64
Project string
SourceID int64
TargetID int64
Type string
Properties map[string]any
}
Edge represents a graph edge stored in SQLite.
func (*Edge) ConfidenceTier ¶
ConfidenceTier returns the stored confidence tier for an edge, defaulting to EXTRACTED when the property is absent (e.g. edges created before this column was introduced, or by passes that do not set it).
type EdgeEndpoint ¶
EdgeEndpoint is the lightweight edge shape needed by topology-only consumers. It intentionally omits IDs, project names, and properties so a graph walk does not allocate full Edge objects or decode unrelated JSON.
type EdgeInfo ¶
type EdgeInfo struct {
FromName string
ToName string
Type string
Confidence float64
HasConfidence bool
}
EdgeInfo is a simplified edge for output.
type EdgeTypeInfo ¶
type EdgeTypeInfo struct {
Type string
// Family groups related kinds for filtering: structure, calls, types,
// dataflow, tests, config, messaging, derived.
Family string
// Source and Target name the node roles in "source -> target" order.
Source, Target string
Doc string
}
EdgeTypeInfo documents one edge type.
type EmbeddingResult ¶
type EmbeddingResult struct {
NodeID int64 `json:"node_id"`
Name string `json:"name"`
QName string `json:"qualified_name"`
Label string `json:"label"`
FilePath string `json:"file_path"`
Score float64 `json:"score"`
}
EmbeddingResult holds a node ID and its cosine similarity score.
type EntryPointInfo ¶
type EntryPointInfo struct {
Name string `json:"name"`
QualifiedName string `json:"qualified_name"`
File string `json:"file"`
}
EntryPointInfo describes an entry point function.
type FileHash ¶
type FileHash struct {
Project string
RelPath string
SHA256 string
MtimeNs int64 // file mtime in nanoseconds (for stat pre-filter)
Size int64 // file size in bytes (for stat pre-filter)
}
FileHash represents a stored file content hash with stat metadata for incremental reindex.
type FileTreeEntry ¶
type FileTreeEntry struct {
Path string `json:"path"`
Type string `json:"type"`
Children int `json:"children"`
}
FileTreeEntry describes a node in the condensed file tree.
type HotspotFunction ¶
type HotspotFunction struct {
Name string `json:"name"`
QualifiedName string `json:"qualified_name"`
FanIn int `json:"fan_in"`
}
HotspotFunction is a function with high fan-in.
type ImpactSummary ¶
type ImpactSummary struct {
Critical int `json:"critical"`
High int `json:"high"`
Medium int `json:"medium"`
Low int `json:"low"`
Total int `json:"total"`
HasCrossService bool `json:"has_cross_service"`
}
ImpactSummary aggregates risk counts from a BFS traversal.
func BuildImpactSummary ¶
func BuildImpactSummary(hops []*NodeHop, edges []EdgeInfo) ImpactSummary
BuildImpactSummary computes risk distribution from deduplicated node hops.
type LabelCount ¶
LabelCount is a label with its count.
type LanguageCount ¶
LanguageCount counts files per language.
type Node ¶
type Node struct {
ID int64
Project string
Label string
Name string
QualifiedName string
FilePath string
StartLine int
EndLine int
Properties map[string]any
}
Node represents a graph node stored in SQLite.
type NodeHop ¶
NodeHop is a node with its BFS hop distance.
func DeduplicateHops ¶
DeduplicateHops removes duplicate nodes from BFS results, keeping the minimum hop (highest risk) for each node.
type PackageLayer ¶
type PackageLayer struct {
Name string `json:"name"`
Layer string `json:"layer"`
Reason string `json:"reason"`
}
PackageLayer classifies a package into an architectural layer.
type PackageSummary ¶
type PackageSummary struct {
Name string `json:"name"`
NodeCount int `json:"node_count"`
FanIn int `json:"fan_in"`
FanOut int `json:"fan_out"`
}
PackageSummary summarizes a package with its connectivity.
type PartialBatchInsertError ¶
InsertEdgeBatch inserts multiple edges in batched multi-row INSERTs. PartialBatchInsertError is returned by InsertEdgeBatch when the per-edge fallback path skipped one or more edges (typically due to FK constraint violations from stale source/target IDs). The function completes — successful edges are inserted — but the error signals data loss so callers can choose to log, retry, or escalate.
PR #334 closed the most-common upstream cause of these FK violations (InsertEdge LastInsertId race); this error type exists so any remaining cause (resolver pointing at uncreated phantoms, concurrent deletes) surfaces explicitly rather than via Info-level logs that no caller checks. Use errors.As to inspect counts:
var partial *PartialBatchInsertError
if errors.As(err, &partial) { ... }
func (*PartialBatchInsertError) Error ¶
func (e *PartialBatchInsertError) Error() string
type ProjectInfo ¶
ProjectInfo holds metadata about a discovered project database.
type Querier ¶
type Querier interface {
Exec(query string, args ...any) (sql.Result, error)
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
Query(query string, args ...any) (*sql.Rows, error)
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRow(query string, args ...any) *sql.Row
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
Prepare(query string) (*sql.Stmt, error)
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}
Querier abstracts *sql.DB and *sql.Tx so store methods work in both contexts. Both variants support the Context-accepting counterparts; we expose them so callers inside a WithTransaction block can honor caller cancellation without reaching past the tx (which would ask the single-connection pool for a second connection and deadlock on the write lock).
type QueryCache ¶
type QueryCache struct {
// contains filtered or unexported fields
}
QueryCache is a thread-safe LRU cache for query results. Eviction order is maintained by a doubly-linked list so promote-to-MRU and oldest-eviction are O(1) regardless of cache size. LRU is updated on Set (re-insert promotes), not on Get — preserving prior semantics.
func NewQueryCache ¶
func NewQueryCache(maxSize int, ttl time.Duration) *QueryCache
NewQueryCache creates a cache with the given max entries and TTL.
func (*QueryCache) Get ¶
func (c *QueryCache) Get(key string) (any, bool)
Get returns a cached result and true if found and not expired. Get does NOT promote — promotion happens on Set only.
func (*QueryCache) Invalidate ¶
func (c *QueryCache) Invalidate()
Invalidate clears all cached entries.
func (*QueryCache) Set ¶
func (c *QueryCache) Set(key string, result any)
Set stores a result in the cache.
type RecoveryEvent ¶
type RecoveryEvent int
RecoveryEvent classifies what auto-recovery did, if anything.
Callers use this to decide whether to schedule a fresh re-index after the recovery cleared corrupt artifacts. See `OpenPathWithAutoRecovery`.
const ( // RecoveryNone means OpenPath succeeded without recovery; no action needed. RecoveryNone RecoveryEvent = iota // RecoveryCorruptHeader means Mode 4 (corrupt header) was detected and // the on-disk artifacts were removed. The returned Store is a fresh // empty DB; caller must re-index from source. RecoveryCorruptHeader // RecoveryOrphanSidecar means Mode 5 (main DB missing + orphan WAL/SHM) // was detected and the orphan sidecars were removed. The returned Store // is a fresh empty DB; caller must re-index from source. RecoveryOrphanSidecar // RecoveryBulkWriteCrash means Mode 7 (BulkWrite/MEMORY-journal crash) // was detected and the inconsistent DB + sidecars were removed. The // returned Store is a fresh empty DB; caller must re-index from source. RecoveryBulkWriteCrash )
func (RecoveryEvent) String ¶
func (r RecoveryEvent) String() string
String returns the human-readable name for the event, used in logs and the operator-facing slog records.
type ReleaseFunc ¶
type ReleaseFunc func()
ReleaseFunc must be called when the caller is done with the store.
type RouteInfo ¶
type RouteInfo struct {
Method string `json:"method"`
Path string `json:"path"`
Handler string `json:"handler"`
}
RouteInfo describes an HTTP route.
type SchemaInfo ¶
type SchemaInfo struct {
NodeLabels []LabelCount `json:"node_labels"`
RelationshipTypes []TypeCount `json:"relationship_types"`
RelationshipPatterns []string `json:"relationship_patterns"`
SampleFunctionNames []string `json:"sample_function_names"`
SampleClassNames []string `json:"sample_class_names"`
SampleQualifiedNames []string `json:"sample_qualified_names"`
}
SchemaInfo contains graph schema statistics.
type SearchOutput ¶
type SearchOutput struct {
Results []*SearchResult
Total int
}
SearchOutput wraps search results with total count for pagination.
type SearchParams ¶
type SearchParams struct {
Project string
Label string
NamePattern string // regex matched against short name only
QNPattern string // regex matched against qualified name only
FilePattern string
Relationship string
Direction string // "inbound", "outbound", "any"
MinDegree int
MaxDegree int
MinComplexity int // -1 = no filter; else require node's `complexity` property >= this
MaxComplexity int // -1 = no filter; else require node's `complexity` property <= this
Limit int
Offset int
ExcludeEntryPoints bool // when true, exclude nodes with is_entry_point=true
IncludeConnected bool // when true, load connected node names (expensive, off by default)
ExcludeLabels []string // labels to exclude from results
SortBy string // "relevance" (default), "name", "degree"
CaseSensitive bool // false (zero value) = case-insensitive by default
}
SearchParams defines structured search parameters.
type SearchResult ¶
SearchResult is a node with edge degree info.
type ServiceLink ¶
type ServiceLink struct {
From string `json:"from"`
To string `json:"to"`
Type string `json:"type"`
Count int `json:"count"`
}
ServiceLink represents a cross-service link (HTTP or async).
type SkippedFile ¶ added in v0.9.1
type SkippedFile struct {
Path string `json:"path"`
Reason string `json:"reason"` // "crash" or "timeout"
Detail string `json:"detail,omitempty"`
}
SkippedFile records a source file the extraction supervisor could not index because the worker crashed or hung on it. Skips live in a sidecar next to the project database rather than in the schema, so recording one never changes the index format.
func ReadSkips ¶ added in v0.9.1
func ReadSkips(project string) ([]SkippedFile, error)
ReadSkips returns the project's recorded skips, or an empty slice when the sidecar does not exist.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store wraps a SQLite connection for graph storage.
func OpenInDir ¶
OpenInDir opens or creates a SQLite database for the given project in a specific directory.
func OpenMemory ¶
OpenMemory opens an in-memory SQLite database (for testing).
func OpenPath ¶
OpenPath opens a SQLite database at the given path.
If the main .db file is missing but sidecar files (-wal or -shm) exist, this returns a structured error instead of silently re-creating an empty DB. The orphan-sidecar condition usually means the operator deleted the .db accidentally; silent re-create would be data loss with no signal. Recovery: call DeleteProject (or remove the sidecars manually) and re-index.
If neither main DB nor sidecars exist, this is a normal fresh-create.
func (*Store) AllEdges ¶
AllEdges returns every edge in a project. Used by whole-graph algorithms (PageRank, centrality) that need to load the full edge set into memory. For large projects consumers should prefer streaming or type-scoped reads.
func (*Store) BFS ¶
func (s *Store) BFS(startNodeID int64, direction string, edgeTypes []string, maxDepth, maxResults int) (*TraverseResult, error)
BFS performs breadth-first traversal following edges of given types using a recursive CTE, replacing the previous per-node Go-side loop with a single SQL round-trip. direction: "outbound" follows source->target, "inbound" follows target->source. maxDepth caps the BFS depth, maxResults caps total visited nodes (clipping is reported via TraverseResult.Truncated). An empty edgeTypes list traverses ALL edge types — consistent with FindEdgesBySourceIDs / FindEdgesByTargetIDs. (Previously empty silently defaulted to CALLS; every caller passes an explicit list, and the one caller that wants untyped traversal — Cypher variable-length patterns with no relationship type — was silently narrowed.)
func (*Store) BFSNodes ¶
func (s *Store) BFSNodes(startNodeID int64, direction string, edgeTypes []string, maxDepth, maxResults int) (*TraverseResult, error)
BFSNodes is BFS without the edge-collection query. The Cypher executor's variable-length expansion only consumes Visited/Truncated, and the edge CTE is as expensive as the node CTE — skipping it halves the per-source traversal cost for `-[*..]->` patterns.
func (*Store) BFSWithMinConfidence ¶
func (s *Store) BFSWithMinConfidence(startNodeID int64, direction string, edgeTypes []string, maxDepth, maxResults int, minConfidence float64) (*TraverseResult, error)
BFSWithMinConfidence performs BFS while treating edges below minConfidence as absent. Edges with a missing or null confidence value remain traversable; an explicit numeric zero is filtered when minConfidence is positive. Applying the threshold to the recursive frontier guarantees every visited node has a retained path from the root.
func (*Store) BeginBulkWrite ¶
BeginBulkWrite switches to MEMORY journal mode for faster bulk writes. Also boosts cache to 64 MB for write throughput. Call EndBulkWrite when done to restore WAL mode and adaptive cache.
Writes a Mode 7 crash-marker (RECOVERY_TAXONOMY.md) before switching journal mode. EndBulkWrite removes the marker. If the process is killed inside this window, the marker survives and the next OpenPath will run PRAGMA quick_check to detect MEMORY-journal-corruption that the missing on-disk journal can't recover.
func (*Store) BulkInsertEdges ¶
BulkInsertEdges inserts edges in batches using plain INSERT (no ON CONFLICT). Assumes no duplicates exist for the project after a prior DELETE. Honors ctx the same way BulkInsertNodes does.
func (*Store) BulkInsertNodes ¶
BulkInsertNodes inserts nodes in batches using plain INSERT (no ON CONFLICT). Assumes no duplicates exist for the project after a prior DELETE. Honors ctx — at the start of each chunk we check ctx.Err() so a cancel stops the next batch even before SQL would notice. The chunk itself also uses ExecContext so the in-flight statement aborts.
func (*Store) CallsConfidenceTierStats ¶
CallsConfidenceTierStats returns CALLS edge counts grouped by confidence_tier (EXTRACTED, HIGH, MEDIUM, LOW, SPECULATIVE, …). Same shape as CallsResolverRuleStats; uses the indexed confidence_tier_gen generated column. Gives operators a quick "how risky is this graph?" summary — a graph dominated by SPECULATIVE has different reliability characteristics than one dominated by HIGH, even if total edge count is the same.
func (*Store) CallsResolutionStats ¶
CallsResolutionStats returns CALLS edge counts grouped by resolution_strategy.
func (*Store) CallsResolverRuleStats ¶
CallsResolverRuleStats returns CALLS edge counts grouped by resolver_rule. Reads the indexed resolver_rule_gen generated column, so the aggregation stays cheap (O(distinct rules) seeks) even on graphs with millions of edges. Rows whose resolver_rule property is missing land in the "unset" bucket — these are typically pre-migration edges from older indexes or edges emitted by passes that don't categorize (HTTP_CALLS, INHERITS, etc., which CALLS rows shouldn't contain). The output is suitable for surfacing in index_health so operators can see precision-distribution at a glance ("how many edges came from cross-package-suffix vs cross-package-import-map?") without scanning JSON properties.
func (*Store) Checkpoint ¶
Checkpoint forces a WAL checkpoint, moving pages from WAL to the main DB, then runs PRAGMA optimize so the query planner has up-to-date statistics. PRAGMA optimize (SQLite 3.46+) auto-limits sampling per index, only re-analyzing stale stats. Cost is absorbed during indexing rather than the first read query.
func (*Store) CosineSearch ¶
func (s *Store) CosineSearch(project string, queryVec []float32, limit int) ([]EmbeddingResult, error)
CosineSearch finds the top-k nodes most similar to the query vector. Uses in-memory dot product (vectors are L2-normalized).
func (*Store) CountEdges ¶
CountEdges returns the number of edges in a project.
func (*Store) CountEdgesByType ¶
CountEdgesByType returns the number of edges of a given type for a project.
func (*Store) CountFileHashes ¶ added in v0.9.1
CountFileHashes returns the number of tracked files for a project.
func (*Store) CountNodes ¶
CountNodes returns the number of nodes in a project.
func (*Store) CreateUserIndexes ¶
CreateUserIndexes recreates all user-created indexes (single sorted pass, O(N)). Honors ctx so a slow CREATE INDEX on a large table is cancellable.
func (*Store) DB ¶
DB returns the underlying sql.DB (for advanced queries).
Prefer Q() for query execution inside pipeline passes: Q() returns the active querier (either *sql.DB or *sql.Tx), which honors the surrounding transaction. Using DB() from code running under WithTransaction bypasses the tx and asks the single-connection pool for another connection, which blocks indefinitely on the write lock held by the outer tx.
func (*Store) DeleteEdgesBetweenFiles ¶
func (s *Store) DeleteEdgesBetweenFiles(project, edgeType string, srcFiles, tgtFiles []string) (int64, error)
DeleteEdgesBetweenFiles deletes edges of the given type whose SOURCE node lives in srcFiles AND whose TARGET node lives in tgtFiles, for the project. Used by the SCIP ingest pass to replace heuristic CALLS edges only where the index can actually re-derive them: requiring BOTH endpoints to be index-covered keeps heuristic edges into files the indexer cannot see (CGO sources, platform-gated files) — ground-truth eval showed source-only deletion cost 210 real edges on this repo. Returns the number of edges deleted.
func (*Store) DeleteEdgesByProject ¶
DeleteEdgesByProject deletes all edges for a project.
func (*Store) DeleteEdgesBySourceFile ¶
DeleteEdgesBySourceFile deletes edges of a given type where the source node belongs to a specific file. Used for incremental re-indexing of CALLS edges.
func (*Store) DeleteEdgesByType ¶
DeleteEdgesByType deletes all edges of a given type for a project.
func (*Store) DeleteFileHash ¶
DeleteFileHash deletes a single file hash entry.
func (*Store) DeleteFileHashes ¶
DeleteFileHashes deletes all file hashes for a project.
func (*Store) DeleteNodesByFile ¶
DeleteNodesByFile deletes all nodes for a specific file in a project.
func (*Store) DeleteNodesByLabel ¶
DeleteNodesByLabel deletes all nodes with a given label in a project.
func (*Store) DeleteNodesByProject ¶
DeleteNodesByProject deletes all nodes for a project.
func (*Store) DeleteOrphanNodesByLabel ¶
DeleteOrphanNodesByLabel deletes labeled nodes with no incoming or outgoing edges. Incremental passes use this after FK cascade removes changed sources.
func (*Store) DeleteProject ¶
DeleteProject deletes a project and all associated data (CASCADE).
func (*Store) DropUserIndexes ¶
DropUserIndexes drops all user-created indexes for faster bulk writes. Honors ctx — callers cancelling a long-running bulk pass need the SQL to abort, not run to completion.
func (*Store) EdgeCountsByType ¶
EdgeCountsByType returns edge counts grouped by edge type.
func (*Store) EmbeddingCount ¶
EmbeddingCount returns the number of embeddings stored for a project. Uses s.q so callers inside Store.WithTransaction don't deadlock on the single-connection pool.
func (*Store) EmbeddingModelCounts ¶
EmbeddingModelCounts returns the observed stored embedding inventory for a project, grouped by the model recorded alongside each vector.
func (*Store) EndBulkWrite ¶
EndBulkWrite restores WAL journal mode, NORMAL synchronous, and adaptive cache.
Removes the Mode 7 crash-marker. Order matters: switch back to WAL (which forces a checkpoint) BEFORE removing the marker, so a crash between mode-switch and marker-removal still leaves a valid signal.
func (*Store) FindArchitectureDocs ¶
FindArchitectureDocs discovers existing architecture documentation files in a project. Returns file paths matching common architecture doc patterns.
func (*Store) FindCallerFilesOfTargetsInFiles ¶
func (s *Store) FindCallerFilesOfTargetsInFiles(project string, targetFilePaths, edgeTypes []string) ([]string, error)
FindCallerFilesOfTargetsInFiles returns the set of file paths containing source nodes for any edge of one of the given types whose target node's file_path is in targetFilePaths.
This is the building block for Plan 1 Phase 3's invalidation rewrite. Today findDependentFiles only walks one hop of the import graph (callers of changed modules); it misses cases where a call site's resolution depended on a changed function in a different module that the caller's module DIDN'T import directly (transitive callers, type-based dispatch, stranded handlers). This helper lets the pipeline ask the question directly: "Which files contain edges pointing AT functions in the changed files?" The result is the union of those caller-files; if their target's resolution may have shifted, we re-resolve them.
Uses idx_nodes_file (project, file_path) to scope the target side and idx_edges_target_type (project, target_id, type) on the edge join — both present from initial schema, no migration needed. Edge types are filtered explicitly rather than IN() so the planner can use the composite index; the typical caller passes ["CALLS", "USAGE", "HTTP_CALLS", "ASYNC_CALLS", "INDIRECT_CALLS"].
Returns a deduped, sorted slice of relative file paths. Empty targetFilePaths or edgeTypes returns nil without querying.
func (*Store) FindEdgeEndpointsByTypes ¶
func (s *Store) FindEdgeEndpointsByTypes(project string, edgeTypes []string) ([]EdgeEndpoint, error)
FindEdgeEndpointsByTypes returns only endpoint columns for the requested edge types. Callers that need topology but not edge metadata should prefer this over AllEdges: filtering happens in SQLite and properties are never materialized or decoded.
func (*Store) FindEdgesBySource ¶
FindEdgesBySource finds all edges from a given source node.
func (*Store) FindEdgesBySourceAndType ¶
FindEdgesBySourceAndType finds edges from a source with a specific type.
func (*Store) FindEdgesBySourceIDs ¶
func (s *Store) FindEdgesBySourceIDs(sourceIDs []int64, edgeTypes []string) (map[int64][]*Edge, error)
FindEdgesBySourceIDs returns all edges where source_id is in the given set, optionally filtered by edge types. Groups results by source_id for efficient lookup.
func (*Store) FindEdgesByTarget ¶
FindEdgesByTarget finds all edges to a given target node.
func (*Store) FindEdgesByTargetAndType ¶
FindEdgesByTargetAndType finds edges to a target with a specific type.
func (*Store) FindEdgesByTargetIDs ¶
func (s *Store) FindEdgesByTargetIDs(targetIDs []int64, edgeTypes []string) (map[int64][]*Edge, error)
FindEdgesByTargetIDs returns all edges where target_id is in the given set, optionally filtered by edge types. Groups results by target_id.
func (*Store) FindEdgesByType ¶
FindEdgesByType returns all edges of a given type for a project.
func (*Store) FindEdgesByURLPath ¶
FindEdgesByURLPath returns edges where url_path contains the given substring. Uses the generated column index for prefix matches, falls back to json_extract for substring.
func (*Store) FindNodeByID ¶
FindNodeByID finds a node by its primary key ID.
func (*Store) FindNodeByQN ¶
FindNodeByQN finds a node by project and qualified name.
func (*Store) FindNodeIDsByQNs ¶
FindNodeIDsByQNs returns a map of qualifiedName → ID for the given QNs in a project.
func (*Store) FindNodeLabelsByQNs ¶
FindNodeLabelsByQNs returns a map of qualifiedName → label for the given QNs. Used by the CALLS pass to filter out edges targeting Variable/Class/File nodes (a CALLS edge should only target Function or Method). Before this existed, 38% of CALLS edges on some Rust projects pointed at Variable nodes generated from config files (diesel.toml entries, Cargo.toml), inflating false-positive rate with zero semantic value (see 2026-04-24 accuracy harness incident).
func (*Store) FindNodeSeedCandidates ¶
func (s *Store) FindNodeSeedCandidates(project string, exactNameTokens, qnTokens []string) ([]*Node, error)
FindNodeSeedCandidates returns the minimal node projection that could match any exact-name or qualified-name token. It is used by substring seed selection to avoid loading every project node and decoding properties that cannot affect the match.
func (*Store) FindNodesByFile ¶
FindNodesByFile finds all nodes in a given file.
func (*Store) FindNodesByFileOverlap ¶
func (s *Store) FindNodesByFileOverlap(project, fileSuffix string, startLine, endLine int) ([]*Node, error)
FindNodesByFileOverlap returns nodes whose line range overlaps [startLine, endLine]. The fileSuffix is matched with LIKE '%' || ? against the file_path column to handle relative/absolute path differences.
func (*Store) FindNodesByIDs ¶
FindNodesByIDs returns a map of nodeID → *Node for the given IDs.
func (*Store) FindNodesByLabel ¶
FindNodesByLabel finds all nodes with a given label in a project.
func (*Store) FindNodesByName ¶
FindNodesByName finds nodes by project and name.
func (*Store) FindNodesByProperty ¶
FindNodesByProperty finds nodes with a specific JSON property value. If label is non-empty, also filters by label.
func (*Store) FindNodesByQNSuffix ¶
FindNodesByQNSuffix finds nodes whose qualified_name ends with "."+suffix. Matches at QN segment boundaries to prevent partial word matches.
func (*Store) FindSimilarNodes ¶
func (s *Store) FindSimilarNodes(project string, nodeID int64, limit int) ([]EmbeddingResult, error)
FindSimilarNodes returns the top-k embedded nodes most cosine-similar to the given node's own embedding, excluding the node itself. Returns nil, nil when the node has no embedding or no other embeddings exist for the project.
Reuses the same in-memory, L2-normalized embedding cache that CosineSearch uses, so repeated calls across all nodes in a pass do not re-scan SQLite. The cost is O(N * dim) per query where N is embedded nodes in the project — ~546 nodes × 2048-dim embeddings on rmf-corsair measures at <1ms per query on a modern CPU.
func (*Store) FormatVersionOf ¶
FormatVersionOf reports the format version recorded in this store's database.
func (*Store) GetArchitecture ¶
func (s *Store) GetArchitecture(project string, aspects []string) (*ArchitectureInfo, error)
GetArchitecture computes architecture aspects for a project. An empty/nil aspects slice defaults to the compact "summary" aspect only — see buildAspectSet for the full set of names. Callers that want detail fields (Languages / Packages / EntryPoints / Routes / Hotspots / Boundaries / Services / Layers / Clusters / FileTree) must pass them explicitly, or pass `[]string{"all"}` for everything.
The "empty = summary only" default landed in PR #301 (2026-05-12) so the cheap path is the default; the older "empty = all aspects" contract is removed. Callers that relied on the old contract must pass `[]string{"all"}` instead.
func (*Store) GetFileHashes ¶
GetFileHashes returns all file hashes with stat metadata for a project.
func (*Store) GetIncrementalsSinceFull ¶
GetIncrementalsSinceFull returns how many incremental reindexes have run since the last full reindex for this project. The pipeline uses this to enforce a periodic-full-reindex sentinel (Plan 1 Phase 1), bounding the staleness window of any edges that the incremental dependency-discovery heuristic missed.
func (*Store) GetIndexIdentity ¶
func (s *Store) GetIndexIdentity(project string) (*indexidentity.Record, error)
GetIndexIdentity returns the persisted envelope state. A legacy project with no identity row is represented explicitly as missing.
func (*Store) GetIndexProgress ¶
GetIndexProgress returns the live index progress for a project.
func (*Store) GetProject ¶
GetProject returns a project by name.
func (*Store) GetSchema ¶
func (s *Store) GetSchema(project string) (*SchemaInfo, error)
GetSchema returns graph schema statistics for a project.
func (*Store) IncrementIncrementalsSinceFull ¶
IncrementIncrementalsSinceFull bumps the counter by 1. Called after a successful incremental reindex.
func (*Store) InsertEdge ¶
InsertEdge inserts an edge (dedup by source_id, target_id, type) and returns its row id.
Uses SQLite's RETURNING clause (available since 3.35, March 2021) so the id is read directly from the row written or updated by this statement. The pre-RETURNING path used LastInsertId(), which after `ON CONFLICT DO UPDATE` can return a STALE non-zero id — the most-recent-insert rowid the AUTOINCREMENT counter would have used, not the rowid of the conflict-targeted row. Callers that operated on the returned id (downstream node lookups, dedup) silently pointed at the wrong edge. The InsertEdgeBatch comment at edges.go:416 still names this as the upstream cause of its FK-violation fallback path.
Mirrors the fix applied to UpsertNode in PR #332 / commit 2085f8f.
func (*Store) InsertEdgeBatch ¶
func (*Store) InvalidateEmbeddingCache ¶
func (s *Store) InvalidateEmbeddingCache()
InvalidateEmbeddingCache clears the in-memory cache (call after reindex).
func (*Store) IterEmbeddedNodeIDs ¶
IterEmbeddedNodeIDs returns the list of node IDs that currently have embeddings for this project, loading the cache if needed. Enables the similarity pass to enumerate every embedded node without re-querying SQLite.
func (*Store) ListFilesForProject ¶
ListFilesForProject returns source-file paths tracked by the incremental index. Node file_path also contains directory paths for Folder/Package nodes, so it is not a valid source of truth for deleted-file detection.
func (*Store) ListProjects ¶
ListProjects returns all indexed projects.
func (*Store) LoadNodeIDMap ¶
LoadNodeIDMap returns a map of qualified_name → SQLite ID for all nodes in a project.
func (*Store) NodeDegree ¶
NodeDegree returns inbound and outbound CALLS-family edge counts for a node. Includes CALLS, CALLS_EXTERNAL (real-to-stub), and CALLS_PSEUDO (module-default caller) so degree reflects the same surface users saw before the type split.
func (*Store) NodeNeighborNames ¶
NodeNeighborNames returns the names of callers and callees for a node, considering CALLS-family (CALLS, CALLS_EXTERNAL, CALLS_PSEUDO), HTTP_CALLS, and ASYNC_CALLS edge types.
func (*Store) Q ¶
Q returns the active Querier. Inside WithTransaction, this is the tx; at other times, it is the raw *sql.DB. Passes should use Q for ad-hoc queries so they participate in whatever transaction their caller set up.
func (*Store) ReachableExcluding ¶
func (s *Store) ReachableExcluding(startID, targetID int64, direction string, edgeTypes []string, maxDepth int, exclude map[int64]bool) (bool, error)
ReachableExcluding reports whether targetID is reachable from startID within maxDepth hops, following edges of the given types in the given direction, WITHOUT routing through any node in the exclude set. A node in exclude is a cut point: it is never entered, so no path may pass through it (the target itself is still detectable even if excluded).
Taint analysis uses this to decide sanitization soundly: a (source, sink) pair is "sanitized" iff the sink is NOT reachable from the source once every sanitizer/auth_boundary node is excluded — i.e. EVERY path from source to sink crosses a sanitizer. If any sanitizer-free path exists, the pair is unsanitized. This replaces the prior heuristic, which flagged a pair sanitized whenever a sanitizer merely appeared anywhere in the BFS-reachable set and so produced false "sanitized" verdicts when the sanitizer sat on an unrelated branch.
func (*Store) ResetIncrementalsSinceFull ¶
ResetIncrementalsSinceFull zeroes the counter. Called after a successful full reindex.
func (*Store) RewriteProject ¶ added in v0.9.1
RewriteProject renames a project in place: the projects row, every table with a project column, the project prefix of node qualified names, and qualified names embedded in node/edge properties JSON. Used when an exported graph artifact is imported for a checkout at a different path (project names are derived from the absolute repository path).
func (*Store) Search ¶
func (s *Store) Search(params *SearchParams) (*SearchOutput, error)
Search executes a parameterized search query with pagination support.
func (*Store) SetEnrichmentVersion ¶
SetEnrichmentVersion updates the enrichment_version for a project.
func (*Store) SetIndexIdentity ¶
func (s *Store) SetIndexIdentity(project string, identity *indexidentity.Envelope) error
SetIndexIdentity persists a successfully captured checkout identity.
func (*Store) SetIndexIdentityState ¶
SetIndexIdentityState invalidates any previous envelope and records why a coherent identity is not currently available.
func (*Store) SetIndexProgress ¶
SetIndexProgress updates the live index progress for a project.
func (*Store) SetNodeIntProperty ¶
SetNodeIntProperty atomically sets a single integer property on a node by project + qualified_name. Uses SQLite's json_set so the rest of the properties map is preserved. Returns the number of rows updated (0 if the node doesn't exist).
Added 2026-05-02 for the unresolved_call_count diagnostic. Generalized so future int counters (e.g. cyclomatic_call_count, dispatch_count) can use the same path without re-implementing read-modify-write.
func (*Store) ShortestPath ¶
func (s *Store) ShortestPath(startID, targetID int64, direction string, edgeTypes []string, maxDepth int) ([]int64, error)
ShortestPath returns the node-ID sequence of a shortest path (fewest hops) from startID to targetID following edges of the given types in the given direction, bounded by maxDepth, or nil if no such path exists within the bound. It is a BFS that records one parent pointer per discovered node and reconstructs the path by walking parents back from the target. It is used to produce a concrete witness path (e.g. to name the sanitizer on a sanitized taint path).
func (*Store) SnapshotTo ¶ added in v0.9.1
SnapshotTo writes a consistent copy of the database to path using `VACUUM INTO`, which produces a compact single-file image regardless of the WAL state of the live database. path must not exist.
func (*Store) StoreADR ¶
StoreADR persists an ADR (upsert). The source_hash column is kept as a dead column to avoid ALTER TABLE issues — we write an empty string.
func (*Store) UpdateADRSections ¶
UpdateADRSections merges the provided sections into the existing ADR. Unmentioned sections are preserved. Returns the updated record. Returns an error if the merged content exceeds maxADRLength.
func (*Store) UpsertEmbedding ¶
UpsertEmbedding stores or updates the embedding vector for a node. Uses s.q (the active Querier) so this can run inside Store.WithTransaction without deadlocking on the single-connection pool — same pattern as UpsertEmbeddingBatch (see comment there for the deadlock story).
func (*Store) UpsertEmbeddingBatch ¶
UpsertEmbeddingBatch stores embeddings for multiple nodes.
Uses the store's active Querier (s.q) rather than calling s.db.Begin() so that when this is invoked from inside Store.WithTransaction (as the whole indexing pipeline does), the writes participate in the outer tx instead of opening a nested one. A nested tx on the SetMaxOpenConns(1) pool deadlocks waiting for the write lock held by the outer tx — this was the root cause of TestMemoryStability hanging and of the multi-minute stalls observed at "phase=embeddings pct=97" during live indexing (2026-04-22).
When called outside a tx (s.q == s.db), each prepared Exec auto-commits. That is fine for this call site: UpsertEmbeddingBatch is invoked from the embeddings pass which runs inside the pipeline's WithTransaction; the only other caller would be ad-hoc tooling where atomicity across 64 rows is not a correctness requirement.
func (*Store) UpsertFileHash ¶
UpsertFileHash stores a file's content hash with stat metadata.
func (*Store) UpsertFileHashBatch ¶
UpsertFileHashBatch inserts or updates multiple file hashes in batched multi-row INSERTs.
func (*Store) UpsertNode ¶
UpsertNode inserts or replaces a node (dedup by qualified_name) and returns the node's row id.
Uses SQLite's RETURNING clause (available since 3.35, March 2021) so the id is read directly from the row written or updated by this statement. The pre-RETURNING path used LastInsertId() with a fallback SELECT when it returned 0, and accepted "occasional FK failures in downstream edge inserts" when LastInsertId returned a stale (non-zero) id on a conflict. RETURNING closes that race: SQLite emits one row per inserted or updated row, so the id is always the id of the row this statement just touched, regardless of conflict behavior.
func (*Store) UpsertNodeBatch ¶
UpsertNodeBatch inserts or updates multiple nodes in batched multi-row INSERTs. Returns a map of qualifiedName → ID for all upserted nodes.
func (*Store) UpsertProject ¶
UpsertProject creates or updates a project record.
func (*Store) WALSize ¶
WALSize returns the current WAL file size in bytes, or -1 if unavailable. Useful for diagnosing memory bloat from un-checkpointed WAL files.
func (*Store) WithLargeCache ¶
WithLargeCache temporarily boosts the page cache to 64 MB for heavy read operations (e.g. GetSchema, Louvain clustering), then restores the adaptive default.
func (*Store) WithTransaction ¶
WithTransaction executes fn within a single SQLite transaction. The callback receives a transaction-scoped Store — all store methods called on txStore use the transaction. The receiver's q field is never mutated, so concurrent read-only handlers (using s.q == s.db) are unaffected.
type StoreRouter ¶
type StoreRouter struct {
// contains filtered or unexported fields
}
StoreRouter manages per-project SQLite databases. Each project gets its own .db file in the cache directory. Idle stores are evicted after idleTimeout (configurable) to free memory.
func NewRouter ¶
func NewRouter() (*StoreRouter, error)
NewRouter creates a StoreRouter, ensuring the cache directory exists. Runs migration from single-DB layout if needed.
func NewRouterWithDir ¶
func NewRouterWithDir(dir string) (*StoreRouter, error)
NewRouterWithDir creates a StoreRouter using a custom directory (for testing). No migration is run.
func (*StoreRouter) AcquireStore ¶
func (r *StoreRouter) AcquireStore(project string) (*Store, ReleaseFunc, error)
AcquireStore returns a store with an incremented ref count plus a release function. The evictor will not close the store while refs > 0.
func (*StoreRouter) AllStores ¶
func (r *StoreRouter) AllStores() map[string]*Store
AllStores opens all .db files in the cache dir and returns a name→Store map.
func (*StoreRouter) CloseAll ¶
func (r *StoreRouter) CloseAll()
CloseAll closes all open Store connections.
func (*StoreRouter) DeleteProject ¶
func (r *StoreRouter) DeleteProject(name string) error
DeleteProject closes the Store connection and removes the .db, WAL/SHM sidecars, and the BulkWrite crash marker. The marker must be in this set: it survives a SIGTERM'd indexing run, and leaving it orphaned means the documented Mode 7 recovery (delete_project + index_repository force=true) can still trip the crash-marker check on the recreated DB (observed 2026-06-11 on a Loc-Bench eval instance — every retry failed until the marker was removed by hand).
func (*StoreRouter) ForProject ¶
func (r *StoreRouter) ForProject(name string) (*Store, error)
ForProject returns the Store for the given project, opening it lazily. Updates lastUsed but does NOT hold a ref: the evictor may close the returned store once it sits idle past idleTimeout (30s). Only safe for short-lived use that completes well inside that window. Operations that can run longer — indexing, agent loops, report generation on large graphs — MUST use AcquireStore/UseStore so the ref blocks eviction for their full duration (see the 2026-06-11 incident note in tools/index.go).
func (*StoreRouter) HasProject ¶
func (r *StoreRouter) HasProject(name string) bool
HasProject checks if a .db file exists for the given project (without opening it).
func (*StoreRouter) ListProjects ¶
func (r *StoreRouter) ListProjects() ([]*ProjectInfo, error)
ListProjects scans .db files and queries each for metadata. Uses AcquireStore to prevent the evictor from closing stores mid-query. Individual DB failures are logged and skipped (never block the full list).
func (*StoreRouter) OnDelete ¶
func (r *StoreRouter) OnDelete(fn func(name string))
OnDelete registers a callback invoked after a project is deleted.
func (*StoreRouter) StartEvictor ¶
func (r *StoreRouter) StartEvictor(ctx context.Context)
StartEvictor runs a background goroutine that closes idle stores. Ticks every 5 seconds. Evicts stores idle for > idleTimeout with refs == 0. Exits when ctx is cancelled.
type TraverseResult ¶
type TraverseResult struct {
Root *Node
Visited []*NodeHop
Edges []EdgeInfo
// Truncated is true when the visited set was clipped at maxResults —
// the traversal had more matching nodes than the limit allowed.
// Callers that aggregate over Visited (e.g. the Cypher executor's
// variable-length expansion) must surface this instead of silently
// undercounting.
Truncated bool
}
TraverseResult holds BFS traversal results.