arcature-cli 2026.1.1

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

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(crate) enum FrontendArg {
    React,
    Vue,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(crate) enum OutputFormat {
    Human,
    Json,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct NewOptions {
    pub(crate) destination: PathBuf,
    pub(crate) frontend: FrontendArg,
    /// When true, generate a project without the database subsystem (no
    /// `arcature-db` dependency, no `migration/` package, no `AppState`).
    pub(crate) no_db: bool,
}

/// The `arc db` subcommand family (Phase 4 spec §14).
///
/// `arc db` orchestrates lifecycle and delegates migration semantics to the
/// application-owned SeaORM migrator. Destructive commands (`fresh`/`reset`/
/// `refresh`) require `--force` — the flag IS the explicit confirmation
/// (Phase 4 spec §23: no interactive prompt, no hostname heuristic).
///
/// AP2.1-6 adds `arc db lint`: a deterministic, database-free classifier of
/// real PostgreSQL migration risks (destructive drops, unsafe `NOT NULL`,
/// type narrowing, dangerous renames, blocking indexes). It reads SQL from
/// stdin and never connects to a database.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum DbCommand {
    /// Apply pending migrations (`migrate` → SeaORM `up`).
    Migrate,
    /// Roll back applied migrations (`rollback` → SeaORM `down`). Optional
    /// step count.
    Rollback { steps: Option<u32> },
    /// Show migration status.
    Status,
    /// Drop all tables and reapply all migrations. Destructive — requires
    /// `--force`.
    Fresh { force: bool },
    /// Roll back all migrations. Destructive — requires `--force`.
    Reset { force: bool },
    /// Roll back all, then reapply all. Destructive — requires `--force`.
    Refresh { force: bool },
    /// Generate SQLx offline metadata (`cargo sqlx prepare --workspace`).
    Prepare,
    /// Check SQLx offline metadata is current (`cargo sqlx prepare --check`).
    PrepareCheck,
    /// Classify migration SQL for PostgreSQL risks (AP2.1-6). Reads SQL from
    /// stdin, never connects to a database. `--json` emits machine-readable
    /// output.
    Lint { format: OutputFormat },
}

/// The `arc make` subcommand (A13 spec; AP2.1-11 adds transactional
/// generators). Generates source files for the given kind. `--module`
/// scopes the generator to a module directory.
///
/// AP2.1-11 additions:
/// * `--dry-run` reports what would happen (conflicts included) without
///   touching the filesystem. Works for the transactional kinds (`mail`,
///   `test`) and the per-file kinds alike.
/// * `--force` explicitly overwrites an existing file. Default is refuse:
///   user files are never silently overwritten (PROGRAM.md AP2.1-11).
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct MakeOptions {
    pub(crate) kind: String,
    pub(crate) name: String,
    pub(crate) module: Option<String>,
    /// Report what would happen; touch no files.
    pub(crate) dry_run: bool,
    /// Explicitly overwrite an existing file.
    pub(crate) force: bool,
}

/// The `arc stubs` subcommand family (PROGRAM.md AP2.1-11). Publishes a fixed
/// set of real stub/scaffolding files into the application. The publish is a
/// transactional `plan::Plan`: conflict-detect → dry-run → stage →
/// rollback-on-failure. A pre-existing user file is never silently
/// overwritten; `--force` overwrites explicitly.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum StubsCommand {
    /// Publish stub/scaffolding files into the project.
    Publish {
        /// Report what would happen; touch no files.
        dry_run: bool,
        /// Explicitly overwrite existing stub files.
        force: bool,
    },
}

/// The `arc mcp` options (AP2.1-9). Runs the MCP server over stdio.
///
/// Capability flags are explicit opt-in per capability (master Reservation
/// #4). Safe defaults: read-only DB is always available; **destructive
/// writes are disabled by default and enabled only with
/// `--allow-destructive-writes`**; **arbitrary shell execution is never
/// available** — there is no flag for it, and a `shell` capability request
/// from a client is refused with a typed error. No arbitrary command
/// execution.
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub(crate) struct McpOptions {
    /// Explicit opt-in to the destructive-write capability (e.g. applying
    /// migrations through a future gated tool). Off by default. The
    /// shipped read-only tools require no capabilities, so this flag has no
    /// effect on the tools implemented this wave — it is the production
    /// capability-gating boundary the deferred destructive tools will
    /// require, exercised by negative tests now.
    pub(crate) allow_destructive_writes: bool,
}

/// The `arc release` subcommand family (ADR-0005 / Release V2). RV2.1
/// adds `validate`; RV2.3 adds `changes validate`; RV2.4 adds `graph`;
/// RV2.5 adds `version`; RV2.6 adds `plan`; RV2.7 adds `prepare`;
/// RV2.8 adds `platform validate`; RV2.9 adds `publish`.
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum ReleaseCommand {
    /// Validate every crate's `[package.metadata.arcature]` (side-effect-free).
    Validate(OutputFormat),
    /// Validate change fragments under `changes/` (side-effect-free).
    ChangesValidate(OutputFormat),
    /// Show the publishable dependency graph and topological order (side-effect-free).
    Graph(OutputFormat),
    /// Show current YBF versions and validate sibling dependency ranges (side-effect-free).
    Version(OutputFormat),
    /// Compute and display a proposed Release Plan (side-effect-free).
    Plan(OutputFormat),
    /// Materialize a committed Release Plan: manifest edits, plan TOML, fragment archive.
    Prepare { format: OutputFormat, dry_run: bool },
    /// Validate a Platform manifest against the workspace (side-effect-free).
    PlatformValidate {
        format: OutputFormat,
        platform: String,
    },
    /// Execute a committed Release Plan: selective topological publish,
    /// idempotent resume, create crate version tags (ADR-0005 Decision §6).
    ///
    /// `--dry-run` shows what would happen (which crates would publish, in
    /// what order, what tags would be created) without running `cargo publish`
    /// or creating git tags. The actual production publish runs in GitHub
    /// Actions / Trusted Publishing, not from this workstation command
    /// (ADR-0005 Decision §7).
    Publish { format: OutputFormat, dry_run: bool },
}

/// The `arc package` options (AP2.1-10). `arc package` assembles a
/// production artifact bundle at `dist/<app-target>/` from the `arc build`
/// output (the release binary + Vite's `public/build/`). Distinct from
/// `arc release` (RV2 framework publishing — ADR-0005).
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct PackageOptions {
    /// Skip the precondition `arc build` (assume the build output is fresh).
    pub no_build: bool,
    /// Override the output target name (defaults to `<app>-<host-target>`).
    pub target_label: Option<String>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum CliCommand {
    New(NewOptions),
    Install,
    Dev,
    Build,
    Package(PackageOptions),
    Check(OutputFormat),
    Doctor {
        format: OutputFormat,
        /// `arc doctor --checks` — run only the system-check framework
        /// (AP2.1-7) instead of the environment/certification diagnostics.
        checks_only: bool,
    },
    Exposure(OutputFormat),
    Routes(OutputFormat),
    Modules(OutputFormat),
    Services(OutputFormat),
    Schedule(OutputFormat),
    Run {
        name: String,
        arguments: Vec<String>,
    },
    Make(MakeOptions),
    Stubs(StubsCommand),
    Script {
        name: String,
        arguments: Vec<String>,
    },
    Db(DbCommand),
    Release(ReleaseCommand),
    Inspect(InspectTarget),
    /// `arc mcp` — the MCP (Model Context Protocol) server over stdio
    /// (AP2.1-9). Reads the canonical UAG and serves tool calls. Safe
    /// defaults: read-only, secrets redacted, shell disabled, destructive
    /// writes capability-gated.
    Mcp(McpOptions),
}

/// The `arc inspect` target (AP2.1-1). Reads the UAG metadata artifact and
/// presents a focused view: the whole application, a single route, or a
/// single module. All side-effect-free (no boot).
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) enum InspectTarget {
    /// `arc inspect app` — the whole application graph summary.
    App(OutputFormat),
    /// `arc inspect route <name>` — a single named route's details.
    Route { name: String, format: OutputFormat },
    /// `arc inspect model <name>` — a single module's metadata (the closest
    /// current analogue to a "model" until `#[model]` lands in AP2.1-6).
    Module { name: String, format: OutputFormat },
}