use std::path::PathBuf;
use clap::{Parser, ValueEnum};
use crate::ValidationError;
use crate::commands::Command;
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
Text,
Json,
}
#[derive(Debug, Clone, Parser)]
#[command(
version,
long_version = nils_build_info::long_version(env!("CARGO_PKG_VERSION")),
about = "Rust implementation of the plan-issue orchestration workflow.",
long_about = "Run live or local plan-issue orchestration flows with a typed command contract and deterministic runtime workspace.",
after_help = "EXAMPLES:\n plan-issue start-plan --issue 123 --repo owner/repo\n plan-issue-local build-task-spec --plan docs/plans/example/example-plan.md --sprint 1\n plan-issue status-plan --issue 123 --format json\n\nENVIRONMENT:\n PLAN_ISSUE_HOME Runtime workspace override.\n XDG_STATE_HOME Base state directory when PLAN_ISSUE_HOME is unset.\n HOME Fallback base state directory.\n\nEXIT CODES:\n 0 success\n 1 runtime error\n 64 command-line usage error\n 65 invalid input data\n\nUSAGE PATHS:\n - plan-issue: live GitHub-backed orchestration\n - plan-issue-local: local-first rehearsal and dry-run flow\n\nUNSUPPORTED IN PLAN-ISSUE-LOCAL:\n - Any --issue path that requires live GitHub reads/writes (for example: status-plan/ready-plan with --issue, close-plan with --issue-only, cleanup-worktrees).\n\nUSE INSTEAD:\n - plan-issue <command> ... (live GitHub path)\n - --body-file + --dry-run flows (local rehearsal path where supported)\n\nRUNTIME WORKSPACE:\n - Pass --state-dir <PATH> to override the workspace root, or export PLAN_ISSUE_HOME.\n - Default: ${XDG_STATE_HOME:-$HOME/.local/state}/plan-issue.\n\nBoth binaries share the same typed command contract.",
disable_help_subcommand = true
)]
pub struct Cli {
/// Pass-through repository target for issue/PR/MR operations.
#[arg(long, global = true, value_name = "owner/repo")]
pub repo: Option<String>,
/// Print write actions without mutating GitHub state.
#[arg(long, global = true)]
pub dry_run: bool,
/// Bypass markdown payload guard for GitHub body/comment writes.
#[arg(short = 'f', long, global = true)]
pub force: bool,
/// Hidden alias for `--format json` (kept for backwards compatibility).
#[arg(long, global = true, hide = true, conflicts_with = "format")]
pub json: bool,
/// Output format.
#[arg(long, global = true, value_enum)]
pub format: Option<OutputFormat>,
/// Runtime workspace root. Overrides $PLAN_ISSUE_HOME and the
/// $XDG_STATE_HOME/plan-issue default. Artefacts land under
/// `<state-dir>/out/plan-issue-delivery/...`.
#[arg(long, global = true, value_name = "PATH")]
pub state_dir: Option<PathBuf>,
#[command(subcommand)]
pub command: Command,
}
impl Cli {
pub fn resolve_output_format(&self) -> Result<OutputFormat, ValidationError> {
if self.json || matches!(self.format, Some(OutputFormat::Json)) {
return Ok(OutputFormat::Json);
}
Ok(OutputFormat::Text)
}
pub fn validate(&self) -> Result<(), ValidationError> {
self.command.validate(self.dry_run)
}
}