1use crate::core::config;
5use crate::shell::cli::workspace_path;
6use crate::store::Store;
7use anyhow::{Context, Result};
8use std::path::Path;
9
10pub fn cmd_gc(workspace: Option<&Path>, days: Option<u32>, vacuum: bool) -> Result<()> {
12 let ws = workspace_path(workspace)?;
13 let cfg = config::load(&ws)?;
14 let keep = days.unwrap_or(cfg.retention.hot_days);
15 if keep == 0 {
16 anyhow::bail!(
17 "refusing to prune: keep window is 0 days (unlimited). \
18 Set [retention].hot_days > 0 or pass --days <N>"
19 );
20 }
21 let store = Store::open(&ws.join(".kaizen/kaizen.db"))?;
22 let now = std::time::SystemTime::now()
23 .duration_since(std::time::UNIX_EPOCH)
24 .unwrap_or_default()
25 .as_millis() as u64;
26 let cutoff = now.saturating_sub((keep as u64).saturating_mul(86_400_000));
27 let stats = store
28 .prune_sessions_started_before(cutoff as i64)
29 .context("prune sessions")?;
30 println!(
31 "pruned {} sessions, {} events (cutoff started_at_ms < {})",
32 stats.sessions_removed, stats.events_removed, cutoff
33 );
34 if vacuum {
35 store.vacuum().context("VACUUM")?;
36 println!("vacuum complete");
37 }
38 Ok(())
39}