From 6a2b835fdfb12a7065e9b3a1d7ab7cf603b52c2e Mon Sep 17 00:00:00 2001 From: Lukas May Date: Sun, 1 Feb 2026 11:51:54 +0100 Subject: [PATCH] feat(12-06): add plan CLI commands and architect decompose command Add CLI commands for plan management: - cw plan list --phase : List plans in a phase - cw plan create --phase --name : Create a plan - cw plan get : Get plan details - cw plan tasks : List tasks in a plan Add architect decompose command: - cw architect decompose : Spawn agent to decompose plan into tasks --- src/cli/index.ts | 116 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/src/cli/index.ts b/src/cli/index.ts index b48400f..7609557 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -800,6 +800,122 @@ export function createCli(serverHandler?: (port?: number) => Promise): Com } }); + // cw architect decompose + architectCommand + .command('decompose ') + .description('Decompose a plan into tasks') + .requiredOption('--name ', 'Agent name') + .option('-c, --context ', 'Additional context') + .action(async (planId: string, options: { name: string; context?: string }) => { + try { + const client = createDefaultTrpcClient(); + const agent = await client.spawnArchitectDecompose.mutate({ + name: options.name, + planId, + context: options.context, + }); + console.log(`Started architect agent in decompose mode`); + console.log(` Agent: ${agent.name} (${agent.id})`); + console.log(` Mode: ${agent.mode}`); + console.log(` Plan: ${planId}`); + } catch (error) { + console.error('Failed to start decompose:', (error as Error).message); + process.exit(1); + } + }); + + // Plan command group + const planCommand = program + .command('plan') + .description('Plan management'); + + // cw plan list --phase + planCommand + .command('list') + .description('List plans in a phase') + .requiredOption('--phase ', 'Phase ID') + .action(async (options: { phase: string }) => { + try { + const client = createDefaultTrpcClient(); + const plans = await client.listPlans.query({ phaseId: options.phase }); + if (plans.length === 0) { + console.log('No plans found'); + return; + } + console.table(plans.map(p => ({ + id: p.id, + number: p.number, + name: p.name, + status: p.status, + }))); + } catch (error) { + console.error('Failed to list plans:', (error as Error).message); + process.exit(1); + } + }); + + // cw plan create --phase --name + planCommand + .command('create') + .description('Create a plan in a phase') + .requiredOption('--phase ', 'Phase ID') + .requiredOption('--name ', 'Plan name') + .option('--description ', 'Plan description') + .action(async (options: { phase: string; name: string; description?: string }) => { + try { + const client = createDefaultTrpcClient(); + const plan = await client.createPlan.mutate({ + phaseId: options.phase, + name: options.name, + description: options.description, + }); + console.log(`Created plan: ${plan.id} (${plan.name})`); + } catch (error) { + console.error('Failed to create plan:', (error as Error).message); + process.exit(1); + } + }); + + // cw plan get + planCommand + .command('get ') + .description('Get plan details') + .action(async (id: string) => { + try { + const client = createDefaultTrpcClient(); + const plan = await client.getPlan.query({ id }); + console.log(JSON.stringify(plan, null, 2)); + } catch (error) { + console.error('Failed to get plan:', (error as Error).message); + process.exit(1); + } + }); + + // cw plan tasks + planCommand + .command('tasks ') + .description('List tasks in a plan') + .action(async (id: string) => { + try { + const client = createDefaultTrpcClient(); + const tasks = await client.listTasks.query({ planId: id }); + if (tasks.length === 0) { + console.log('No tasks found'); + return; + } + console.table(tasks.map(t => ({ + id: t.id, + order: t.order, + name: t.name, + type: t.type, + status: t.status, + }))); + } catch (error) { + console.error('Failed to list tasks:', (error as Error).message); + process.exit(1); + } + }); + return program; }