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    MachineWorkspaceCommand,
24};
25use crate::cli::machine::common::{
26    build_config_resolve_document, build_workspace_overview_document, machine_safety_context,
27};
28use crate::cli::machine::io::print_json;
29use crate::cli::machine::{queue, run, task};
30use crate::commands::{cli_spec, doctor};
31use crate::config;
32use crate::contracts::{
33    MACHINE_CLI_SPEC_VERSION, MACHINE_DOCTOR_REPORT_VERSION, MACHINE_SYSTEM_INFO_VERSION,
34    MachineCliSpecDocument, MachineConfigResolveDocument, MachineDashboardReadDocument,
35    MachineDecomposeDocument, MachineDoctorReportDocument, MachineErrorDocument,
36    MachineGraphReadDocument, MachineParallelStatusDocument, MachineQueueReadDocument,
37    MachineQueueRepairDocument, MachineQueueUndoDocument, MachineQueueValidateDocument,
38    MachineRunEventEnvelope, MachineRunSummaryDocument, MachineSystemInfoDocument,
39    MachineTaskCreateDocument, MachineTaskCreateRequest, MachineTaskMutationDocument,
40    MachineWorkspaceOverviewDocument,
41};
42
43pub fn handle_machine(args: MachineArgs, force: bool) -> Result<()> {
44    match args.command {
45        MachineCommand::System(args) => match args.command {
46            MachineSystemCommand::Info => print_json(&MachineSystemInfoDocument {
47                version: MACHINE_SYSTEM_INFO_VERSION,
48                cli_version: env!("CARGO_PKG_VERSION").to_string(),
49            }),
50        },
51        MachineCommand::Queue(args) => queue::handle_queue(args, force),
52        MachineCommand::Config(args) => match args.command {
53            MachineConfigCommand::Resolve => {
54                let resolved = config::resolve_from_cwd()?;
55                let (repo_trusted, dirty_repo) = machine_safety_context(&resolved)?;
56                let resume_preview = crate::cli::machine::common::build_resume_preview(
57                    &resolved, None, true, true, false,
58                )?;
59                print_json(&build_config_resolve_document(
60                    &resolved,
61                    repo_trusted,
62                    dirty_repo,
63                    resume_preview,
64                ))
65            }
66        },
67        MachineCommand::Workspace(args) => match args.command {
68            MachineWorkspaceCommand::Overview => {
69                let resolved = config::resolve_from_cwd()?;
70                let (repo_trusted, dirty_repo) = machine_safety_context(&resolved)?;
71                let resume_preview = crate::cli::machine::common::build_resume_preview(
72                    &resolved, None, true, true, false,
73                )?;
74                print_json(&build_workspace_overview_document(
75                    &resolved,
76                    repo_trusted,
77                    dirty_repo,
78                    resume_preview,
79                )?)
80            }
81        },
82        MachineCommand::Task(args) => task::handle_task(args, force),
83        MachineCommand::Run(args) => run::handle_run(*args),
84        MachineCommand::Doctor(args) => match args.command {
85            MachineDoctorCommand::Report => {
86                let resolved = config::resolve_from_cwd_for_doctor()?;
87                let report = doctor::run_doctor(&resolved, false)?;
88                print_json(&MachineDoctorReportDocument {
89                    version: MACHINE_DOCTOR_REPORT_VERSION,
90                    blocking: report.blocking.clone(),
91                    report: serde_json::to_value(report)?,
92                })
93            }
94        },
95        MachineCommand::CliSpec => print_json(&MachineCliSpecDocument {
96            version: MACHINE_CLI_SPEC_VERSION,
97            spec: cli_spec::build_cli_spec(),
98        }),
99        MachineCommand::Schema => print_json(&json!({
100            "system_info": schema_for!(MachineSystemInfoDocument),
101            "queue_read": schema_for!(MachineQueueReadDocument),
102            "queue_validate": schema_for!(MachineQueueValidateDocument),
103            "queue_repair": schema_for!(MachineQueueRepairDocument),
104            "queue_undo": schema_for!(MachineQueueUndoDocument),
105            "config_resolve": schema_for!(MachineConfigResolveDocument),
106            "workspace_overview": schema_for!(MachineWorkspaceOverviewDocument),
107            "task_create_request": schema_for!(MachineTaskCreateRequest),
108            "task_create": schema_for!(MachineTaskCreateDocument),
109            "task_mutation": schema_for!(MachineTaskMutationDocument),
110            "graph_read": schema_for!(MachineGraphReadDocument),
111            "dashboard_read": schema_for!(MachineDashboardReadDocument),
112            "decompose": schema_for!(MachineDecomposeDocument),
113            "doctor_report": schema_for!(MachineDoctorReportDocument),
114            "parallel_status": schema_for!(MachineParallelStatusDocument),
115            "cli_spec": schema_for!(MachineCliSpecDocument),
116            "machine_error": schema_for!(MachineErrorDocument),
117            "run_event": schema_for!(MachineRunEventEnvelope),
118            "run_summary": schema_for!(MachineRunSummaryDocument),
119        })),
120    }
121}