/** * CLI for split-exec: parse plan file path and options. * WHY Commander: Same as prr/pill/story/split-plan; consistent option parsing. */ import { Command } from 'commander'; import chalk from 'chalk'; export interface SplitExecOptions { workdir?: string; dryRun: boolean; yes: boolean; verbose: boolean; forcePush: boolean; /** Run pill analysis on output log when the run finishes. */ pill: boolean; /** Path to rewrite plan (.split-rewrite-plan.md/.yaml/.json). If unset, looked up beside group plan. */ rewritePlan?: string; /** Suffix for rebuild branch (e.g. -rebuild). When using rewrite plan, push to newBranch+suffix first. */ rebuildSuffix: string; /** When true and rewrite plan was used, force-push each rebuild branch over the original branch. */ promote: boolean; } export interface SplitExecParsedArgs { planPath: string; options: SplitExecOptions; } export function createCLI(): Command { const program = new Command(); program .name('split-exec') .description( 'Execute a split plan: clone repo, cherry-pick commits per split, push branches, create new PRs. Processes one split at a time (iterative).' ) .argument('[plan-file]', 'Path to .split-plan.md (from split-plan); can also use --plan-file') .option('-p, --plan-file ', 'Path to .split-plan.md (alternative to positional)') .option('-w, --workdir ', 'Git workdir for clone and cherry-picks (default: .split-exec-workdir in cwd)') .option('-n, --dry-run', 'Only parse plan and print what would be done; do not clone, cherry-pick, or push', false) .option('-y, --yes', 'Skip confirmation prompts (not used yet; for future per-split confirm)', false) .option('-v, --verbose', 'Verbose logging', false) .option('--force-push', 'On push rejection (remote has newer commits), force-push to overwrite (use when re-running a plan)', false) .option('--pill', 'Run pill analysis on the output log when the run finishes', false) .option('--rewrite-plan ', 'Path to rewrite plan (.split-rewrite-plan.md/.yaml/.json). If unset, looked up beside group plan.') .option('--rebuild-suffix ', 'Suffix for rebuild branch when using rewrite plan (default: -rebuild)', '-rebuild') .option('--promote', 'After building rebuild branches, force-push each over the original branch (use when satisfied)', false); return program; } export function parseArgs(program: Command): SplitExecParsedArgs { program.parse(); const args = program.args as string[]; const opts = program.opts(); const planPath = (opts.planFile ?? args[0])?.trim(); if (!planPath) { program.outputHelp(); process.exit(1); } return { planPath, options: { workdir: opts.workdir ? String(opts.workdir).trim() : undefined, dryRun: opts.dryRun ?? false, yes: opts.yes ?? false, verbose: opts.verbose ?? false, forcePush: opts.forcePush ?? false, pill: opts.pill ?? false, rewritePlan: opts.rewritePlan ? String(opts.rewritePlan).trim() : undefined, rebuildSuffix: opts.rebuildSuffix != null ? String(opts.rebuildSuffix) : '-rebuild', promote: opts.promote ?? false, }, }; }