1use anyhow::Result;
4use clap::Args;
5
6use crate::config::Resolved;
7use crate::queue;
8
9use super::StatusArg;
10
11#[derive(Args)]
13#[command(
14 after_long_help = "Prune removes old tasks from .ralph/done.jsonc while preserving recent history.\n\nSafety:\n --keep-last always protects the N most recently completed tasks (by completed_at).\n If no filters are provided, all tasks are pruned except those protected by --keep-last.\n Missing or invalid completed_at timestamps are treated as oldest for keep-last ordering\n but do NOT match the age filter (safety-first).\n\nExamples:\n ralph queue prune --dry-run --age 30 --status rejected\n ralph queue prune --keep-last 100\n ralph queue prune --age 90\n ralph queue prune --age 30 --status done --keep-last 50"
15)]
16pub struct QueuePruneArgs {
17 #[arg(long)]
19 pub age: Option<u32>,
20
21 #[arg(long, value_enum)]
23 pub status: Vec<StatusArg>,
24
25 #[arg(long)]
27 pub keep_last: Option<u32>,
28
29 #[arg(long)]
31 pub dry_run: bool,
32}
33
34pub(crate) fn handle(resolved: &Resolved, force: bool, args: QueuePruneArgs) -> Result<()> {
35 let _queue_lock = queue::acquire_queue_lock(&resolved.repo_root, "queue prune", force)?;
36
37 if !args.dry_run {
39 crate::undo::create_undo_snapshot(resolved, "queue prune")?;
40 }
41
42 let report: queue::PruneReport = queue::prune_done_tasks(
43 &resolved.done_path,
44 queue::PruneOptions {
45 age_days: args.age,
46 statuses: args.status.into_iter().map(|s| s.into()).collect(),
47 keep_last: args.keep_last,
48 dry_run: args.dry_run,
49 },
50 )?;
51 if args.dry_run {
52 log::info!("Dry run: would prune {} task(s).", report.pruned_ids.len());
53 if !report.pruned_ids.is_empty() {
54 log::info!("Pruned IDs: {}", report.pruned_ids.join(", "));
55 }
56 if !report.kept_ids.is_empty() {
57 log::info!("Kept IDs: {}", report.kept_ids.join(", "));
58 }
59 } else {
60 if report.pruned_ids.is_empty() {
61 log::info!("No tasks pruned.");
62 } else {
63 log::info!("Pruned {} task(s).", report.pruned_ids.len());
64 }
65 if !report.kept_ids.is_empty() {
66 log::debug!("Kept {} task(s).", report.kept_ids.len());
67 }
68 }
69 Ok(())
70}