Problem
The current design uses max_entries as a capacity cap with LRU/LeastRelevant eviction at the boundary. The 24h recency half-life helps ranking but does not delete old entries. Over weeks/months of daily use, the database accumulates entries where even the "top" entries may be months old and irrelevant.
Without age-based pruning, a user with max_entries: 500 could have all 500 entries spanning 3 months — the DB stays bounded by count but not by freshness.
Proposed Solution
Add a configurable TTL (time-to-live) that auto-deletes entries older than N days.
Config Change
pub struct CoreConfig {
// ... existing fields ...
/// Maximum age of entries in seconds. Entries older than this are pruned.
/// `None` disables TTL pruning. Default: 30 days (2_592_000 seconds).
pub max_age_seconds: Option<u64>,
}
Engine Change
Add prune_expired(&self) -> Result<usize> to ContextEngine:
- Runs
DELETE FROM entries WHERE timestamp < ? with now - max_age_seconds
- Returns count of deleted rows
- Called at the start of
save_snapshot() (before the capacity eviction check)
- Also exposed as a standalone method for CLI/napi callers
CLI Surface
context-forge vacuum --db <path> [--max-age-days <n>]
Prunes expired entries and runs PRAGMA optimize + VACUUM.
SQLite Maintenance
PRAGMA optimize — lets SQLite re-analyze query plans periodically
VACUUM — reclaims disk space after bulk deletes (optional, can be expensive on large DBs)
Complexity
Low — single SQL DELETE statement, one new config field, one new engine method.
Prep During V1
CoreConfig already uses serde — adding max_age_seconds: Option<u64> is backward-compatible (defaults to None via #[serde(default)])
- No schema changes needed —
idx_entries_timestamp already exists for efficient range deletes
- The
vacuum CLI subcommand can be added alongside Phase 4 CLI work
Dependencies
- Can be implemented after Phase 4 (CLI) for the
vacuum subcommand surface
- Engine-side
prune_expired() could land as early as Phase 3 patch
- No schema migration required — uses existing
timestamp column + index
Labels
backlog, core, cli
Problem
The current design uses
max_entriesas a capacity cap with LRU/LeastRelevant eviction at the boundary. The 24h recency half-life helps ranking but does not delete old entries. Over weeks/months of daily use, the database accumulates entries where even the "top" entries may be months old and irrelevant.Without age-based pruning, a user with
max_entries: 500could have all 500 entries spanning 3 months — the DB stays bounded by count but not by freshness.Proposed Solution
Add a configurable TTL (time-to-live) that auto-deletes entries older than N days.
Config Change
Engine Change
Add
prune_expired(&self) -> Result<usize>toContextEngine:DELETE FROM entries WHERE timestamp < ?withnow - max_age_secondssave_snapshot()(before the capacity eviction check)CLI Surface
SQLite Maintenance
PRAGMA optimize— lets SQLite re-analyze query plans periodicallyVACUUM— reclaims disk space after bulk deletes (optional, can be expensive on large DBs)Complexity
Low — single SQL
DELETEstatement, one new config field, one new engine method.Prep During V1
CoreConfigalready usesserde— addingmax_age_seconds: Option<u64>is backward-compatible (defaults toNonevia#[serde(default)])idx_entries_timestampalready exists for efficient range deletesvacuumCLI subcommand can be added alongside Phase 4 CLI workDependencies
vacuumsubcommand surfaceprune_expired()could land as early as Phase 3 patchtimestampcolumn + indexLabels
backlog, core, cli