gorm

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Mar 15, 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 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 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 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"`
	Narrative                sql.NullString          `gorm:"type:text"`
	Concepts                 models.JSONStringArray  `gorm:"type:text"`
	FilesRead                models.JSONStringArray  `gorm:"type:text"`
	FilesModified            models.JSONStringArray  `gorm:"type:text"`
	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:"default:0"`
	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"`
}

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, conflictStore, relationStore any) *ObservationStore

NewObservationStore creates a new observation store. The conflictStore and relationStore parameters are optional (can be nil) and will be used in Phase 4.

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) 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) 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) 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, limit, offset int) ([]*models.Observation, int64, error)

GetAllRecentObservationsPaginated retrieves recent observations with pagination.

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) 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) 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, limit, offset int) ([]*models.Observation, int64, error)

GetObservationsByProjectStrictPaginated retrieves observations strictly from a project with pagination.

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

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

GetTopScoringObservations returns the highest-scoring observations.

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) 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) 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) 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) 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 int) ([]*models.Pattern, error)

GetActivePatterns retrieves all active 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 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) 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 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 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) 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 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 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.

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

Jump to

Keyboard shortcuts

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