Documentation
¶
Overview ¶
Package store owns the SQLite index. The DB is a disposable cache of the knowledge file store: schema changes bump schemaVersion and trigger a full drop-and-rebuild — never an ALTER migration.
Index ¶
- Constants
- func GranLevel(g string) int
- type BM25Hit
- type CardStats
- type EmbedTarget
- type FileState
- type InjectionAgg
- type InjectionRecord
- type InjectionRow
- type Store
- func (s *Store) AddFeedback(ctx context.Context, cardID, kind string, delta float64) error
- func (s *Store) AllCardStats(ctx context.Context, now time.Time) (map[string]CardStats, error)
- func (s *Store) AllCards(ctx context.Context) ([]StoredCard, error)
- func (s *Store) AllCardsMeta(ctx context.Context) ([]StoredCard, error)
- func (s *Store) CardByID(ctx context.Context, id string) (StoredCard, error)
- func (s *Store) CardsByRowid(ctx context.Context, rowids []int64) ([]StoredCard, error)
- func (s *Store) Close() error
- func (s *Store) DailyTokens(ctx context.Context, days int) ([]int, error)
- func (s *Store) DeleteCardByPath(ctx context.Context, path string) error
- func (s *Store) Embeddings(ctx context.Context, model string) (map[int64][]float32, error)
- func (s *Store) FileStates(ctx context.Context) (map[string]FileState, error)
- func (s *Store) InjectedCardIDs(ctx context.Context) (map[string]bool, error)
- func (s *Store) InjectedLevels(ctx context.Context, sessionID string) (map[string]int, error)
- func (s *Store) InjectionAggs(ctx context.Context) ([]InjectionAgg, error)
- func (s *Store) MetaGet(ctx context.Context, key string) (string, error)
- func (s *Store) MetaSet(ctx context.Context, key, value string) error
- func (s *Store) MissingEmbeddings(ctx context.Context, model string) ([]EmbedTarget, error)
- func (s *Store) PenalizeAbandonedPointers(ctx context.Context, sessionID string) error
- func (s *Store) PruneStale(ctx context.Context, retainDays int) error
- func (s *Store) Rebuild(ctx context.Context) error
- func (s *Store) RecentInjections(ctx context.Context, limit int) ([]InjectionRow, error)
- func (s *Store) RecordInjections(ctx context.Context, sessionID, event, promptHash, cwd string, ...) error
- func (s *Store) ResetSession(ctx context.Context, sessionID string) error
- func (s *Store) SearchBM25(ctx context.Context, matchExpr string, limit int) ([]BM25Hit, error)
- func (s *Store) SessionCount(ctx context.Context) (int, error)
- func (s *Store) SessionTokens(ctx context.Context, sessionID string) (int, error)
- func (s *Store) SwapLastPrompt(ctx context.Context, sessionID, prompt string) (string, error)
- func (s *Store) UpsertCard(ctx context.Context, c knowledge.Card, mtime, size int64) error
- func (s *Store) UpsertEmbedding(ctx context.Context, rowid int64, model string, vec []float32, ...) error
- func (s *Store) UtilityMultipliers(ctx context.Context) (map[string]float64, error)
- type StoredCard
Constants ¶
const ( GranHook = "hook" GranSummary = "summary" GranBody = "body" )
Granularity levels, ordered: hook < summary < body. Session dedup is monotonic — a card is only re-sent at a strictly higher level (14.43).
const ( FeedbackInjected = "injected" FeedbackExpanded = "expanded" // expand_card pull — strong positive FeedbackReferenced = "referenced" // cited by a saved lesson — strongest positive; recorded by the Phase 4 miner FeedbackDownvoted = "downvoted" // explicit `culi down` (weight 1.0) or abandoned pointer (0.1) )
Feedback kinds — event counters on card_stats. Weights are applied at multiplier time (utilityWeights), so counters stay interpretable as decayed event counts.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type BM25Hit ¶
SearchBM25 runs an FTS5 MATCH over the corpus and returns (rowid, rank) pairs, best first. matchExpr MUST be pre-sanitized by the caller (internal/retrieve owns the sanitizer) — raw prompt text here is a bug.
type EmbedTarget ¶
type EmbedTarget struct {
Rowid int64
ContentHash string
Text string // title + summary — what gets embedded
}
EmbedTarget is a card needing (re-)embedding.
type FileState ¶
FileState is the (mtime, size) fingerprint the indexer compares before re-hashing a file.
type InjectionAgg ¶
type InjectionAgg struct {
Event string `json:"event"`
Granularity string `json:"granularity"`
Count int `json:"count"`
Tokens int `json:"tokens"`
}
InjectionAgg is one (event, granularity) bucket of the injection history. Only the retention window exists — PruneStale bounds it to ~7 days. JSON tags serve `culi stats --json` (snake_case like the rest of that schema).
type InjectionRecord ¶
InjectionRecord is one emitted card at one granularity.
type InjectionRow ¶
type InjectionRow struct {
SessionID string
TS string
Event string
CardID string
Granularity string
Tokens int
Cwd string
}
InjectionRow is one logged card injection with its timestamp — the raw material the review console groups into the Activity "Injections" view. Read-only, off the hot path.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store wraps the SQLite handle. Safe for concurrent use (database/sql pools; WAL allows one writer + many readers).
func Open ¶
Open opens (creating if needed) the index at path. WAL + busy_timeout are set per-connection via the DSN so every pooled connection gets them.
func (*Store) AddFeedback ¶
AddFeedback folds decay-to-now into a card's counters and bumps one of them. kind must be a Feedback* constant; delta is the event count (0.1 for an abandoned pointer, 1 otherwise).
func (*Store) AllCardStats ¶
AllCardStats returns every card's counters decayed to now — the raw material for stats' top-pulled / noisy lists. Off the hot path.
func (*Store) AllCards ¶
func (s *Store) AllCards(ctx context.Context) ([]StoredCard, error)
AllCards returns every card (corpus is small; callers filter in Go).
func (*Store) AllCardsMeta ¶
func (s *Store) AllCardsMeta(ctx context.Context) ([]StoredCard, error)
AllCardsMeta returns every card WITHOUT bodies — the hot-path scan. Bodies are hydrated per-candidate via CardsByRowid only for the few cards the packer actually emits.
func (*Store) CardsByRowid ¶
CardsByRowid hydrates specific rows (e.g. FTS hits), preserving no order.
func (*Store) DailyTokens ¶
DailyTokens returns injected-token totals per calendar day (UTC), oldest first, for up to the last `days` days present in the retention window — the Overview hero sparkline. Empty when nothing has been injected yet.
func (*Store) DeleteCardByPath ¶
DeleteCardByPath removes a vanished file's card + FTS row.
func (*Store) Embeddings ¶
Embeddings returns rowid → vector for every card whose stored vector is FRESH: same model and same content hash as the current card row. Stale vectors are simply absent — the funnel degrades per-card, never errors.
func (*Store) FileStates ¶
FileStates returns path → state for every indexed card.
func (*Store) InjectedCardIDs ¶
InjectedCardIDs returns the set of card IDs with at least one row in the injection log's retention window — the "was this card ever shown" half of the staleness report.
func (*Store) InjectedLevels ¶
InjectedLevels returns card_id → highest granularity level already injected in this session.
func (*Store) InjectionAggs ¶
func (s *Store) InjectionAggs(ctx context.Context) ([]InjectionAgg, error)
InjectionAggs aggregates the injection log for `culi stats`.
func (*Store) MissingEmbeddings ¶
MissingEmbeddings lists cards with no fresh vector for model.
func (*Store) PenalizeAbandonedPointers ¶
PenalizeAbandonedPointers applies the −0.5-equivalent nudge (0.1 downvote events × weight 5) to cards injected at hook granularity this session and never expanded. Only pointers earn negative inference: pushed bodies are unobservable (plan §9). Runs at session end, off the hot path.
func (*Store) PruneStale ¶
PruneStale deletes injection/session rows older than the retention window. Cheap, runs at SessionStart — keeps the disposable history bounded.
func (*Store) Rebuild ¶
Rebuild drops all tables and recreates the schema. Callers re-index from the file store afterwards.
func (*Store) RecentInjections ¶
RecentInjections returns injection-log rows newest first, capped at limit. The console groups them by session then by (ts, event) in Go; keeping the grouping out of SQL avoids a bespoke query the hot path never needs.
func (*Store) RecordInjections ¶
func (s *Store) RecordInjections(ctx context.Context, sessionID, event, promptHash, cwd string, recs []InjectionRecord) error
RecordInjections logs emitted cards for dedup + stats in one transaction. cwd is the working directory at injection time, stored for repo attribution in the review console ("" when unknown — e.g. a non-git prompt).
func (*Store) ResetSession ¶
ResetSession clears dedup state for a session (SessionStart with source=compact: the context window was rebuilt, prior injections are gone).
func (*Store) SearchBM25 ¶
func (*Store) SessionCount ¶
SessionCount returns the number of distinct sessions in the injection log.
func (*Store) SessionTokens ¶
SessionTokens sums the tokens injected into one session — the statusline's "what did this session cost so far" number.
func (*Store) SwapLastPrompt ¶
SwapLastPrompt returns the previous prompt for the gate's novelty check ("" if none) and stores the new one, bounded to maxStoredPrompt bytes.
func (*Store) UpsertCard ¶
UpsertCard inserts or replaces a card and its FTS row atomically.
func (*Store) UpsertEmbedding ¶
func (s *Store) UpsertEmbedding(ctx context.Context, rowid int64, model string, vec []float32, contentHash string) error
UpsertEmbedding stores one card's vector, replacing any prior row. The content hash ties the vector to the card revision it was computed from.
func (*Store) UtilityMultipliers ¶
UtilityMultipliers returns card_id → ranking multiplier, decayed read-side (no writes on the hot path). Laplace-smoothed and clamped to [0.5, 1.5]: feedback tunes ordering but can never bury a card (plan §9). Cards without stats are simply absent — callers treat missing as 1.0.