domain

package
v2.3.4 Latest Latest
Warning

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

Go to latest
Published: Sep 2, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package domain defines the core domain models and business rules for Cortex.

This package contains the pure domain types that represent the core concepts of the memory system: Observations, Sessions, Knowledge Graph Edges, Prompts, and Importance Scoring. These types are independent of storage mechanisms and can be used across different layers of the application.

Index

Constants

View Source
const (
	// ClassDedupSkipped marks a duplicate observation that was intentionally
	// skipped. It is not an error: IsError is false.
	ClassDedupSkipped = "dedup_skipped"

	// ClassRejected marks an observation rejected for a content rule; no partial
	// row is written.
	ClassRejected = "rejected"

	// ClassFailed marks a persistence failure; Cause wraps the real error so it
	// is inspectable via errors.Unwrap / errors.Is.
	ClassFailed = "failed"
)

Classification codes for passive-type outcomes (REQ-FOUND-003).

These codes let callers distinguish an intentional dedup skip from a policy rejection from a real persistence failure via errors.As plus a code check (IsClass). The legacy dedup path swallowed non-duplicate errors as dedup skips (REQ-MCPH-002 defect pin); ValidationError fixes that by carrying an explicit code. W1 stub: codes are defined here; wiring into the dedup/save path lands in W6.2.

View Source
const (
	StatusHealthy   = "healthy"
	StatusDegraded  = "degraded"
	StatusUnhealthy = "unhealthy"
)

Health status constants used by Storage, VectorIndex, and EmbeddingProvider ports. Keeping them as typed constants (not magic strings) lets adapters and consumers compare deterministically.

View Source
const (
	// TruncationReasonMaxVisited marks eligible nodes omitted because the
	// max_visited budget (root plus unique admitted nodes) was exhausted.
	TruncationReasonMaxVisited = "max_visited"
	// TruncationReasonMaxResults marks eligible rows omitted because the
	// max_results budget (emitted unique non-root observations) was exhausted.
	TruncationReasonMaxResults = "max_results"
)

Truncation reasons reported by bounded local graph traversal (GRAPH-02).

View Source
const (
	TypeManual         = "manual"
	TypeToolUse        = "tool_use"
	TypeDecision       = "decision"
	TypeArchitecture   = "architecture"
	TypeBugfix         = "bugfix"
	TypePattern        = "pattern"
	TypeConfig         = "config"
	TypeDiscovery      = "discovery"
	TypeLearning       = "learning"
	TypeSessionSummary = "session_summary"
	TypePassive        = "passive"
)

Observation types - common values for the Type field

View Source
const (
	ScopeProject  = "project"
	ScopePersonal = "personal"
)

Scope types - common values for the Scope field

View Source
const (
	SourceManual = "manual"
	SourceAI     = "ai"
	SourceAuto   = "auto"
	SourceImport = "import"
)

Source types - common values for the Source field

View Source
const (
	RelationReferences  = "references"
	RelationRelatesTo   = "relates_to"
	RelationFollows     = "follows"
	RelationContradicts = "contradicts"
	RelationSupersedes  = "supersedes"
)

Relation types - common values for Edge.RelationType

View Source
const (
	EntityFile     = "file"
	EntityURL      = "url"
	EntityPackage  = "package"
	EntitySymbol   = "symbol"
	EntityConcept  = "concept"
	EntitySQLTable = "sql_table"
	EntityEndpoint = "endpoint"
	EntityEnvVar   = "env_var"
	EntityVersion  = "version"
	EntityCLIFlag  = "cli_flag"
	EntityError    = "error"
)

Entity types

View Source
const (
	EvolutionOriginal     = "original"
	EvolutionModified     = "modified"
	EvolutionSuperseded   = "superseded"
	EvolutionContradicted = "contradicted"
)

Evolution types for temporal graph edges

View Source
const (
	FactStateCurrent    = "current"
	FactStateHistorical = "historical"
	FactStateDeprecated = "deprecated"
	FactStateSuperseded = "superseded"
)

Fact states for temporal graph edges

View Source
const MaxHandoffPayloadSize = 1 << 20

MaxHandoffPayloadSize matches the runtime's accepted request-body limit. Durable handoffs reject larger canonical payloads rather than truncating them.

View Source
const (
	RelationTemporal = "temporal" // Tracks how facts evolve over time
)

Additional temporal relation types.

Variables

View Source
var (
	// ErrNotFound indicates that the requested entity was not found.
	ErrNotFound = errors.New("entity not found")

	// ErrAlreadyExists indicates that an entity with the same key already exists.
	ErrAlreadyExists = errors.New("entity already exists")

	// ErrInvalidInput indicates that the input data is invalid.
	ErrInvalidInput = errors.New("invalid input")

	// ErrConflict indicates a conflict with the current state (e.g., optimistic locking).
	ErrConflict = errors.New("conflict with current state")

	// ErrUnauthorized indicates lack of permissions for the operation.
	ErrUnauthorized = errors.New("unauthorized")

	// ErrSessionEnded indicates an attempt to modify an ended session.
	ErrSessionEnded = errors.New("session has already ended")

	// ErrInvalidRelation indicates an invalid edge relation type.
	ErrInvalidRelation = errors.New("invalid relation type")

	// ErrCircularReference indicates a circular reference in the knowledge graph.
	ErrCircularReference = errors.New("circular reference detected")

	// ErrVectorSearchDisabled indicates that vector search is not available.
	// This happens when the cortex_vectors build tag is not enabled.
	ErrVectorSearchDisabled = errors.New("vector search is disabled - rebuild with cortex_vectors tag")

	// ErrInvalidEmbedding indicates an invalid embedding vector.
	ErrInvalidEmbedding = errors.New("invalid embedding vector")

	// ErrDimensionMismatch indicates a vector whose dimension does not match
	// the declared model namespace. REQ-VEC-001 error scenario: mismatched
	// vectors MUST be rejected (not scored 0 and stored) to prevent
	// dimension-mismatch corruption. The legacy cosine path logged a warning
	// and returned 0 — this sentinel pins the corrected, fail-closed behavior.
	ErrDimensionMismatch = errors.New("vector dimension mismatch")

	// ErrNamespaceMismatch indicates a vector whose model/version namespace
	// differs from the index namespace. REQ-VEC-001: model-version namespace
	// prevents dimension-mismatch corruption; a cross-namespace upsert is
	// rejected rather than silently overwriting.
	ErrNamespaceMismatch = errors.New("vector model namespace mismatch")
)

Common domain errors that can be returned by repository implementations.

View Source
var (
	ErrHandoffValidation      = &HandoffError{Code: HandoffErrorValidation, Message: "invalid handoff request"}
	ErrHandoffPayloadTooLarge = &HandoffError{Code: HandoffErrorPayloadTooLarge, Message: "handoff payload exceeds accepted size"}
	ErrHandoffUnauthorized    = &HandoffError{Code: HandoffErrorUnauthorized, Message: "handoff authorization required"}
	ErrHandoffForbidden       = &HandoffError{Code: HandoffErrorForbidden, Message: "handoff is not permitted"}
	ErrHandoffConflict        = &HandoffError{Code: HandoffErrorConflict, Message: "handoff conflicts with an existing receipt"}
	ErrHandoffUnavailable     = &HandoffError{Code: HandoffErrorUnavailable, Message: "handoff service unavailable", Retryable: true}
	ErrHandoffTimeout         = &HandoffError{Code: HandoffErrorTimeout, Message: "handoff timed out", Retryable: true}
	ErrHandoffPersistence     = &HandoffError{Code: HandoffErrorPersistence, Message: "handoff could not be persisted", Retryable: true}
)

Functions

func IsClass

func IsClass(err error, code string) bool

IsClass reports whether err is a ValidationError whose Code equals code. It combines errors.As with a code check so callers can distinguish a dedup skip from a policy rejection from a persistence failure (REQ-FOUND-003).

func IsConflictError

func IsConflictError(err error) bool

IsConflictError checks if an error is a ConflictError.

func IsDimensionMismatch

func IsDimensionMismatch(err error) bool

IsDimensionMismatch reports whether err is a dimension-mismatch rejection. Adapters use this to classify upsert failures as non-retryable (the vector itself is wrong, not a transient backend issue).

func IsNotFoundError

func IsNotFoundError(err error) bool

IsNotFoundError checks if an error is a NotFoundError.

func IsValidationError

func IsValidationError(err error) bool

IsValidationError checks if an error is a ValidationError.

func IsVectorIndexHealthy

func IsVectorIndexHealthy(ctx context.Context, idx VectorIndex) bool

IsVectorIndexHealthy reports whether idx is non-nil and reports a healthy status. It is the W8 replacement for the legacy VectorRepository.IsAvailable() bool: consumers gate expensive work (embedding generation, reindex loops) on this check before calling Upsert/Search. A nil index or a degraded/unhealthy adapter returns false (REQ-VEC-001 zero-CGO default: the sqlite_blob stub reports unhealthy and operations return ErrVectorSearchDisabled).

Types

type AggregatedMetrics

type AggregatedMetrics struct {
	TimeRange           *TimeRange `json:"time_range,omitempty"`
	TotalOperations     int        `json:"total_operations"`
	SuccessfulOps       int        `json:"successful_ops"`
	FailedOps           int        `json:"failed_ops"`
	AvgDurationMs       float64    `json:"avg_duration_ms"`
	TotalMemoryUsage    int64      `json:"total_memory_usage"`
	AvgObservationCount float64    `json:"avg_observation_count"`
	AvgEdgeCount        float64    `json:"avg_edge_count"`
	AvgQueryComplexity  float64    `json:"avg_query_complexity"`
	AvgConfidenceScore  float64    `json:"avg_confidence_score"`
	EvaluatedAt         time.Time  `json:"evaluated_at"`
}

AggregatedMetrics represents rolled-up performance metrics for a time range.

type AuditEntry

type AuditEntry struct {
	ID           string    `json:"id"`
	ActorSubject string    `json:"actor_subject"`
	Action       string    `json:"action"`
	ResourceType string    `json:"resource_type"`
	ResourceID   string    `json:"resource_id"`
	Reason       string    `json:"reason"`
	Allowed      bool      `json:"allowed"`
	CreatedAt    time.Time `json:"created_at"`
}

AuditEntry is the public, non-hash portion of an authorization audit event.

type BusyRetryConfig

type BusyRetryConfig struct {
	// MaxRetries is the maximum number of application-level retries on a
	// SQLITE_BUSY error after the driver-level busy_timeout has been exceeded.
	// Default: 3. A value of 0 disables application-level retry (the driver
	// busy_timeout is the only bound).
	MaxRetries int

	// BaseBackoff is the initial backoff duration before the first retry.
	// Default: 5ms. Each subsequent retry multiplies the backoff by 2
	// (exponential) up to MaxBackoff.
	BaseBackoff time.Duration

	// MaxBackoff caps the backoff duration for any single retry.
	// Default: 50ms. This prevents a single retry from sleeping too long.
	MaxBackoff time.Duration

	// JitterFactor is the fraction of randomness added to each backoff
	// (0.0–1.0) to decorrelate concurrent retries. Default: 0.2 (±20%).
	JitterFactor float64
}

BusyRetryConfig bounds the SQLITE_BUSY retry behavior of a UnitOfWork implementation (REQ-TX-002). A save MUST NOT block unbounded; the retry cap and backoff ceiling keep latency within a measurable envelope (the envelope itself is registered separately by the latency-budget task).

func DefaultBusyRetryConfig

func DefaultBusyRetryConfig() BusyRetryConfig

DefaultBusyRetryConfig returns a BusyRetryConfig with the W2 defaults: 3 retries, 5ms base backoff, 50ms cap, ±20% jitter. These keep total worst-case retry latency well under the 5s driver busy_timeout.

type CanonicalHandoff

type CanonicalHandoff struct {
	Observation     SaveObservationInput  `json:"observation"`
	Relation        *HandoffRelationInput `json:"relation,omitempty"`
	CapabilityTuple json.RawMessage       `json:"capability_tuple,omitempty"`
}

CanonicalHandoff is the complete payload persisted in a receipt. The idempotency key and request-derived security scope are intentionally absent.

func CanonicalizeHandoff

func CanonicalizeHandoff(req HandoffRequest) (CanonicalHandoff, []byte, [32]byte, error)

CanonicalizeHandoff returns deterministic full JSON bytes and their SHA-256. CapabilityTuple is normalized as JSON data only; it is never interpreted.

type Capabilities

type Capabilities struct {
	IndexType       string   // sqlite_blob, qdrant, pgvector
	DistanceMetrics []string // cosine, dot, euclidean
	MaxDimensions   int
	Filters         string // PreFilter, PostFilter, none
	Hybrid          string // enabled, disabled
	Namespaces      string // supported, unsupported
	Consistency     string // strong, eventual
	BatchUpsert     bool
	MaxBatchSize    int
}

Capabilities declares what a VectorIndex adapter supports, enabling capability-driven strategy selection (filter push-down, batch size, etc.).

type ConflictError

type ConflictError struct {
	Entity string
	Reason string
}

ConflictError wraps ErrConflict with details about the conflict.

func (*ConflictError) Error

func (e *ConflictError) Error() string

func (*ConflictError) Unwrap

func (e *ConflictError) Unwrap() error

type DimensionMismatchError

type DimensionMismatchError struct {
	Expected  int    // ModelInfo.Dimension declared on the point (or index namespace)
	Actual    int    // len(Vector) observed
	Namespace string // model:version namespace (may be empty)
}

DimensionMismatchError wraps ErrDimensionMismatch with the expected and actual dimensions plus the offending namespace. It is the structured form returned by VectorIndex adapters when an upsert violates the model-version namespace invariant (REQ-VEC-001).

func NewDimensionMismatchError

func NewDimensionMismatchError(expected, actual int, namespace string) *DimensionMismatchError

NewDimensionMismatchError constructs a structured DimensionMismatchError.

func (*DimensionMismatchError) Error

func (e *DimensionMismatchError) Error() string

Error renders the mismatch with enough context to diagnose the cause.

func (*DimensionMismatchError) Unwrap

func (e *DimensionMismatchError) Unwrap() error

Unwrap returns ErrDimensionMismatch so errors.Is(err, ErrDimensionMismatch) works for every adapter's mismatch rejection.

type Edge

type Edge struct {
	ID           int64      `json:"id"`
	PublicID     string     `json:"-"`
	FromObsID    int64      `json:"from_obs_id"`
	ToObsID      int64      `json:"to_obs_id"`
	FromPublicID string     `json:"-"`
	ToPublicID   string     `json:"-"`
	RelationType string     `json:"relation_type"`         // references, relates_to, follows
	Weight       float64    `json:"weight"`                // Strength of relationship (0.0 to 10.0, default 1.0)
	Confidence   float64    `json:"confidence"`            // Confidence in this relationship (0.0 to 1.0)
	Source       string     `json:"source,omitempty"`      // Who/what created this edge
	Reasoning    string     `json:"reasoning,omitempty"`   // Why this relationship exists
	ValidFrom    *time.Time `json:"valid_from,omitempty"`  // Temporal validity start
	InvalidAt    *time.Time `json:"invalid_at,omitempty"`  // Temporal validity end (NULL = still valid)
	ValidUntil   *time.Time `json:"valid_until,omitempty"` // Bi-temporal valid-time end
	TxFrom       *time.Time `json:"tx_from,omitempty"`     // System/transaction-time start
	TxUntil      *time.Time `json:"tx_until,omitempty"`    // System/transaction-time end
	TenantID     string     `json:"tenant_id,omitempty"`
	WorkspaceID  string     `json:"workspace_id,omitempty"`
	CreatedAt    time.Time  `json:"created_at"`

	// Enhanced temporal graph fields
	EvolutionID     *int64 `json:"evolution_id,omitempty"`  // Track edge evolution (NULL = original)
	EvolutionType   string `json:"evolution_type"`          // evolution types: original, modified, superseded, contradicted
	FactState       string `json:"fact_state"`              // fact states: current, historical, deprecated, superseded
	ChangeReason    string `json:"change_reason,omitempty"` // Why the edge changed
	AssertionKind   string `json:"assertion_kind,omitempty"`
	AssertionStatus string `json:"assertion_status,omitempty"`
}

Edge represents a relationship between two observations in the knowledge graph. Edges enable semantic navigation and discovery of related knowledge with temporal awareness.

func (Edge) MarshalJSON

func (e Edge) MarshalJSON() ([]byte, error)

type EmbeddingProvider

type EmbeddingProvider interface {
	Embed(ctx context.Context, texts []string) ([][]float32, ModelInfo, error)
	ModelInfo() ModelInfo
	Health(ctx context.Context) Health
}

EmbeddingProvider abstracts the embedding model (local Ollama, remote API). Declared as a port so the retrieval engine and worker depend on the interface, not a concrete provider (ADR-04/ADR-05).

type EntityLink struct {
	ID                  int64     `json:"id"`
	PublicID            string    `json:"-"`
	ObservationID       int64     `json:"observation_id"`
	ObservationPublicID string    `json:"-"`
	EntityType          string    `json:"entity_type"` // file, url, package, symbol, concept
	EntityValue         string    `json:"entity_value"`
	NormalizedValue     string    `json:"normalized_value,omitempty"`
	Provenance          string    `json:"provenance,omitempty"`
	CreatedAt           time.Time `json:"created_at"`
}

EntityLink represents an extracted entity from an observation.

func (EntityLink) MarshalJSON

func (e EntityLink) MarshalJSON() ([]byte, error)

type EntityRepository

type EntityRepository interface {
	// SaveLinks stores extracted entity links for an observation.
	SaveLinks(ctx context.Context, links []*EntityLink) error

	// GetByObservation retrieves all entity links for an observation.
	GetByObservation(ctx context.Context, obsID int64) ([]*EntityLink, error)

	// FindByEntity retrieves observations that reference a given entity.
	FindByEntity(ctx context.Context, entityType, entityValue string) ([]*EntityLink, error)

	// DeleteByObservation removes all entity links for an observation.
	DeleteByObservation(ctx context.Context, obsID int64) error
}

EntityRepository defines the interface for entity linking operations.

type GraphLink struct {
	ID              string         `json:"id"`
	Source          string         `json:"source"`
	Target          string         `json:"target"`
	Type            string         `json:"type"`
	Weight          float64        `json:"weight,omitempty"`
	Confidence      float64        `json:"confidence,omitempty"`
	AssertionKind   string         `json:"assertion_kind,omitempty"`
	AssertionStatus string         `json:"assertion_status,omitempty"`
	Metadata        map[string]any `json:"metadata,omitempty"`
}

type GraphNode

type GraphNode struct {
	ID       string         `json:"id"`
	Kind     string         `json:"kind"`
	Subtype  string         `json:"subtype,omitempty"`
	Label    string         `json:"label"`
	Project  string         `json:"project,omitempty"`
	Hop      int            `json:"hop"`
	Metadata map[string]any `json:"metadata,omitempty"`
}

GraphNode and GraphLink form the transport-neutral heterogeneous graph read model. IDs are kind-prefixed so independently stored aggregates cannot collide when projected into one graph.

type GraphRepository

type GraphRepository interface {
	// CreateEdge creates a relationship between two observations.
	CreateEdge(ctx context.Context, edge *Edge) error

	// GetRelated retrieves observations related to the given observation ID,
	// up to the specified depth (for graph traversal).
	GetRelated(ctx context.Context, obsID int64, depth int) ([]*Observation, error)

	// DeleteEdge removes a relationship between observations.
	DeleteEdge(ctx context.Context, id int64) error

	// GetEdgesForObservation retrieves all edges where the observation is either source or target.
	GetEdgesForObservation(ctx context.Context, obsID int64) ([]*Edge, error)

	// GetEdge retrieves a specific edge by its ID.
	GetEdge(ctx context.Context, id int64) (*Edge, error)

	// GetEvolutionChain retrieves all edges that share the same evolution chain.
	GetEvolutionChain(ctx context.Context, fromObsID, toObsID int64) ([]*Edge, error)

	// CountEdgesByObservation counts edges connected to a specific observation.
	CountEdgesByObservation(ctx context.Context, obsID int64) (int, error)

	// CountAllEdges counts all edges in the system.
	CountAllEdges(ctx context.Context) (int, error)

	// GetContradictions retrieves edges marked as contradictions in a time range.
	GetContradictions(ctx context.Context, from, to time.Time) ([]*Edge, error)

	// UpdateEdge updates an existing edge.
	UpdateEdge(ctx context.Context, edge *Edge) error
}

GraphRepository defines the interface for knowledge graph operations. This enables semantic relationships between observations.

type GraphSubgraph

type GraphSubgraph struct {
	Root      string      `json:"root"`
	Nodes     []GraphNode `json:"nodes"`
	Edges     []GraphLink `json:"edges"`
	Truncated bool        `json:"truncated"`
}

type GraphTraversalOptions

type GraphTraversalOptions struct {
	Depth       int
	MaxVisited  int
	MaxResults  int
	TenantID    string
	WorkspaceID string
	Project     string
	AsOf        *time.Time
}

GraphTraversalOptions bounds graph expansion and carries server isolation filters. Empty tenant/project values are valid only for local mode.

type GraphTraversalResult

type GraphTraversalResult struct {
	Observations      []*Observation `json:"observations"`
	Truncated         bool           `json:"truncated"`
	TruncationReasons []string       `json:"truncation_reasons,omitempty"`
}

GraphTraversalResult is the bounded local traversal envelope. Truncated is true ONLY when a one-past-the-limit sentinel probe admitted/emitted eligible data that was then dropped; a result exactly equal to a limit is complete.

type HandoffAuthorizer

type HandoffAuthorizer interface {
	AuthorizeAll(context.Context, Principal, HandoffRequest) (HandoffScope, error)
}

type HandoffCoordinator

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

HandoffCoordinator keeps authorization and scope derivation ahead of the single UoW boundary. CapabilityTuple is merely forwarded as opaque evidence.

func NewHandoffCoordinator

func NewHandoffCoordinator(authorizer HandoffAuthorizer, executor HandoffExecutor) *HandoffCoordinator

func (*HandoffCoordinator) Execute

type HandoffError

type HandoffError struct {
	Code      HandoffErrorCode
	Message   string
	Retryable bool
	Operation string
	Context   string
}

HandoffError contains only a stable classification and safe message. It must never contain an idempotency key, observation reference, payload, or secret.

func (*HandoffError) Error

func (e *HandoffError) Error() string

func (*HandoffError) Is

func (e *HandoffError) Is(target error) bool

type HandoffErrorCode

type HandoffErrorCode string

HandoffErrorCode is the stable, transport-neutral handoff failure class.

const (
	HandoffErrorValidation      HandoffErrorCode = "validation"
	HandoffErrorPayloadTooLarge HandoffErrorCode = "payload_too_large"
	HandoffErrorUnauthorized    HandoffErrorCode = "unauthorized"
	HandoffErrorForbidden       HandoffErrorCode = "forbidden"
	HandoffErrorConflict        HandoffErrorCode = "conflict"
	HandoffErrorUnavailable     HandoffErrorCode = "unavailable"
	HandoffErrorTimeout         HandoffErrorCode = "timeout"
	HandoffErrorPersistence     HandoffErrorCode = "persistence"
)

type HandoffExecutor

type HandoffExecutor interface {
	ExecuteHandoff(context.Context, HandoffScope, string, CanonicalHandoff, [32]byte) (ObservationWriteResult, error)
}

type HandoffRelationInput

type HandoffRelationInput struct {
	Target     ObservationRef `json:"target"`
	Type       string         `json:"type"`
	Weight     float64        `json:"weight"`
	Confidence float64        `json:"confidence"`
	Reasoning  string         `json:"reasoning"`
}

type HandoffRequest

type HandoffRequest struct {
	IdempotencyKey  string                `json:"idempotency_key"`
	Observation     SaveObservationInput  `json:"observation"`
	Relation        *HandoffRelationInput `json:"relation,omitempty"`
	CapabilityTuple json.RawMessage       `json:"capability_tuple,omitempty"`
}

type HandoffScope

type HandoffScope string

type Health

type Health struct {
	Status  string // healthy, degraded, unhealthy
	Message string
}

Health is the lightweight health status returned by Storage, VectorIndex, and EmbeddingProvider ports.

type HealthCheck

type HealthCheck struct {
	Status           string    `json:"status"` // healthy, degraded, critical
	CheckTime        time.Time `json:"check_time"`
	TotalOperations  int       `json:"total_operations"`
	FailedOperations int       `json:"failed_operations"`
	SlowOperations   int       `json:"slow_operations"`
	AvgDurationMs    float64   `json:"avg_duration_ms"`
	Message          string    `json:"message"`
}

HealthCheck represents system health status.

type ImportanceScore

type ImportanceScore struct {
	ObservationID int64     `json:"observation_id"`
	Score         float64   `json:"score"`         // Importance score (0.0 to 5.0)
	AccessCount   int       `json:"access_count"`  // Number of times accessed
	LastAccessed  time.Time `json:"last_accessed"` // Last access timestamp
	UpdatedAt     time.Time `json:"updated_at"`
}

ImportanceScore tracks the importance of an observation based on access patterns, recency, and other metrics.

type Metrics

type Metrics struct {
	ID               int64     `json:"id"`
	SessionID        string    `json:"session_id"`
	OperationType    string    `json:"operation_type"`     // save, search, relate, get_related, etc.
	Duration         int64     `json:"duration_ms"`        // Operation duration in milliseconds
	ResultCount      int       `json:"result_count"`       // Number of results returned
	Success          bool      `json:"success"`            // Whether operation succeeded
	Error            string    `json:"error,omitempty"`    // Error message if failed
	MemoryUsage      int64     `json:"memory_usage_bytes"` // Memory usage in bytes
	Timestamp        time.Time `json:"timestamp"`
	ObservationCount int       `json:"observation_count"` // Total observations in system
	EdgeCount        int       `json:"edge_count"`        // Total edges in knowledge graph
	QueryComplexity  float64   `json:"query_complexity"`  // Estimated query complexity (0.0-1.0)
	ConfidenceScore  float64   `json:"confidence_score"`  // Average confidence score
}

Metrics represents observability metrics for memory system performance.

type MetricsRepository

type MetricsRepository interface {
	// CreateMetric records a performance metric.
	CreateMetric(ctx context.Context, metric *Metrics) error

	// GetTemporalMetrics retrieves metrics for a session within a time range.
	GetTemporalMetrics(ctx context.Context, sessionID string, from, to time.Time) ([]*Metrics, error)

	// GetByOperationType retrieves metrics filtered by operation type.
	GetByOperationType(ctx context.Context, operationType string, from, to time.Time) ([]*Metrics, error)

	// GetAggregatedMetrics gets aggregated metrics for a time range.
	GetAggregatedMetrics(ctx context.Context, from, to time.Time) (*AggregatedMetrics, error)
}

MetricsRepository defines the interface for observability metrics.

type ModelInfo

type ModelInfo struct {
	Name       string
	Dimension  int
	Version    string
	Normalized bool
}

ModelInfo describes the embedding model that produced a vector. Used for model-version namespacing to prevent dimension-mismatch corruption (ADR-05, REQ-VEC-001).

type NotFoundError

type NotFoundError struct {
	Type string // "observation", "session", "edge", "prompt"
	ID   interface{}
}

NotFoundError wraps ErrNotFound with context about what was not found.

func (*NotFoundError) Error

func (e *NotFoundError) Error() string

func (*NotFoundError) Unwrap

func (e *NotFoundError) Unwrap() error

type Observation

type Observation struct {
	ID int64 `json:"id"`
	// PublicID is the opaque server identifier. ID remains an internal/local
	// compatibility field and must not be used at a server API boundary.
	PublicID     string    `json:"-"`
	Title        string    `json:"title"`
	Content      string    `json:"content"`
	Type         string    `json:"type"`    // manual, tool_use, decision, bugfix, etc.
	Project      string    `json:"project"` // Project name or identifier
	Scope        string    `json:"scope"`   // project, personal
	OwnerSubject string    `json:"owner_subject,omitempty"`
	SessionID    string    `json:"session_id"`
	TopicKey     string    `json:"topic_key"`  // Optional topic key for upserts
	Confidence   float64   `json:"confidence"` // Confidence score (0.0 to 1.0), default 1.0
	Source       string    `json:"source"`     // Origin: manual, ai, auto, import
	Tags         []string  `json:"tags,omitempty"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`

	// RAG & Vector Indexing Status (Visible tracking)
	HasEmbedding   bool   `json:"has_embedding"`
	EmbeddingModel string `json:"embedding_model,omitempty"`
	EmbeddingDim   int    `json:"embedding_dimensions,omitempty"`
	RAGStatus      string `json:"rag_status,omitempty"` // "indexed", "pending", "failed", "unindexed"
}

Observation represents a single piece of knowledge or memory captured during an AI coding session. It can be a manual note, tool usage record, decision, bugfix, pattern, or any other type of observation.

func (Observation) MarshalJSON

func (o Observation) MarshalJSON() ([]byte, error)

type ObservationFilter

type ObservationFilter struct {
	Project         string     `json:"project,omitempty"`
	Scope           string     `json:"scope,omitempty"`
	OwnerSubject    string     `json:"owner_subject,omitempty"`
	Type            string     `json:"type,omitempty"`
	Source          string     `json:"source,omitempty"`
	SessionID       string     `json:"session_id,omitempty"`
	Tags            []string   `json:"tags,omitempty"`
	MinConfidence   float64    `json:"min_confidence,omitempty"`
	Limit           int        `json:"limit,omitempty"`
	Offset          int        `json:"offset,omitempty"`
	CreatedBefore   *time.Time `json:"created_before,omitempty"`
	CreatedAfter    *time.Time `json:"created_after,omitempty"`
	OrderAsc        bool       `json:"order_asc,omitempty"`
	IncludeArchived bool       `json:"include_archived,omitempty"`
}

ObservationFilter provides filtering options for listing observations.

type ObservationRef

type ObservationRef struct {
	// LocalID addresses the observation in the local SQLite namespace.
	LocalID *int64 `json:"local_id,omitempty"`
	// PublicID addresses the observation in the shared server namespace.
	PublicID *uuid.UUID `json:"public_id,omitempty"`
}

ObservationRef is the exclusive local/public identifier union for addressing an observation across storage namespaces. Exactly one namespace must be set; Validate enforces the XOR invariant.

func NewLocalObservationRef

func NewLocalObservationRef(id int64) (ObservationRef, error)

NewLocalObservationRef returns a validated local-namespace reference. The local identifier must be positive.

func NewPublicObservationRef

func NewPublicObservationRef(id uuid.UUID) (ObservationRef, error)

NewPublicObservationRef returns a validated public-namespace reference. The identifier must not be the nil UUID.

func (ObservationRef) Validate

func (r ObservationRef) Validate() error

Validate enforces the exclusive local/public ObservationRef union.

type ObservationRepository

type ObservationRepository interface {
	// Save creates a new observation or updates an existing one if it has a topic_key.
	Save(ctx context.Context, obs *Observation) error

	// GetByID retrieves an observation by its ID.
	GetByID(ctx context.Context, id int64) (*Observation, error)

	// GetByTopicKey retrieves an observation by its topic key within a project.
	// Returns ErrNotFound if no matching observation exists.
	GetByTopicKey(ctx context.Context, project, topicKey string) (*Observation, error)

	// Update modifies an existing observation.
	Update(ctx context.Context, obs *Observation) error

	// Delete removes an observation (soft delete by default).
	Delete(ctx context.Context, id int64) error

	// List retrieves observations based on filter criteria.
	List(ctx context.Context, filter ObservationFilter) ([]*Observation, error)

	// CountAll counts all observations in the system.
	CountAll(ctx context.Context) (int, error)

	// CountByRoot counts observations related to a root observation.
	CountByRoot(ctx context.Context, rootObsID int64) (int, error)

	// GetBySource retrieves observations filtered by source type.
	GetBySource(ctx context.Context, source string, limit int) ([]*Observation, error)

	// GetByType retrieves observations filtered by type.
	GetByType(ctx context.Context, obsType string, limit int) ([]*Observation, error)
}

ObservationRepository defines the interface for observation persistence operations. Implementations must handle CRUD operations and support filtering.

type ObservationWriteResult

type ObservationWriteResult struct {
	Ref    ObservationRef `json:"observation_ref"`
	Status WriteStatus    `json:"status"`
}

ObservationWriteResult is the transport-neutral outcome of executing a handoff: which observation namespace holds the payload and what kind of write materialized it.

type Principal

type Principal struct {
	Subject      string
	Type         string // user, service_account, agent
	OrgID        string
	WorkspaceIDs []string
	Roles        []string
	Scopes       []string
	AuthMethod   string // oidc, client_credentials, api_key, static
	GrantDigest  string
	GrantVersion int64
	// RateLimitTier is loaded from the verified credential record. Request
	// bodies and headers must never populate or override it.
	RateLimitTier string
	// ProjectIDs and ClassificationClearance are verified grants. They are
	// intentionally separate from OAuth scopes: a client supplied project
	// selector can never create either grant.
	ProjectIDs              []string
	ClassificationClearance []string
}

Principal is the immutable authenticated identity resolved from a token (REQ-ID-001). It is NEVER populated from client input — always from the verified credential (ADR-08).

func (Principal) ClassificationClearanceCopy

func (p Principal) ClassificationClearanceCopy() []string

func (Principal) ProjectsCopy

func (p Principal) ProjectsCopy() []string

func (Principal) RolesCopy

func (p Principal) RolesCopy() []string

RolesCopy returns a defensive copy of the role grants.

func (Principal) ScopesCopy

func (p Principal) ScopesCopy() []string

ScopesCopy returns a defensive copy of the granted scopes.

func (Principal) WorkspacesCopy

func (p Principal) WorkspacesCopy() []string

WorkspacesCopy returns a defensive copy of the workspace grants.

type ProjectArtifactItem

type ProjectArtifactItem struct {
	ID          string         `json:"id"`
	Kind        string         `json:"kind"` // "rule" or "skill"
	Key         string         `json:"key"`
	Title       string         `json:"title"`
	Description string         `json:"description,omitempty"`
	Content     string         `json:"content"`
	Scope       string         `json:"scope"` // "project" or "workspace_default"
	Project     string         `json:"project,omitempty"`
	Parameters  map[string]any `json:"parameters,omitempty"`
	Revision    int64          `json:"revision"`
	Status      string         `json:"status"` // "active" or "deleted"
	UpdatedAt   time.Time      `json:"updated_at"`
}

ProjectArtifactItem represents a rule or skill artifact row for administration.

type ProjectContext

type ProjectContext struct {
	Project      string                `json:"project"`
	SystemPrompt string                `json:"system_prompt"`
	Rules        []ProjectRule         `json:"rules"`
	Skills       []ProjectSkillSummary `json:"skills"`
}

ProjectContext aggregates corporate governance rules and available skills.

type ProjectDuplicateGroup

type ProjectDuplicateGroup struct {
	CanonicalName string   `json:"canonical_name"`
	Variants      []string `json:"variants"`
	TotalCount    int      `json:"total_count"`
}

ProjectDuplicateGroup represents a canonical project and its detected casing/similar variants.

type ProjectMergeResult

type ProjectMergeResult struct {
	SourceProject      string `json:"source_project"`
	TargetProject      string `json:"target_project"`
	ObservationsMerged int    `json:"observations_merged"`
	SessionsMerged     int    `json:"sessions_merged"`
	PromptsMerged      int    `json:"prompts_merged"`
}

ProjectMergeResult holds details about consolidated project records.

type ProjectProtocolStore

type ProjectProtocolStore interface {
	// SaveArtifact creates an artifact with its first revision. Input
	// validation (key, limits, canonical metadata, REQUIRED idempotency key)
	// is owned by projectprotocol.ValidateSaveArtifactInput; the store MUST
	// honor artifact-level idempotency (replay/conflict) via the input's
	// idempotency key and RequestDigest.
	SaveArtifact(ctx context.Context, in projectprotocol.SaveArtifactInput) (projectprotocol.Artifact, error)

	// SaveRevision appends an immutable revision under optimistic
	// concurrency (expected_revision or If-Match ETag). RevisionInput
	// carries a REQUIRED typed IdempotencyKey (REQ-ART-002): same
	// key+digest replays the original result, key reuse with a different
	// payload returns idempotency_conflict. A stale precondition returns
	// revision_conflict with zero effects.
	SaveRevision(ctx context.Context, artifactID string, in projectprotocol.RevisionInput, pre projectprotocol.Preconditions) (projectprotocol.Revision, error)

	// GetArtifact returns the artifact record, including soft-deleted ones
	// (authorized history remains readable; REQ-RET-002).
	GetArtifact(ctx context.Context, artifactID string) (projectprotocol.Artifact, error)

	// ListArtifacts returns a bounded, cursor-paginated artifact page
	// (REQ-PAGE-001): opaque snapshot-bound cursors, limit normalized by
	// PageRequest.Normalize (default 20, max 100).
	ListArtifacts(ctx context.Context, filter projectprotocol.ArtifactFilter, page projectprotocol.PageRequest) (projectprotocol.ArtifactPage, error)

	// ListRevisions returns a bounded, cursor-paginated revision history.
	ListRevisions(ctx context.Context, artifactID string, page projectprotocol.PageRequest) (projectprotocol.RevisionPage, error)

	// ListEvents returns a bounded, cursor-paginated audit-event history for
	// one artifact (activations, rollbacks, revision appends, soft delete).
	// Events are immutable and retained indefinitely, including for
	// soft-deleted artifacts (REQ-RET-001/002).
	ListEvents(ctx context.Context, artifactID string, page projectprotocol.PageRequest) (projectprotocol.ArtifactEventPage, error)

	// Activate points the artifact at one revision under activation CAS
	// (expected_activation_revision); stale tokens fail with
	// activation_conflict and leave exactly one active revision.
	Activate(ctx context.Context, in projectprotocol.ActivateInput) (projectprotocol.Activation, error)

	// Rollback repoints the activation at an earlier revision under
	// activation CAS, appending a new audited activation event.
	Rollback(ctx context.Context, in projectprotocol.RollbackInput) (projectprotocol.Activation, error)

	// SoftDelete marks the artifact deleted (actor, reason, time) and
	// excludes it from default lists and the effective protocol. The input
	// carries a REQUIRED If-Match ETag as the ONLY precondition form
	// (REQ-API-003: delete requires If-Match; there is no expected_revision
	// path for deletion): a stale ETag returns revision_conflict with zero
	// effects. DeletedBy and Reason are mandatory. The returned Artifact
	// carries the full delete provenance (deleted_at/deleted_by/
	// delete_reason) and a freshly derived canonical ETag. Revisions and
	// events are retained. This is the ONLY deletion transition in v1.
	SoftDelete(ctx context.Context, in projectprotocol.SoftDeleteInput) (projectprotocol.Artifact, error)

	// EffectiveProtocol resolves the deterministic effective protocol for a
	// project (project-over-workspace precedence), rejecting beyond
	// projectprotocol.MaxEffectiveArtifacts and
	// projectprotocol.MaxProtocolBundleBytes without partial results.
	EffectiveProtocol(ctx context.Context, project string) (projectprotocol.Protocol, error)
}

ProjectProtocolStore is the store-side port of the Project Context Protocol. All validation limits and canonical forms live in the projectprotocol package so local, HTTP and MCP paths cannot diverge.

type ProjectRule

type ProjectRule struct {
	Key     string `json:"key"`
	Title   string `json:"title"`
	Content string `json:"content"`
	Scope   string `json:"scope"` // "project" or "workspace_default"
}

ProjectRule represents a corporate or project governance rule / system prompt.

type ProjectSkill

type ProjectSkill struct {
	ID          string         `json:"id"`
	Key         string         `json:"key"`
	Title       string         `json:"title"`
	Description string         `json:"description"`
	Content     string         `json:"content"`
	Scope       string         `json:"scope"`
	Project     string         `json:"project,omitempty"`
	Parameters  map[string]any `json:"parameters,omitempty"`
	Revision    int64          `json:"revision"`
	UpdatedAt   time.Time      `json:"updated_at"`
}

ProjectSkill represents a specialized workflow, guideline or skill.

type ProjectSkillSummary

type ProjectSkillSummary struct {
	Key         string `json:"key"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Scope       string `json:"scope"`
	Project     string `json:"project,omitempty"`
}

ProjectSkillSummary is a lightweight overview of an available skill.

type Prompt

type Prompt struct {
	ID        int64     `json:"id"`
	PublicID  string    `json:"-"`
	Content   string    `json:"content"`
	Project   string    `json:"project"`
	SessionID string    `json:"session_id"`
	CreatedAt time.Time `json:"created_at"`
}

Prompt represents a user prompt captured during a session for replay and context understanding.

func (Prompt) MarshalJSON

func (p Prompt) MarshalJSON() ([]byte, error)

type PromptRepository

type PromptRepository interface {
	// Save stores a user prompt for later retrieval.
	Save(ctx context.Context, prompt *Prompt) error

	// List retrieves recent prompts for a project.
	List(ctx context.Context, project string, limit int) ([]*Prompt, error)
}

PromptRepository defines the interface for user prompt storage.

type QualityMetrics

type QualityMetrics struct {
	ID                   int64     `json:"id"`
	SessionID            string    `json:"session_id"`
	EvaluationType       string    `json:"evaluation_type"`       // relevance, completeness, consistency, temporal_accuracy
	Score                float64   `json:"score"`                 // Score 0.0-1.0
	TotalQueries         int       `json:"total_queries"`         // Number of queries evaluated
	SuccessfulRetrievals int       `json:"successful_retrievals"` // Number of successful retrievals
	AverageLatency       float64   `json:"average_latency_ms"`    // Average response time
	AverageRelevance     float64   `json:"average_relevance"`     // Average relevance score
	TemporalAccuracy     float64   `json:"temporal_accuracy"`     // How well temporal facts are preserved
	KnowledgeCoverage    float64   `json:"knowledge_coverage"`    // How much relevant knowledge is covered
	EvaluatedAt          time.Time `json:"evaluated_at"`
}

QualityMetrics represents memory quality evaluation metrics.

type QualityMetricsRepository

type QualityMetricsRepository interface {
	// CreateQualityMetric records a quality evaluation result.
	CreateQualityMetric(ctx context.Context, quality *QualityMetrics) error

	// GetBySession retrieves quality metrics for a session.
	GetBySession(ctx context.Context, sessionID string, limit int) ([]*QualityMetrics, error)

	// GetByType retrieves quality metrics filtered by evaluation type.
	GetByType(ctx context.Context, evaluationType string, from, to time.Time) ([]*QualityMetrics, error)

	// GetLatest gets the most recent quality metrics.
	GetLatest(ctx context.Context, limit int) ([]*QualityMetrics, error)
}

QualityMetricsRepository defines the interface for quality evaluation.

type RAGStats added in v2.3.0

type RAGStats struct {
	Project             string  `json:"project"`
	TotalObservations   int     `json:"total_observations"`
	IndexedObservations int     `json:"indexed_observations"`
	PendingObservations int     `json:"pending_observations"`
	FailedObservations  int     `json:"failed_observations"`
	CoveragePct         float64 `json:"coverage_pct"`
	EmbeddingModel      string  `json:"embedding_model"`
	EmbeddingDim        int     `json:"embedding_dimensions"`
	VectorProvider      string  `json:"vector_provider"`
}

RAGStats encapsulates the indexing coverage and vector pipeline metrics for a project or workspace.

type SaveEffect

type SaveEffect struct {
	Observation *Observation `json:"observation"`
	Status      WriteStatus  `json:"status"`
}

SaveEffect reports the durable effect of a transactional observation save. Observation is nil only when the save did not commit; a non-nil value is the committed aggregate, never a speculation read back after the fact.

type SaveObservationInput

type SaveObservationInput struct {
	Title      string   `json:"title"`
	Content    string   `json:"content"`
	Type       string   `json:"type"`
	Project    string   `json:"project"`
	Scope      string   `json:"scope"`
	SessionID  string   `json:"session_id"`
	TopicKey   string   `json:"topic_key"`
	Confidence float64  `json:"confidence"`
	Source     string   `json:"source"`
	Tags       []string `json:"tags,omitempty"`
}

SaveObservationInput is the transport-neutral observation portion of a handoff. Derived identifiers and timestamps are deliberately excluded.

type SaveProjectArtifactInput

type SaveProjectArtifactInput struct {
	Kind        string         `json:"kind"` // "rule" or "skill"
	Key         string         `json:"key"`
	Title       string         `json:"title"`
	Description string         `json:"description,omitempty"`
	Content     string         `json:"content"`
	Scope       string         `json:"scope"` // "project" or "workspace_default"
	Project     string         `json:"project,omitempty"`
	Parameters  map[string]any `json:"parameters,omitempty"`
}

SaveProjectArtifactInput is the input for creating or updating a project artifact.

type ScoringRepository

type ScoringRepository interface {
	// GetScore retrieves the importance score for an observation.
	GetScore(ctx context.Context, obsID int64) (*ImportanceScore, error)

	// UpdateScore adjusts the importance score for an observation.
	// The increment can be positive (increase importance) or negative.
	UpdateScore(ctx context.Context, obsID int64, increment float64) error

	// GetTop retrieves the most important observations for a project.
	GetTop(ctx context.Context, project string, limit int) ([]*ImportanceScore, error)
}

ScoringRepository defines the interface for importance scoring operations. This enables adaptive relevance ranking based on usage patterns.

type SearchID

type SearchID string

SearchID is a request/session-scoped identifier for retrieval feedback attribution (REQ-RET-001). Replaces the removed shared mutable search-query field.

type SearchOptions

type SearchOptions struct {
	Query       string     `json:"query"`
	Type        string     `json:"type,omitempty"`
	Project     string     `json:"project,omitempty"`
	Scope       string     `json:"scope,omitempty"`
	Limit       int        `json:"limit,omitempty"`
	FusionK     float64    `json:"fusion_k,omitempty"`     // RRF constant (default 60, lower = favor top ranks)
	GraphExpand bool       `json:"graph_expand,omitempty"` // Boost graph neighbors of top results
	AsOf        *time.Time `json:"as_of,omitempty"`        // Temporal point-in-time filter for graph expansion
	// Cursor is an opaque pagination cursor (REQ-RET-002). When set, the search
	// store resumes AFTER the encoded resume point. The cursor is bound to the
	// active filter context (query+project+scope+type+local identity); a cursor
	// from a different context is rejected and treated as a fresh page 0. This is
	// a storage-layer seam; the MCP/HTTP envelope is unified in W6. Local-mode
	// only: no tenant/principal/grant binding yet (W11/W13).
	Cursor string `json:"cursor,omitempty"`
}

SearchOptions provides options for full-text search queries.

type SearchRepository

type SearchRepository interface {
	// Search performs a full-text search with optional filters.
	Search(ctx context.Context, query string, opts SearchOptions) ([]*SearchResult, error)
}

SearchRepository defines the interface for full-text search operations. Implementations should use FTS5 or similar for efficient text search.

type SearchResult

type SearchResult struct {
	Observation
	Rank           float64              `json:"rank"` // Relevance score from FTS
	ScoreBreakdown SearchScoreBreakdown `json:"score_breakdown,omitempty"`
	// SearchID is the request-scoped identifier of the search that produced this
	// result (REQ-RET-001). Feedback references this ID so attribution binds to
	// the originating search, not a shared global. It replaces the removed shared
	// mutable search-query field on the Stores bundle.
	SearchID SearchID `json:"search_id,omitempty"`
	// NextCursor is the opaque cursor for the following page. It is set ONLY on
	// the LAST result of a page when more results may exist; absent otherwise.
	// It is a storage-layer seam (REQ-RET-002): the unified response envelope at
	// the MCP/HTTP layer is introduced in W6. Opaque + context-bound, never a
	// secret.
	NextCursor string `json:"next_cursor,omitempty"`
}

SearchResult represents a search result with relevance ranking.

func (SearchResult) MarshalJSON

func (s SearchResult) MarshalJSON() ([]byte, error)

type SearchScoreBreakdown

type SearchScoreBreakdown struct {
	Strategy       string  `json:"strategy,omitempty"`         // keyword, topic_key, hybrid
	TopicKeyExact  bool    `json:"topic_key_exact,omitempty"`  // exact topic key hit
	TopicKeyExpand bool    `json:"topic_key_expand,omitempty"` // topic key expansion (LIKE match)
	KeywordBM25    float64 `json:"keyword_bm25,omitempty"`     // raw BM25 score for keyword search
	FusionScore    float64 `json:"fusion_score,omitempty"`     // RRF score for hybrid search
	RecencyBoost   float64 `json:"recency_boost,omitempty"`    // recency decay multiplier (0-1)
	ImportanceRank float64 `json:"importance_rank,omitempty"`  // importance score contribution
}

SearchScoreBreakdown explains which retrieval path produced a result.

type ServerStats

type ServerStats struct {
	Observations   int `json:"observations"`
	Sessions       int `json:"sessions"`
	ActiveSessions int `json:"active_sessions"`
	Edges          int `json:"edges"`
	Projects       int `json:"projects"`
}

ServerStats contains tenant/workspace-scoped counters for the server dashboard.

type Session

type Session struct {
	ID        string     `json:"id"`
	Project   string     `json:"project"`
	Directory string     `json:"directory"`
	StartedAt time.Time  `json:"started_at"`
	EndedAt   *time.Time `json:"ended_at,omitempty"`
	Summary   string     `json:"summary,omitempty"`
}

Session represents a coding session that groups related observations. Sessions track when work started and ended, along with an optional summary.

type SessionRepository

type SessionRepository interface {
	// Create starts a new coding session.
	Create(ctx context.Context, session *Session) error

	// GetByID retrieves a session by its ID.
	GetByID(ctx context.Context, id string) (*Session, error)

	// End marks a session as completed with an optional summary.
	End(ctx context.Context, id string, summary string) error

	// List retrieves sessions for a project, ordered by most recent first.
	List(ctx context.Context, project string) ([]*Session, error)
}

SessionRepository defines the interface for session lifecycle management.

type Storage

type Storage interface {
	// Backend returns the backend identifier: "sqlite" or "postgres".
	Backend() string
	// BeginTx starts a new transaction.
	BeginTx(ctx context.Context) (Tx, error)
	// Health reports the current backend health status.
	Health(ctx context.Context) Health
}

Storage is the narrow port every backend (SQLite, Postgres) implements. It provides backend identification, transaction initiation, and health.

type SyncBatch

type SyncBatch struct {
	Sessions      []SyncSession      `json:"sessions,omitempty"`
	Observations  []SyncObservation  `json:"observations,omitempty"`
	Prompts       []SyncPrompt       `json:"prompts,omitempty"`
	Edges         []SyncEdge         `json:"edges,omitempty"`
	CodeSymbols   []SyncCodeSymbol   `json:"code_symbols,omitempty"`
	CodeRelations []SyncCodeRelation `json:"code_relations,omitempty"`
}

SyncBatch is the transport-neutral replication unit. SyncID is generated by the originating client and remains stable across retries and devices.

type SyncCodeRelation added in v2.3.0

type SyncCodeRelation struct {
	ID         int64     `json:"id,omitempty"`
	Project    string    `json:"project"`
	SourceID   string    `json:"source_id"`
	TargetID   string    `json:"target_id"`
	Relation   string    `json:"relation"`
	Confidence float64   `json:"confidence"`
	Reasoning  string    `json:"reasoning,omitempty"`
	CreatedAt  time.Time `json:"created_at"`
	Deleted    bool      `json:"deleted,omitempty"`
}

type SyncCodeSymbol added in v2.3.0

type SyncCodeSymbol struct {
	ID          string         `json:"id"`
	Project     string         `json:"project"`
	FilePath    string         `json:"file_path"`
	LineNumber  int            `json:"line_number"`
	EndLine     int            `json:"end_line"`
	StartCol    int            `json:"start_col,omitempty"`
	EndCol      int            `json:"end_col,omitempty"`
	Kind        string         `json:"kind"`
	Name        string         `json:"name"`
	PackageName string         `json:"package_name,omitempty"`
	ParentID    string         `json:"parent_id,omitempty"`
	Visibility  string         `json:"visibility,omitempty"`
	Signature   string         `json:"signature,omitempty"`
	DocSummary  string         `json:"doc_summary,omitempty"`
	Parameters  map[string]any `json:"parameters,omitempty"`
	ReturnType  string         `json:"return_type,omitempty"`
	Complexity  int            `json:"complexity,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
	FileHash    string         `json:"file_hash,omitempty"`
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
	Deleted     bool           `json:"deleted,omitempty"`
}

type SyncEdge

type SyncEdge struct {
	SyncID     string     `json:"sync_id"`
	FromSyncID string     `json:"from_sync_id"`
	ToSyncID   string     `json:"to_sync_id"`
	Relation   string     `json:"relation_type"`
	Weight     float64    `json:"weight"`
	Confidence float64    `json:"confidence"`
	Source     string     `json:"source,omitempty"`
	Reasoning  string     `json:"reasoning,omitempty"`
	ValidFrom  *time.Time `json:"valid_from,omitempty"`
	ValidUntil *time.Time `json:"valid_until,omitempty"`
	CreatedAt  time.Time  `json:"created_at"`
	UpdatedAt  time.Time  `json:"updated_at"`
	Deleted    bool       `json:"deleted,omitempty"`
}

type SyncObservation

type SyncObservation struct {
	SyncID        string    `json:"sync_id"`
	SessionSyncID string    `json:"session_sync_id"`
	Title         string    `json:"title"`
	Content       string    `json:"content"`
	Type          string    `json:"type"`
	Project       string    `json:"project"`
	Scope         string    `json:"scope"`
	TopicKey      string    `json:"topic_key,omitempty"`
	Confidence    float64   `json:"confidence"`
	Source        string    `json:"source"`
	Tags          []string  `json:"tags,omitempty"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	Deleted       bool      `json:"deleted,omitempty"`
}

type SyncPage

type SyncPage struct {
	SyncBatch
	Cursor  int64 `json:"cursor"`
	HasMore bool  `json:"has_more"`
}

type SyncPrompt

type SyncPrompt struct {
	SyncID        string    `json:"sync_id"`
	SessionSyncID string    `json:"session_sync_id"`
	Content       string    `json:"content"`
	Project       string    `json:"project"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	Deleted       bool      `json:"deleted,omitempty"`
}

type SyncResult

type SyncResult struct {
	Accepted int `json:"accepted"`
}

type SyncSession

type SyncSession struct {
	SyncID    string     `json:"sync_id"`
	Project   string     `json:"project"`
	Directory string     `json:"directory,omitempty"`
	StartedAt time.Time  `json:"started_at"`
	EndedAt   *time.Time `json:"ended_at,omitempty"`
	Summary   string     `json:"summary,omitempty"`
	UpdatedAt time.Time  `json:"updated_at"`
	Deleted   bool       `json:"deleted,omitempty"`
}

type SystemMetrics

type SystemMetrics struct {
	SessionID          string         `json:"session_id"`
	TimeRange          *TimeRange     `json:"time_range"`
	TotalOperations    int            `json:"total_operations"`
	SuccessfulOps      int            `json:"successful_ops"`
	FailedOps          int            `json:"failed_ops"`
	AvgDurationMs      float64        `json:"avg_duration_ms"`
	TotalMemoryUsage   int64          `json:"total_memory_usage"`
	TotalObservations  int            `json:"total_observations"`
	TotalEdges         int            `json:"total_edges"`
	AvgQueryComplexity float64        `json:"avg_query_complexity"`
	AvgConfidence      float64        `json:"avg_confidence"`
	EvaluatedAt        time.Time      `json:"evaluated_at"`
	OperationBreakdown map[string]int `json:"operation_breakdown"`
	TopSlowOperations  []string       `json:"top_slow_operations"`
}

SystemMetrics represents aggregated system metrics.

type TemporalSnapshot

type TemporalSnapshot struct {
	ID                int64     `json:"id"`
	SnapshotKey       string    `json:"snapshot_key"` // Unique identifier for this snapshot
	Timestamp         time.Time `json:"timestamp"`
	Description       string    `json:"description,omitempty"`
	ObservationCount  int       `json:"observation_count"`
	EdgeCount         int       `json:"edge_count"`
	RootObservationID int64     `json:"root_observation_id,omitempty"` // Root observation for this snapshot
}

TemporalSnapshot represents a point-in-time snapshot of the knowledge graph.

type TemporalSnapshotRepository

type TemporalSnapshotRepository interface {
	// CreateSnapshot creates a point-in-time snapshot of the knowledge graph.
	CreateSnapshot(ctx context.Context, snapshot *TemporalSnapshot) error

	// GetByID retrieves a snapshot by its ID.
	GetByID(ctx context.Context, id int64) (*TemporalSnapshot, error)

	// GetBySnapshotKey retrieves snapshots by their key.
	GetBySnapshotKey(ctx context.Context, snapshotKey string) ([]*TemporalSnapshot, error)

	// GetSnapshotsInRange retrieves snapshots within a time range.
	GetSnapshotsInRange(ctx context.Context, from, to time.Time) ([]*TemporalSnapshot, error)

	// GetByRootObservation retrieves snapshots for a root observation.
	GetByRootObservation(ctx context.Context, rootObsID int64) ([]*TemporalSnapshot, error)
}

TemporalSnapshotRepository defines the interface for temporal snapshots.

type TenantContext

type TenantContext struct {
	TenantID     string
	WorkspaceID  string
	OwnerSubject string
}

TenantContext carries the resolved tenant/workspace/owner for a request. In local mode this is nil; in server mode it is resolved from the authenticated Principal (NEVER from client input — ADR-06/ADR-07).

type TimeRange

type TimeRange struct {
	From time.Time `json:"from"`
	To   time.Time `json:"to"`
}

TimeRange represents a time range with start and end.

type Tx

type Tx interface {
	Commit() error
	Rollback() error
	// Handle returns the backend-specific transaction handle.
	// For SQLite this is *sql.Tx; for Postgres it is pgx.Tx.
	// The `any` return type is intentional: it keeps domain free of any
	// backend import (database/sql, pgx) so the port compiles in both
	// local-only and server builds without build tags.
	Handle() any
}

Tx abstracts a backend transaction. The concrete handle is exposed via Handle() so TxParticipant implementations can enlist in it.

type TxParticipant

type TxParticipant interface {
	// WithinTx enlists this participant in the given transaction handle and
	// runs fn within it. handle is the value returned by Tx.Handle().
	WithinTx(ctx context.Context, handle any, fn func(context.Context) error) error
}

TxParticipant enlists a store or service in a shared transaction. Each participant runs its work via WithinTx using the same handle.

type UnitOfWork

type UnitOfWork interface {
	// Do runs fn with all participants sharing ONE logical transaction.
	// On any participant failure, all prior work is rolled back (REQ-TX-001).
	// On SQLITE_BUSY, Do retries up to BusyRetryConfig.MaxRetries with capped
	// backoff before returning a stable retryable error (REQ-TX-002).
	Do(ctx context.Context, tctx *TenantContext, participants []TxParticipant, fn func(context.Context) error) error
}

UnitOfWork coordinates multiple TxParticipants within one logical transaction, ensuring atomic cross-store saves (ADR-02, REQ-TX-001).

type ValidationError

type ValidationError struct {
	// Legacy field-validation field (unchanged behavior).
	Field string

	// Passive-outcome classification fields (REQ-FOUND-003). Code is "" for
	// legacy field-validation errors, so legacy and classification modes never
	// collide.
	Code    string // ClassDedupSkipped | ClassRejected | ClassFailed
	Rule    string // violated rule name (set for ClassRejected)
	Cause   error  // wrapped real error (set for ClassFailed)
	Message string // human-readable message (shared by legacy and classification)
}

ValidationError classifies a passive-type outcome so callers can distinguish an intentional dedup skip (ClassDedupSkipped) from a policy rejection (ClassRejected) from a real persistence failure (ClassFailed).

This type is ALSO the legacy field-validation error: when Code is empty and Field is set, it preserves the original field-level validation semantics so every existing caller is unaffected (zero local-mode behavior change). The classification fields (Code, Rule, Cause) are only populated by the NewDedupSkipped / NewRejected / NewFailed constructors.

W1 stub: the type and classification codes are defined here; wiring into the dedup/save path lands in W6.2 (REQ-MCPH-002).

func NewDedupSkipped

func NewDedupSkipped(message string) *ValidationError

NewDedupSkipped constructs a ValidationError marking a duplicate observation that was intentionally skipped (ClassDedupSkipped; IsError is false).

func NewFailed

func NewFailed(cause error, message string) *ValidationError

NewFailed constructs a ValidationError wrapping a real persistence failure (ClassFailed). The cause is inspectable via errors.Unwrap / errors.Is.

func NewRejected

func NewRejected(rule, message string) *ValidationError

NewRejected constructs a ValidationError marking a policy rejection for the given rule. No partial row is written for a rejected observation.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Error renders the validation error. For legacy field-validation (empty Code) it preserves the original format byte-for-byte. For passive-outcome classification it renders "code: message (rule: <rule>): cause".

func (*ValidationError) Unwrap

func (e *ValidationError) Unwrap() error

Unwrap returns the wrapped cause for a classified failure (ClassFailed). For legacy field-validation errors and code-only classifications (no Cause) it preserves the original ErrInvalidInput chain so errors.Is(err, ErrInvalidInput) keeps working unchanged.

type VectorCandidate

type VectorCandidate struct {
	ID         int64
	Score      float64
	Provenance string // adapter that produced this candidate
}

VectorCandidate is a single search result from a VectorIndex.

type VectorIndex

type VectorIndex interface {
	ID() string
	Upsert(ctx context.Context, points []VectorPoint) error
	Search(ctx context.Context, q VectorQuery) ([]VectorCandidate, error)
	Delete(ctx context.Context, ids []int64) error
	Health(ctx context.Context) Health
	Capabilities(ctx context.Context) (Capabilities, error)
	Close() error
}

VectorIndex abstracts vector storage backends (sqlite_blob, qdrant, pgvector). Each adapter declares Capabilities for strategy selection (ADR-05, REQ-VEC-001).

type VectorPoint

type VectorPoint struct {
	ID        int64
	Vector    []float32
	ModelInfo ModelInfo
	Metadata  map[string]any
}

VectorPoint is a single vector to upsert into a VectorIndex.

type VectorQuery

type VectorQuery struct {
	Vector    []float32
	Limit     int
	Threshold float64
	Filters   map[string]any
	Namespace string
}

VectorQuery is a similarity search request against a VectorIndex.

type VectorRepository

type VectorRepository interface {
	// StoreEmbedding stores an embedding vector for an observation.
	// The embedding dimensions must be between 64 and 4096.
	// Returns an error if the observation doesn't exist or embedding dimension is wrong.
	StoreEmbedding(ctx context.Context, observationID int64, embedding []float32, model string) error

	// SearchByVector performs a similarity search using the query embedding.
	// Returns results sorted by cosine similarity (descending).
	// Returns ErrVectorSearchDisabled if vector search is not available.
	SearchByVector(ctx context.Context, opts VectorSearchOptions) ([]*VectorSearchResult, error)

	// GetEmbedding retrieves the embedding for an observation.
	// Returns ErrNotFound if no embedding exists for the observation.
	GetEmbedding(ctx context.Context, observationID int64) ([]float32, string, error)

	// DeleteEmbedding removes the embedding for an observation.
	DeleteEmbedding(ctx context.Context, observationID int64) error

	// IsAvailable returns true if vector search is enabled and available.
	IsAvailable() bool
}

VectorRepository defines the interface for vector similarity search operations. This enables semantic search using embeddings with cosine distance.

Note: This is an optional feature that requires the "cortex_vectors" build tag. When not enabled, all methods return ErrVectorSearchDisabled.

type VectorSearchOptions

type VectorSearchOptions struct {
	// Embedding is the query embedding vector (64-4096 dimensions depending on model).
	Embedding []float32
	// Limit is the maximum number of results to return.
	Limit int
	// Threshold is the minimum similarity score (0.0 to 1.0).
	// Results with similarity below this threshold are excluded.
	Threshold float64
	// Project filters results to a specific project (optional).
	Project string
	// Scope filters results to a specific scope (optional).
	Scope string
}

VectorSearchOptions provides options for vector similarity search.

type VectorSearchResult

type VectorSearchResult struct {
	Observation
	Similarity float64 `json:"similarity"` // Cosine similarity score (0.0 to 1.0)
}

VectorSearchResult represents a vector search result with similarity score.

type WriteStatus

type WriteStatus string

WriteStatus classifies the durable effect of an observation write relative to previously persisted state. The set is closed: created, replayed, updated.

const (
	// WriteStatusCreated marks the first durable materialization.
	WriteStatusCreated WriteStatus = "created"
	// WriteStatusReplayed marks an idempotent replay of an identical write.
	WriteStatusReplayed WriteStatus = "replayed"
	// WriteStatusUpdated marks an in-place update of an existing observation.
	WriteStatusUpdated WriteStatus = "updated"
)

Directories

Path Synopsis
Package agent implements the transport-neutral, read-only conversational RAG domain.
Package agent implements the transport-neutral, read-only conversational RAG domain.
Package ast provides zero-CGO static code analysis, rich symbol extraction, and cross-file call graph resolution for Go, TypeScript/JavaScript, Python, Rust, SQL, and polyglot codebases.
Package ast provides zero-CGO static code analysis, rich symbol extraction, and cross-file call graph resolution for Go, TypeScript/JavaScript, Python, Rust, SQL, and polyglot codebases.
Package code defines domain entities, ports, and analytics for static code graphs, symbol indexes, and architectural insights.
Package code defines domain entities, ports, and analytics for static code graphs, symbol indexes, and architectural insights.
Package dna generates Project DNA — a structured summary of a project's key decisions, patterns, tech stack, and gotchas extracted from observations.
Package dna generates Project DNA — a structured summary of a project's key decisions, patterns, tech stack, and gotchas extracted from observations.
Package entity implements entity extraction and linking for Cortex.
Package entity implements entity extraction and linking for Cortex.
Package extraction provides automated extraction and synthesis of observations, entities, and knowledge-graph relationships from raw text, code notes, and session logs.
Package extraction provides automated extraction and synthesis of observations, entities, and knowledge-graph relationships from raw text, code notes, and session logs.
Package graph provides graph analytics, clustering, and structural code intelligence algorithms inspired by Graphify, ported natively to Go with zero-CGO.
Package graph provides graph analytics, clustering, and structural code intelligence algorithms inspired by Graphify, ported natively to Go with zero-CGO.
Package lifecycle implements auto-archival and lifecycle management for Cortex.
Package lifecycle implements auto-archival and lifecycle management for Cortex.
Package memory provides the business logic layer for observation management.
Package memory provides the business logic layer for observation management.
Package observability provides metrics and quality evaluation for the Cortex memory system.
Package observability provides metrics and quality evaluation for the Cortex memory system.
Package projectprotocol defines the Project Context Protocol domain contract: skill and rule artifacts, immutable revisions, activation compare-and-swap (CAS) pointers, idempotency DTOs, canonical hashing and the deterministic effective protocol resolution with its approved limits.
Package projectprotocol defines the Project Context Protocol domain contract: skill and rule artifacts, immutable revisions, activation compare-and-swap (CAS) pointers, idempotency DTOs, canonical hashing and the deterministic effective protocol resolution with its approved limits.
Package scoring implements the importance scoring business logic for Cortex.
Package scoring implements the importance scoring business logic for Cortex.
Package search provides FTS5-based full-text search business logic for Cortex.
Package search provides FTS5-based full-text search business logic for Cortex.
Package session provides business logic for session management.
Package session provides business logic for session management.
Package temporal provides temporal graph semantics and evolution tracking for the knowledge graph in Cortex.
Package temporal provides temporal graph semantics and evolution tracking for the knowledge graph in Cortex.

Jump to

Keyboard shortcuts

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