Skip to main content

ralph/cli/queue/
repair.rs

1//! Queue repair subcommand.
2//!
3//! Responsibilities:
4//! - Preview or apply recoverable queue normalization.
5//! - Ensure mutating repairs are undoable.
6//! - Narrate the operator continuation state instead of emergency-only repair wording.
7//!
8//! Not handled here:
9//! - Arbitrary manual queue surgery.
10//! - Non-queue recovery workflows.
11//!
12//! Invariants/assumptions:
13//! - `--dry-run` is read-only.
14//! - Mutating repairs create an undo checkpoint before queue files change.
15
16use anyhow::Result;
17use clap::Args;
18
19use crate::cli::machine::MachineQueueRepairArgs;
20use crate::config::Resolved;
21
22/// Arguments for `ralph queue repair`.
23#[derive(Args)]
24pub struct RepairArgs {
25    /// Show what Ralph would normalize without writing queue files.
26    #[arg(long)]
27    pub dry_run: bool,
28}
29
30pub(crate) fn handle(resolved: &Resolved, force: bool, args: RepairArgs) -> Result<()> {
31    let document = crate::cli::machine::build_queue_repair_document(
32        resolved,
33        force,
34        &MachineQueueRepairArgs {
35            dry_run: args.dry_run,
36        },
37    )?;
38
39    println!("{}", document.continuation.headline);
40    println!("{}", document.continuation.detail);
41
42    if let Some(blocking) = document
43        .blocking
44        .as_ref()
45        .or(document.continuation.blocking.as_ref())
46    {
47        println!();
48        println!(
49            "Operator state: {}",
50            format!("{:?}", blocking.status).to_lowercase()
51        );
52        println!("{}", blocking.message);
53        if !blocking.detail.is_empty() {
54            println!("{}", blocking.detail);
55        }
56    }
57
58    println!();
59    println!("Repair report:");
60    println!("{}", serde_json::to_string_pretty(&document.report)?);
61
62    if !document.continuation.next_steps.is_empty() {
63        println!();
64        println!("Next:");
65        for (index, step) in document.continuation.next_steps.iter().enumerate() {
66            println!("  {}. {} — {}", index + 1, step.command, step.detail);
67        }
68    }
69
70    Ok(())
71}