---
description: Guidelines for integrating new features into the Task Master CLI
globs: scripts/modules/*.js
alwaysApply: false
---

# Task Master Feature Integration Guidelines

## Feature Placement Decision Process

- **Identify Feature Type**:
  - **Data Manipulation**: Features that create, read, update, or delete tasks belong in [`task-manager.js`](mdc:scripts/modules/task-manager.js)
  - **Dependency Management**: Features that handle task relationships belong in [`dependency-manager.js`](mdc:scripts/modules/dependency-manager.js)
  - **User Interface**: Features that display information to users belong in [`ui.js`](mdc:scripts/modules/ui.js)
  - **AI Integration**: Features that use AI models belong in [`ai-services.js`](mdc:scripts/modules/ai-services.js)
  - **Cross-Cutting**: Features that don't fit one category may need components in multiple modules

- **Command-Line Interface**:
  - All new user-facing commands should be added to [`commands.js`](mdc:scripts/modules/commands.js)
  - Use consistent patterns for option naming and help text
  - Follow the Commander.js model for subcommand structure

## Implementation Pattern

The standard pattern for adding a feature follows this workflow:

1. **Core Logic**: Implement the business logic in the appropriate module
2. **UI Components**: Add any display functions to [`ui.js`](mdc:scripts/modules/ui.js)
3. **Command Integration**: Add the CLI command to [`commands.js`](mdc:scripts/modules/commands.js)
4. **Testing**: Write tests for all components of the feature (following [`tests.mdc`](mdc:.cursor/rules/tests.mdc))
5. **Configuration**: Update any configuration in [`utils.js`](mdc:scripts/modules/utils.js) if needed
6. **Documentation**: Update help text and documentation in [dev_workflow.mdc](mdc:scripts/modules/dev_workflow.mdc)

```javascript
// 1. CORE LOGIC: Add function to appropriate module (example in task-manager.js)
/**
 * Archives completed tasks to archive.json
 * @param {string} tasksPath - Path to the tasks.json file
 * @param {string} archivePath - Path to the archive.json file
 * @returns {number} Number of tasks archived
 */
async function archiveTasks(tasksPath, archivePath = 'tasks/archive.json') {
  // Implementation...
  return archivedCount;
}

// Export from the module
export {
  // ... existing exports ...
  archiveTasks,
};
```

```javascript
// 2. UI COMPONENTS: Add display function to ui.js
/**
 * Display archive operation results
 * @param {string} archivePath - Path to the archive file
 * @param {number} count - Number of tasks archived
 */
function displayArchiveResults(archivePath, count) {
  console.log(boxen(
    chalk.green(`Successfully archived ${count} tasks to ${archivePath}`),
    { padding: 1, borderColor: 'green', borderStyle: 'round' }
  ));
}

// Export from the module
export {
  // ... existing exports ...
  displayArchiveResults,
};
```

```javascript
// 3. COMMAND INTEGRATION: Add to commands.js
import { archiveTasks } from './task-manager.js';
import { displayArchiveResults } from './ui.js';

// In registerCommands function
programInstance
  .command('archive')
  .description('Archive completed tasks to separate file')
  .option('-f, --file <file>', 'Path to the tasks file', 'tasks/tasks.json')
  .option('-o, --output <file>', 'Archive output file', 'tasks/archive.json')
  .action(async (options) => {
    const tasksPath = options.file;
    const archivePath = options.output;

    console.log(chalk.blue(`Archiving completed tasks from ${tasksPath} to ${archivePath}...`));

    const archivedCount = await archiveTasks(tasksPath, archivePath);
    displayArchiveResults(archivePath, archivedCount);
  });
```

## Cross-Module Features

For features requiring components in multiple modules:

- ✅ **DO**: Create a clear unidirectional flow of dependencies
  ```javascript
  // In task-manager.js
  function analyzeTasksDifficulty(tasks) {
    // Implementation...
    return difficultyScores;
  }

  // In ui.js - depends on task-manager.js
  import { analyzeTasksDifficulty } from './task-manager.js';

  function displayDifficultyReport(tasks) {
    const scores = analyzeTasksDifficulty(tasks);
    // Render the scores...
  }
  ```

- ❌ **DON'T**: Create circular dependencies between modules
  ```javascript
  // In task-manager.js - depends on ui.js
  import { displayDifficultyReport } from './ui.js';

  function analyzeTasks() {
    // Implementation...
    displayDifficultyReport(tasks); // WRONG! Don't call UI functions from task-manager
  }

  // In ui.js - depends on task-manager.js
  import { analyzeTasks } from './task-manager.js';
  ```

## Command-Line Interface Standards

- **Naming Conventions**:
  - Use kebab-case for command names (`analyze-complexity`, not `analyzeComplexity`)
  - Use kebab-case for option names (`--output-format`, not `--outputFormat`)
  - Use the same option names across commands when they represent the same concept

- **Command Structure**:
  ```javascript
  programInstance
    .command('command-name')
    .description('Clear, concise description of what the command does')
    .option('-s, --short-option <value>', 'Option description', 'default value')
    .option('--long-option <value>', 'Option description')
    .action(async (options) => {
      // Command implementation
    });
  ```

## Utility Function Guidelines

When adding utilities to [`utils.js`](mdc:scripts/modules/utils.js):

- Only add functions that could be used by multiple modules
- Keep utilities single-purpose and purely functional
- Document parameters and return values

```javascript
/**
 * Formats a duration in milliseconds to a human-readable string
 * @param {number} ms - Duration in milliseconds
 * @returns {string} Formatted duration string (e.g., "2h 30m 15s")
 */
function formatDuration(ms) {
  // Implementation...
  return formatted;
}
```

## Writing Testable Code

When implementing new features, follow these guidelines to ensure your code is testable:

- **Dependency Injection**
  - Design functions to accept dependencies as parameters
  - Avoid hard-coded dependencies that are difficult to mock
  ```javascript
  // ✅ DO: Accept dependencies as parameters
  function processTask(task, fileSystem, logger) {
    fileSystem.writeFile('task.json', JSON.stringify(task));
    logger.info('Task processed');
  }

  // ❌ DON'T: Use hard-coded dependencies
  function processTask(task) {
    fs.writeFile('task.json', JSON.stringify(task));
    console.log('Task processed');
  }
  ```

- **Separate Logic from Side Effects**
  - Keep pure logic separate from I/O operations or UI rendering
  - This allows testing the logic without mocking complex dependencies
  ```javascript
  // ✅ DO: Separate logic from side effects
  function calculateTaskPriority(task, dependencies) {
    // Pure logic that returns a value
    return computedPriority;
  }

  function displayTaskPriority(task, dependencies) {
    const priority = calculateTaskPriority(task, dependencies);
    console.log(`Task priority: ${priority}`);
  }
  ```

- **Callback Functions and Testing**
  - When using callbacks (like in Commander.js commands), define them separately
  - This allows testing the callback logic independently
  ```javascript
  // ✅ DO: Define callbacks separately for testing
  function getVersionString() {
    // Logic to determine version
    return version;
  }

  // In setupCLI
  programInstance.version(getVersionString);

  // In tests
  test('getVersionString returns correct version', () => {
    expect(getVersionString()).toBe('1.5.0');
  });
  ```

- **UI Output Testing**
  - For UI components, focus on testing conditional logic rather than exact output
  - Use string pattern matching (like `expect(result).toContain('text')`)
  - Pay attention to emojis and formatting which can make exact string matching difficult
  ```javascript
  // ✅ DO: Test the essence of the output, not exact formatting
  test('statusFormatter shows done status correctly', () => {
    const result = formatStatus('done');
    expect(result).toContain('done');
    expect(result).toContain('✅');
  });
  ```

## Testing Requirements

Every new feature **must** include comprehensive tests following the guidelines in [`tests.mdc`](mdc:.cursor/rules/tests.mdc). Testing should include:

1. **Unit Tests**: Test individual functions and components in isolation
   ```javascript
   // Example unit test for a new utility function
   describe('newFeatureUtil', () => {
     test('should perform expected operation with valid input', () => {
       expect(newFeatureUtil('valid input')).toBe('expected result');
     });

     test('should handle edge cases appropriately', () => {
       expect(newFeatureUtil('')).toBeNull();
     });
   });
   ```

2. **Integration Tests**: Verify the feature works correctly with other components
   ```javascript
   // Example integration test for a new command
   describe('newCommand integration', () => {
     test('should call the correct service functions with parsed arguments', () => {
       const mockService = jest.fn().mockResolvedValue('success');
       // Set up test with mocked dependencies
       // Call the command handler
       // Verify service was called with expected arguments
     });
   });
   ```

3. **Edge Cases**: Test boundary conditions and error handling
   - Invalid inputs
   - Missing dependencies
   - File system errors
   - API failures

4. **Test Coverage**: Aim for at least 80% coverage for all new code

5. **Jest Mocking Best Practices**
   - Follow the mock-first-then-import pattern as described in [`tests.mdc`](mdc:.cursor/rules/tests.mdc)
   - Use jest.spyOn() to create spy functions for testing
   - Clear mocks between tests to prevent interference
   - See the Jest Module Mocking Best Practices section in [`tests.mdc`](mdc:.cursor/rules/tests.mdc) for details

When submitting a new feature, always run the full test suite to ensure nothing was broken:

```bash
npm test
```

## Documentation Requirements

For each new feature:

1. Add help text to the command definition
2. Update [`dev_workflow.mdc`](mdc:scripts/modules/dev_workflow.mdc) with command reference
3. Add examples to the appropriate sections in [`MODULE_PLAN.md`](mdc:scripts/modules/MODULE_PLAN.md)

Follow the existing command reference format:
```markdown
- **Command Reference: your-command**
  - CLI Syntax: `task-manager your-command [options]`
  - Description: Brief explanation of what the command does
  - Parameters:
    - `--option1=<value>`: Description of option1 (default: 'default')
    - `--option2=<value>`: Description of option2 (required)
  - Example: `task-manager your-command --option1=value --option2=value2`
  - Notes: Additional details, limitations, or special considerations
```

For more information on module structure, see [`MODULE_PLAN.md`](mdc:scripts/modules/MODULE_PLAN.md) and follow [`self_improve.mdc`](mdc:scripts/modules/self_improve.mdc) for best practices on updating documentation.
