Documentation
¶
Overview ¶
Package graphstore — CRG bridge.
CRGBridge delegates code-graph build, update, and query operations to the Python code-review-graph CLI installed at crgBin. It does not require Go tree-sitter bindings; instead it shells out to the CRG executable and marshals its output back to Go types compatible with the graphstore.Store interface contracts.
Package graphstore — CRG dual-read parity surface (t4-crg-dual-read).
This file ships the structural-equivalence parity oracle that the CRG migration (spec §11) is gated on. It folds the O6 proposal refinements (.agents/proposals/crg-dual-read-parity-surface-2026-05.md):
- A: per-kind ±tolerance on nodes.kind / nodes.language / edges.kind, replacing the under-specified "±1% of kg build output" total check. A bootstrap that drops every Type row but doubles Function rows stays within 1% on the grand total — per-kind tolerance catches it.
- C: STRUCTURAL equivalence (set-equality, partition-equivalence via pair-agreement, Spearman rank correlation > τ) replacing the "bytes-equivalent" criterion, which can never pass against LLM-derived summary fields.
- D: a STRUCTURED upsert-tuple oracle — the set of (qualified_name, kind, file_path, line_start, op) tuples an update produces — replacing the free-text parseCRGMutationSummary regex (crg.go:504+) as the `update` row oracle.
O6 item G (SQL-callable parity views) is REJECTED here: it violates the §2.2/§5.2 no-raw-SQL invariant. The oracle is computed in Go over data both adapters expose through the Store seam, never via adapter-authored SQL views.
Package graphstore provides the storage interface and types for the unified code-structure + knowledge-note graph. It is a Go port of the Python code-review-graph storage layer, extended with KG note tables.
Index ¶
- Constants
- func CRGDBPath(repoRoot string) string
- func DiscoverCRGBin(repoRoot string) (string, error)
- func PartitionAgreement(a, b map[string]string) (float64, bool)
- func SpearmanTau(a, b map[string]float64) (float64, bool)
- type BridgeConsumer
- type BuildOptions
- type CRGBridge
- func (b *CRGBridge) Available() bool
- func (b *CRGBridge) Build(opts BuildOptions) error
- func (b *CRGBridge) BuildReport(opts BuildOptions) (*CRGOperationReport, error)
- func (b *CRGBridge) DetectChanges(opts DetectChangesOptions) (*CRGChangeReport, error)
- func (b *CRGBridge) GetImpactRadius(opts ImpactOptions) (*CRGImpactResult, error)
- func (b *CRGBridge) ListCommunities(minSize int, sortBy string) (*CommunitiesResult, error)
- func (b *CRGBridge) ListFlows(limit int, sortBy string) (*FlowsResult, error)
- func (b *CRGBridge) Postprocess(opts PostprocessOptions) error
- func (b *CRGBridge) ReadEdges(limit int) ([]GraphEdge, error)
- func (b *CRGBridge) ReadNodes(limit int) ([]GraphNode, error)
- func (b *CRGBridge) Status() (*CRGStatus, error)
- func (b *CRGBridge) Update(opts UpdateOptions) error
- func (b *CRGBridge) UpdateReport(opts UpdateOptions) (*CRGOperationReport, error)
- type CRGChangeReport
- type CRGChangedNode
- type CRGFlow
- type CRGImpactResult
- type CRGOperationReport
- type CRGPriority
- type CRGStatus
- type CRGTestGap
- type Closer
- type CodeGraphReader
- type CodeGraphWriter
- type CommunitiesResult
- type CommunityInfo
- type DetectChangesOptions
- type EdgeInfo
- type FlowInfo
- type FlowsResult
- type GraphEdge
- type GraphNode
- type GraphStats
- type Handle
- type ImpactNode
- type ImpactOptions
- type ImpactResult
- type ImpactRow
- type KGNote
- type KGNoteStore
- type MCPServer
- type NodeInfo
- type NoteSymbolLink
- type NoteSymbolLinkStore
- type ParityReport
- type ParitySnapshot
- type PostgresStore
- func (s *PostgresStore) Close() error
- func (s *PostgresStore) Commit() error
- func (s *PostgresStore) DeleteNoteSymbolLink(id int64) error
- func (s *PostgresStore) GetAllFiles() ([]string, error)
- func (s *PostgresStore) GetEdgesAmong(qualifiedNames []string) ([]GraphEdge, error)
- func (s *PostgresStore) GetEdgesBySource(qualifiedName string) ([]GraphEdge, error)
- func (s *PostgresStore) GetEdgesByTarget(qualifiedName string) ([]GraphEdge, error)
- func (s *PostgresStore) GetImpactRadius(changedFiles []string, maxDepth, maxNodes int) (ImpactResult, error)
- func (s *PostgresStore) GetKGNote(id string) (*KGNote, error)
- func (s *PostgresStore) GetLinksForNote(noteID string) ([]NoteSymbolLink, error)
- func (s *PostgresStore) GetLinksForSymbol(qualifiedName string) ([]NoteSymbolLink, error)
- func (s *PostgresStore) GetMetadata(key string) (string, error)
- func (s *PostgresStore) GetNode(qualifiedName string) (*GraphNode, error)
- func (s *PostgresStore) GetNodesByFile(filePath string) ([]GraphNode, error)
- func (s *PostgresStore) GetStats() (GraphStats, error)
- func (s *PostgresStore) ListArchivedKGNotes() ([]KGNote, error)
- func (s *PostgresStore) RemoveFileData(filePath string) error
- func (s *PostgresStore) SearchKGNotes(query string, limit int) ([]KGNote, error)
- func (s *PostgresStore) SearchNodes(query string, limit int) ([]GraphNode, error)
- func (s *PostgresStore) SetMetadata(key, value string) error
- func (s *PostgresStore) StoreFileNodesEdges(filePath string, nodes []NodeInfo, edges []EdgeInfo, fileHash string) error
- func (s *PostgresStore) UpsertEdge(edge EdgeInfo) (int64, error)
- func (s *PostgresStore) UpsertKGNote(note KGNote) error
- func (s *PostgresStore) UpsertNode(node NodeInfo, fileHash string) (int64, error)
- func (s *PostgresStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)
- type PostprocessOptions
- type SQLiteStore
- func (s *SQLiteStore) Close() error
- func (s *SQLiteStore) Commit() error
- func (s *SQLiteStore) CountKGNotes() int
- func (s *SQLiteStore) CountNodes() int
- func (s *SQLiteStore) DeleteNoteSymbolLink(id int64) error
- func (s *SQLiteStore) GetAllFiles() ([]string, error)
- func (s *SQLiteStore) GetEdgesAmong(qualifiedNames []string) ([]GraphEdge, error)
- func (s *SQLiteStore) GetEdgesBySource(qualifiedName string) ([]GraphEdge, error)
- func (s *SQLiteStore) GetEdgesByTarget(qualifiedName string) ([]GraphEdge, error)
- func (s *SQLiteStore) GetImpactRadius(changedFiles []string, maxDepth, maxNodes int) (ImpactResult, error)
- func (s *SQLiteStore) GetKGNote(id string) (*KGNote, error)
- func (s *SQLiteStore) GetLinksForNote(noteID string) ([]NoteSymbolLink, error)
- func (s *SQLiteStore) GetLinksForSymbol(qualifiedName string) ([]NoteSymbolLink, error)
- func (s *SQLiteStore) GetMetadata(key string) (string, error)
- func (s *SQLiteStore) GetNode(qualifiedName string) (*GraphNode, error)
- func (s *SQLiteStore) GetNodesByFile(filePath string) ([]GraphNode, error)
- func (s *SQLiteStore) GetStats() (GraphStats, error)
- func (s *SQLiteStore) ListArchivedKGNotes() ([]KGNote, error)
- func (s *SQLiteStore) RemoveFileData(filePath string) error
- func (s *SQLiteStore) SearchKGNotes(query string, limit int) ([]KGNote, error)
- func (s *SQLiteStore) SearchNodes(query string, limit int) ([]GraphNode, error)
- func (s *SQLiteStore) SetMetadata(key, value string) error
- func (s *SQLiteStore) StoreFileNodesEdges(filePath string, nodes []NodeInfo, edges []EdgeInfo, fileHash string) error
- func (s *SQLiteStore) UpsertEdge(edge EdgeInfo) (int64, error)
- func (s *SQLiteStore) UpsertKGNote(note KGNote) error
- func (s *SQLiteStore) UpsertNode(node NodeInfo, fileHash string) (int64, error)
- func (s *SQLiteStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)
- type Store
- type UpdateOptions
- type UpsertOp
- type UpsertTuple
Constants ¶
const ( CRGReadinessUnbuilt = "unbuilt" CRGReadinessReady = "ready" CRGReadinessBusyOrLocked = "busy_or_locked" CRGReadinessError = "error" )
const ( NodeKindFile = "File" NodeKindClass = "Class" NodeKindFunction = "Function" NodeKindType = "Type" NodeKindTest = "Test" )
NodeKind enumerates structural node types in the code graph.
const ( EdgeKindCalls = "CALLS" EdgeKindImportsFrom = "IMPORTS_FROM" EdgeKindInherits = "INHERITS" EdgeKindImplements = "IMPLEMENTS" EdgeKindContains = "CONTAINS" EdgeKindTestedBy = "TESTED_BY" EdgeKindDependsOn = "DEPENDS_ON" )
EdgeKind enumerates relationship types between code nodes.
const BridgeAdapterName = "crg-bridge"
BridgeAdapterName is the migration-only crg-bridge adapter's name as it appears in consumer lockfiles' view dependencies (§11.2).
const DefaultKindTolerance = 0.01
DefaultKindTolerance is the per-kind drift tolerance (O6 refinement A: "±1% per (kind) AND per (language)"). A divergence of this fraction or less on any single anchor bucket passes; anything larger fails parity.
const DefaultSpearmanTau = 0.85
DefaultSpearmanTau is the pinned Spearman rank-correlation floor for rank-ordered derived tables such as risk_index (O6 refinement C, "pin τ — likely 0.85"). A correlation strictly below this fails parity.
Variables ¶
This section is empty.
Functions ¶
func DiscoverCRGBin ¶
DiscoverCRGBin looks for the code-review-graph executable in this order:
- .venv/{bin,Scripts}/code-review-graph[.exe] relative to repoRoot
- the same under repoRoot's parent .venv
- code-review-graph on PATH (exec.LookPath applies PATHEXT on Windows)
func PartitionAgreement ¶ added in v0.4.2
PartitionAgreement is the pair-agreement score between two community partitions over the union of their members (O6 refinement C: partition equivalence via pair-agreement, "simplest, defensible, computable"). It returns the fraction of co-membership decisions the two partitions agree on, in [0,1] (1.0 = identical partition up to cluster relabeling). community maps node id → cluster id; cluster ids need not match between the two inputs.
The second return is false when the two partitions do NOT cover the same node set — a missing or extra node is a parity divergence, not a free pass, so the score is meaningless and callers must treat ok=false as a failure. (Earlier this leniently returned 1.0 for <2 ids, which masked a dropped node; that was MEDIUM #5.) When ok is true and there is at most one shared node, agreement is trivially 1.0 (no pair to disagree on).
func SpearmanTau ¶ added in v0.4.2
SpearmanTau is the Spearman rank correlation between two rankings keyed by the same ids (O6 refinement C: risk_index parity via Spearman τ). Each map is id → score. The second return is false when the two rankings do NOT cover the same id set — a missing or extra ranked node is a parity divergence, not a free pass (MEDIUM #5: this no longer silently correlates only the shared ids and passes). When ok is true the score is in [-1,1]; 1.0 is identical rank order. With at most one shared id the order is trivially identical (1.0).
Types ¶
type BridgeConsumer ¶ added in v0.4.2
type BridgeConsumer struct {
// Adapter is the adapter that owns the view.
Adapter string
// View is the materialized view name declaring reads_from [crg-bridge].
View string
}
BridgeConsumer is one materialized view that still reads from the crg-bridge mirror — a consumer not yet migrated off the legacy bridge (§11.4 gate condition 4, surfaced by `workflow drift`).
func BridgeConsumers ¶ added in v0.4.2
func BridgeConsumers(lf *lockfile.Lockfile) []BridgeConsumer
BridgeConsumers scans a lockfile for materialized views whose dependencies include the crg-bridge mirror, returning them sorted by (adapter, view). This is the §11.4-gate-condition-4 check the `workflow drift` command consumes: while any consumer is returned, the bridge must stay active and decommissioning (t6) is blocked. An empty result means zero consumers read the bridge — the gate condition is satisfied.
type BuildOptions ¶
type BuildOptions struct {
// SkipFlows skips community/flow detection (faster, code signatures only).
SkipFlows bool
// SkipPostprocess skips all post-processing (raw parse only).
SkipPostprocess bool
}
BuildOptions configures a full-graph build.
type CRGBridge ¶
type CRGBridge struct {
// RepoRoot is the directory that code-review-graph treats as the project root.
RepoRoot string
// Bin is the path to the code-review-graph executable. If empty,
// DiscoverCRGBin() is called to auto-detect it.
Bin string
}
CRGBridge shells out to the code-review-graph Python CLI.
func NewCRGBridge ¶
NewCRGBridge returns a CRGBridge rooted at repoRoot, auto-detecting the CRG binary from standard locations (workspace .venv, PATH).
func (*CRGBridge) Build ¶
func (b *CRGBridge) Build(opts BuildOptions) error
Build triggers a full graph rebuild via `code-review-graph build`. The structured report is intentionally discarded for legacy callers.
func (*CRGBridge) BuildReport ¶
func (b *CRGBridge) BuildReport(opts BuildOptions) (*CRGOperationReport, error)
BuildReport triggers a full graph rebuild and returns a structured summary.
func (*CRGBridge) DetectChanges ¶
func (b *CRGBridge) DetectChanges(opts DetectChangesOptions) (*CRGChangeReport, error)
DetectChanges returns the change-impact report for the current diff.
When opts.Brief is true the CRG CLI emits human-readable text rather than JSON. In that case we populate only CRGChangeReport.Summary with the raw text and leave structured fields empty.
func (*CRGBridge) GetImpactRadius ¶
func (b *CRGBridge) GetImpactRadius(opts ImpactOptions) (*CRGImpactResult, error)
GetImpactRadius returns the blast-radius for the given files (or current diff).
func (*CRGBridge) ListCommunities ¶
func (b *CRGBridge) ListCommunities(minSize int, sortBy string) (*CommunitiesResult, error)
ListCommunities returns detected code communities.
func (*CRGBridge) ListFlows ¶
func (b *CRGBridge) ListFlows(limit int, sortBy string) (*FlowsResult, error)
ListFlows returns the top execution flows detected in the graph.
func (*CRGBridge) Postprocess ¶
func (b *CRGBridge) Postprocess(opts PostprocessOptions) error
Postprocess runs flows/communities/FTS rebuilding via `code-review-graph postprocess`.
func (*CRGBridge) ReadEdges ¶
ReadEdges reads up to limit edges directly from the CRG SQLite database. If limit <= 0, ALL edges are returned. Like ReadNodes this is a bulk export path: the search-limit clamp is intentionally NOT applied (see the CONTRACT-PRESSURE note on ReadNodes); only the provider request timeout is added. The contract is left unchanged and the divergence is flagged for the spec/gcc3.
func (*CRGBridge) ReadNodes ¶
ReadNodes reads up to limit nodes directly from the CRG SQLite database. If limit <= 0, ALL nodes are returned.
CONTRACT-PRESSURE (Path A, gcc2): ReadNodes/ReadEdges are bulk *export* operations — the warm-link sync (commands/kg/sync_code_warm_link.go) calls ReadNodes(0)/ReadEdges(0) to mirror the ENTIRE CRG graph into the warm store. The published contract's "hard uniform cap, 0 = default" bound model fits user-facing bounded queries (SearchNodes, GetImpactRadius) but NOT a full-graph mirror: clamping 0 -> a default limit would silently truncate the sync on any repo with more rows than the cap. So Path A intentionally does NOT apply the search-limit clamp here; it only adds the provider-owned request timeout (still a valid, uniform guarantee). The contract is left UNCHANGED and this divergence is flagged for the spec/gcc3 to resolve (e.g. exempt bulk export, or give it a streaming/paged contract) rather than silently bent.
func (*CRGBridge) Status ¶
Status returns the current graph stats from `code-review-graph status`. The bridge reads the SQLite database directly so code-status can work even when the CRG binary is unavailable.
func (*CRGBridge) Update ¶
func (b *CRGBridge) Update(opts UpdateOptions) error
Update triggers an incremental graph update via `code-review-graph update`. The structured report is intentionally discarded for legacy callers.
func (*CRGBridge) UpdateReport ¶
func (b *CRGBridge) UpdateReport(opts UpdateOptions) (*CRGOperationReport, error)
UpdateReport triggers an incremental graph update and returns a structured summary.
type CRGChangeReport ¶
type CRGChangeReport struct {
Summary string `json:"summary"`
RiskScore float64 `json:"risk_score"`
ChangedFunctions []CRGChangedNode `json:"changed_functions"`
AffectedFlows []CRGFlow `json:"affected_flows"`
TestGaps []CRGTestGap `json:"test_gaps"`
ReviewPriorities []CRGPriority `json:"review_priorities"`
}
CRGChangeReport is the JSON output of `code-review-graph detect-changes`.
type CRGChangedNode ¶
type CRGChangedNode struct {
Name string `json:"name"`
QualifiedName string `json:"qualified_name"`
FilePath string `json:"file_path"`
RiskScore float64 `json:"risk_score"`
Callers int `json:"callers"`
}
CRGChangedNode represents a function or class that changed.
type CRGFlow ¶
type CRGFlow struct {
ID int64 `json:"id"`
EntryPoint string `json:"entry_point"`
Description string `json:"description"`
}
CRGFlow is a data-flow path affected by the change.
type CRGImpactResult ¶
type CRGImpactResult struct {
Status string `json:"status"`
Summary string `json:"summary"`
ChangedFiles []string `json:"changed_files"`
ChangedNodes []ImpactNode `json:"changed_nodes"`
ImpactedNodes []ImpactNode `json:"impacted_nodes"`
ImpactedFiles []string `json:"impacted_files"`
Truncated bool `json:"truncated"`
TotalImpacted int `json:"total_impacted"`
}
CRGImpactResult is the structured output of an impact-radius query via CRG.
type CRGOperationReport ¶
type CRGOperationReport struct {
Operation string `json:"operation"`
Outcome string `json:"outcome"`
Summary string `json:"summary"`
ChangedFiles []string `json:"changed_files,omitempty"`
Status *CRGStatus `json:"status,omitempty"`
RawOutput string `json:"raw_output,omitempty"`
}
CRGOperationReport captures a build/update outcome for CLI callers.
type CRGPriority ¶
type CRGPriority struct {
QualifiedName string `json:"qualified_name"`
Reason string `json:"reason"`
RiskScore float64 `json:"risk_score"`
}
CRGPriority is a review priority item.
type CRGStatus ¶
type CRGStatus struct {
Nodes int `json:"nodes"`
Edges int `json:"edges"`
Files int `json:"files"`
Languages string `json:"languages"`
LastUpdated string `json:"last_updated"`
State string `json:"state"`
Ready bool `json:"ready"`
Message string `json:"message,omitempty"`
}
CRGStatus is the parsed output of `code-review-graph status`.
type CRGTestGap ¶
type CRGTestGap struct {
QualifiedName string `json:"qualified_name"`
FilePath string `json:"file_path"`
}
CRGTestGap is a changed symbol lacking test coverage.
type Closer ¶
type Closer interface {
Close() error
}
Closer is the acquire/release view (idiomatic single-method interface, io.Closer shape). Callers that own a handle's lifetime depend on this role to release it; callers handed a borrowed handle should NOT depend on it (they must not Close what they do not own).
type CodeGraphReader ¶
type CodeGraphReader interface {
GetNode(qualifiedName string) (*GraphNode, error)
GetNodesByFile(filePath string) ([]GraphNode, error)
GetEdgesBySource(qualifiedName string) ([]GraphEdge, error)
GetEdgesByTarget(qualifiedName string) ([]GraphEdge, error)
GetEdgesAmong(qualifiedNames []string) ([]GraphEdge, error)
GetAllFiles() ([]string, error)
SearchNodes(query string, limit int) ([]GraphNode, error)
GetMetadata(key string) (string, error)
GetStats() (GraphStats, error)
GetImpactRadius(changedFiles []string, maxDepth, maxNodes int) (ImpactResult, error)
}
CodeGraphReader is the read-only view of the code-structure graph: node/edge lookups, file enumeration, search, metadata reads, aggregate stats, and bounded impact-radius traversal. Read-mostly callers (status, review, impact, orient flows) should depend on this role alone.
type CodeGraphWriter ¶
type CodeGraphWriter interface {
UpsertNode(node NodeInfo, fileHash string) (int64, error)
UpsertEdge(edge EdgeInfo) (int64, error)
RemoveFileData(filePath string) error
StoreFileNodesEdges(filePath string, nodes []NodeInfo, edges []EdgeInfo, fileHash string) error
SetMetadata(key, value string) error
Commit() error
}
CodeGraphWriter is the mutation view of the code-structure graph: node/edge upserts, per-file replace, metadata writes, and Commit. Only the build/update pipeline (graph build, precommit refresh) depends on this role.
type CommunitiesResult ¶
type CommunitiesResult struct {
Status string `json:"status"`
Summary string `json:"summary"`
Communities []CommunityInfo `json:"communities"`
}
CommunitiesResult is the output of list_communities.
type CommunityInfo ¶
type CommunityInfo struct {
ID int64 `json:"id"`
Name string `json:"name"`
Size int `json:"size"`
Cohesion float64 `json:"cohesion"`
DominantLanguage string `json:"dominant_language"`
Description string `json:"description"`
Members []string `json:"members"`
}
CommunityInfo is one code community.
type DetectChangesOptions ¶
type DetectChangesOptions struct {
Base string
Brief bool
// Files is an optional list of repo-relative file paths to restrict change
// detection to. NOTE: the CRG CLI detect-changes subcommand does not accept
// a --files argument in v1.x; this field is reserved for a future CRG
// version that supports per-file scoping. When set, the caller must fall
// back to using Files only for impact-radius queries (warm store) and accept
// that changed_functions will reflect the default HEAD~1 diff.
Files []string
}
DetectChangesOptions configures a change-detection run.
type EdgeInfo ¶
type EdgeInfo struct {
Kind string
Source string // qualified name
Target string // qualified name
FilePath string
Line int
Extra map[string]any
}
EdgeInfo carries data for inserting/updating an edge (parser output shape).
type FlowInfo ¶
type FlowInfo struct {
ID int64 `json:"id"`
Name string `json:"name"`
EntryPoint string `json:"entry_point"`
StepCount int `json:"step_count"`
Criticality float64 `json:"criticality"`
Kind string `json:"kind"`
}
FlowInfo is one execution flow entry.
type FlowsResult ¶
type FlowsResult struct {
Status string `json:"status"`
Summary string `json:"summary"`
Flows []FlowInfo `json:"flows"`
}
FlowsResult is the output of list_flows.
type GraphEdge ¶
type GraphEdge struct {
ID int64
Kind string
SourceQualified string
TargetQualified string
FilePath string
Line int
Extra map[string]any
UpdatedAt float64
}
GraphEdge is an edge as stored and returned from the graph.
type GraphNode ¶
type GraphNode struct {
ID int64
Kind string
Name string
QualifiedName string
FilePath string
LineStart int
LineEnd int
Language string
ParentName string
Params string
ReturnType string
IsTest bool
FileHash string
Extra map[string]any
UpdatedAt float64
}
GraphNode is a node as stored and returned from the graph.
type GraphStats ¶
type GraphStats struct {
TotalNodes int
TotalEdges int
NodesByKind map[string]int
EdgesByKind map[string]int
Languages []string
FilesCount int
LastUpdated string
NotesCount int
LinksCount int
}
GraphStats aggregates health metrics for the graph.
type Handle ¶
type Handle struct {
// contains filtered or unexported fields
}
Handle is the contract-typed boundary the dependency-injection singleton (the package-level `deps` in commands/* — di-refactor OD-1) holds. It deliberately exposes ONLY a contract-typed Store accessor: the singleton is justified solely because it carries a Store whose provider owns pooling and serialization. The singleton is NOT the concurrency story and must never reach a concrete backend; it reads the graph exclusively through Store().
Defined here (write scope: internal/graphstore) so the contract and its DI boundary are published together as one reviewable artifact. Binding the actual command-package Deps structs to this handle is gcc3 (refactor all callers) and is intentionally deferred — this type pins the shape gcc3 will adopt without changing any caller now.
func NewHandle ¶
NewHandle wraps a contract-typed Store for the DI singleton to hold. Acquisition is cheap and explicit; the provider behind store owns all connection/pool/serialization concerns.
func (Handle) Store ¶
Store returns the whole-store contract-typed handle. Callers bind to this interface, never to a concrete backend. Returns nil if the handle is unset, letting callers fall back to their existing direct-open path until gcc3 wires this end-to-end.
To narrow to a single role, do NOT add a per-role accessor — a Store already satisfies every role (it embeds them). Declare the dependency as the narrow role type and assign it from Store():
var r CodeGraphReader = h.Store() // a Store IS a CodeGraphReader
This is the idiomatic "accept interfaces" Go: the call site documents exactly the role it needs, a test fake stubs only that role, and there is exactly one nil-safe accessor (no duplicated narrowing bodies). The nil-safety is inherited: an unset handle's Store() is nil, so the narrowed interface value is nil too.
type ImpactNode ¶
type ImpactNode struct {
ID int64 `json:"id"`
Kind string `json:"kind"`
Name string `json:"name"`
QualifiedName string `json:"qualified_name"`
FilePath string `json:"file_path"`
LineStart int `json:"line_start"`
LineEnd int `json:"line_end"`
Language string `json:"language"`
IsTest bool `json:"is_test"`
}
ImpactNode is one node in an impact result.
type ImpactOptions ¶
type ImpactOptions struct {
// ChangedFiles is the list of repo-relative or absolute file paths to analyze.
// If empty, the current git diff (HEAD~1) is used.
ChangedFiles []string
MaxDepth int
MaxResults int
Base string
}
ImpactOptions configures a blast-radius query.
type ImpactResult ¶
type ImpactResult struct {
ChangedNodes []GraphNode
ImpactedNodes []GraphNode
ImpactedFiles []string
Edges []GraphEdge
}
ImpactResult is the output of a GetImpactRadius query.
type ImpactRow ¶ added in v0.4.2
ImpactRow is one row of an impact-radius result (O6 refinement C: the impact-radius row compares by node-id SET equality, "may differ in order").
type KGNote ¶
type KGNote struct {
ID string // KG note ID (matches frontmatter id)
Title string
NoteType string // concept, decision, entity, etc.
Status string
Summary string
FilePath string // path to the .md file in KG_HOME
Version int
ArchivedAt string // RFC3339 or empty
IndexedAt float64
}
KGNote is a knowledge-graph note record in the warm database layer.
type KGNoteStore ¶
type KGNoteStore interface {
UpsertKGNote(note KGNote) error
GetKGNote(id string) (*KGNote, error)
SearchKGNotes(query string, limit int) ([]KGNote, error)
ListArchivedKGNotes() ([]KGNote, error)
}
KGNoteStore is the knowledge-graph note view: upsert/get/search a note and list archived notes. KG curation/sync callers depend on this role (often paired with NoteSymbolLinkStore).
type MCPServer ¶
type MCPServer struct {
// contains filtered or unexported fields
}
func NewMCPServer ¶
type NodeInfo ¶
type NodeInfo struct {
Kind string
Name string
FilePath string
LineStart int
LineEnd int
Language string
ParentName string
Params string
ReturnType string
Modifiers string
IsTest bool
Extra map[string]any
}
NodeInfo carries data for inserting/updating a node (parser output shape).
type NoteSymbolLink ¶
type NoteSymbolLink struct {
ID int64
NoteID string
QualifiedName string
LinkKind string // "mentions", "implements", "documents", etc.
CreatedAt float64
}
NoteSymbolLink connects a KG note to a code symbol.
type NoteSymbolLinkStore ¶
type NoteSymbolLinkStore interface {
UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)
GetLinksForNote(noteID string) ([]NoteSymbolLink, error)
GetLinksForSymbol(qualifiedName string) ([]NoteSymbolLink, error)
DeleteNoteSymbolLink(id int64) error
}
NoteSymbolLinkStore is the note↔code-symbol link view: upsert, the two directional lookups, and delete. The warm-link sync flow depends on this role.
type ParityReport ¶ added in v0.4.2
ParityReport is the verdict of a single parity comparison. Pass is the row-level gate; Detail carries human-readable divergence for diagnostics.
func CompareImpactRadius ¶ added in v0.4.2
func CompareImpactRadius(a, b []ImpactRow) ParityReport
CompareImpactRadius checks impact-radius parity via O6 refinement C: node-id SET equality ("same node set, may differ in order"). Edges and hop depth are not compared here — the row's pinned criterion is the node set.
func CompareSnapshots ¶ added in v0.4.2
func CompareSnapshots(a, b ParitySnapshot, tol float64) ParityReport
CompareSnapshots checks build/status parity between two snapshots under the O6 refinement-A per-kind tolerance: file count exact, every node-kind, node-language and edge-kind bucket within tol. Buckets present in one snapshot but absent in the other are compared against zero (so a dropped kind fails). tol is a fraction (e.g. 0.01 for ±1%).
func CompareUpserts ¶ added in v0.4.2
func CompareUpserts(a, b []UpsertTuple) ParityReport
CompareUpserts checks `update`-row parity via O6 refinement D: the two adapters agree iff their upsert-tuple SETS are equal. Reports the symmetric difference on failure.
type ParitySnapshot ¶ added in v0.4.2
type ParitySnapshot struct {
// Adapter is the adapter name the snapshot was taken from ("crg" or
// "crg-bridge").
Adapter string
// SchemaDigest is the adapter's schema digest at snapshot time.
SchemaDigest string
// Commit is the pinned source commit the snapshot was bootstrapped at.
Commit string
// NodesTotal is the grand total node (symbol) count.
NodesTotal int
// NodesByKind maps a node kind (Function, Type, ...) to its count. This is
// the per-kind anchor column O6 refinement A requires.
NodesByKind map[string]int
// NodesByLanguage maps a node language (go, ts, ...) to its count — the
// second per-kind anchor column.
NodesByLanguage map[string]int
// EdgesByKind maps an edge kind (CALLS, TESTED_BY, ...) to its count.
EdgesByKind map[string]int
// Files is the exact distinct file count (O6 refinement A: "total file
// count exact", not toleranced).
Files int
}
ParitySnapshot is the structured build/status oracle for one adapter at one commit (O6 refinement A, replacing the under-specified §11.1 "build" row). It is computed in Go from data the adapter exposes through the Store seam — it is NOT a SQL-callable view (O6 item G rejected, §2.2/§5.2 no-raw-SQL).
type PostgresStore ¶
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore is the Postgres-backed implementation of Store. It uses pgxpool for connection pooling and is safe for concurrent use.
func OpenPostgres ¶
func OpenPostgres(ctx context.Context, dsn string) (*PostgresStore, error)
OpenPostgres connects to a Postgres database at dsn (a libpq-style connection string or URL, e.g. "postgres://user:pass@host:5432/dbname") and initialises the schema.
func (*PostgresStore) Close ¶
func (s *PostgresStore) Close() error
Close closes the connection pool.
func (*PostgresStore) Commit ¶
func (s *PostgresStore) Commit() error
Commit is a no-op for PostgresStore — writes auto-commit individually.
func (*PostgresStore) DeleteNoteSymbolLink ¶
func (s *PostgresStore) DeleteNoteSymbolLink(id int64) error
func (*PostgresStore) GetAllFiles ¶
func (s *PostgresStore) GetAllFiles() ([]string, error)
func (*PostgresStore) GetEdgesAmong ¶
func (s *PostgresStore) GetEdgesAmong(qualifiedNames []string) ([]GraphEdge, error)
func (*PostgresStore) GetEdgesBySource ¶
func (s *PostgresStore) GetEdgesBySource(qualifiedName string) ([]GraphEdge, error)
func (*PostgresStore) GetEdgesByTarget ¶
func (s *PostgresStore) GetEdgesByTarget(qualifiedName string) ([]GraphEdge, error)
func (*PostgresStore) GetImpactRadius ¶
func (s *PostgresStore) GetImpactRadius(changedFiles []string, maxDepth, maxNodes int) (ImpactResult, error)
GetImpactRadius performs a pure-Go BFS from the nodes in changedFiles, traversing both outbound and inbound edges up to maxDepth hops. Postgres-specific: uses pgx for the seed/edge queries; the BFS body is shared with the SQLite backend via computeImpactRadius (impact.go).
func (*PostgresStore) GetLinksForNote ¶
func (s *PostgresStore) GetLinksForNote(noteID string) ([]NoteSymbolLink, error)
func (*PostgresStore) GetLinksForSymbol ¶
func (s *PostgresStore) GetLinksForSymbol(qualifiedName string) ([]NoteSymbolLink, error)
func (*PostgresStore) GetMetadata ¶
func (s *PostgresStore) GetMetadata(key string) (string, error)
func (*PostgresStore) GetNode ¶
func (s *PostgresStore) GetNode(qualifiedName string) (*GraphNode, error)
func (*PostgresStore) GetNodesByFile ¶
func (s *PostgresStore) GetNodesByFile(filePath string) ([]GraphNode, error)
func (*PostgresStore) GetStats ¶
func (s *PostgresStore) GetStats() (GraphStats, error)
func (*PostgresStore) ListArchivedKGNotes ¶
func (s *PostgresStore) ListArchivedKGNotes() ([]KGNote, error)
func (*PostgresStore) RemoveFileData ¶
func (s *PostgresStore) RemoveFileData(filePath string) error
func (*PostgresStore) SearchKGNotes ¶
func (s *PostgresStore) SearchKGNotes(query string, limit int) ([]KGNote, error)
func (*PostgresStore) SearchNodes ¶
func (s *PostgresStore) SearchNodes(query string, limit int) ([]GraphNode, error)
SearchNodes performs a case-insensitive LIKE search on name and qualified_name. For production workloads with large graphs, consider adding a tsvector GIN index and using to_tsquery instead.
func (*PostgresStore) SetMetadata ¶
func (s *PostgresStore) SetMetadata(key, value string) error
func (*PostgresStore) StoreFileNodesEdges ¶
func (s *PostgresStore) StoreFileNodesEdges(filePath string, nodes []NodeInfo, edges []EdgeInfo, fileHash string) error
StoreFileNodesEdges atomically replaces all nodes and edges for a file.
func (*PostgresStore) UpsertEdge ¶
func (s *PostgresStore) UpsertEdge(edge EdgeInfo) (int64, error)
func (*PostgresStore) UpsertKGNote ¶
func (s *PostgresStore) UpsertKGNote(note KGNote) error
func (*PostgresStore) UpsertNode ¶
func (s *PostgresStore) UpsertNode(node NodeInfo, fileHash string) (int64, error)
func (*PostgresStore) UpsertNoteSymbolLink ¶
func (s *PostgresStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)
type PostprocessOptions ¶
PostprocessOptions controls which post-processing steps to run.
type SQLiteStore ¶
type SQLiteStore struct {
// contains filtered or unexported fields
}
SQLiteStore is the SQLite-backed implementation of Store.
func OpenSQLite ¶
func OpenSQLite(dbPath string) (*SQLiteStore, error)
OpenSQLite opens (or creates) the SQLite database at dbPath and initialises the schema. The parent directory is created if it does not exist.
func (*SQLiteStore) Close ¶
func (s *SQLiteStore) Close() error
Close shuts the store down deterministically: it marks the store closed (so no new tracked reaper can register), waits for every in-flight abandon-and-fail reaper to finish draining its orphaned connection, then closes the pool. Waiting on reapers before db.Close() is the correctness point — a timed-out request abandons its connection to a background reaper (see queryContextGuarded); closing the pool while that reaper still holds the conn would race db.Close() against an in-flight step and could leak the goroutine + connection past the store's lifetime.
func (*SQLiteStore) Commit ¶
func (s *SQLiteStore) Commit() error
Commit is a no-op for SQLiteStore — writes auto-commit via individual transactions. Exposed on the interface for backends that need explicit flush.
func (*SQLiteStore) CountKGNotes ¶
func (s *SQLiteStore) CountKGNotes() int
CountKGNotes returns the number of KG notes in the warm store.
func (*SQLiteStore) CountNodes ¶
func (s *SQLiteStore) CountNodes() int
CountNodes returns the number of nodes in the code graph.
func (*SQLiteStore) DeleteNoteSymbolLink ¶
func (s *SQLiteStore) DeleteNoteSymbolLink(id int64) error
func (*SQLiteStore) GetAllFiles ¶
func (s *SQLiteStore) GetAllFiles() ([]string, error)
func (*SQLiteStore) GetEdgesAmong ¶
func (s *SQLiteStore) GetEdgesAmong(qualifiedNames []string) ([]GraphEdge, error)
func (*SQLiteStore) GetEdgesBySource ¶
func (s *SQLiteStore) GetEdgesBySource(qualifiedName string) ([]GraphEdge, error)
func (*SQLiteStore) GetEdgesByTarget ¶
func (s *SQLiteStore) GetEdgesByTarget(qualifiedName string) ([]GraphEdge, error)
func (*SQLiteStore) GetImpactRadius ¶
func (s *SQLiteStore) GetImpactRadius(changedFiles []string, maxDepth, maxNodes int) (ImpactResult, error)
GetImpactRadius performs a pure-Go BFS from the nodes in changedFiles, traversing both outbound and inbound edges up to maxDepth hops. The BFS + node-resolution + edge-aggregation body lives in computeImpactRadius (impact.go); this method only handles the SQLite-specific seed gathering and edge adjacency loading.
func (*SQLiteStore) GetLinksForNote ¶
func (s *SQLiteStore) GetLinksForNote(noteID string) ([]NoteSymbolLink, error)
func (*SQLiteStore) GetLinksForSymbol ¶
func (s *SQLiteStore) GetLinksForSymbol(qualifiedName string) ([]NoteSymbolLink, error)
func (*SQLiteStore) GetMetadata ¶
func (s *SQLiteStore) GetMetadata(key string) (string, error)
func (*SQLiteStore) GetNode ¶
func (s *SQLiteStore) GetNode(qualifiedName string) (*GraphNode, error)
func (*SQLiteStore) GetNodesByFile ¶
func (s *SQLiteStore) GetNodesByFile(filePath string) ([]GraphNode, error)
func (*SQLiteStore) GetStats ¶
func (s *SQLiteStore) GetStats() (GraphStats, error)
func (*SQLiteStore) ListArchivedKGNotes ¶
func (s *SQLiteStore) ListArchivedKGNotes() ([]KGNote, error)
func (*SQLiteStore) RemoveFileData ¶
func (s *SQLiteStore) RemoveFileData(filePath string) error
func (*SQLiteStore) SearchKGNotes ¶
func (s *SQLiteStore) SearchKGNotes(query string, limit int) ([]KGNote, error)
func (*SQLiteStore) SearchNodes ¶
func (s *SQLiteStore) SearchNodes(query string, limit int) ([]GraphNode, error)
func (*SQLiteStore) SetMetadata ¶
func (s *SQLiteStore) SetMetadata(key, value string) error
func (*SQLiteStore) StoreFileNodesEdges ¶
func (s *SQLiteStore) StoreFileNodesEdges(filePath string, nodes []NodeInfo, edges []EdgeInfo, fileHash string) error
StoreFileNodesEdges atomically replaces all nodes and edges for a file.
func (*SQLiteStore) UpsertEdge ¶
func (s *SQLiteStore) UpsertEdge(edge EdgeInfo) (int64, error)
func (*SQLiteStore) UpsertKGNote ¶
func (s *SQLiteStore) UpsertKGNote(note KGNote) error
func (*SQLiteStore) UpsertNode ¶
func (s *SQLiteStore) UpsertNode(node NodeInfo, fileHash string) (int64, error)
func (*SQLiteStore) UpsertNoteSymbolLink ¶
func (s *SQLiteStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)
type Store ¶
type Store interface {
CodeGraphReader
CodeGraphWriter
KGNoteStore
NoteSymbolLinkStore
Closer
}
Store is the published, backend-agnostic whole-store contract: every role composed. Existing whole-store callers and the Deps handle bind to this; callers that use only one concern should instead depend on the matching role above. It is the single stable surface that makes the ephemeral→pooled→daemon evolution (spec graphstore-concurrency-contract, decision C-Hybrid) a transparent provider swap with no caller-visible change.
func NewLazyStore ¶
NewLazyStore wraps a provider-open thunk in a Store whose backend is opened lazily on first use. open is the cheap, late, per-process acquisition (e.g. func() (Store, error) { return OpenSQLite(path) }). Acquisition stays explicit and cheap (CONTRACT.md guarantee #4): the returned value is constructed with zero I/O.
type UpdateOptions ¶
type UpdateOptions struct {
// Base is the git ref to diff against (default: HEAD~1).
Base string
// SkipFlows skips community/flow detection.
SkipFlows bool
// SkipPostprocess skips all post-processing.
SkipPostprocess bool
}
UpdateOptions configures an incremental graph update.
type UpsertOp ¶ added in v0.4.2
type UpsertOp string
UpsertOp is the operation an update applied to a single symbol.
type UpsertTuple ¶ added in v0.4.2
type UpsertTuple struct {
QualifiedName string
Kind string
FilePath string
LineStart int
Op UpsertOp
}
UpsertTuple is the structured upsert oracle of O6 refinement D — the unit a `kg update` produces. The set of these tuples replaces the free-text parseCRGMutationSummary regex as the `update`-row parity oracle: two adapters agree iff they produce set-equal upsert tuples.