graphstore

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

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

View Source
const (
	CRGReadinessUnbuilt      = "unbuilt"
	CRGReadinessReady        = "ready"
	CRGReadinessBusyOrLocked = "busy_or_locked"
	CRGReadinessError        = "error"
)
View Source
const (
	NodeKindFile     = "File"
	NodeKindClass    = "Class"
	NodeKindFunction = "Function"
	NodeKindType     = "Type"
	NodeKindTest     = "Test"
)

NodeKind enumerates structural node types in the code graph.

View Source
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.

View Source
const BridgeAdapterName = "crg-bridge"

BridgeAdapterName is the migration-only crg-bridge adapter's name as it appears in consumer lockfiles' view dependencies (§11.2).

View Source
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.

View Source
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 CRGDBPath

func CRGDBPath(repoRoot string) string

CRGDBPath returns the path to the CRG SQLite database for repoRoot.

func DiscoverCRGBin

func DiscoverCRGBin(repoRoot string) (string, error)

DiscoverCRGBin looks for the code-review-graph executable in this order:

  1. .venv/{bin,Scripts}/code-review-graph[.exe] relative to repoRoot
  2. the same under repoRoot's parent .venv
  3. code-review-graph on PATH (exec.LookPath applies PATHEXT on Windows)

func PartitionAgreement added in v0.4.2

func PartitionAgreement(a, b map[string]string) (float64, bool)

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

func SpearmanTau(a, b map[string]float64) (float64, bool)

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

func NewCRGBridge(repoRoot string) (*CRGBridge, error)

NewCRGBridge returns a CRGBridge rooted at repoRoot, auto-detecting the CRG binary from standard locations (workspace .venv, PATH).

func (*CRGBridge) Available

func (b *CRGBridge) Available() bool

Available returns true if the CRG binary exists and is executable.

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

func (b *CRGBridge) ReadEdges(limit int) ([]GraphEdge, error)

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

func (b *CRGBridge) ReadNodes(limit int) ([]GraphNode, error)

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

func (b *CRGBridge) Status() (*CRGStatus, error)

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

func NewHandle(store Store) Handle

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

func (h Handle) Store() 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

type ImpactRow struct {
	NodeID        string
	Kind          string
	QualifiedName string
	FilePath      string
	Hop           int
}

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

func NewMCPServer(workDir string) *MCPServer

func (*MCPServer) Serve

func (s *MCPServer) Serve(r io.Reader, w io.Writer) error

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 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

type ParityReport struct {
	Row    string
	Pass   bool
	Detail []string
}

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 (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) GetKGNote

func (s *PostgresStore) GetKGNote(id string) (*KGNote, error)

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 (s *PostgresStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)

type PostprocessOptions

type PostprocessOptions struct {
	NoFlows       bool
	NoCommunities bool
	NoFTS         bool
}

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 (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) GetKGNote

func (s *SQLiteStore) GetKGNote(id string) (*KGNote, error)

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 (s *SQLiteStore) UpsertNoteSymbolLink(link NoteSymbolLink) (int64, error)

type Store

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

func NewLazyStore(open func() (Store, error)) Store

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.

const (
	// OpInsert is a newly-added symbol.
	OpInsert UpsertOp = "insert"
	// OpUpdate is an existing symbol whose content changed.
	OpUpdate UpsertOp = "update"
	// OpDelete is a removed symbol.
	OpDelete UpsertOp = "delete"
)

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.

Directories

Path Synopsis
internal
storetest
Package storetest provides shared backend-agnostic test bodies for graphstore.Store implementations.
Package storetest provides shared backend-agnostic test bodies for graphstore.Store implementations.

Jump to

Keyboard shortcuts

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