feat: Vestige v1.9.1 AUTONOMIC — self-regulating memory with graph visualization

Retention Target System: auto-GC low-retention memories during consolidation
(VESTIGE_RETENTION_TARGET env var, default 0.8). Auto-Promote: memories
accessed 3+ times in 24h get frequency-dependent potentiation. Waking SWR
Tagging: promoted memories get preferential 70/30 dream replay. Improved
Consolidation Scheduler: triggers on 6h staleness or 2h active use.

New tools: memory_health (retention dashboard with distribution buckets,
trend tracking, recommendations) and memory_graph (subgraph export with
Fruchterman-Reingold force-directed layout, up to 200 nodes).

Dream connections now persist to database via save_connection(), enabling
memory_graph traversal. Schema Migration V8 adds waking_tag, utility_score,
times_retrieved/useful columns and retention_snapshots table. 21 MCP tools.

v1.9.1 fixes: ConnectionRecord export, UTF-8 safe truncation, link_type
normalization, utility_score clamping, only-new-connections persistence,
70/30 split capacity fill, nonexistent center_id error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sam Valladares 2026-02-21 02:02:06 -06:00
parent c29023dd80
commit 5b90a73055
62 changed files with 2922 additions and 931 deletions

View file

@ -394,7 +394,7 @@ fn run_consolidate() -> anyhow::Result<()> {
println!("Running memory consolidation cycle...");
println!();
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
let result = storage.run_consolidation()?;
println!("{}: {}", "Nodes Processed".white().bold(), result.nodes_processed);
@ -456,7 +456,7 @@ fn run_restore(backup_path: PathBuf) -> anyhow::Result<()> {
// Initialize storage
println!("Initializing storage...");
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
println!("Generating embeddings and ingesting memories...");
println!();
@ -728,7 +728,7 @@ fn run_gc(
println!("{}", "=== Vestige Garbage Collection ===".cyan().bold());
println!();
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
let all_nodes = fetch_all_nodes(&storage)?;
let now = Utc::now();
@ -892,7 +892,7 @@ fn run_ingest(
valid_until: None,
};
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
// Try smart_ingest (PE Gating) if available, otherwise regular ingest
#[cfg(all(feature = "embeddings", feature = "vector-search"))]
@ -943,7 +943,7 @@ fn run_dashboard(port: u16, open_browser: bool) -> anyhow::Result<()> {
println!();
println!("Starting dashboard at {}...", format!("http://127.0.0.1:{}", port).cyan());
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
// Try to initialize embeddings for search support
#[cfg(feature = "embeddings")]
@ -957,7 +957,7 @@ fn run_dashboard(port: u16, open_browser: bool) -> anyhow::Result<()> {
}
}
let storage = std::sync::Arc::new(tokio::sync::Mutex::new(storage));
let storage = std::sync::Arc::new(storage);
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async move {

View file

@ -43,7 +43,7 @@ fn main() -> anyhow::Result<()> {
// Initialize storage (uses default path)
println!("Initializing storage...");
let mut storage = Storage::new(None)?;
let storage = Storage::new(None)?;
println!("Generating embeddings and ingesting memories...\n");