arcature-cli 2026.1.1

Developer lifecycle CLI for Arcature applications.
Documentation
use std::fmt;

use arcature_templates::TemplateError;

use crate::metadata::SchemaError;
use crate::process::ProcessError;
use crate::project::ProjectError;
use crate::release::ReleaseError;
use crate::script::ScriptError;
use crate::tool::ToolError;

#[derive(Debug)]
pub(crate) enum CommandError {
    Generation(TemplateError),
    Process(ProcessError),
    Project(ProjectError),
    Script(ScriptError),
    Tool(ToolError),
    Report(serde_json::Error),
    Contract(String),
    Metadata(String),
    /// Loading or validating the UAG (Unified Application Graph) artifact
    /// failed — typed failure from the UAG read path (AP2.1-9).
    Schema(SchemaError),
    /// The MCP server failed — a typed failure from a tool, the capability
    /// gate, the JSON-RPC transport, or the UAG load path (AP2.1-9).
    Mcp(crate::commands::mcp::error::McpError),
    Unhealthy(&'static str),
    Db(crate::error::DbCommandError),
    Release(ReleaseError),
    Package(crate::commands::package::PackageError),
}

impl fmt::Display for CommandError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Generation(error) => error.fmt(formatter),
            Self::Process(error) => error.fmt(formatter),
            Self::Project(error) => error.fmt(formatter),
            Self::Script(error) => error.fmt(formatter),
            Self::Tool(error) => error.fmt(formatter),
            Self::Report(error) => write!(formatter, "cannot serialize health report: {error}"),
            Self::Contract(error) => write!(formatter, "Cross-Stack Linker failed: {error}"),
            Self::Metadata(error) => {
                write!(formatter, "application metadata inspection failed: {error}")
            }
            Self::Schema(error) => {
                write!(formatter, "application graph inspection failed: {error}")
            }
            Self::Mcp(error) => write!(formatter, "MCP server failed: {error}"),
            Self::Unhealthy(scope) => write!(formatter, "{scope} checks reported errors"),
            Self::Db(error) => error.fmt(formatter),
            Self::Release(error) => error.fmt(formatter),
            Self::Package(error) => error.fmt(formatter),
        }
    }
}

impl std::error::Error for CommandError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Generation(error) => Some(error),
            Self::Process(error) => Some(error),
            Self::Project(error) => Some(error),
            Self::Script(error) => Some(error),
            Self::Tool(error) => Some(error),
            Self::Report(error) => Some(error),
            Self::Contract(_) => None,
            Self::Metadata(_) => None,
            Self::Schema(error) => Some(error),
            Self::Mcp(error) => Some(error),
            Self::Unhealthy(_) => None,
            Self::Db(error) => Some(error),
            Self::Release(error) => Some(error),
            Self::Package(error) => Some(error),
        }
    }
}

impl From<TemplateError> for CommandError {
    fn from(value: TemplateError) -> Self {
        Self::Generation(value)
    }
}
impl From<ProcessError> for CommandError {
    fn from(value: ProcessError) -> Self {
        Self::Process(value)
    }
}
impl From<ProjectError> for CommandError {
    fn from(value: ProjectError) -> Self {
        Self::Project(value)
    }
}
impl From<ScriptError> for CommandError {
    fn from(value: ScriptError) -> Self {
        Self::Script(value)
    }
}
impl From<ToolError> for CommandError {
    fn from(value: ToolError) -> Self {
        Self::Tool(value)
    }
}
impl From<serde_json::Error> for CommandError {
    fn from(value: serde_json::Error) -> Self {
        Self::Report(value)
    }
}
impl From<crate::error::DbCommandError> for CommandError {
    fn from(value: crate::error::DbCommandError) -> Self {
        Self::Db(value)
    }
}
impl From<ReleaseError> for CommandError {
    fn from(value: ReleaseError) -> Self {
        Self::Release(value)
    }
}

impl From<crate::commands::package::PackageError> for CommandError {
    fn from(value: crate::commands::package::PackageError) -> Self {
        Self::Package(value)
    }
}
impl From<SchemaError> for CommandError {
    fn from(value: SchemaError) -> Self {
        Self::Schema(value)
    }
}
impl From<crate::commands::mcp::error::McpError> for CommandError {
    fn from(value: crate::commands::mcp::error::McpError) -> Self {
        Self::Mcp(value)
    }
}