Skip to main content

ralph/cli/machine/
handle.rs

1//! Top-level routing for `ralph machine`.
2//!
3//! Responsibilities:
4//! - Dispatch machine subcommands to focused handlers.
5//! - Keep schema/config/system/doctor branches centralized and thin.
6//! - Emit only versioned JSON machine documents on stdout.
7//!
8//! Not handled here:
9//! - Machine queue/task/run business logic.
10//! - Machine contract type definitions.
11//! - Human-facing CLI rendering.
12//!
13//! Invariants/assumptions:
14//! - Machine routing never emits prose on stdout.
15//! - Schema output stays aligned with the machine contract types.
16
17use anyhow::Result;
18use schemars::schema_for;
19use serde_json::json;
20
21use crate::cli::machine::args::{
22    MachineArgs, MachineCommand, MachineConfigCommand, MachineDoctorCommand, MachineSystemCommand,
23};
24use crate::cli::machine::common::build_config_resolve_document;
25use crate::cli::machine::io::print_json;
26use crate::cli::machine::{queue, run, task};
27use crate::commands::{cli_spec, doctor};
28use crate::config;
29use crate::contracts::{
30    MACHINE_CLI_SPEC_VERSION, MACHINE_DOCTOR_REPORT_VERSION, MACHINE_SYSTEM_INFO_VERSION,
31    MachineCliSpecDocument, MachineConfigResolveDocument, MachineDashboardReadDocument,
32    MachineDecomposeDocument, MachineDoctorReportDocument, MachineGraphReadDocument,
33    MachineParallelStatusDocument, MachineQueueReadDocument, MachineQueueRepairDocument,
34    MachineQueueUndoDocument, MachineQueueValidateDocument, MachineRunEventEnvelope,
35    MachineRunSummaryDocument, MachineSystemInfoDocument, MachineTaskCreateDocument,
36    MachineTaskCreateRequest, MachineTaskMutationDocument,
37};
38
39pub fn handle_machine(args: MachineArgs, force: bool) -> Result<()> {
40    match args.command {
41        MachineCommand::System(args) => match args.command {
42            MachineSystemCommand::Info => print_json(&MachineSystemInfoDocument {
43                version: MACHINE_SYSTEM_INFO_VERSION,
44                cli_version: env!("CARGO_PKG_VERSION").to_string(),
45            }),
46        },
47        MachineCommand::Queue(args) => queue::handle_queue(args, force),
48        MachineCommand::Config(args) => match args.command {
49            MachineConfigCommand::Resolve => {
50                let resolved = config::resolve_from_cwd()?;
51                let repo_trust = config::load_repo_trust(&resolved.repo_root)?;
52                let dirty_repo = crate::git::status_porcelain(&resolved.repo_root)
53                    .map(|status| !status.trim().is_empty())
54                    .unwrap_or(false);
55                let resume_preview = crate::cli::machine::common::build_resume_preview(
56                    &resolved, None, true, true, false,
57                )?;
58                print_json(&build_config_resolve_document(
59                    &resolved,
60                    repo_trust.is_trusted(),
61                    dirty_repo,
62                    resume_preview,
63                ))
64            }
65        },
66        MachineCommand::Task(args) => task::handle_task(args, force),
67        MachineCommand::Run(args) => run::handle_run(*args),
68        MachineCommand::Doctor(args) => match args.command {
69            MachineDoctorCommand::Report => {
70                let resolved = config::resolve_from_cwd_for_doctor()?;
71                let report = doctor::run_doctor(&resolved, false)?;
72                print_json(&MachineDoctorReportDocument {
73                    version: MACHINE_DOCTOR_REPORT_VERSION,
74                    blocking: report.blocking.clone(),
75                    report: serde_json::to_value(report)?,
76                })
77            }
78        },
79        MachineCommand::CliSpec => print_json(&MachineCliSpecDocument {
80            version: MACHINE_CLI_SPEC_VERSION,
81            spec: cli_spec::build_cli_spec(),
82        }),
83        MachineCommand::Schema => print_json(&json!({
84            "system_info": schema_for!(MachineSystemInfoDocument),
85            "queue_read": schema_for!(MachineQueueReadDocument),
86            "queue_validate": schema_for!(MachineQueueValidateDocument),
87            "queue_repair": schema_for!(MachineQueueRepairDocument),
88            "queue_undo": schema_for!(MachineQueueUndoDocument),
89            "config_resolve": schema_for!(MachineConfigResolveDocument),
90            "task_create_request": schema_for!(MachineTaskCreateRequest),
91            "task_create": schema_for!(MachineTaskCreateDocument),
92            "task_mutation": schema_for!(MachineTaskMutationDocument),
93            "graph_read": schema_for!(MachineGraphReadDocument),
94            "dashboard_read": schema_for!(MachineDashboardReadDocument),
95            "decompose": schema_for!(MachineDecomposeDocument),
96            "doctor_report": schema_for!(MachineDoctorReportDocument),
97            "parallel_status": schema_for!(MachineParallelStatusDocument),
98            "cli_spec": schema_for!(MachineCliSpecDocument),
99            "run_event": schema_for!(MachineRunEventEnvelope),
100            "run_summary": schema_for!(MachineRunSummaryDocument),
101        })),
102    }
103}