AgentSkillsCN

V3 Qe Cli

V3 Qe CLI

SKILL.md

v3-qe-cli

Purpose

Guide the implementation of modernized CLI commands for AQE v3 with DDD-aligned operations and enhanced UX.

Activation

  • When implementing new CLI commands
  • When refactoring existing CLI
  • When adding v3-specific operations
  • When improving CLI user experience

CLI Architecture

1. Command Structure

typescript
// v3/src/cli/index.ts
import { Command } from 'commander';
import { QEFleetCoordinator } from '../coordination';
import { QEAgentDB } from '../infrastructure/memory';

export const createCLI = (): Command => {
  const program = new Command();

  program
    .name('aqe')
    .version('3.0.0')
    .description('Agentic Quality Engineering CLI v3');

  // Domain-aligned command groups
  addTestGenerationCommands(program);
  addCoverageCommands(program);
  addQualityCommands(program);
  addExecutionCommands(program);
  addLearningCommands(program);
  addFleetCommands(program);

  return program;
};

// Test Generation Domain Commands
function addTestGenerationCommands(program: Command): void {
  const test = program
    .command('test')
    .description('Test generation domain commands');

  test
    .command('generate <path>')
    .description('Generate tests for source code')
    .option('-f, --framework <framework>', 'Test framework (jest|vitest|playwright)', 'jest')
    .option('-t, --type <type>', 'Test type (unit|integration|e2e)', 'unit')
    .option('-c, --coverage <target>', 'Target coverage percentage', '80')
    .option('--ai', 'Use AI-powered generation', true)
    .option('--tdd', 'Generate TDD-style tests')
    .option('--property', 'Include property-based tests')
    .action(async (path, options) => {
      const coordinator = await getCoordinator();
      const result = await coordinator.orchestrate({
        type: 'test-generation',
        task: 'generate',
        target: path,
        options
      });
      displayResult(result);
    });

  test
    .command('optimize <suite>')
    .description('Optimize existing test suite')
    .option('--remove-redundant', 'Remove redundant tests')
    .option('--prioritize', 'Prioritize by risk')
    .action(async (suite, options) => {
      // Implementation
    });
}

// Coverage Domain Commands
function addCoverageCommands(program: Command): void {
  const coverage = program
    .command('coverage')
    .description('Coverage analysis domain commands');

  coverage
    .command('analyze [path]')
    .description('Analyze code coverage with O(log n) gap detection')
    .option('--threshold <percent>', 'Minimum coverage threshold', '80')
    .option('--gaps', 'Show coverage gaps')
    .option('--risk', 'Include risk scoring')
    .option('--vectors', 'Use vector-based analysis')
    .action(async (path, options) => {
      const coordinator = await getCoordinator();
      const result = await coordinator.orchestrate({
        type: 'coverage-analysis',
        task: 'analyze',
        target: path || '.',
        options
      });
      displayCoverageResult(result);
    });

  coverage
    .command('gaps [path]')
    .description('Find coverage gaps using HNSW')
    .option('--limit <n>', 'Maximum gaps to show', '20')
    .option('--severity <level>', 'Minimum severity (low|medium|high|critical)')
    .action(async (path, options) => {
      // Implementation
    });
}

// Quality Domain Commands
function addQualityCommands(program: Command): void {
  const quality = program
    .command('quality')
    .description('Quality assessment domain commands');

  quality
    .command('gate [name]')
    .description('Evaluate quality gate')
    .option('--strict', 'Use strict criteria')
    .option('--report', 'Generate detailed report')
    .action(async (name, options) => {
      const coordinator = await getCoordinator();
      const result = await coordinator.orchestrate({
        type: 'quality-assessment',
        task: 'evaluate-gate',
        gateName: name || 'default',
        options
      });
      displayGateResult(result);
    });

  quality
    .command('metrics')
    .description('Show quality metrics')
    .option('--trend', 'Show trend over time')
    .option('--compare <baseline>', 'Compare to baseline')
    .action(async (options) => {
      // Implementation
    });
}

// Fleet Commands
function addFleetCommands(program: Command): void {
  const fleet = program
    .command('fleet')
    .description('QE agent fleet management');

  fleet
    .command('status')
    .description('Show fleet status')
    .option('-v, --verbose', 'Verbose output')
    .action(async (options) => {
      const coordinator = await getCoordinator();
      const status = await coordinator.getFleetStatus();
      displayFleetStatus(status, options.verbose);
    });

  fleet
    .command('spawn <agent>')
    .description('Spawn a specific agent')
    .option('--task <task>', 'Assign initial task')
    .action(async (agent, options) => {
      // Implementation
    });

  fleet
    .command('orchestrate <task>')
    .description('Orchestrate a QE task across fleet')
    .option('--protocol <name>', 'Use specific protocol')
    .option('--agents <list>', 'Specific agents to use')
    .action(async (task, options) => {
      const coordinator = await getCoordinator();
      const result = await coordinator.orchestrate({
        task,
        protocol: options.protocol,
        agents: options.agents?.split(',')
      });
      displayResult(result);
    });
}

2. Output Formatting

typescript
// v3/src/cli/formatters/output.ts
import chalk from 'chalk';
import { table } from 'table';

export function displayFleetStatus(status: FleetStatus, verbose: boolean): void {
  console.log(chalk.bold.cyan('\n🤖 AQE v3 Fleet Status\n'));

  // Agent groups table
  const groupData = [
    [chalk.bold('Group'), chalk.bold('Agents'), chalk.bold('Active'), chalk.bold('Status')]
  ];

  for (const group of status.groups) {
    groupData.push([
      chalk.yellow(group.name),
      group.totalAgents.toString(),
      chalk.green(group.activeAgents.toString()),
      getStatusIcon(group.status)
    ]);
  }

  console.log(table(groupData));

  // Summary
  console.log(chalk.dim('─'.repeat(50)));
  console.log(`Total Agents: ${chalk.bold(status.totalAgents)}`);
  console.log(`Active: ${chalk.green(status.activeAgents)}`);
  console.log(`Tasks Completed: ${chalk.blue(status.tasksCompleted)}`);
  console.log(`Learning Patterns: ${chalk.magenta(status.patternsLearned)}`);

  if (verbose) {
    displayDetailedAgentStatus(status.agents);
  }
}

export function displayCoverageResult(result: CoverageResult): void {
  console.log(chalk.bold.cyan('\n📊 Coverage Analysis Results\n'));

  // Coverage summary
  const coverageColor = result.lineCoverage >= 80 ? chalk.green : chalk.yellow;
  console.log(`Line Coverage: ${coverageColor(result.lineCoverage + '%')}`);
  console.log(`Branch Coverage: ${coverageColor(result.branchCoverage + '%')}`);
  console.log(`Function Coverage: ${coverageColor(result.functionCoverage + '%')}`);

  // Gaps
  if (result.gaps.length > 0) {
    console.log(chalk.bold.yellow('\n⚠️  Coverage Gaps Detected:\n'));

    const gapData = [
      [chalk.bold('File'), chalk.bold('Lines'), chalk.bold('Risk'), chalk.bold('Suggested')]
    ];

    for (const gap of result.gaps.slice(0, 10)) {
      gapData.push([
        chalk.dim(gap.file),
        gap.uncoveredLines.join(', '),
        getRiskIcon(gap.riskScore),
        chalk.cyan(gap.suggestedTestType)
      ]);
    }

    console.log(table(gapData));
  }
}

export function displayGateResult(result: GateResult): void {
  const icon = result.passed ? chalk.green('✓') : chalk.red('✗');
  console.log(chalk.bold.cyan(`\n🚦 Quality Gate: ${icon} ${result.passed ? 'PASSED' : 'FAILED'}\n`));

  for (const criterion of result.criteria) {
    const status = criterion.passed ? chalk.green('✓') : chalk.red('✗');
    console.log(`  ${status} ${criterion.name}: ${criterion.actual} ${criterion.operator} ${criterion.threshold}`);
  }

  if (result.blockers.length > 0) {
    console.log(chalk.bold.red('\n❌ Blockers:'));
    for (const blocker of result.blockers) {
      console.log(`  • ${blocker}`);
    }
  }

  if (result.recommendations.length > 0) {
    console.log(chalk.bold.yellow('\n💡 Recommendations:'));
    for (const rec of result.recommendations) {
      console.log(`  • ${rec}`);
    }
  }
}

function getStatusIcon(status: string): string {
  const icons: Record<string, string> = {
    active: chalk.green('●'),
    idle: chalk.yellow('○'),
    error: chalk.red('✗'),
    busy: chalk.blue('◉')
  };
  return icons[status] || chalk.dim('?');
}

function getRiskIcon(risk: number): string {
  if (risk >= 0.8) return chalk.red('🔴 Critical');
  if (risk >= 0.6) return chalk.yellow('🟡 High');
  if (risk >= 0.4) return chalk.blue('🔵 Medium');
  return chalk.green('🟢 Low');
}

3. Interactive Mode

typescript
// v3/src/cli/interactive.ts
import inquirer from 'inquirer';

export async function runInteractive(): Promise<void> {
  console.log(chalk.bold.cyan('\n🤖 AQE v3 Interactive Mode\n'));

  const { action } = await inquirer.prompt([
    {
      type: 'list',
      name: 'action',
      message: 'What would you like to do?',
      choices: [
        { name: '📝 Generate Tests', value: 'generate-tests' },
        { name: '📊 Analyze Coverage', value: 'analyze-coverage' },
        { name: '🚦 Evaluate Quality Gate', value: 'quality-gate' },
        { name: '🔍 Find Coverage Gaps', value: 'find-gaps' },
        { name: '🤖 Manage Fleet', value: 'manage-fleet' },
        { name: '🧠 View Learning Patterns', value: 'view-patterns' },
        new inquirer.Separator(),
        { name: '❌ Exit', value: 'exit' }
      ]
    }
  ]);

  switch (action) {
    case 'generate-tests':
      await interactiveTestGeneration();
      break;
    case 'analyze-coverage':
      await interactiveCoverageAnalysis();
      break;
    case 'quality-gate':
      await interactiveQualityGate();
      break;
    // ... other cases
  }
}

async function interactiveTestGeneration(): Promise<void> {
  const answers = await inquirer.prompt([
    {
      type: 'input',
      name: 'path',
      message: 'Path to source code:',
      default: 'src/'
    },
    {
      type: 'list',
      name: 'framework',
      message: 'Test framework:',
      choices: ['jest', 'vitest', 'playwright', 'pytest']
    },
    {
      type: 'checkbox',
      name: 'options',
      message: 'Generation options:',
      choices: [
        { name: 'AI-powered generation', value: 'ai', checked: true },
        { name: 'TDD-style tests', value: 'tdd' },
        { name: 'Property-based tests', value: 'property' },
        { name: 'Integration tests', value: 'integration' }
      ]
    },
    {
      type: 'number',
      name: 'coverage',
      message: 'Target coverage %:',
      default: 80
    }
  ]);

  // Execute with answers
  const coordinator = await getCoordinator();
  const result = await coordinator.orchestrate({
    type: 'test-generation',
    task: 'generate',
    target: answers.path,
    options: answers
  });

  displayResult(result);
}

4. Progress Display

typescript
// v3/src/cli/progress.ts
import ora from 'ora';
import cliProgress from 'cli-progress';

export class ProgressDisplay {
  private spinner: ora.Ora;
  private multiBar: cliProgress.MultiBar;

  constructor() {
    this.spinner = ora();
    this.multiBar = new cliProgress.MultiBar({
      clearOnComplete: false,
      hideCursor: true,
      format: '{agent} |' + chalk.cyan('{bar}') + '| {percentage}% | {status}'
    });
  }

  // Show spinner for single operation
  async withSpinner<T>(message: string, fn: () => Promise<T>): Promise<T> {
    this.spinner.start(message);
    try {
      const result = await fn();
      this.spinner.succeed();
      return result;
    } catch (error) {
      this.spinner.fail();
      throw error;
    }
  }

  // Show multi-bar progress for parallel agents
  trackAgents(agents: string[]): AgentProgressTrackers {
    const trackers: AgentProgressTrackers = {};

    for (const agent of agents) {
      trackers[agent] = this.multiBar.create(100, 0, {
        agent: agent.padEnd(20),
        status: 'Initializing...'
      });
    }

    return trackers;
  }

  updateAgent(tracker: cliProgress.SingleBar, progress: number, status: string): void {
    tracker.update(progress, { status });
  }

  complete(): void {
    this.multiBar.stop();
  }
}

Command Reference

CommandDescription
aqe test generate <path>Generate tests for source code
aqe test optimize <suite>Optimize existing test suite
aqe coverage analyzeAnalyze coverage with O(log n)
aqe coverage gapsFind coverage gaps
aqe quality gateEvaluate quality gate
aqe quality metricsShow quality metrics
aqe fleet statusShow fleet status
aqe fleet spawn <agent>Spawn specific agent
aqe fleet orchestrateOrchestrate task
aqe learn statusLearning progress
aqe learn patternsView learned patterns
aqe initInitialize project
aqe interactiveInteractive mode

Implementation Checklist

  • Implement domain-aligned commands
  • Add output formatters
  • Create interactive mode
  • Add progress display
  • Implement config management
  • Add shell completions
  • Write CLI tests
  • Create man pages

Related Skills

  • v3-qe-core-implementation - Domain logic
  • v3-qe-fleet-coordination - Agent orchestration
  • v3-qe-mcp - MCP tool integration