chore: apply requested changes
This commit is contained in:
@@ -8,7 +8,12 @@ import { Command } from 'commander';
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import ora, { type Ora } from 'ora';
|
import ora, { type Ora } from 'ora';
|
||||||
import { createTaskMasterCore, type TaskMasterCore } from '@tm/core';
|
import {
|
||||||
|
createTaskMasterCore,
|
||||||
|
type TaskMasterCore,
|
||||||
|
type Task,
|
||||||
|
type Subtask
|
||||||
|
} from '@tm/core';
|
||||||
import * as ui from '../utils/ui.js';
|
import * as ui from '../utils/ui.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,13 +25,32 @@ export interface AutopilotCommandOptions {
|
|||||||
dryRun?: boolean;
|
dryRun?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preflight check result for a single check
|
||||||
|
*/
|
||||||
|
export interface PreflightCheckResult {
|
||||||
|
success: boolean;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overall preflight check results
|
||||||
|
*/
|
||||||
|
export interface PreflightResult {
|
||||||
|
success: boolean;
|
||||||
|
testCommand: PreflightCheckResult;
|
||||||
|
gitWorkingTree: PreflightCheckResult;
|
||||||
|
requiredTools: PreflightCheckResult;
|
||||||
|
defaultBranch: PreflightCheckResult;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CLI-specific result type from autopilot command
|
* CLI-specific result type from autopilot command
|
||||||
*/
|
*/
|
||||||
export interface AutopilotCommandResult {
|
export interface AutopilotCommandResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
taskId: string;
|
taskId: string;
|
||||||
task?: any;
|
task?: Task;
|
||||||
error?: string;
|
error?: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
}
|
}
|
||||||
@@ -107,7 +131,7 @@ export class AutopilotCommand extends Command {
|
|||||||
|
|
||||||
// Display results
|
// Display results
|
||||||
this.displayResults(result, options);
|
this.displayResults(result, options);
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (spinner) {
|
if (spinner) {
|
||||||
spinner.fail('Operation failed');
|
spinner.fail('Operation failed');
|
||||||
}
|
}
|
||||||
@@ -151,7 +175,7 @@ export class AutopilotCommand extends Command {
|
|||||||
/**
|
/**
|
||||||
* Load task from tm-core
|
* Load task from tm-core
|
||||||
*/
|
*/
|
||||||
private async loadTask(taskId: string): Promise<any | null> {
|
private async loadTask(taskId: string): Promise<Task | null> {
|
||||||
if (!this.tmCore) {
|
if (!this.tmCore) {
|
||||||
throw new Error('TaskMasterCore not initialized');
|
throw new Error('TaskMasterCore not initialized');
|
||||||
}
|
}
|
||||||
@@ -167,7 +191,7 @@ export class AutopilotCommand extends Command {
|
|||||||
/**
|
/**
|
||||||
* Display task information before execution
|
* Display task information before execution
|
||||||
*/
|
*/
|
||||||
private displayTaskInfo(task: any, isDryRun: boolean): void {
|
private displayTaskInfo(task: Task, isDryRun: boolean): void {
|
||||||
const prefix = isDryRun ? '[DRY RUN] ' : '';
|
const prefix = isDryRun ? '[DRY RUN] ' : '';
|
||||||
console.log();
|
console.log();
|
||||||
console.log(
|
console.log(
|
||||||
@@ -196,22 +220,11 @@ export class AutopilotCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
private async performAutopilot(
|
private async performAutopilot(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
task: any,
|
task: Task,
|
||||||
options: AutopilotCommandOptions
|
options: AutopilotCommandOptions
|
||||||
): Promise<AutopilotCommandResult> {
|
): Promise<AutopilotCommandResult> {
|
||||||
const { PreflightChecker, TaskLoaderService } = await import('@tm/core');
|
|
||||||
|
|
||||||
// Run preflight checks
|
// Run preflight checks
|
||||||
console.log();
|
const preflightResult = await this.runPreflightChecks(options);
|
||||||
console.log(chalk.cyan.bold('Running preflight checks...'));
|
|
||||||
const preflightChecker = new PreflightChecker(
|
|
||||||
options.project || process.cwd()
|
|
||||||
);
|
|
||||||
const preflightResult = await preflightChecker.runAllChecks();
|
|
||||||
|
|
||||||
// Display preflight results
|
|
||||||
this.displayPreflightResults(preflightResult);
|
|
||||||
|
|
||||||
if (!preflightResult.success) {
|
if (!preflightResult.success) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@@ -222,9 +235,67 @@ export class AutopilotCommand extends Command {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load and validate task
|
// Validate task structure and get execution order
|
||||||
|
const validationResult = await this.validateTaskStructure(
|
||||||
|
taskId,
|
||||||
|
task,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
if (!validationResult.success) {
|
||||||
|
return validationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display execution plan
|
||||||
|
this.displayExecutionPlan(
|
||||||
|
validationResult.task!,
|
||||||
|
validationResult.orderedSubtasks!,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
taskId,
|
||||||
|
task: validationResult.task,
|
||||||
|
message: options.dryRun
|
||||||
|
? 'Dry run completed successfully'
|
||||||
|
: 'Autopilot execution ready (actual execution not yet implemented)'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run preflight checks and display results
|
||||||
|
*/
|
||||||
|
private async runPreflightChecks(
|
||||||
|
options: AutopilotCommandOptions
|
||||||
|
): Promise<PreflightResult> {
|
||||||
|
const { PreflightChecker } = await import('@tm/core');
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
console.log(chalk.cyan.bold('Running preflight checks...'));
|
||||||
|
|
||||||
|
const preflightChecker = new PreflightChecker(
|
||||||
|
options.project || process.cwd()
|
||||||
|
);
|
||||||
|
const result = await preflightChecker.runAllChecks();
|
||||||
|
|
||||||
|
this.displayPreflightResults(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate task structure and get execution order
|
||||||
|
*/
|
||||||
|
private async validateTaskStructure(
|
||||||
|
taskId: string,
|
||||||
|
task: Task,
|
||||||
|
options: AutopilotCommandOptions
|
||||||
|
): Promise<AutopilotCommandResult & { orderedSubtasks?: Subtask[] }> {
|
||||||
|
const { TaskLoaderService } = await import('@tm/core');
|
||||||
|
|
||||||
console.log();
|
console.log();
|
||||||
console.log(chalk.cyan.bold('Validating task structure...'));
|
console.log(chalk.cyan.bold('Validating task structure...'));
|
||||||
|
|
||||||
const taskLoader = new TaskLoaderService(options.project || process.cwd());
|
const taskLoader = new TaskLoaderService(options.project || process.cwd());
|
||||||
const validationResult = await taskLoader.loadAndValidateTask(taskId);
|
const validationResult = await taskLoader.loadAndValidateTask(taskId);
|
||||||
|
|
||||||
@@ -239,19 +310,33 @@ export class AutopilotCommand extends Command {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get execution order
|
|
||||||
const orderedSubtasks = taskLoader.getExecutionOrder(
|
const orderedSubtasks = taskLoader.getExecutionOrder(
|
||||||
validationResult.task!
|
validationResult.task!
|
||||||
);
|
);
|
||||||
|
|
||||||
await taskLoader.cleanup();
|
await taskLoader.cleanup();
|
||||||
|
|
||||||
// Display execution plan
|
return {
|
||||||
|
success: true,
|
||||||
|
taskId,
|
||||||
|
task: validationResult.task,
|
||||||
|
orderedSubtasks
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display execution plan with subtasks and TDD workflow
|
||||||
|
*/
|
||||||
|
private displayExecutionPlan(
|
||||||
|
task: Task,
|
||||||
|
orderedSubtasks: Subtask[],
|
||||||
|
options: AutopilotCommandOptions
|
||||||
|
): void {
|
||||||
console.log();
|
console.log();
|
||||||
console.log(chalk.green.bold('✓ All checks passed!'));
|
console.log(chalk.green.bold('✓ All checks passed!'));
|
||||||
console.log();
|
console.log();
|
||||||
console.log(chalk.cyan.bold('Execution Plan:'));
|
console.log(chalk.cyan.bold('Execution Plan:'));
|
||||||
console.log(chalk.white(`Task: ${validationResult.task!.title}`));
|
console.log(chalk.white(`Task: ${task.title}`));
|
||||||
console.log(
|
console.log(
|
||||||
chalk.gray(
|
chalk.gray(
|
||||||
`${orderedSubtasks.length} subtasks will be executed in dependency order`
|
`${orderedSubtasks.length} subtasks will be executed in dependency order`
|
||||||
@@ -260,11 +345,9 @@ export class AutopilotCommand extends Command {
|
|||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
// Display subtasks
|
// Display subtasks
|
||||||
orderedSubtasks.forEach((subtask: any, index: number) => {
|
orderedSubtasks.forEach((subtask: Subtask, index: number) => {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.yellow(
|
chalk.yellow(`${index + 1}. ${task.id}.${subtask.id}: ${subtask.title}`)
|
||||||
`${index + 1}. ${validationResult.task!.id}.${subtask.id}: ${subtask.title}`
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
if (subtask.dependencies && subtask.dependencies.length > 0) {
|
if (subtask.dependencies && subtask.dependencies.length > 0) {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -287,21 +370,12 @@ export class AutopilotCommand extends Command {
|
|||||||
chalk.yellow('This was a dry run. Use without --dry-run to execute.')
|
chalk.yellow('This was a dry run. Use without --dry-run to execute.')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
taskId,
|
|
||||||
task: validationResult.task,
|
|
||||||
message: options.dryRun
|
|
||||||
? 'Dry run completed successfully'
|
|
||||||
: 'Autopilot execution ready (actual execution not yet implemented)'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display preflight check results
|
* Display preflight check results
|
||||||
*/
|
*/
|
||||||
private displayPreflightResults(result: any): void {
|
private displayPreflightResults(result: PreflightResult): void {
|
||||||
const checks = [
|
const checks = [
|
||||||
{ name: 'Test command', result: result.testCommand },
|
{ name: 'Test command', result: result.testCommand },
|
||||||
{ name: 'Git working tree', result: result.gitWorkingTree },
|
{ name: 'Git working tree', result: result.gitWorkingTree },
|
||||||
@@ -387,16 +461,22 @@ export class AutopilotCommand extends Command {
|
|||||||
/**
|
/**
|
||||||
* Handle general errors
|
* Handle general errors
|
||||||
*/
|
*/
|
||||||
private handleError(error: any): void {
|
private handleError(error: unknown): void {
|
||||||
const msg = error?.getSanitizedDetails?.() ?? {
|
const errorObj = error as {
|
||||||
message: error?.message ?? String(error)
|
getSanitizedDetails?: () => { message: string };
|
||||||
|
message?: string;
|
||||||
|
stack?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const msg = errorObj?.getSanitizedDetails?.() ?? {
|
||||||
|
message: errorObj?.message ?? String(error)
|
||||||
};
|
};
|
||||||
console.error(chalk.red(`Error: ${msg.message || 'Unexpected error'}`));
|
console.error(chalk.red(`Error: ${msg.message || 'Unexpected error'}`));
|
||||||
|
|
||||||
// Show stack trace in development mode or when DEBUG is set
|
// Show stack trace in development mode or when DEBUG is set
|
||||||
const isDevelopment = process.env.NODE_ENV !== 'production';
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
if ((isDevelopment || process.env.DEBUG) && error.stack) {
|
if ((isDevelopment || process.env.DEBUG) && errorObj.stack) {
|
||||||
console.error(chalk.gray(error.stack));
|
console.error(chalk.gray(errorObj.stack));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user