gorm

package
v1.7.2 Latest Latest
Warning

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

Go to latest
Published: Mar 25, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package gorm provides GORM-based database operations for engram.

Package gorm provides a GORM-based database implementation for engram.

Uses PostgreSQL 17 + pgvector for persistent storage with:

  • Type-safe query building via GORM
  • Automatic statement caching
  • Auto-migrations for schema management

Usage

import "github.com/thebtf/engram/internal/db/gorm"

store, err := gorm.NewStore(gorm.Config{...})

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database stores for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database stores for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Package gorm provides GORM-based database operations for engram.

Index

Constants

View Source
const (
	// DefaultQueryTimeout is the default timeout for regular queries.
	DefaultQueryTimeout = 5 * time.Second
	// FastQueryTimeout is for queries that should be very fast (health checks, etc).
	FastQueryTimeout = 1 * time.Second
	// SlowQueryTimeout is for queries that may take longer (bulk operations, rebuilds).
	SlowQueryTimeout = 30 * time.Second
)

QueryTimeout constants for different query types.

View Source
const MaxObservationsPerProject = 100

MaxObservationsPerProject is the maximum number of observations to keep per project.

View Source
const MaxPaginationLimit = 1000

MaxPaginationLimit is the maximum allowed limit for pagination queries. This protects against resource exhaustion from excessively large requests.

View Source
const MaxPromptsGlobal = 500

MaxPromptsGlobal is the hard limit of prompts across all projects.

View Source
const SupersededRetentionDays = 3

SupersededRetentionDays is the number of days to keep superseded observations before deletion.

Variables

This section is empty.

Functions

func EnsureSessionExists

func EnsureSessionExists(ctx context.Context, db *gorm.DB, sdkSessionID, project string) error

EnsureSessionExists creates a session if it doesn't exist. Uses INSERT OR IGNORE pattern for atomic idempotent creation (single query instead of COUNT + INSERT). This is shared between stores to avoid duplication.

func ParseLimitParam

func ParseLimitParam(r *http.Request, defaultLimit int) int

ParseLimitParam parses the "limit" query parameter from an HTTP request. Returns defaultLimit if the parameter is missing or invalid. Note: This does NOT enforce a maximum limit. Use ParseLimitParamWithMax for that.

func ParseLimitParamWithMax

func ParseLimitParamWithMax(r *http.Request, defaultLimit, maxLimit int) int

ParseLimitParamWithMax parses the "limit" query parameter with a maximum cap. Returns min(parsed, maxLimit) or defaultLimit if missing/invalid. If maxLimit is 0, uses MaxPaginationLimit (1000).

func ParseOffsetParam

func ParseOffsetParam(r *http.Request) int

ParseOffsetParam parses the "offset" query parameter from an HTTP request. Returns 0 if the parameter is missing or invalid.

func ResolveProjectID added in v0.4.0

func ResolveProjectID(ctx context.Context, db *gorm.DB, projectID string) string

ResolveProjectID checks if projectID is a legacy alias in the projects table. Returns the canonical project ID when a matching alias is found, otherwise returns the input projectID unchanged.

func ToModelObservation added in v1.7.0

func ToModelObservation(o *Observation) *models.Observation

ToModelObservation converts a GORM Observation to pkg/models.Observation. This exported wrapper allows packages outside the gorm package to perform the conversion without directly importing the private toModelObservation function.

func ToModelRelations added in v1.7.0

func ToModelRelations(relations []ObservationRelation) []*models.ObservationRelation

ToModelRelations converts a slice of GORM ObservationRelation to pkg/models.ObservationRelation. This exported wrapper is provided for use by maintenance and other packages that need to convert raw GORM rows without going through RelationStore methods.

func UpsertProject added in v0.4.0

func UpsertProject(ctx context.Context, db *gorm.DB, newID, legacyID, gitRemote, relativePath, displayName string) error

UpsertProject registers or updates a project identity record.

newID is the canonical git-remote-based project ID. legacyID is the old path-based ID (may be empty on first git-based registration). gitRemote and relativePath are the git metadata used to derive newID. displayName is the human-readable project name (typically the directory name).

When legacyID is non-empty, this function:

  1. Upserts the project row (idempotent by primary key).
  2. Appends legacyID to legacy_ids if not already present.
  3. Launches a background goroutine to re-associate observations from legacyID to newID.

Types

type APIToken added in v1.0.0

type APIToken struct {
	ID           string     `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"`
	Name         string     `gorm:"type:text;not null;uniqueIndex"`
	TokenHash    string     `gorm:"type:text;not null"`
	TokenPrefix  string     `gorm:"type:text;not null;index"`
	Scope        string     `gorm:"type:text;not null;default:read-write"`
	CreatedAt    time.Time  `gorm:"not null;default:now()"`
	LastUsedAt   *time.Time `gorm:"column:last_used_at"`
	RequestCount int64      `gorm:"not null;default:0"`
	ErrorCount   int64      `gorm:"not null;default:0"`
	Revoked      bool       `gorm:"not null;default:false"`
	RevokedAt    *time.Time `gorm:"column:revoked_at"`
}

APIToken represents a client API token for agent authentication. Tokens are stored as bcrypt hashes with a prefix for fast lookup.

func (APIToken) TableName added in v1.0.0

func (APIToken) TableName() string

type AggregatedRetrievalStats added in v1.2.0

type AggregatedRetrievalStats struct {
	TotalRequests      int64 `json:"total_requests"`
	ObservationsServed int64 `json:"observations_served"`
	SearchRequests     int64 `json:"search_requests"`
	ContextInjections  int64 `json:"context_injections"`
	StaleExcluded      int64 `json:"stale_excluded"`
	FreshCount         int64 `json:"fresh_count"`
	DuplicatesRemoved  int64 `json:"duplicates_removed"`
}

AggregatedRetrievalStats contains aggregated retrieval metrics from the DB.

type ArchivalStats

type ArchivalStats struct {
	TotalCount          int64 `json:"total_count"`
	ActiveCount         int64 `json:"active_count"`
	ArchivedCount       int64 `json:"archived_count"`
	OldestArchivedEpoch int64 `json:"oldest_archived_epoch,omitempty"`
	NewestArchivedEpoch int64 `json:"newest_archived_epoch,omitempty"`
}

ArchivalStats contains statistics about archived observations.

type CleanupFunc

type CleanupFunc func(ctx context.Context, deletedIDs []int64)

CleanupFunc is a callback for when observations are cleaned up. Receives the IDs of deleted observations for downstream cleanup (e.g., vector DB).

type ConceptWeight

type ConceptWeight struct {
	Concept   string  `gorm:"primaryKey;type:text"`
	UpdatedAt string  `gorm:"not null"`
	Weight    float64 `gorm:"type:real;not null;default:0.1"`
}

ConceptWeight stores configurable weights for importance scoring.

func (*ConceptWeight) BeforeCreate

func (c *ConceptWeight) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamp is set.

func (ConceptWeight) TableName

func (ConceptWeight) TableName() string

type Config

type Config struct {
	DSN      string          // PostgreSQL DSN (e.g. postgres://user:pass@host/db)
	MaxConns int             // Maximum number of open connections (default: 10)
	LogLevel logger.LogLevel // GORM log level (logger.Silent for production)
}

Config holds database configuration.

type ConflictStore

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

ConflictStore provides conflict-related database operations using GORM.

func NewConflictStore

func NewConflictStore(store *Store) *ConflictStore

NewConflictStore creates a new conflict store.

func (*ConflictStore) CleanupSupersededObservations

func (s *ConflictStore) CleanupSupersededObservations(ctx context.Context, project string) ([]int64, error)

CleanupSupersededObservations deletes observations that have been superseded for longer than SupersededRetentionDays. Returns the IDs of deleted observations for downstream cleanup (e.g., vector DB).

func (*ConflictStore) DeleteConflictsByObservationID

func (s *ConflictStore) DeleteConflictsByObservationID(ctx context.Context, obsID int64) error

DeleteConflictsByObservationID deletes all conflicts involving an observation. Called when an observation is deleted.

func (*ConflictStore) GetConflictsByObservationID

func (s *ConflictStore) GetConflictsByObservationID(ctx context.Context, obsID int64) ([]*models.ObservationConflict, error)

GetConflictsByObservationID retrieves all conflicts involving an observation.

func (*ConflictStore) GetConflictsWithDetails

func (s *ConflictStore) GetConflictsWithDetails(ctx context.Context, project string, limit int) ([]*ConflictWithDetails, error)

GetConflictsWithDetails retrieves all conflicts with observation titles for display.

func (*ConflictStore) GetSupersededObservationIDs

func (s *ConflictStore) GetSupersededObservationIDs(ctx context.Context, project string) ([]int64, error)

GetSupersededObservationIDs returns IDs of all observations that have been superseded.

func (*ConflictStore) GetUnresolvedConflicts

func (s *ConflictStore) GetUnresolvedConflicts(ctx context.Context, limit int) ([]*models.ObservationConflict, error)

GetUnresolvedConflicts retrieves all unresolved conflicts.

func (*ConflictStore) MarkObservationSuperseded

func (s *ConflictStore) MarkObservationSuperseded(ctx context.Context, obsID int64) error

MarkObservationSuperseded marks an observation as superseded.

func (*ConflictStore) MarkObservationsSuperseded

func (s *ConflictStore) MarkObservationsSuperseded(ctx context.Context, obsIDs []int64) error

MarkObservationsSuperseded marks multiple observations as superseded.

func (*ConflictStore) ResolveConflict

func (s *ConflictStore) ResolveConflict(ctx context.Context, conflictID int64, resolution models.ConflictResolution) error

ResolveConflict marks a conflict as resolved.

func (*ConflictStore) StoreConflict

func (s *ConflictStore) StoreConflict(ctx context.Context, conflict *models.ObservationConflict) (int64, error)

StoreConflict stores a new observation conflict.

type ConflictWithDetails

type ConflictWithDetails struct {
	Conflict      *models.ObservationConflict
	NewerObsTitle string
	OlderObsTitle string
}

ConflictWithDetails contains a conflict with its observation details.

type Content

type Content struct {
	Hash      string    `gorm:"primaryKey;type:text" json:"hash"`
	Doc       string    `gorm:"type:text;not null" json:"doc"`
	CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
}

Content holds deduplicated document bodies keyed by SHA-256 hash.

func (Content) TableName

func (Content) TableName() string

TableName returns the table name for Content.

type ContentChunk

type ContentChunk struct {
	Embedding pgvec.Vector `gorm:"-" json:"-"`
	Hash      string       `gorm:"type:text;not null;primaryKey" json:"hash"`
	Seq       int          `gorm:"primaryKey" json:"seq"`
	Text      string       `gorm:"type:text;not null;default:''" json:"text"`
	Pos       int          `gorm:"not null" json:"pos"`
	Model     string       `gorm:"type:text;not null" json:"model"`
	CreatedAt time.Time    `gorm:"autoCreateTime" json:"created_at"`
}

ContentChunk holds per-chunk embeddings for a content hash.

func (ContentChunk) TableName

func (ContentChunk) TableName() string

TableName returns the table name for ContentChunk.

type Document

type Document struct {
	ID         int64          `gorm:"primaryKey;autoIncrement" json:"id"`
	Collection string         `gorm:"type:text;not null;uniqueIndex:idx_doc_collection_path" json:"collection"`
	Path       string         `gorm:"type:text;not null;uniqueIndex:idx_doc_collection_path" json:"path"`
	Title      sql.NullString `gorm:"type:text" json:"title"`
	Hash       sql.NullString `gorm:"type:text" json:"hash"`
	Active     bool           `gorm:"default:true" json:"active"`
	CreatedAt  time.Time      `gorm:"autoCreateTime" json:"created_at"`
	UpdatedAt  time.Time      `gorm:"autoUpdateTime" json:"updated_at"`
}

Document represents an ingested file in a collection.

func (Document) TableName

func (Document) TableName() string

TableName returns the table name for Document.

type DocumentStore

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

DocumentStore provides document and chunk persistence for content-addressable storage.

func NewDocumentStore

func NewDocumentStore(store *Store) *DocumentStore

NewDocumentStore creates a new document store.

func (*DocumentStore) ChunksExist added in v0.3.0

func (s *DocumentStore) ChunksExist(ctx context.Context, hash string) (bool, error)

ChunksExist checks if any chunks exist for a given content hash.

func (*DocumentStore) CollectionDocCounts

func (s *DocumentStore) CollectionDocCounts(ctx context.Context) (map[string]int64, error)

CollectionDocCounts returns active document counts by collection.

func (*DocumentStore) DeactivateDocument

func (s *DocumentStore) DeactivateDocument(ctx context.Context, collection, path string) error

DeactivateDocument marks a document as inactive.

func (*DocumentStore) GetContent

func (s *DocumentStore) GetContent(ctx context.Context, hash string) (*Content, error)

GetContent fetches content by hash.

func (*DocumentStore) GetDocument

func (s *DocumentStore) GetDocument(ctx context.Context, collection, path string) (*Document, error)

GetDocument returns the active document for the collection and path.

func (*DocumentStore) ListDocuments

func (s *DocumentStore) ListDocuments(ctx context.Context, collection string, activeOnly bool) ([]Document, error)

ListDocuments lists documents in a collection, optionally filtered to active-only.

func (*DocumentStore) SearchChunks

func (s *DocumentStore) SearchChunks(ctx context.Context, embedding []float32, collection string, limit int) ([]ContentChunk, error)

SearchChunks performs vector similarity search across content chunks. If collection is empty, searches all active documents.

func (*DocumentStore) UpsertChunks

func (s *DocumentStore) UpsertChunks(ctx context.Context, hash string, chunks []ContentChunk) error

UpsertChunks replaces existing chunks for a content hash with new chunk rows. Uses raw SQL to include the pgvector embedding column which is excluded from GORM mapping.

func (*DocumentStore) UpsertDocument

func (s *DocumentStore) UpsertDocument(ctx context.Context, collection, path, title, contentBody string) (*Document, error)

UpsertDocument stores the document body in content and upserts the document metadata.

type FeedbackStats

type FeedbackStats struct {
	Total        int     `json:"total"`
	Positive     int     `json:"positive"`
	Negative     int     `json:"negative"`
	Neutral      int     `json:"neutral"`
	AvgScore     float64 `json:"avg_score"`
	AvgRetrieval float64 `json:"avg_retrieval"`
}

FeedbackStats contains statistics about observation feedback and scoring.

type HealthInfo

type HealthInfo struct {
	Timestamp         time.Time      `json:"timestamp"`
	Status            string         `json:"status"`
	Error             string         `json:"error,omitempty"`
	Warning           string         `json:"warning,omitempty"`
	HistoricalMetrics MetricsSummary `json:"historical_metrics,omitempty"`
	PoolStats         PoolStats      `json:"pool_stats"`
	QueryLatency      time.Duration  `json:"query_latency_ns"`
}

HealthInfo contains database health check results.

type IndexedSession

type IndexedSession struct {
	ID            string         `gorm:"primaryKey;type:text" json:"id"`
	WorkstationID string         `gorm:"type:text;not null;index:idx_sessions_ws" json:"workstation_id"`
	ProjectID     string         `gorm:"type:text;not null;index:idx_sessions_proj" json:"project_id"`
	ProjectPath   sql.NullString `gorm:"type:text" json:"project_path"`
	GitBranch     sql.NullString `gorm:"type:text" json:"git_branch"`
	FirstMsgAt    sql.NullTime   `gorm:"type:timestamptz" json:"first_msg_at"`
	LastMsgAt     sql.NullTime   `gorm:"type:timestamptz" json:"last_msg_at"`
	ExchangeCount int            `gorm:"default:0" json:"exchange_count"`
	ToolCounts    sql.NullString `gorm:"type:jsonb" json:"tool_counts"`
	Topics        sql.NullString `gorm:"type:jsonb" json:"topics"`
	Content       sql.NullString `gorm:"type:text" json:"content"`
	FileMtime     sql.NullTime   `gorm:"type:timestamptz" json:"file_mtime"`
	IndexedAt     time.Time      `gorm:"autoCreateTime" json:"indexed_at"`
}

IndexedSession represents an indexed Claude Code JSONL session.

func (IndexedSession) TableName

func (IndexedSession) TableName() string

type MetricsSummary

type MetricsSummary struct {
	LastSampleTime time.Time     `json:"last_sample_time"`
	TotalQueries   int64         `json:"total_queries"`
	SampleCount    int           `json:"sample_count"`
	AvgLatency     time.Duration `json:"avg_latency_ns"`
	MinLatency     time.Duration `json:"min_latency_ns"`
	MaxLatency     time.Duration `json:"max_latency_ns"`
	P95Latency     time.Duration `json:"p95_latency_ns,omitempty"`
	PeakInUse      int           `json:"peak_in_use"`
	PeakWaitCount  int64         `json:"peak_wait_count"`
	TotalWaitTime  time.Duration `json:"total_wait_time_ns"`
}

MetricsSummary contains aggregated pool metrics.

type Observation

type Observation struct {
	FileMtimes               models.JSONInt64Map     `gorm:"type:text"`
	SDKSessionID             string                  `gorm:"index;not null"`
	Project                  string                  `gorm:"index:idx_observations_project;index:idx_observations_project_created,priority:1;not null"`
	Scope                    models.ObservationScope `` /* 157-byte string literal not displayed */
	AgentID                  string                  `gorm:"type:text;default:'';index:idx_observations_agent_id"`
	Type                     models.ObservationType  `` /* 126-byte string literal not displayed */
	MemoryType               models.MemoryType       `gorm:"type:text;index:idx_observations_memory_type"`
	SourceType               models.SourceType       `gorm:"type:text;index:idx_observations_source_type"`
	CreatedAt                string                  `gorm:"not null"`
	Facts                    models.JSONStringArray  `gorm:"type:text"`
	Rejected                 models.JSONStringArray  `gorm:"type:jsonb;default:'[]'"`
	Narrative                sql.NullString          `gorm:"type:text"`
	Concepts                 models.JSONStringArray  `gorm:"type:jsonb"`
	FilesRead                models.JSONStringArray  `gorm:"type:jsonb"`
	FilesModified            models.JSONStringArray  `gorm:"type:jsonb"`
	Subtitle                 sql.NullString          `gorm:"type:text"`
	Title                    sql.NullString          `gorm:"type:text"`
	ArchivedReason           sql.NullString
	ScoreUpdatedAt           sql.NullInt64 `gorm:"column:score_updated_at_epoch;index:idx_observations_score_updated"`
	PromptNumber             sql.NullInt64
	ArchivedAt               sql.NullInt64  `gorm:"column:archived_at_epoch"`
	LastRetrievedAt          sql.NullInt64  `gorm:"column:last_retrieved_at_epoch"`
	ID                       int64          `gorm:"primaryKey;autoIncrement"`
	ImportanceScore          float64        `gorm:"type:real;default:1.0;index:idx_observations_importance,priority:1,sort:desc"`
	UtilityScore             float64        `gorm:"type:real;default:0.5"`
	UserFeedback             int            `gorm:"not null;default:0"`
	IsSuppressed             bool           `gorm:"not null;default:false"`
	RetrievalCount           int            `gorm:"default:0"`
	InjectionCount           int            `gorm:"default:0"`
	CreatedAtEpoch           int64          `gorm:"index:idx_observations_created,sort:desc;index:idx_observations_project_created,priority:2,sort:desc;not null"`
	DiscoveryTokens          int64          `gorm:"default:0"`
	IsSuperseded             int            `gorm:"default:0;index:idx_observations_superseded;index:idx_observations_active,priority:2"`
	IsArchived               int            `gorm:"default:0;index:idx_observations_archived;index:idx_observations_active,priority:1"`
	EncryptedSecret          []byte         `gorm:"type:bytea"`
	EncryptionKeyFingerprint sql.NullString `gorm:"type:text"`
	ExpiresAt                sql.NullTime   `gorm:"type:timestamptz"`
	TtlDays                  sql.NullInt32
}

Observation represents a stored observation (learning). Field order optimized for memory alignment (fieldalignment).

func (*Observation) BeforeCreate

func (o *Observation) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure defaults are set.

func (Observation) TableName

func (Observation) TableName() string

type ObservationConflict

type ObservationConflict struct {
	ConflictType    models.ConflictType       `gorm:"type:text;check:conflict_type IN ('superseded', 'contradicts', 'outdated_pattern');not null"`
	Resolution      models.ConflictResolution `gorm:"type:text;check:resolution IN ('prefer_newer', 'prefer_older', 'manual');not null"`
	DetectedAt      string                    `gorm:"not null"`
	Reason          sql.NullString            `gorm:"type:text"`
	ResolvedAt      sql.NullString
	ID              int64 `gorm:"primaryKey;autoIncrement"`
	NewerObsID      int64 `gorm:"index:idx_conflicts_newer;not null"`
	OlderObsID      int64 `gorm:"index:idx_conflicts_older;not null"`
	DetectedAtEpoch int64 `gorm:"index:idx_conflicts_unresolved,priority:2,sort:desc;not null"`
	Resolved        int   `gorm:"default:0;index:idx_conflicts_unresolved,priority:1"`
}

ObservationConflict tracks conflicts between observations.

func (*ObservationConflict) BeforeCreate

func (c *ObservationConflict) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps are set.

func (ObservationConflict) TableName

func (ObservationConflict) TableName() string

type ObservationRelation

type ObservationRelation struct {
	RelationType    models.RelationType            `` /* 357-byte string literal not displayed */
	DetectionSource models.RelationDetectionSource `` /* 198-byte string literal not displayed */
	CreatedAt       string                         `gorm:"not null"`
	Reason          sql.NullString                 `gorm:"type:text"`
	ID              int64                          `gorm:"primaryKey;autoIncrement"`
	SourceID        int64                          `gorm:"index:idx_relations_source;index:idx_relations_both,priority:1;uniqueIndex:idx_relations_unique,priority:1;not null"`
	TargetID        int64                          `gorm:"index:idx_relations_target;index:idx_relations_both,priority:2;uniqueIndex:idx_relations_unique,priority:2;not null"`
	Confidence      float64                        `gorm:"type:real;default:0.5;index:idx_relations_confidence,sort:desc;not null"`
	CreatedAtEpoch  int64                          `gorm:"not null"`
}

ObservationRelation tracks relationships between observations.

func (*ObservationRelation) BeforeCreate

func (r *ObservationRelation) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps are set.

func (ObservationRelation) TableName

func (ObservationRelation) TableName() string

type ObservationStore

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

ObservationStore provides observation-related database operations using GORM.

func NewObservationStore

func NewObservationStore(store *Store, cleanupFunc CleanupFunc) *ObservationStore

NewObservationStore creates a new observation store.

func (*ObservationStore) ArchiveObservation

func (s *ObservationStore) ArchiveObservation(ctx context.Context, id int64, reason string) error

ArchiveObservation archives a single observation with an optional reason.

func (*ObservationStore) ArchiveOldObservations

func (s *ObservationStore) ArchiveOldObservations(ctx context.Context, project string, maxAgeDays int, reason string) ([]int64, error)

ArchiveOldObservations archives observations older than the specified age. Returns the count of archived observations and their IDs.

func (*ObservationStore) BatchGetObservationsWithScores

func (s *ObservationStore) BatchGetObservationsWithScores(ctx context.Context, ids []int64) (map[int64]*models.Observation, error)

BatchGetObservationsWithScores retrieves observations with associated scores. Returns a map of ID -> observation for efficient lookup.

func (*ObservationStore) CleanupInjectionLog added in v1.5.0

func (s *ObservationStore) CleanupInjectionLog(ctx context.Context, retentionDays int) (int64, error)

CleanupInjectionLog removes entries older than the given number of days.

func (*ObservationStore) CleanupOldObservations

func (s *ObservationStore) CleanupOldObservations(ctx context.Context, project string) ([]int64, error)

CleanupOldObservations removes observations beyond the limit for a project. Returns the IDs of deleted observations.

func (*ObservationStore) Close

func (s *ObservationStore) Close()

Close stops the cleanup worker and waits for it to finish. Safe to call even if the worker was never started.

func (*ObservationStore) CountCredentials added in v0.4.0

func (s *ObservationStore) CountCredentials(ctx context.Context) (int64, error)

CountCredentials returns the total number of active (non-archived) credential observations.

func (*ObservationStore) CountCredentialsWithDifferentFingerprint added in v1.3.3

func (s *ObservationStore) CountCredentialsWithDifferentFingerprint(ctx context.Context, currentFingerprint string) (int64, error)

CountCredentialsWithDifferentFingerprint counts credentials whose encryption_key_fingerprint differs from the given fingerprint — indicating they cannot be decrypted with the current key.

func (*ObservationStore) DeleteCredential added in v0.4.0

func (s *ObservationStore) DeleteCredential(ctx context.Context, name, project, scope string) error

DeleteCredential removes a credential observation by name and scope. scope must be "project" or "global" (empty defaults to "project"). Project-scoped callers cannot delete global credentials — pass scope="global" explicitly to delete a global credential (requires the caller to have verified this intent, e.g. via MCP scope parameter validation).

func (*ObservationStore) DeleteObservation

func (s *ObservationStore) DeleteObservation(ctx context.Context, id int64) error

DeleteObservation deletes a single observation by ID.

func (*ObservationStore) DeleteObservations

func (s *ObservationStore) DeleteObservations(ctx context.Context, ids []int64) (int64, error)

DeleteObservations deletes observations by IDs.

func (*ObservationStore) DeleteOrphanedCredentials added in v1.5.2

func (s *ObservationStore) DeleteOrphanedCredentials(ctx context.Context, currentFingerprint string) (int64, error)

DeleteOrphanedCredentials removes credentials encrypted with a key that doesn't match the current fingerprint. These credentials cannot be decrypted and are irrecoverable.

func (*ObservationStore) GetActiveObservations

func (s *ObservationStore) GetActiveObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetActiveObservations retrieves recent non-superseded, non-archived observations for a project. This excludes observations that have been marked as superseded or archived. Results are ordered by importance_score DESC, then created_at_epoch DESC.

func (*ObservationStore) GetAllObservations

func (s *ObservationStore) GetAllObservations(ctx context.Context) ([]*models.Observation, error)

GetAllObservations retrieves all observations (for vector rebuild). Note: For large datasets, prefer GetAllObservationsIterator to avoid memory issues.

func (*ObservationStore) GetAllObservationsIterator

func (s *ObservationStore) GetAllObservationsIterator(ctx context.Context, batchSize int, callback func([]*models.Observation) bool) error

GetAllObservationsIterator returns observations in batches to avoid loading all into memory. The callback is called for each batch. Return false from callback to stop iteration. batchSize controls how many observations are loaded at once (default 500 if <= 0).

func (*ObservationStore) GetAllRecentObservations

func (s *ObservationStore) GetAllRecentObservations(ctx context.Context, limit int) ([]*models.Observation, error)

GetAllRecentObservations retrieves recent observations across all projects.

func (*ObservationStore) GetAllRecentObservationsPaginated

func (s *ObservationStore) GetAllRecentObservationsPaginated(ctx context.Context, obsType string, limit, offset int) ([]*models.Observation, int64, error)

GetAllRecentObservationsPaginated retrieves recent observations with pagination. Pass obsType="" to return all types.

func (*ObservationStore) GetAlwaysInjectObservations added in v1.7.0

func (s *ObservationStore) GetAlwaysInjectObservations(ctx context.Context, limit int) ([]*models.Observation, error)

GetAlwaysInjectObservations retrieves observations tagged with the "always-inject" concept. These are unconditionally injected in every session regardless of similarity matching. Results are ordered by importance_score DESC, limited to the configured cap.

func (*ObservationStore) GetArchivalStats

func (s *ObservationStore) GetArchivalStats(ctx context.Context, project string) (*ArchivalStats, error)

GetArchivalStats returns statistics about archived observations. Optimized to use a single query instead of 4 separate queries.

func (*ObservationStore) GetArchivedObservations

func (s *ObservationStore) GetArchivedObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetArchivedObservations retrieves archived observations for a project.

func (*ObservationStore) GetConceptWeights

func (s *ObservationStore) GetConceptWeights(ctx context.Context) (map[string]float64, error)

GetConceptWeights returns all concept weights from the database.

func (*ObservationStore) GetCredential added in v0.4.0

func (s *ObservationStore) GetCredential(ctx context.Context, name, project string) (*Observation, error)

GetCredential retrieves a credential observation by name and project. Project-scoped credentials shadow global credentials with the same name. Returns nil, nil if not found.

func (*ObservationStore) GetDB added in v1.4.1

func (s *ObservationStore) GetDB() *gorm.DB

GetDB returns the underlying GORM DB instance for direct queries.

func (*ObservationStore) GetDiversityScores added in v1.5.0

func (s *ObservationStore) GetDiversityScores(ctx context.Context, observationIDs []int64) (map[int64]float64, error)

GetDiversityScores returns injection diversity for observations. diversity = unique_projects / total_injections. Higher = more generic = should penalize.

func (*ObservationStore) GetGuidanceObservations

func (s *ObservationStore) GetGuidanceObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetGuidanceObservations retrieves active guidance-type observations for a project. These are behavioral corrections and preferences that should be prominently surfaced. Results are ordered by importance_score DESC, then created_at_epoch DESC.

func (*ObservationStore) GetMostRetrievedObservations

func (s *ObservationStore) GetMostRetrievedObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetMostRetrievedObservations returns the most frequently retrieved observations.

func (*ObservationStore) GetObservationByID

func (s *ObservationStore) GetObservationByID(ctx context.Context, id int64) (*models.Observation, error)

GetObservationByID retrieves an observation by its ID.

func (*ObservationStore) GetObservationCount

func (s *ObservationStore) GetObservationCount(ctx context.Context, project string) (int, error)

GetObservationCount returns the count of observations for a project.

func (*ObservationStore) GetObservationFeedbackStats

func (s *ObservationStore) GetObservationFeedbackStats(ctx context.Context, project string) (*FeedbackStats, error)

GetObservationFeedbackStats returns statistics about user feedback.

func (*ObservationStore) GetObservationsByFile added in v1.7.0

func (s *ObservationStore) GetObservationsByFile(ctx context.Context, filePath string, limit int) ([]*models.Observation, error)

GetObservationsByFile retrieves observations related to a specific file path. Matches against both files_modified and files_read JSONB arrays. Results are ordered by importance_score DESC.

func (*ObservationStore) GetObservationsByIDs

func (s *ObservationStore) GetObservationsByIDs(ctx context.Context, ids []int64, orderBy string, limit int) ([]*models.Observation, error)

GetObservationsByIDs retrieves observations by a list of IDs.

func (*ObservationStore) GetObservationsByIDsPreserveOrder

func (s *ObservationStore) GetObservationsByIDsPreserveOrder(ctx context.Context, ids []int64) ([]*models.Observation, error)

GetObservationsByIDsPreserveOrder retrieves observations by IDs, preserving the input order. This is useful when the caller has already sorted/ranked the IDs (e.g., by vector similarity).

func (*ObservationStore) GetObservationsByProjectStrict

func (s *ObservationStore) GetObservationsByProjectStrict(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetObservationsByProjectStrict retrieves observations for a project (strict - no global observations).

func (*ObservationStore) GetObservationsByProjectStrictPaginated

func (s *ObservationStore) GetObservationsByProjectStrictPaginated(ctx context.Context, project string, obsType string, limit, offset int) ([]*models.Observation, int64, error)

GetObservationsByProjectStrictPaginated retrieves observations strictly from a project with pagination. Pass obsType="" to return all types.

func (*ObservationStore) GetObservationsNeedingScoreUpdate

func (s *ObservationStore) GetObservationsNeedingScoreUpdate(ctx context.Context, threshold time.Duration, limit int) ([]*models.Observation, error)

GetObservationsNeedingScoreUpdate returns observations that need their importance score recalculated. Returns observations where score_updated_at_epoch is NULL or older than the threshold.

func (*ObservationStore) GetObservationsSinceEpoch added in v1.1.0

func (s *ObservationStore) GetObservationsSinceEpoch(ctx context.Context, project string, sinceEpochMs int64) ([]*models.Observation, error)

GetObservationsSinceEpoch retrieves observations created at or after the given epoch (ms). Includes project-scoped observations for the specified project AND global observations. Results are ordered by created_at_epoch DESC.

func (*ObservationStore) GetOldestObservations

func (s *ObservationStore) GetOldestObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetOldestObservations retrieves the oldest non-archived observations for a project. Used by consolidation for stratified sampling to find cross-temporal associations.

func (*ObservationStore) GetPreviousObservationInSession added in v1.7.0

func (s *ObservationStore) GetPreviousObservationInSession(ctx context.Context, sessionID string, promptNumber int) (*models.Observation, error)

GetPreviousObservationInSession finds the observation that immediately precedes the given prompt_number within the same session. Used for temporal chain linking.

func (*ObservationStore) GetRecentObservations

func (s *ObservationStore) GetRecentObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetRecentObservations retrieves recent observations for a project. This includes project-scoped observations for the specified project AND global observations. Results are ordered by importance_score DESC, then created_at_epoch DESC.

func (*ObservationStore) GetRecentObservationsFiltered added in v0.4.0

func (s *ObservationStore) GetRecentObservationsFiltered(ctx context.Context, f ScopeFilter, limit int) ([]*models.Observation, error)

GetRecentObservationsFiltered retrieves recent observations using a ScopeFilter. When f.AgentID is set, also includes scope="agent" observations for that agent. Results are ordered by importance_score DESC, then created_at_epoch DESC.

func (*ObservationStore) GetRecentSessionIDs added in v1.7.0

func (s *ObservationStore) GetRecentSessionIDs(ctx context.Context, project string, since time.Time) (map[string]bool, error)

GetRecentSessionIDs returns a set of sdk_session_id values that have observations created on or after the given time, within the specified project. Used by the composite scoring pipeline to apply a session activity boost.

func (*ObservationStore) GetRecentlyInjectedObservations

func (s *ObservationStore) GetRecentlyInjectedObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetRecentlyInjectedObservations returns observations that have been injected at least once. Used by the stop hook to detect utility signals in the transcript.

func (*ObservationStore) GetSearchMissStats added in v0.5.0

func (s *ObservationStore) GetSearchMissStats(ctx context.Context, project string, limit int) ([]SearchMissStat, error)

GetSearchMissStats returns analytics about search misses grouped by query. When project is empty, results are aggregated across all projects.

func (*ObservationStore) GetSessionInjectedObservations added in v0.3.0

func (s *ObservationStore) GetSessionInjectedObservations(ctx context.Context, sessionID int64) ([]int64, error)

GetSessionInjectedObservations returns observation IDs that were injected into a specific session.

func (*ObservationStore) GetSupersededObservations

func (s *ObservationStore) GetSupersededObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetSupersededObservations retrieves observations that have been superseded by newer ones. Results are ordered by created_at_epoch DESC.

func (*ObservationStore) GetTopImportanceObservations added in v1.7.0

func (s *ObservationStore) GetTopImportanceObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetTopImportanceObservations retrieves observations for a project ordered by importance DESC. Used to fill the injection floor when the main result set falls below the minimum. Delegates to GetActiveObservations which applies the same filter/ordering.

func (*ObservationStore) GetTopScoringObservations

func (s *ObservationStore) GetTopScoringObservations(ctx context.Context, project string, limit int) ([]*models.Observation, error)

GetTopScoringObservations returns the highest-scoring observations.

func (*ObservationStore) GetTotalObservationCount added in v1.5.2

func (s *ObservationStore) GetTotalObservationCount(ctx context.Context, project string) (int, error)

GetTotalObservationCount returns the count of active (non-archived, non-superseded) observations. If project is empty, counts across all projects.

func (*ObservationStore) IncrementImportanceScores

func (s *ObservationStore) IncrementImportanceScores(ctx context.Context, deltas map[int64]float64, cap float64) error

IncrementImportanceScores atomically increments importance scores for multiple observations. Each observation's score is increased by its delta, capped at the given maximum. Uses atomic SQL to avoid read-then-write race with concurrent decay cycles.

func (*ObservationStore) IncrementInjectionCounts

func (s *ObservationStore) IncrementInjectionCounts(ctx context.Context, ids []int64) error

IncrementInjectionCounts increments the injection counter for the given observation IDs. Called when observations are injected into Claude Code context.

func (*ObservationStore) IncrementRetrievalCount

func (s *ObservationStore) IncrementRetrievalCount(ctx context.Context, ids []int64) error

IncrementRetrievalCount increments the retrieval counter for the given observation IDs. This is called when observations are returned in search results.

func (*ObservationStore) ListCredentials added in v0.4.0

func (s *ObservationStore) ListCredentials(ctx context.Context, project string) ([]Observation, error)

ListCredentials returns all credential observations accessible from the given project (project-scoped credentials for this project, plus global credentials).

func (*ObservationStore) LogInjection added in v1.5.0

func (s *ObservationStore) LogInjection(ctx context.Context, observationID int64, project, taskContext, sessionID string) error

LogInjection records that an observation was injected into a session's context.

func (*ObservationStore) LogInjections added in v1.5.0

func (s *ObservationStore) LogInjections(ctx context.Context, observationIDs []int64, project, taskContext, sessionID string) error

LogInjections records multiple observations injected into a session's context (batch).

func (*ObservationStore) MarkAsSuperseded

func (s *ObservationStore) MarkAsSuperseded(ctx context.Context, id int64) error

MarkAsSuperseded marks an observation as superseded (stale).

func (*ObservationStore) MarkAsSupersededBatch

func (s *ObservationStore) MarkAsSupersededBatch(ctx context.Context, ids []int64) (int64, error)

MarkAsSupersededBatch marks multiple observations as superseded in a single query. Returns the number of observations updated and any error.

func (*ObservationStore) RecordSearchMiss added in v0.5.0

func (s *ObservationStore) RecordSearchMiss(ctx context.Context, project, query string) error

RecordSearchMiss stores a search query that returned 0 results. Query is trimmed, validated (non-empty), and capped at 500 chars to prevent storage flooding and PII retention from arbitrarily long inputs.

func (*ObservationStore) RecordSessionInjections added in v0.3.0

func (s *ObservationStore) RecordSessionInjections(ctx context.Context, sessionID int64, observationIDs []int64) error

RecordSessionInjections records which observations were injected into a specific session. Uses ON CONFLICT DO NOTHING for idempotency (safe to call multiple times per session).

func (*ObservationStore) ResetObservationScores

func (s *ObservationStore) ResetObservationScores(ctx context.Context) error

ResetObservationScores resets all observation scores to their default values. This is useful for testing or when changing the scoring algorithm.

func (*ObservationStore) SearchObservationsFTS

func (s *ObservationStore) SearchObservationsFTS(ctx context.Context, query, project string, limit int) ([]*models.Observation, error)

SearchObservationsFTS performs full-text search on observations using FTS5. Falls back to LIKE search if FTS5 fails.

func (*ObservationStore) SearchObservationsFTSFiltered added in v0.4.0

func (s *ObservationStore) SearchObservationsFTSFiltered(ctx context.Context, query string, f ScopeFilter, limit int) ([]*models.Observation, error)

SearchObservationsFTSFiltered performs full-text search with a ScopeFilter. When f.AgentID is set, also includes scope="agent" observations for that agent. Falls back to LIKE search if FTS fails.

func (*ObservationStore) SearchObservationsFTSScored

func (s *ObservationStore) SearchObservationsFTSScored(ctx context.Context, query, project string, limit int) ([]ScoredObservation, error)

SearchObservationsFTSScored performs full-text search and returns ts_rank scores. Falls back to empty slice (not error) if FTS produces no results.

func (*ObservationStore) SetCleanupFunc

func (s *ObservationStore) SetCleanupFunc(fn CleanupFunc)

SetCleanupFunc sets the callback for when observations are deleted during cleanup.

func (*ObservationStore) SetConceptWeights

func (s *ObservationStore) SetConceptWeights(ctx context.Context, weights map[string]float64) error

SetConceptWeights stores concept weights in the database using UPSERT.

func (*ObservationStore) SetObservationTTL added in v1.2.0

func (s *ObservationStore) SetObservationTTL(ctx context.Context, id int64, ttlDays int) error

SetObservationTTL sets the TTL (expires_at and ttl_days) on an observation.

func (*ObservationStore) SetRelationDetector added in v1.0.2

func (s *ObservationStore) SetRelationDetector(d RelationDetector)

SetRelationDetector sets the async relation detector for post-creation detection.

func (*ObservationStore) StoreObservation

func (s *ObservationStore) StoreObservation(ctx context.Context, sdkSessionID, project string, obs *models.ParsedObservation, promptNumber int, discoveryTokens int64) (int64, int64, error)

StoreObservation stores a new observation.

func (*ObservationStore) UnarchiveObservation

func (s *ObservationStore) UnarchiveObservation(ctx context.Context, id int64) error

UnarchiveObservation restores an archived observation.

func (*ObservationStore) UpdateConceptWeight

func (s *ObservationStore) UpdateConceptWeight(ctx context.Context, concept string, weight float64) error

UpdateConceptWeight updates a single concept weight in the database using UPSERT.

func (*ObservationStore) UpdateImportanceScore

func (s *ObservationStore) UpdateImportanceScore(ctx context.Context, id int64, score float64) error

UpdateImportanceScore updates the importance score for a single observation.

func (*ObservationStore) UpdateImportanceScores

func (s *ObservationStore) UpdateImportanceScores(ctx context.Context, scores map[int64]float64) error

UpdateImportanceScores bulk updates importance scores for multiple observations. Uses a single SQL statement with CASE/WHEN for efficient batch updates.

func (*ObservationStore) UpdateObservation

func (s *ObservationStore) UpdateObservation(ctx context.Context, id int64, update *ObservationUpdate) (*models.Observation, error)

UpdateObservation updates an existing observation with the provided fields. Only non-nil fields in the update struct will be modified. Returns the updated observation or an error.

func (*ObservationStore) UpdateObservationFeedback

func (s *ObservationStore) UpdateObservationFeedback(ctx context.Context, id int64, feedback int) error

UpdateObservationFeedback updates the user feedback for an observation. Feedback values: -1 (thumbs down), 0 (neutral), 1 (thumbs up).

func (*ObservationStore) UpdateUtilityScore

func (s *ObservationStore) UpdateUtilityScore(ctx context.Context, id int64, signal, alpha, maxDelta float64) error

UpdateUtilityScore updates the utility score for a single observation using EMA. signal: 1.0 = used, 0.0 = corrected/ignored alpha: EMA smoothing factor (default 0.1 for slow adaptation) maxDelta: maximum score change per session (default 0.05 for confidence cap)

type ObservationUpdate

type ObservationUpdate struct {
	Title         *string   // New title
	Subtitle      *string   // New subtitle
	Narrative     *string   // New narrative
	Facts         *[]string // New facts (replaces existing)
	Concepts      *[]string // New concepts (replaces existing)
	FilesRead     *[]string // New files read (replaces existing)
	FilesModified *[]string // New files modified (replaces existing)
	Scope         *string   // New scope (project or global)
}

ObservationUpdate contains fields that can be updated on an observation. Only non-nil fields will be updated.

type PaginationParams

type PaginationParams struct {
	Limit  int
	Offset int
}

PaginationParams holds pagination parameters.

func ParsePaginationParams

func ParsePaginationParams(r *http.Request, defaultLimit int) PaginationParams

ParsePaginationParams parses both limit and offset from an HTTP request.

type Pattern

type Pattern struct {
	Status          models.PatternStatus   `gorm:"type:text;default:'active';check:status IN ('active', 'deprecated', 'merged');index"`
	Name            string                 `gorm:"type:text;not null"`
	Type            models.PatternType     `gorm:"type:text;check:type IN ('bug', 'refactor', 'architecture', 'anti-pattern', 'best-practice');index;not null"`
	CreatedAt       string                 `gorm:"not null"`
	LastSeenAt      string                 `gorm:"not null"`
	Signature       models.JSONStringArray `gorm:"type:text"`
	Projects        models.JSONStringArray `gorm:"type:text"`
	ObservationIDs  models.JSONInt64Array  `gorm:"type:text"`
	Recommendation  sql.NullString         `gorm:"type:text"`
	Description     sql.NullString         `gorm:"type:text"`
	MergedIntoID    sql.NullInt64
	Frequency       int     `gorm:"default:1;index:idx_patterns_frequency,sort:desc"`
	Confidence      float64 `gorm:"type:real;default:0.5;index:idx_patterns_confidence,sort:desc"`
	ID              int64   `gorm:"primaryKey;autoIncrement"`
	LastSeenAtEpoch int64   `gorm:"index:idx_patterns_last_seen,sort:desc;not null"`
	CreatedAtEpoch  int64   `gorm:"not null"`
}

Pattern represents a detected recurring pattern.

func (*Pattern) BeforeCreate

func (p *Pattern) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps and defaults are set.

func (Pattern) TableName

func (Pattern) TableName() string

type PatternCleanupFunc

type PatternCleanupFunc func(ctx context.Context, deletedIDs []int64)

PatternCleanupFunc is a callback for when patterns are deleted.

type PatternStats

type PatternStats struct {
	Total            int     `json:"total"`
	Active           int     `json:"active"`
	Deprecated       int     `json:"deprecated"`
	Merged           int     `json:"merged"`
	TotalOccurrences int     `json:"total_occurrences"`
	AvgConfidence    float64 `json:"avg_confidence"`
	Bugs             int     `json:"bugs"`
	Refactors        int     `json:"refactors"`
	Architectures    int     `json:"architectures"`
	AntiPatterns     int     `json:"anti_patterns"`
	BestPractices    int     `json:"best_practices"`
}

PatternStats contains aggregate statistics about patterns.

type PatternStore

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

PatternStore provides pattern-related database operations using GORM.

func NewPatternStore

func NewPatternStore(store *Store) *PatternStore

NewPatternStore creates a new pattern store.

func (*PatternStore) CountActivePatterns added in v1.3.0

func (s *PatternStore) CountActivePatterns(ctx context.Context) (int64, error)

CountActivePatterns returns the total count of active patterns.

func (*PatternStore) DeletePattern

func (s *PatternStore) DeletePattern(ctx context.Context, id int64) error

DeletePattern deletes a pattern by ID.

func (*PatternStore) FindMatchingPatterns

func (s *PatternStore) FindMatchingPatterns(ctx context.Context, signature []string, minScore float64) ([]*models.Pattern, error)

FindMatchingPatterns searches for patterns that match a given signature. Pattern matching is done in Go code for simplicity.

func (*PatternStore) GetActivePatterns

func (s *PatternStore) GetActivePatterns(ctx context.Context, limit, offset int, sort string) ([]*models.Pattern, error)

GetActivePatterns retrieves active patterns with pagination and sorting. sort accepts "frequency", "confidence", or "last_seen"; anything else defaults to frequency DESC.

func (*PatternStore) GetDeprecatedPatterns added in v1.3.0

func (s *PatternStore) GetDeprecatedPatterns(ctx context.Context) ([]*models.Pattern, error)

GetDeprecatedPatterns retrieves all deprecated patterns.

func (*PatternStore) GetPatternByID

func (s *PatternStore) GetPatternByID(ctx context.Context, id int64) (*models.Pattern, error)

GetPatternByID retrieves a pattern by ID.

func (*PatternStore) GetPatternByName

func (s *PatternStore) GetPatternByName(ctx context.Context, name string) (*models.Pattern, error)

GetPatternByName retrieves a pattern by name.

func (*PatternStore) GetPatternStats

func (s *PatternStore) GetPatternStats(ctx context.Context) (*PatternStats, error)

GetPatternStats returns statistics about patterns. Uses raw SQL for complex aggregate query.

func (*PatternStore) GetPatternsByProject

func (s *PatternStore) GetPatternsByProject(ctx context.Context, project string, limit int) ([]*models.Pattern, error)

GetPatternsByProject retrieves patterns that have been observed in a specific project. Uses raw SQL since JSON_EACH is complex in GORM.

func (*PatternStore) GetPatternsByType

func (s *PatternStore) GetPatternsByType(ctx context.Context, patternType models.PatternType, limit int) ([]*models.Pattern, error)

GetPatternsByType retrieves patterns of a specific type.

func (*PatternStore) IncrementPatternFrequency

func (s *PatternStore) IncrementPatternFrequency(ctx context.Context, id int64, project string, observationID int64) error

IncrementPatternFrequency atomically increments a pattern's frequency and updates last_seen.

func (*PatternStore) MarkPatternDeprecated

func (s *PatternStore) MarkPatternDeprecated(ctx context.Context, id int64) error

MarkPatternDeprecated marks a pattern as deprecated.

func (*PatternStore) MergePatterns

func (s *PatternStore) MergePatterns(ctx context.Context, sourceID, targetID int64) error

MergePatterns merges a source pattern into a target pattern.

func (*PatternStore) SearchPatternsFTS

func (s *PatternStore) SearchPatternsFTS(ctx context.Context, searchQuery string, limit int) ([]*models.Pattern, error)

SearchPatternsFTS performs full-text search on patterns. Uses raw SQL for FTS5 query.

func (*PatternStore) SetCleanupFunc

func (s *PatternStore) SetCleanupFunc(fn PatternCleanupFunc)

SetCleanupFunc sets the callback for when patterns are deleted.

func (*PatternStore) StorePattern

func (s *PatternStore) StorePattern(ctx context.Context, pattern *models.Pattern) (int64, error)

StorePattern stores a new pattern.

func (*PatternStore) UpdatePattern

func (s *PatternStore) UpdatePattern(ctx context.Context, pattern *models.Pattern) error

UpdatePattern updates an existing pattern.

type PoolMetrics

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

PoolMetrics tracks historical connection pool metrics with a sliding window.

func NewPoolMetrics

func NewPoolMetrics(windowSize int) *PoolMetrics

NewPoolMetrics creates a new pool metrics collector with the given window size.

func (*PoolMetrics) GetMetricsSummary

func (m *PoolMetrics) GetMetricsSummary() MetricsSummary

GetMetricsSummary returns a summary of collected metrics.

func (*PoolMetrics) RecordLatency

func (m *PoolMetrics) RecordLatency(latency time.Duration)

RecordLatency records a query latency sample.

func (*PoolMetrics) RecordPoolStats

func (m *PoolMetrics) RecordPoolStats(stats sql.DBStats)

RecordPoolStats records pool statistics for peak tracking.

type PoolStats

type PoolStats struct {
	OpenConnections   int           `json:"open_connections"`
	InUse             int           `json:"in_use"`
	Idle              int           `json:"idle"`
	WaitCount         int64         `json:"wait_count"`
	WaitDuration      time.Duration `json:"wait_duration_ns"`
	MaxIdleClosed     int64         `json:"max_idle_closed"`
	MaxLifetimeClosed int64         `json:"max_lifetime_closed"`
}

PoolStats contains connection pool statistics.

type Project added in v0.4.0

type Project struct {
	GitRemote    sql.NullString `gorm:"column:git_remote;index"`
	RelativePath sql.NullString `gorm:"column:relative_path"`
	DisplayName  sql.NullString `gorm:"column:display_name"`
	LegacyIDs    pq.StringArray `gorm:"column:legacy_ids;type:text[]"`
	ID           string         `gorm:"primaryKey"`
	CreatedAt    time.Time      `gorm:"autoCreateTime"`
}

Project represents a repository's stable identity record for cross-platform project ID resolution. Maps a canonical git-remote-based project ID to optional legacy path-based aliases, enabling zero-downtime migration when clients upgrade to git-remote IDs.

func (Project) TableName added in v0.4.0

func (Project) TableName() string

type ProjectSettings added in v1.7.0

type ProjectSettings struct {
	Project            string    `gorm:"column:project;primaryKey"`
	RelevanceThreshold float64   `gorm:"column:relevance_threshold;default:0.3"`
	FeedbackCount      int       `gorm:"column:feedback_count;default:0"`
	UpdatedAt          time.Time `gorm:"column:updated_at;not null"`
}

ProjectSettings holds per-project adaptive threshold configuration.

func (ProjectSettings) TableName added in v1.7.0

func (ProjectSettings) TableName() string

TableName returns the table name for GORM.

type ProjectSettingsStore added in v1.7.0

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

ProjectSettingsStore provides access to per-project settings.

func NewProjectSettingsStore added in v1.7.0

func NewProjectSettingsStore(db *gorm.DB) *ProjectSettingsStore

NewProjectSettingsStore creates a new ProjectSettingsStore.

func (*ProjectSettingsStore) AdjustThreshold added in v1.7.0

func (s *ProjectSettingsStore) AdjustThreshold(ctx context.Context, project string, delta float64) error

AdjustThreshold atomically adjusts the relevance threshold for a project by delta. The threshold is clamped to the range [0.1, 0.8]. Also increments feedback_count. Uses UPSERT (INSERT ON CONFLICT UPDATE) to auto-create the entry if it does not exist.

func (*ProjectSettingsStore) GetThreshold added in v1.7.0

func (s *ProjectSettingsStore) GetThreshold(ctx context.Context, project string) (float64, error)

GetThreshold returns the relevance threshold for a project. If no entry exists, returns the default threshold of 0.3.

func (*ProjectSettingsStore) UpsertSettings added in v1.7.0

func (s *ProjectSettingsStore) UpsertSettings(ctx context.Context, ps *ProjectSettings) error

UpsertSettings creates or replaces settings for a project. Exported for testing; normal callers use GetThreshold and AdjustThreshold.

type PromptCleanupFunc

type PromptCleanupFunc func(ctx context.Context, deletedIDs []int64)

PromptCleanupFunc is a callback for when prompts are cleaned up. Receives the IDs of deleted prompts for downstream cleanup (e.g., vector DB).

type PromptStore

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

PromptStore provides user prompt-related database operations using GORM.

func NewPromptStore

func NewPromptStore(store *Store, cleanupFunc PromptCleanupFunc) *PromptStore

NewPromptStore creates a new prompt store.

func (*PromptStore) CleanupOldPrompts

func (s *PromptStore) CleanupOldPrompts(ctx context.Context) ([]int64, error)

CleanupOldPrompts deletes prompts beyond the global limit. Keeps the most recent MaxPromptsGlobal prompts. Returns the IDs of deleted prompts for downstream cleanup (e.g., vector DB).

func (*PromptStore) FindRecentPromptByText

func (s *PromptStore) FindRecentPromptByText(ctx context.Context, claudeSessionID, promptText string, withinSeconds int) (int64, int, bool)

FindRecentPromptByText finds a recent prompt by exact text match within a time window. Returns (promptID, promptNumber, found).

func (*PromptStore) FindRecentPromptByTextGlobal added in v0.4.0

func (s *PromptStore) FindRecentPromptByTextGlobal(ctx context.Context, promptText string, withinSeconds int) (int64, int, bool)

FindRecentPromptByTextGlobal finds a recent prompt by exact text match across ALL sessions within a time window. This detects cross-session duplicates when the same hook fires from different session IDs (e.g., subagent spawning). Returns (promptID, promptNumber, found).

func (*PromptStore) GetAllPrompts

func (s *PromptStore) GetAllPrompts(ctx context.Context) ([]*models.UserPromptWithSession, error)

GetAllPrompts retrieves all user prompts (for vector rebuild).

func (*PromptStore) GetAllRecentUserPrompts

func (s *PromptStore) GetAllRecentUserPrompts(ctx context.Context, limit int) ([]*models.UserPromptWithSession, error)

GetAllRecentUserPrompts retrieves recent user prompts across all projects.

func (*PromptStore) GetPromptForObservation added in v1.7.0

func (s *PromptStore) GetPromptForObservation(ctx context.Context, sdkSessionID string, promptNumber int) (int64, error)

GetPromptForObservation finds the user prompt that triggered a given observation. Matches: same sdk_session_id (via sessions join), prompt_number <= observation's prompt_number. Returns the closest preceding prompt. Used for causal chain linking (FR-5).

func (*PromptStore) GetPromptsByIDs

func (s *PromptStore) GetPromptsByIDs(ctx context.Context, ids []int64, orderBy string, limit int) ([]*models.UserPromptWithSession, error)

GetPromptsByIDs retrieves user prompts by a list of IDs.

func (*PromptStore) GetRecentUserPromptsByProject

func (s *PromptStore) GetRecentUserPromptsByProject(ctx context.Context, project string, limit int) ([]*models.UserPromptWithSession, error)

GetRecentUserPromptsByProject retrieves recent user prompts for a specific project.

func (*PromptStore) SaveUserPromptWithMatches

func (s *PromptStore) SaveUserPromptWithMatches(ctx context.Context, claudeSessionID string, promptNumber int, promptText string, matchedObservations int) (int64, error)

SaveUserPromptWithMatches saves a user prompt with matched observation count. Uses INSERT OR IGNORE to be idempotent - duplicate (session, prompt_number) pairs are silently ignored. This prevents duplicate prompts when the user-prompt hook fires multiple times.

func (*PromptStore) SetCleanupFunc

func (s *PromptStore) SetCleanupFunc(fn PromptCleanupFunc)

SetCleanupFunc sets the callback for when prompts are deleted during cleanup.

type RawEventGORM

type RawEventGORM struct {
	SessionID      string          `gorm:"column:session_id;index:idx_raw_events_session"`
	ToolName       string          `gorm:"column:tool_name"`
	ToolInput      json.RawMessage `gorm:"column:tool_input;type:jsonb"`
	ToolResult     json.RawMessage `gorm:"column:tool_result;type:jsonb"`
	Project        string          `gorm:"column:project"`
	WorkstationID  string          `gorm:"column:workstation_id"`
	ID             int64           `gorm:"primaryKey;autoIncrement"`
	CreatedAtEpoch int64           `gorm:"column:created_at_epoch;index:idx_raw_events_session"`
	Processed      bool            `gorm:"column:processed;default:false;index:idx_raw_events_unprocessed"`
}

RawEventGORM is the GORM model for raw_events table. Matches the schema created in migration 022.

func (RawEventGORM) TableName

func (RawEventGORM) TableName() string

TableName returns the database table name.

type RawEventStore

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

RawEventStore provides raw event database operations.

func NewRawEventStore

func NewRawEventStore(store *Store) *RawEventStore

NewRawEventStore creates a new raw event store.

func (*RawEventStore) InsertRawEvent

func (s *RawEventStore) InsertRawEvent(ctx context.Context, event *models.RawEvent) (int64, error)

InsertRawEvent stores a raw tool event. Returns the assigned event ID.

func (*RawEventStore) MarkProcessed

func (s *RawEventStore) MarkProcessed(ctx context.Context, id int64) error

MarkProcessed marks a raw event as processed so background jobs skip it.

type RecentQueryEntry added in v1.2.0

type RecentQueryEntry struct {
	Timestamp  time.Time `json:"timestamp"`
	Query      string    `json:"query"`
	Project    string    `json:"project,omitempty"`
	SearchType string    `json:"type,omitempty"`
	Results    int       `json:"results"`
	UsedVector bool      `json:"used_vector"`
}

RecentQueryEntry represents a recent search query from the persistent log.

type RelationCallback

type RelationCallback func(relations []*models.ObservationRelation)

RelationCallback is called after relations are stored in the database. Fired AFTER transaction commits, not inside the transaction.

type RelationDetector added in v1.0.2

type RelationDetector interface {
	Enqueue(obsID int64, project string)
}

RelationDetector is the interface for async relation detection. Implemented by relation.Detector; defined here to avoid circular imports.

type RelationStore

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

RelationStore provides relation-related database operations using GORM.

func NewRelationStore

func NewRelationStore(store *Store) *RelationStore

NewRelationStore creates a new relation store.

func (*RelationStore) DeleteRelationsByObservationID

func (s *RelationStore) DeleteRelationsByObservationID(ctx context.Context, obsID int64) error

DeleteRelationsByObservationID deletes all relations involving an observation. Called when an observation is deleted.

func (*RelationStore) GetAvgConfidenceBatch

func (s *RelationStore) GetAvgConfidenceBatch(ctx context.Context, obsIDs []int64) (map[int64]float64, error)

GetAvgConfidenceBatch returns average confidence for the requested observations.

func (*RelationStore) GetDistinctNodeCount added in v1.1.0

func (s *RelationStore) GetDistinctNodeCount(ctx context.Context) (int, error)

GetDistinctNodeCount returns the count of unique observation IDs participating in relations.

func (*RelationStore) GetHighConfidenceRelations

func (s *RelationStore) GetHighConfidenceRelations(ctx context.Context, minConfidence float64, limit int) ([]*models.ObservationRelation, error)

GetHighConfidenceRelations retrieves relations with confidence above threshold.

func (*RelationStore) GetIncomingRelations

func (s *RelationStore) GetIncomingRelations(ctx context.Context, obsID int64) ([]*models.ObservationRelation, error)

GetIncomingRelations retrieves relations where the observation is the target.

func (*RelationStore) GetOutgoingRelations

func (s *RelationStore) GetOutgoingRelations(ctx context.Context, obsID int64) ([]*models.ObservationRelation, error)

GetOutgoingRelations retrieves relations where the observation is the source.

func (*RelationStore) GetRelatedObservationIDs

func (s *RelationStore) GetRelatedObservationIDs(ctx context.Context, obsID int64, minConfidence float64) ([]int64, error)

GetRelatedObservationIDs returns IDs of observations related to the given one. This is useful for expanding search results. Uses CASE expression for bidirectional ID lookup (GORM doesn't support this well, so we use raw SQL).

func (*RelationStore) GetRelationCount

func (s *RelationStore) GetRelationCount(ctx context.Context, obsID int64) (int, error)

GetRelationCount returns the count of relations for an observation.

func (*RelationStore) GetRelationCountsBatch

func (s *RelationStore) GetRelationCountsBatch(ctx context.Context, obsIDs []int64) (map[int64]int, error)

GetRelationCountsBatch returns relation counts for the requested observations.

func (*RelationStore) GetRelationGraph

func (s *RelationStore) GetRelationGraph(ctx context.Context, centerID int64, maxDepth int) (*models.RelationGraph, error)

GetRelationGraph retrieves a relation graph centered on an observation. This returns all observations within N hops from the center.

func (*RelationStore) GetRelationsByObservationID

func (s *RelationStore) GetRelationsByObservationID(ctx context.Context, obsID int64) ([]*models.ObservationRelation, error)

GetRelationsByObservationID retrieves all relations involving an observation (as source or target).

func (*RelationStore) GetRelationsByType

func (s *RelationStore) GetRelationsByType(ctx context.Context, relationType models.RelationType, limit int) ([]*models.ObservationRelation, error)

GetRelationsByType retrieves all relations of a specific type.

func (*RelationStore) GetRelationsWithDetails

func (s *RelationStore) GetRelationsWithDetails(ctx context.Context, obsID int64) ([]*models.RelationWithDetails, error)

GetRelationsWithDetails retrieves relations with observation titles for display.

func (*RelationStore) GetTotalRelationCount

func (s *RelationStore) GetTotalRelationCount(ctx context.Context) (int, error)

GetTotalRelationCount returns the total count of all relations.

func (*RelationStore) SetCallback

func (s *RelationStore) SetCallback(cb RelationCallback)

SetCallback sets a callback that fires after relations are stored.

func (*RelationStore) StoreRelation

func (s *RelationStore) StoreRelation(ctx context.Context, relation *models.ObservationRelation) (int64, error)

StoreRelation stores a new observation relation. Uses INSERT OR IGNORE to handle duplicate (source_id, target_id, relation_type) combinations.

func (*RelationStore) StoreRelations

func (s *RelationStore) StoreRelations(ctx context.Context, relations []*models.ObservationRelation) error

StoreRelations stores multiple relations in a single transaction.

func (*RelationStore) UpdateRelationConfidence

func (s *RelationStore) UpdateRelationConfidence(ctx context.Context, relationID int64, newConfidence float64) error

UpdateRelationConfidence updates the confidence of a relation.

type RetrievalStatsLogEntry added in v1.2.0

type RetrievalStatsLogEntry struct {
	ID        int64     `gorm:"primaryKey;autoIncrement"`
	Project   string    `gorm:"type:text;not null"`
	EventType string    `gorm:"type:text;not null"`
	Count     int       `gorm:"not null;default:1"`
	CreatedAt time.Time `gorm:"not null;default:NOW()"`
}

RetrievalStatsLogEntry represents a single logged retrieval event.

func (RetrievalStatsLogEntry) TableName added in v1.2.0

func (RetrievalStatsLogEntry) TableName() string

TableName returns the table name for RetrievalStatsLogEntry.

type RetrievalStatsLogStore added in v1.2.0

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

RetrievalStatsLogStore handles batched logging of retrieval stats to PostgreSQL. Events are buffered in a channel and flushed periodically or when the buffer reaches a threshold.

func NewRetrievalStatsLogStore added in v1.2.0

func NewRetrievalStatsLogStore(db *gorm.DB) *RetrievalStatsLogStore

NewRetrievalStatsLogStore creates a new store and starts the background flusher.

func (*RetrievalStatsLogStore) Cleanup added in v1.2.0

func (s *RetrievalStatsLogStore) Cleanup(ctx context.Context, olderThan time.Duration) (int64, error)

Cleanup deletes entries older than the given duration.

func (*RetrievalStatsLogStore) Close added in v1.2.0

func (s *RetrievalStatsLogStore) Close()

Close drains the channel and stops the background flusher.

func (*RetrievalStatsLogStore) GetStats added in v1.2.0

func (s *RetrievalStatsLogStore) GetStats(ctx context.Context, project string, since time.Time) (*AggregatedRetrievalStats, error)

GetStats returns aggregated retrieval stats from the persistent log. If project is empty, aggregates across all projects. If since is zero, returns all-time stats.

func (*RetrievalStatsLogStore) LogEvent added in v1.2.0

func (s *RetrievalStatsLogStore) LogEvent(project, eventType string, count int)

LogEvent enqueues a retrieval stats event. Non-blocking: drops if channel is full.

type SDKSession

type SDKSession struct {
	ClaudeSessionID  string         `gorm:"uniqueIndex;not null"`
	Project          string         `gorm:"index;not null"`
	Status           string         `gorm:"type:text;check:status IN ('active', 'completed', 'failed');default:'active';index"`
	StartedAt        string         `gorm:"not null"`
	SDKSessionID     sql.NullString `gorm:"uniqueIndex"`
	UserPrompt       sql.NullString
	CompletedAt      sql.NullString
	WorkerPort       sql.NullInt64
	CompletedAtEpoch sql.NullInt64
	ID               int64 `gorm:"primaryKey;autoIncrement"`
	PromptCounter    int   `gorm:"default:0"`
	StartedAtEpoch   int64 `gorm:"index:idx_sessions_started,sort:desc;not null"`
}

SDKSession represents a Claude Code session.

func (*SDKSession) BeforeCreate

func (s *SDKSession) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps are set.

func (SDKSession) TableName

func (SDKSession) TableName() string

type ScopeFilter added in v0.4.0

type ScopeFilter struct {
	Project string
	AgentID string // If set, include scope="agent" observations with this agent_id
}

ScopeFilter defines the visibility scope for observation queries. When AgentID is set, agent-scoped observations matching that agent are also included.

type ScoredObservation

type ScoredObservation struct {
	Observation *models.Observation
	Score       float64
}

ScoredObservation pairs an observation with its raw BM25 relevance score. Score is a raw PostgreSQL ts_rank value; callers normalize with BM25Normalize.

type SearchAnalytics added in v1.2.0

type SearchAnalytics struct {
	TotalSearches      int64   `json:"total_searches"`
	SearchesToday      int64   `json:"searches_today"`
	AvgLatencyMs       float64 `json:"avg_latency_ms"`
	ZeroResultRate     float64 `json:"zero_result_rate"`
	VectorSearches     int64   `json:"vector_searches"`
	FilterSearches     int64   `json:"filter_searches"`
	CacheHits          int64   `json:"cache_hits"`
	SearchErrors       int64   `json:"search_errors"`
	AvgVectorLatencyMs float64 `json:"avg_vector_latency_ms"`
	AvgFilterLatencyMs float64 `json:"avg_filter_latency_ms"`
	CoalescedRequests  int64   `json:"coalesced_requests"`
}

SearchAnalytics contains aggregated search analytics derived from search_query_log.

type SearchMissStat added in v0.5.0

type SearchMissStat struct {
	Query     string    `json:"query"`
	MissCount int       `json:"miss_count"`
	LastSeen  time.Time `json:"last_seen"`
}

SearchMissStat holds aggregated analytics for a search query that returned zero results.

type SearchQueryLogEntry added in v1.2.0

type SearchQueryLogEntry struct {
	ID         int64     `gorm:"primaryKey;autoIncrement"`
	Project    string    `gorm:"type:text"`
	Query      string    `gorm:"type:text;not null"`
	SearchType string    `gorm:"type:text;not null"`
	Results    int       `gorm:"not null;default:0"`
	UsedVector bool      `gorm:"not null;default:false"`
	LatencyMs  float32   `gorm:"type:real"`
	CreatedAt  time.Time `gorm:"not null;default:NOW()"`
}

SearchQueryLogEntry represents a single logged search query.

func (SearchQueryLogEntry) TableName added in v1.2.0

func (SearchQueryLogEntry) TableName() string

TableName returns the table name for SearchQueryLogEntry.

type SearchQueryLogStore added in v1.2.0

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

SearchQueryLogStore handles async logging of search queries to PostgreSQL.

func NewSearchQueryLogStore added in v1.2.0

func NewSearchQueryLogStore(db *gorm.DB) *SearchQueryLogStore

NewSearchQueryLogStore creates a new SearchQueryLogStore.

func (*SearchQueryLogStore) Cleanup added in v1.2.0

func (s *SearchQueryLogStore) Cleanup(ctx context.Context, olderThan time.Duration) (int64, error)

Cleanup deletes entries older than the given duration.

func (*SearchQueryLogStore) GetAnalytics added in v1.2.0

func (s *SearchQueryLogStore) GetAnalytics(ctx context.Context, since time.Time) (*SearchAnalytics, error)

GetAnalytics returns aggregated search analytics from the persistent log. If since is zero time, returns all-time stats.

func (*SearchQueryLogStore) GetRecent added in v1.2.0

func (s *SearchQueryLogStore) GetRecent(ctx context.Context, project string, limit int) ([]RecentQueryEntry, error)

GetRecent returns the most recent search queries from the persistent log.

func (*SearchQueryLogStore) LogQuery added in v1.2.0

func (s *SearchQueryLogStore) LogQuery(project, query, searchType string, results int, usedVector bool, latencyMs float32)

LogQuery asynchronously inserts a search query log entry. Fire-and-forget: logs warning on error, never blocks caller.

type SessionStore

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

SessionStore provides session-related database operations using GORM.

func NewSessionStore

func NewSessionStore(store *Store) *SessionStore

NewSessionStore creates a new session store.

func (*SessionStore) CreateSDKSession

func (s *SessionStore) CreateSDKSession(ctx context.Context, claudeSessionID, project, userPrompt string) (int64, error)

CreateSDKSession creates a new SDK session (idempotent - returns existing ID if exists). This is the KEY to how engram stays unified across hooks.

func (*SessionStore) FindAnySDKSession

func (s *SessionStore) FindAnySDKSession(ctx context.Context, claudeSessionID string) (*models.SDKSession, error)

FindAnySDKSession finds any session by Claude session ID (any status).

func (*SessionStore) GetAllProjects

func (s *SessionStore) GetAllProjects(ctx context.Context) ([]string, error)

GetAllProjects returns all unique project names.

func (*SessionStore) GetPromptCounter

func (s *SessionStore) GetPromptCounter(ctx context.Context, id int64) (int, error)

GetPromptCounter returns the current prompt counter for a session.

func (*SessionStore) GetSessionByID

func (s *SessionStore) GetSessionByID(ctx context.Context, id int64) (*models.SDKSession, error)

GetSessionByID retrieves a session by its database ID.

func (*SessionStore) GetSessionsToday

func (s *SessionStore) GetSessionsToday(ctx context.Context) (int, error)

GetSessionsToday returns the count of sessions started today.

func (*SessionStore) IncrementPromptCounter

func (s *SessionStore) IncrementPromptCounter(ctx context.Context, id int64) (int, error)

IncrementPromptCounter increments the prompt counter and returns the new value. Uses a single SQL query with RETURNING clause for optimal performance.

func (*SessionStore) ListSDKSessions added in v1.5.2

func (s *SessionStore) ListSDKSessions(ctx context.Context, project string, limit, offset int) ([]*models.SDKSession, int64, error)

ListSDKSessions returns a paginated list of SDK sessions, optionally filtered by project. Results are ordered by started_at DESC (newest first). Returns sessions and total count.

type SessionSummary

type SessionSummary struct {
	CreatedAt       string `gorm:"not null"`
	SDKSessionID    string `gorm:"index;not null"`
	Project         string `gorm:"index;not null"`
	Completed       sql.NullString
	Investigated    sql.NullString
	Learned         sql.NullString
	NextSteps       sql.NullString `gorm:"column:next_steps"`
	Notes           sql.NullString
	Request         sql.NullString
	PromptNumber    sql.NullInt64
	ID              int64 `gorm:"primaryKey;autoIncrement"`
	DiscoveryTokens int64 `gorm:"default:0"`
	CreatedAtEpoch  int64 `gorm:"index:idx_summaries_created,sort:desc;not null"`
}

SessionSummary represents a session summary.

func (*SessionSummary) BeforeCreate

func (s *SessionSummary) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps are set.

func (SessionSummary) TableName

func (SessionSummary) TableName() string

type Store

type Store struct {
	DB *gorm.DB
	// contains filtered or unexported fields
}

Store represents the GORM database connection with PostgreSQL support.

func NewStore

func NewStore(cfg Config) (*Store, error)

NewStore creates a new Store connected to PostgreSQL.

func (*Store) Close

func (s *Store) Close() error

Close closes the database connection.

func (*Store) ExecWithTimeout

func (s *Store) ExecWithTimeout(ctx context.Context, timeout time.Duration, query string, args ...any) error

ExecWithTimeout executes a raw SQL query with timeout. Returns error if query takes longer than timeout.

func (*Store) GetDB

func (s *Store) GetDB() *gorm.DB

GetDB returns the GORM DB instance for standard queries.

func (*Store) GetMetrics

func (s *Store) GetMetrics() MetricsSummary

GetMetrics returns the current metrics without performing a health check.

func (*Store) GetRawDB

func (s *Store) GetRawDB() *sql.DB

GetRawDB returns the underlying *sql.DB for operations GORM can't handle. Use this for: - tsvector full-text search queries - pgvector operations - Complex raw SQL queries

func (*Store) HealthCheck

func (s *Store) HealthCheck(ctx context.Context) *HealthInfo

HealthCheck performs a comprehensive health check with latency measurement. Returns detailed health information including connection pool stats and query latency. Results are cached for healthCacheTTL (default 5 seconds) to reduce database load from frequent monitoring calls.

func (*Store) HealthCheckForce

func (s *Store) HealthCheckForce(ctx context.Context) *HealthInfo

HealthCheckForce performs a health check bypassing the cache. Use this when you need real-time health data (e.g., debugging, alerting).

func (*Store) Optimize

func (s *Store) Optimize(ctx context.Context) error

Optimize runs ANALYZE to update query planner statistics. Should be called periodically (e.g., daily) during low activity.

func (*Store) Ping

func (s *Store) Ping() error

Ping verifies the database connection is alive.

func (*Store) QueryRowWithTimeout

func (s *Store) QueryRowWithTimeout(ctx context.Context, timeout time.Duration, query string, args ...any) *sql.Row

QueryRowWithTimeout executes a row query with timeout.

func (*Store) ResetMetrics

func (s *Store) ResetMetrics()

ResetMetrics resets the metrics collector (useful for testing or after major changes).

func (*Store) Stats

func (s *Store) Stats() sql.DBStats

Stats returns database connection pool statistics.

func (*Store) TransactionWithTimeout

func (s *Store) TransactionWithTimeout(ctx context.Context, timeout time.Duration, fn func(*gorm.DB) error) error

TransactionWithTimeout wraps a transaction function with timeout handling. The transaction is automatically rolled back if the context times out.

func (*Store) WarmPool

func (s *Store) WarmPool(numConns int)

WarmPool pre-creates connections to avoid cold start latency.

func (*Store) WithTimeout

func (s *Store) WithTimeout(ctx context.Context, timeout time.Duration, operation string) (context.Context, context.CancelFunc)

WithTimeout wraps a context with the given timeout and logs slow queries. Returns the wrapped context and a cancel function that should be called when done.

type SummaryStore

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

SummaryStore provides summary-related database operations using GORM.

func NewSummaryStore

func NewSummaryStore(store *Store) *SummaryStore

NewSummaryStore creates a new summary store.

func (*SummaryStore) GetAllRecentSummaries

func (s *SummaryStore) GetAllRecentSummaries(ctx context.Context, limit int) ([]*models.SessionSummary, error)

GetAllRecentSummaries retrieves recent summaries across all projects.

func (*SummaryStore) GetAllSummaries

func (s *SummaryStore) GetAllSummaries(ctx context.Context) ([]*models.SessionSummary, error)

GetAllSummaries retrieves all summaries (for vector rebuild).

func (*SummaryStore) GetRecentSummaries

func (s *SummaryStore) GetRecentSummaries(ctx context.Context, project string, limit int) ([]*models.SessionSummary, error)

GetRecentSummaries retrieves recent summaries for a project.

func (*SummaryStore) GetSummariesByIDs

func (s *SummaryStore) GetSummariesByIDs(ctx context.Context, ids []int64, orderBy string, limit int) ([]*models.SessionSummary, error)

GetSummariesByIDs retrieves summaries by a list of IDs.

func (*SummaryStore) StoreSummary

func (s *SummaryStore) StoreSummary(ctx context.Context, sdkSessionID, project string, summary *models.ParsedSummary, promptNumber int, discoveryTokens int64) (int64, int64, error)

StoreSummary stores a new session summary.

type TelemetrySnapshot

type TelemetrySnapshot struct {
	ID             int64  `gorm:"primaryKey;autoIncrement"`
	SnapshotType   string `gorm:"type:text;not null;index:idx_telemetry_type_time,priority:1"`
	Project        string `gorm:"type:text;not null;default:''"`
	Data           string `gorm:"type:jsonb;not null"`
	CreatedAtEpoch int64  `gorm:"not null;index:idx_telemetry_type_time,priority:2,sort:desc"`
}

TelemetrySnapshot stores periodic telemetry measurements.

func (TelemetrySnapshot) TableName

func (TelemetrySnapshot) TableName() string

type TokenStore added in v1.0.0

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

TokenStore provides API token database operations using GORM.

func NewTokenStore added in v1.0.0

func NewTokenStore(store *Store) *TokenStore

NewTokenStore creates a new token store.

func (*TokenStore) BatchIncrementStats added in v1.0.0

func (s *TokenStore) BatchIncrementStats(ctx context.Context, counts map[string]int) error

BatchIncrementStats increments request_count and updates last_used_at for multiple tokens in a single UPDATE statement. Used by the buffered stats flusher to reduce DB round-trips.

func (*TokenStore) Create added in v1.0.0

func (s *TokenStore) Create(ctx context.Context, name, tokenHash, tokenPrefix, scope string) (*APIToken, error)

Create stores a new API token record.

func (*TokenStore) FindByPrefix added in v1.0.0

func (s *TokenStore) FindByPrefix(ctx context.Context, prefix string) ([]APIToken, error)

FindByPrefix looks up all non-revoked tokens matching the given prefix. Multiple tokens may share a prefix in the non-unique index, so callers must iterate over the returned slice and compare bcrypt hashes to find the matching token.

func (*TokenStore) GetByID added in v1.0.0

func (s *TokenStore) GetByID(ctx context.Context, id string) (*APIToken, error)

GetByID retrieves a token by ID with full stats.

func (*TokenStore) IncrementErrorCount added in v1.0.0

func (s *TokenStore) IncrementErrorCount(ctx context.Context, id string) error

IncrementErrorCount increments the error_count for a token.

func (*TokenStore) IncrementStats added in v1.0.0

func (s *TokenStore) IncrementStats(ctx context.Context, id string) error

IncrementStats increments request_count and updates last_used_at for a token.

func (*TokenStore) List added in v1.0.0

func (s *TokenStore) List(ctx context.Context) ([]APIToken, error)

List returns all tokens (including revoked, for audit trail). Token hashes are included in the DB model but callers should exclude them from API responses.

func (*TokenStore) Revoke added in v1.0.0

func (s *TokenStore) Revoke(ctx context.Context, id string) error

Revoke marks a token as revoked.

type UserPrompt

type UserPrompt struct {
	ClaudeSessionID     string `gorm:"index;not null;uniqueIndex:idx_user_prompts_session_number_unique,priority:1"`
	PromptText          string `gorm:"type:text;not null"`
	CreatedAt           string `gorm:"not null"`
	ID                  int64  `gorm:"primaryKey;autoIncrement"`
	PromptNumber        int    `gorm:"index;not null;uniqueIndex:idx_user_prompts_session_number_unique,priority:2"`
	MatchedObservations int    `gorm:"default:0"`
	CreatedAtEpoch      int64  `gorm:"index:idx_prompts_created,sort:desc;not null"`
}

UserPrompt represents a user prompt.

func (*UserPrompt) BeforeCreate

func (p *UserPrompt) BeforeCreate(tx *gorm.DB) error

BeforeCreate hook to ensure timestamps are set.

func (UserPrompt) TableName

func (UserPrompt) TableName() string

type VersionedDocument added in v1.7.0

type VersionedDocument struct {
	ID          int64     `gorm:"primaryKey;autoIncrement"`
	Path        string    `gorm:"not null"`
	Project     string    `gorm:"not null"`
	Version     int       `gorm:"not null;default:1"`
	Content     string    `gorm:"not null"`
	ContentHash string    `gorm:"column:content_hash;not null"`
	DocType     string    `gorm:"column:doc_type;not null;default:markdown"`
	Metadata    string    `gorm:"type:jsonb;default:'{}'"`
	Author      string    `gorm:"not null"`
	CreatedAt   time.Time `gorm:"column:created_at;not null;autoCreateTime"`
}

VersionedDocument is the GORM model for the documents table created by migration 051. It stores versioned document content for AI agent collaboration workflows. Named VersionedDocument to avoid collision with the RAG Document model in models.go.

func (VersionedDocument) TableName added in v1.7.0

func (VersionedDocument) TableName() string

TableName maps VersionedDocument to the versioned_documents table.

type VersionedDocumentComment added in v1.7.0

type VersionedDocumentComment struct {
	ID         int64     `gorm:"primaryKey;autoIncrement"`
	DocumentID int64     `gorm:"column:document_id;not null"`
	Author     string    `gorm:"not null"`
	Content    string    `gorm:"not null"`
	LineStart  *int      `gorm:"column:line_start"`
	LineEnd    *int      `gorm:"column:line_end"`
	Status     string    `gorm:"not null;default:open"`
	CreatedAt  time.Time `gorm:"column:created_at;not null;autoCreateTime"`
}

VersionedDocumentComment is the GORM model for the document_comments table.

func (VersionedDocumentComment) TableName added in v1.7.0

func (VersionedDocumentComment) TableName() string

TableName maps VersionedDocumentComment to the versioned_document_comments table.

type VersionedDocumentStore added in v1.7.0

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

VersionedDocumentStore provides CRUD operations for versioned documents and their associated comments (migration 051 schema).

func NewVersionedDocumentStore added in v1.7.0

func NewVersionedDocumentStore(store *Store) *VersionedDocumentStore

NewVersionedDocumentStore creates a new VersionedDocumentStore backed by the given Store.

func (*VersionedDocumentStore) AddComment added in v1.7.0

func (s *VersionedDocumentStore) AddComment(
	ctx context.Context,
	documentID int64,
	author, content string,
	lineStart, lineEnd *int,
) (int64, error)

AddComment inserts a comment associated with the given document ID. lineStart and lineEnd are optional (nil = not line-anchored). Returns the ID of the newly created comment.

func (*VersionedDocumentStore) Create added in v1.7.0

func (s *VersionedDocumentStore) Create(
	ctx context.Context,
	path, project, content, docType, metadata, author string,
) (int64, error)

Create inserts a new versioned document for the given path+project. It computes the SHA-256 content hash, determines the next version number (max existing version + 1), and returns the ID of the newly created row.

func (*VersionedDocumentStore) GetComments added in v1.7.0

func (s *VersionedDocumentStore) GetComments(ctx context.Context, documentID int64) ([]VersionedDocumentComment, error)

GetComments returns all comments for the given document ID, ordered by creation time ascending.

func (*VersionedDocumentStore) GetHistory added in v1.7.0

func (s *VersionedDocumentStore) GetHistory(ctx context.Context, path, project string, limit int) ([]VersionedDocument, error)

GetHistory returns all versions of a document for the given path+project, ordered by version descending (newest first). limit <= 0 means no row limit.

func (*VersionedDocumentStore) List added in v1.7.0

func (s *VersionedDocumentStore) List(ctx context.Context, project, docType, pathPrefix string, limit int) ([]VersionedDocument, error)

List returns the latest version of each distinct document path in a project. Optional filters: docType (exact match), pathPrefix (LIKE prefix match). limit <= 0 means no row limit. Uses DISTINCT ON (path) ORDER BY path, version DESC to return only the latest per path.

func (*VersionedDocumentStore) ReadLatest added in v1.7.0

func (s *VersionedDocumentStore) ReadLatest(ctx context.Context, path, project string) (*VersionedDocument, error)

ReadLatest returns the highest-versioned document for the given path+project. Returns gorm.ErrRecordNotFound if no document exists.

func (*VersionedDocumentStore) ReadVersion added in v1.7.0

func (s *VersionedDocumentStore) ReadVersion(ctx context.Context, path, project string, version int) (*VersionedDocument, error)

ReadVersion returns the document at the exact version specified. Returns gorm.ErrRecordNotFound if no matching row exists.

Jump to

Keyboard shortcuts

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