Documentation
¶
Overview ¶
Package decay implements the Ebbinghaus forgetting curve strength formula used by the SQLite backend (which cannot run SQL math via EXTRACT EPOCH).
Postgres computes strength inside the knowledge_ranked VIEW using native SQL. SQLite computes strength in Go using ComputeStrength before ordering results.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ComputeStrength ¶
ComputeStrength returns the Ebbinghaus-derived memory strength in [0, 1].
Formula (research-validated):
strength = clamp(importance * exp(-baseLambda * (1 - importance*0.8) * ageDays) * (1 + recallCount * 0.2), 0, 1)
Parameters:
- importance: intrinsic value of the item in [0, 1]; default 0.5.
- baseLambda: base decay rate; default 0.1.
- ageDays: days since last recall (or creation when never recalled).
- recallCount: number of times the item has been recalled; boosts retention.
Edge cases:
- ageDays < 0 is clamped to 0 (e.g. clocks skew).
- importance = 0 → strength = 0 regardless of recall (no value, no retention).
- baseLambda ≤ 0 falls back to 0.1 to avoid undefined behaviour (exp(-0*age)=1 always).
Types ¶
type AtomPruner ¶
AtomPruner is the minimal interface the Pruner needs from the atom store. atom.Store (Postgres) and sqlite.AtomStore (SQLite) both satisfy this via duck typing.
type Pruner ¶
type Pruner struct {
// contains filtered or unexported fields
}
Pruner runs the daily soft-prune job across all eligible stores. Decisions table is intentionally excluded.
func NewPruner ¶
func NewPruner(knowledge, concepts PrunerStore, atoms AtomPruner) *Pruner
NewPruner creates a Pruner. Pass nil for any store to skip pruning it.
func (*Pruner) Run ¶
func (p *Pruner) Run()
Run executes the daily soft-prune cycle. It is designed to be called from the gocron scheduler; all errors are logged at warn level so the scheduler keeps running other jobs.
Context is intentionally NOT the request context — each call creates its own timeout-scoped background context.
type PrunerStore ¶
type PrunerStore interface {
// SoftPruneDecayed sets archived_at=NOW() on rows where:
// - archived_at IS NULL (not already pruned)
// - created_at < cutoff (older than 90 days)
// - computed strength < threshold
// Returns the number of rows soft-deleted.
SoftPruneDecayed(ctx context.Context, cutoff time.Time, strengthThreshold float64) (int64, error)
}
PrunerStore is the minimal interface the Pruner needs from each table store. Only knowledge_items and concepts implement this; decisions is excluded by design (it is an audit trail / truth source).