---
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** (See [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) for module details):
  - **Data Manipulation**: Features that create, read, update, or delete tasks belong in [`task-manager.js`](mdc:scripts/modules/task-manager.js). Follow guidelines in [`tasks.mdc`](mdc:.cursor/rules/tasks.mdc).
  - **Dependency Management**: Features that handle task relationships belong in [`dependency-manager.js`](mdc:scripts/modules/dependency-manager.js). Follow guidelines in [`dependencies.mdc`](mdc:.cursor/rules/dependencies.mdc).
  - **User Interface**: Features that display information to users belong in [`ui.js`](mdc:scripts/modules/ui.js). Follow guidelines in [`ui.mdc`](mdc:.cursor/rules/ui.mdc).
  - **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** (See [`commands.mdc`](mdc:.cursor/rules/commands.mdc)):
  - 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 (e.g., [`task-manager.js`](mdc:scripts/modules/task-manager.js)).
2. **Context Gathering (If Applicable)**: 
   - For AI-powered commands that benefit from project context, use the standardized context gathering patterns from [`context_gathering.mdc`](mdc:.cursor/rules/context_gathering.mdc).
   - Import `ContextGatherer` and `FuzzyTaskSearch` utilities for reusable context extraction.
   - Support multiple context types: tasks, files, custom text, project tree.
   - Implement detailed token breakdown display for transparency.
3. **AI Integration (If Applicable)**: 
   - Import necessary service functions (e.g., `generateTextService`, `streamTextService`) from [`ai-services-unified.js`](mdc:scripts/modules/ai-services-unified.js).
   - Prepare parameters (`role`, `session`, `systemPrompt`, `prompt`).
   - Call the service function.
   - Handle the response (direct text or stream object).
   - **Important**: Prefer `generateTextService` for calls sending large context (like stringified JSON) where incremental display is not needed. See [`ai_services.mdc`](mdc:.cursor/rules/ai_services.mdc) for detailed usage patterns and cautions.
4. **UI Components**: Add any display functions to [`ui.js`](mdc:scripts/modules/ui.js) following [`ui.mdc`](mdc:.cursor/rules/ui.mdc). Consider enhanced formatting with syntax highlighting for code blocks.
5. **Command Integration**: Add the CLI command to [`commands.js`](mdc:scripts/modules/commands.js) following [`commands.mdc`](mdc:.cursor/rules/commands.mdc).
6. **Testing**: Write tests for all components of the feature (following [`tests.mdc`](mdc:.cursor/rules/tests.mdc))
7. **Configuration**: Update configuration settings or add new ones in [`config-manager.js`](mdc:scripts/modules/config-manager.js) and ensure getters/setters are appropriate. Update documentation in [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc) and [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc). Update the `.taskmasterconfig` structure if needed.
8. **Documentation**: Update help text and documentation in [`dev_workflow.mdc`](mdc:.cursor/rules/dev_workflow.mdc) and [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc).

## Critical Checklist for New Features

- **Comprehensive Function Exports**:
  - ✅ **DO**: Export **all core functions, helper functions (like `generateSubtaskPrompt`), and utility methods** needed by your new function or command from their respective modules.
  - ✅ **DO**: **Explicitly review the module's `export { ... }` block** at the bottom of the file to ensure every required dependency (even seemingly minor helpers like `findTaskById`, `taskExists`, specific prompt generators, AI call handlers, etc.) is included.
  - ❌ **DON'T**: Assume internal functions are already exported - **always verify**. A missing export will cause runtime errors (e.g., `ReferenceError: generateSubtaskPrompt is not defined`).
  - **Example**: If implementing a feature that checks task existence, ensure the helper function is in exports:
  ```javascript
  // At the bottom of your module file:
  export {
    // ... existing exports ...
    yourNewFunction,
    taskExists,  // Helper function used by yourNewFunction
    findTaskById, // Helper function used by yourNewFunction
    generateSubtaskPrompt, // Helper needed by expand/add features
    getSubtasksFromAI,     // Helper needed by expand/add features
  };
  ```

- **Parameter Completeness and Matching**:
  - ✅ **DO**: Pass all required parameters to functions you call within your implementation
  - ✅ **DO**: Check function signatures before implementing calls to them
  - ✅ **DO**: Verify that direct function parameters match their core function counterparts
  - ✅ **DO**: When implementing a direct function for MCP, ensure it only accepts parameters that exist in the core function
  - ✅ **DO**: Verify the expected *internal structure* of complex object parameters (like the `mcpLog` object, see mcp.mdc for the required logger wrapper pattern)
  - ❌ **DON'T**: Add parameters to direct functions that don't exist in core functions
  - ❌ **DON'T**: Assume default parameter values will handle missing arguments
  - ❌ **DON'T**: Assume object parameters will work without verifying their required internal structure or methods.
  - **Example**: When calling file generation, pass all required parameters:
  ```javascript
  // ✅ DO: Pass all required parameters
  await generateTaskFiles(tasksPath, path.dirname(tasksPath));
  
  // ❌ DON'T: Omit required parameters
  await generateTaskFiles(tasksPath); // Error - missing outputDir parameter
  ```
  
  **Example**: Properly match direct function parameters to core function:
  ```javascript
  // Core function signature
  async function expandTask(tasksPath, taskId, numSubtasks, useResearch = false, additionalContext = '', options = {}) {
    // Implementation...
  }
  
  // ✅ DO: Match direct function parameters to core function
  export async function expandTaskDirect(args, log, context = {}) {
    // Extract only parameters that exist in the core function
    const taskId = parseInt(args.id, 10);
    const numSubtasks = args.num ? parseInt(args.num, 10) : undefined;
    const useResearch = args.research === true;
    const additionalContext = args.prompt || '';
    
    // Call core function with matched parameters
    const result = await expandTask(
      tasksPath,
      taskId,
      numSubtasks,
      useResearch,
      additionalContext,
      { mcpLog: log, session: context.session }
    );
    
    // Return result
    return { success: true, data: result, fromCache: false };
  }
  
  // ❌ DON'T: Use parameters that don't exist in the core function
  export async function expandTaskDirect(args, log, context = {}) {
    // DON'T extract parameters that don't exist in the core function!
    const force = args.force === true; // ❌ WRONG - 'force' doesn't exist in core function
    
    // DON'T pass non-existent parameters to core functions
    const result = await expandTask(
      tasksPath,
      args.id,
      args.num,
      args.research,
      args.prompt,
      force, // ❌ WRONG - this parameter doesn't exist in the core function
      { mcpLog: log }
    );
  }
  ```

- **Consistent File Path Handling**:
  - ✅ DO: Use consistent file naming conventions: `task_${id.toString().padStart(3, '0')}.txt`
  - ✅ DO: Use `path.join()` for composing file paths
  - ✅ DO: Use appropriate file extensions (.txt for tasks, .json for data)
  - ❌ DON'T: Hardcode path separators or inconsistent file extensions
  - **Example**: Creating file paths for tasks:
  ```javascript
  // ✅ DO: Use consistent file naming and path.join
  const taskFileName = path.join(
    path.dirname(tasksPath), 
    `task_${taskId.toString().padStart(3, '0')}.txt`
  );
  
  // ❌ DON'T: Use inconsistent naming or string concatenation 
  const taskFileName = path.dirname(tasksPath) + '/' + taskId + '.md';
  ```

- **Error Handling and Reporting**:
  - ✅ DO: Use structured error objects with code and message properties
  - ✅ DO: Include clear error messages identifying the specific problem
  - ✅ DO: Handle both function-specific errors and potential file system errors
  - ✅ DO: Log errors at appropriate severity levels
  - **Example**: Structured error handling in core functions:
  ```javascript
  try {
    // Implementation...
  } catch (error) {
    log('error', `Error removing task: ${error.message}`);
    throw {
      code: 'REMOVE_TASK_ERROR',
      message: error.message,
      details: error.stack
    };
  }
  ```

- **Silent Mode Implementation**:
  - ✅ **DO**: Import all silent mode utilities together:
    ```javascript
    import { enableSilentMode, disableSilentMode, isSilentMode } from '../../../../scripts/modules/utils.js';
    ```
  - ✅ **DO**: Always use `isSilentMode()` function to check global silent mode status, never reference global variables.
  - ✅ **DO**: Wrap core function calls **within direct functions** using `enableSilentMode()` and `disableSilentMode()` in a `try/finally` block if the core function might produce console output (like banners, spinners, direct `console.log`s) that isn't reliably controlled by an `outputFormat` parameter.
    ```javascript
    // Direct Function Example:
    try {
      // Prefer passing 'json' if the core function reliably handles it
      const result = await coreFunction(...args, 'json'); 
      // OR, if outputFormat is not enough/unreliable:
      // enableSilentMode(); // Enable *before* the call
      // const result = await coreFunction(...args);
      // disableSilentMode(); // Disable *after* the call (typically in finally)

      return { success: true, data: result };
    } catch (error) {
       log.error(`Error: ${error.message}`);
       return { success: false, error: { message: error.message } };
    } finally {
       // If you used enable/disable, ensure disable is called here
       // disableSilentMode(); 
    }
    ```
  - ✅ **DO**: Core functions themselves *should* ideally check `outputFormat === 'text'` before displaying UI elements (banners, spinners, boxes) and use internal logging (`log`/`report`) that respects silent mode. The `enable/disableSilentMode` wrapper in the direct function is a safety net.
  - ✅ **DO**: Handle mixed parameter/global silent mode correctly for functions accepting both (less common now, prefer `outputFormat`):
    ```javascript
    // Check both the passed parameter and global silent mode
    const isSilent = silentMode || (typeof silentMode === 'undefined' && isSilentMode());
    ```
  - ❌ **DON'T**: Forget to disable silent mode in a `finally` block if you enabled it.
  - ❌ **DON'T**: Access the global `silentMode` flag directly.

- **Debugging Strategy**:
  - ✅ **DO**: If an MCP tool fails with vague errors (e.g., JSON parsing issues like `Unexpected token ... is not valid JSON`), **try running the equivalent CLI command directly in the terminal** (e.g., `task-master expand --all`). CLI output often provides much more specific error messages (like missing function definitions or stack traces from the core logic) that pinpoint the root cause.
  - ❌ **DON'T**: Rely solely on MCP logs if the error is unclear; use the CLI as a complementary debugging tool for core logic issues.

- **Telemetry Integration**: Ensure AI calls correctly handle and propagate `telemetryData` as described in [`telemetry.mdc`](mdc:.cursor/rules/telemetry.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. AI Integration: Add import and use necessary service functions
import { generateTextService } from './ai-services-unified.js';

// Example usage:
async function handleAIInteraction() {
  const role = 'user';
  const session = 'exampleSession';
  const systemPrompt = 'You are a helpful assistant.';
  const prompt = 'What is the capital of France?';

  const result = await generateTextService(role, session, systemPrompt, prompt);
  console.log(result);
}

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

```javascript
// 3. 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
// 4. 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:.cursor/rules/dev_workflow.mdc) with command reference
3. Consider updating [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) if the feature significantly changes module responsibilities.

Follow the existing command reference format:
```markdown
- **Command Reference: your-command**
  - CLI Syntax: `task-master 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-master 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.

## Adding MCP Server Support for Commands

Integrating Task Master commands with the MCP server (for use by tools like Cursor) follows a specific pattern distinct from the CLI command implementation, prioritizing performance and reliability.

- **Goal**: Leverage direct function calls to core logic, avoiding CLI overhead.
- **Reference**: See [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) for full details.

**MCP Integration Workflow**:

1.  **Core Logic**: Ensure the command's core logic exists and is exported from the appropriate module (e.g., [`task-manager.js`](mdc:scripts/modules/task-manager.js)).
2.  **Direct Function Wrapper (`mcp-server/src/core/direct-functions/`)**:
    - Create a new file (e.g., `your-command.js`) in `mcp-server/src/core/direct-functions/` using **kebab-case** naming.
    - Import the core logic function, necessary MCP utilities like **`findTasksJsonPath` from `../utils/path-utils.js`**, and **silent mode utilities**: `import { enableSilentMode, disableSilentMode } from '../../../../scripts/modules/utils.js';`
    - Implement an `async function yourCommandDirect(args, log)` using **camelCase** with `Direct` suffix.
    - **Path Finding**: Inside this function, obtain the `tasksPath` by calling `const tasksPath = findTasksJsonPath(args, log);`. This relies on `args.projectRoot` (derived from the session) being passed correctly.
    - Perform validation on other arguments received in `args`.
    - **Implement Silent Mode**: Wrap core function calls with `enableSilentMode()` and `disableSilentMode()` to prevent logs from interfering with JSON responses.
    - **If Caching**: Implement caching using `getCachedOrExecute` from `../../tools/utils.js`.
    - **If Not Caching**: Directly call the core logic function within a try/catch block.
    - Format the return as `{ success: true/false, data/error, fromCache: boolean }`.
    - Export the wrapper function.

3.  **Update `task-master-core.js` with Import/Export**: Import and re-export your `*Direct` function and add it to the `directFunctions` map.

4.  **Create MCP Tool (`mcp-server/src/tools/`)**:
    - Create a new file (e.g., `your-command.js`) using **kebab-case**.
    - Import `zod`, `handleApiResult`, **`withNormalizedProjectRoot` HOF**, and your `yourCommandDirect` function.
    - Implement `registerYourCommandTool(server)`.
    - **Define parameters**: Make `projectRoot` optional (`z.string().optional().describe(...)`) as the HOF handles fallback.
    - Consider if this operation should run in the background using `AsyncOperationManager`.
    - Implement the standard `execute` method **wrapped with `withNormalizedProjectRoot`**:
      ```javascript
      execute: withNormalizedProjectRoot(async (args, { log, session }) => {
          // args.projectRoot is now normalized
          const { projectRoot /*, other args */ } = args;
          // ... resolve tasks path if needed using normalized projectRoot ...
          const result = await yourCommandDirect(
              { /* other args */, projectRoot /* if needed by direct func */ }, 
              log, 
              { session }
          );
          return handleApiResult(result, log);
      })
      ```

5.  **Register Tool**: Import and call `registerYourCommandTool` in `mcp-server/src/tools/index.js`.

6.  **Update `mcp.json`**: Add the new tool definition to the `tools` array in `.cursor/mcp.json`.

## Implementing Background Operations

For long-running operations that should not block the client, use the AsyncOperationManager:

1. **Identify Background-Appropriate Operations**:
   - ✅ **DO**: Use async operations for CPU-intensive tasks like task expansion or PRD parsing
   - ✅ **DO**: Consider async operations for tasks that may take more than 1-2 seconds
   - ❌ **DON'T**: Use async operations for quick read/status operations
   - ❌ **DON'T**: Use async operations when immediate feedback is critical

2. **Use AsyncOperationManager in MCP Tools**:
   ```javascript
   import { asyncOperationManager } from '../core/utils/async-manager.js';
   
   // In execute method:
   const operationId = asyncOperationManager.addOperation(
     expandTaskDirect, // The direct function to run in background
     { ...args, projectRoot: rootFolder }, // Args to pass to the function
     { log, reportProgress, session } // Context to preserve for the operation
   );
   
   // Return immediate response with operation ID
   return createContentResponse({
     message: "Operation started successfully",
     operationId,
     status: "pending"
   });
   ```

3. **Implement Progress Reporting**:
   - ✅ **DO**: Use the reportProgress function in direct functions:
   ```javascript
   // In your direct function:
   if (reportProgress) {
     await reportProgress({ progress: 50 }); // 50% complete
   }
   ```
   - AsyncOperationManager will forward progress updates to the client

4. **Check Operation Status**:
   - Implement a way for clients to check status using the `get_operation_status` MCP tool
   - Return appropriate status codes and messages

## Project Initialization

When implementing project initialization commands:

1. **Support Programmatic Initialization**:
   - ✅ **DO**: Design initialization to work with both CLI and MCP
   - ✅ **DO**: Support non-interactive modes with sensible defaults
   - ✅ **DO**: Handle project metadata like name, description, version
   - ✅ **DO**: Create necessary files and directories

2. **In MCP Tool Implementation**:
   ```javascript
   // In initialize-project.js MCP tool:
   import { z } from "zod";
   import { initializeProjectDirect } from "../core/task-master-core.js";
   
   export function registerInitializeProjectTool(server) {
     server.addTool({
       name: "initialize_project",
       description: "Initialize a new Task Master project",
       parameters: z.object({
         projectName: z.string().optional().describe("The name for the new project"),
         projectDescription: z.string().optional().describe("A brief description"),
         projectVersion: z.string().optional().describe("Initial version (e.g., '0.1.0')"),
         // Add other parameters as needed
       }),
       execute: async (args, { log, reportProgress, session }) => {
         try {
           // No need for project root since we're creating a new project
           const result = await initializeProjectDirect(args, log);
           return handleApiResult(result, log, 'Error initializing project');
         } catch (error) {
           log.error(`Error in initialize_project: ${error.message}`);
           return createErrorResponse(`Failed to initialize project: ${error.message}`);
         }
       }
     });
   }
   ```

## Feature Planning

- **Core Logic First**:
  - ✅ DO: Implement core logic in `scripts/modules/` before CLI or MCP interfaces
  - ✅ DO: Consider tagged task lists system compatibility from the start
  - ✅ DO: Design functions to work with both legacy and tagged data formats
  - ✅ DO: Use tag resolution functions (`getTasksForTag`, `setTasksForTag`) for task data access
  - ❌ DON'T: Directly manipulate tagged data structure in new features

  ```javascript
  // ✅ DO: Design tagged-aware core functions
  async function newFeatureCore(tasksPath, featureParams, options = {}) {
    const tasksData = readJSON(tasksPath);
    const currentTag = getCurrentTag() || 'master';
    const tasks = getTasksForTag(tasksData, currentTag);
    
    // Perform feature logic on tasks array
    const result = performFeatureLogic(tasks, featureParams);
    
    // Save back using tag resolution
    setTasksForTag(tasksData, currentTag, tasks);
    writeJSON(tasksPath, tasksData);
    
    return result;
  }
  ```

- **Backward Compatibility**:
  - ✅ DO: Ensure new features work with existing projects seamlessly
  - ✅ DO: Test with both legacy and tagged task data formats
  - ✅ DO: Support silent migration during feature usage
  - ❌ DON'T: Break existing workflows when adding tagged system features

## CLI Command Implementation

- **Command Structure**:
  - ✅ DO: Follow the established pattern in [`commands.js`](mdc:scripts/modules/commands.js)
  - ✅ DO: Use Commander.js for argument parsing
  - ✅ DO: Include comprehensive help text and examples
  - ✅ DO: Support tagged task context awareness

  ```javascript
  // ✅ DO: Implement CLI commands with tagged system awareness
  program
    .command('new-feature')
    .description('Description of the new feature with tagged task lists support')
    .option('-t, --tag <tag>', 'Specify tag context (defaults to current tag)')
    .option('-p, --param <value>', 'Feature-specific parameter')
    .option('--force', 'Force operation without confirmation')
    .action(async (options) => {
      try {
        const projectRoot = findProjectRoot();
        if (!projectRoot) {
          console.error('Not in a Task Master project directory');
          process.exit(1);
        }
        
        // Use specified tag or current tag
        const targetTag = options.tag || getCurrentTag() || 'master';
        
        const result = await newFeatureCore(
          path.join(projectRoot, '.taskmaster', 'tasks', 'tasks.json'),
          { param: options.param },
          { 
            force: options.force,
            targetTag: targetTag,
            outputFormat: 'text'
          }
        );
        
        console.log('Feature executed successfully');
      } catch (error) {
        console.error(`Error: ${error.message}`);
        process.exit(1);
      }
    });
  ```

- **Error Handling**:
  - ✅ DO: Provide clear error messages for common failures
  - ✅ DO: Handle tagged system migration errors gracefully
  - ✅ DO: Include suggestion for resolution when possible
  - ✅ DO: Exit with appropriate codes for scripting

## MCP Tool Implementation

- **Direct Function Pattern**:
  - ✅ DO: Create direct function wrappers in `mcp-server/src/core/direct-functions/`
  - ✅ DO: Follow silent mode patterns to prevent console output interference
  - ✅ DO: Use `findTasksJsonPath` for consistent path resolution
  - ✅ DO: Ensure tagged system compatibility

  ```javascript
  // ✅ DO: Implement MCP direct functions with tagged awareness
  export async function newFeatureDirect(args, log, context = {}) {
    try {
      const tasksPath = findTasksJsonPath(args, log);
      
      // Enable silent mode for clean MCP responses
      enableSilentMode();
      
      try {
        const result = await newFeatureCore(
          tasksPath,
          { param: args.param },
          { 
            force: args.force,
            targetTag: args.tag || 'master', // Support tag specification
            mcpLog: log,
            session: context.session,
            outputFormat: 'json'
          }
        );
        
        return {
          success: true,
          data: result,
          fromCache: false
        };
      } finally {
        disableSilentMode();
      }
    } catch (error) {
      log.error(`Error in newFeatureDirect: ${error.message}`);
      return {
        success: false,
        error: { code: 'FEATURE_ERROR', message: error.message },
        fromCache: false
      };
    }
  }
  ```

- **Tool Registration**:
  - ✅ DO: Create tool definitions in `mcp-server/src/tools/`
  - ✅ DO: Use Zod for parameter validation
  - ✅ DO: Include optional tag parameter for multi-context support
  - ✅ DO: Follow established naming conventions

  ```javascript
  // ✅ DO: Register MCP tools with tagged system support
  export function registerNewFeatureTool(server) {
    server.addTool({
      name: "new_feature",
      description: "Description of the new feature with tagged task lists support",
      inputSchema: z.object({
        param: z.string().describe("Feature-specific parameter"),
        tag: z.string().optional().describe("Target tag context (defaults to current tag)"),
        force: z.boolean().optional().describe("Force operation without confirmation"),
        projectRoot: z.string().optional().describe("Project root directory")
      }),
      execute: withNormalizedProjectRoot(async (args, { log, session }) => {
        try {
          const result = await newFeatureDirect(
            { ...args, projectRoot: args.projectRoot },
            log,
            { session }
          );
          return handleApiResult(result, log);
        } catch (error) {
          return handleApiResult({
            success: false,
            error: { code: 'EXECUTION_ERROR', message: error.message }
          }, log);
        }
      })
    });
  }
  ```

## Testing Strategy

- **Unit Tests**:
  - ✅ DO: Test core logic independently with both data formats
  - ✅ DO: Mock file system operations appropriately
  - ✅ DO: Test tag resolution behavior
  - ✅ DO: Verify migration compatibility

  ```javascript
  // ✅ DO: Test new features with tagged system awareness
  describe('newFeature', () => {
    beforeEach(() => {
      jest.clearAllMocks();
    });
    
    it('should work with legacy task format', async () => {
      const legacyData = { tasks: [/* test data */] };
      fs.readFileSync.mockReturnValue(JSON.stringify(legacyData));
      
      const result = await newFeatureCore('/test/tasks.json', { param: 'test' });
      
      expect(result).toBeDefined();
      // Test legacy format handling
    });
    
    it('should work with tagged task format', async () => {
      const taggedData = { 
        master: { tasks: [/* test data */] },
        feature: { tasks: [/* test data */] }
      };
      fs.readFileSync.mockReturnValue(JSON.stringify(taggedData));
      
      const result = await newFeatureCore('/test/tasks.json', { param: 'test' });
      
      expect(result).toBeDefined();
      // Test tagged format handling
    });
    
    it('should handle tag migration during feature usage', async () => {
      const legacyData = { tasks: [/* test data */] };
      fs.readFileSync.mockReturnValue(JSON.stringify(legacyData));
      
      await newFeatureCore('/test/tasks.json', { param: 'test' });
      
      // Verify migration occurred
      expect(fs.writeFileSync).toHaveBeenCalledWith(
        '/test/tasks.json',
        expect.stringContaining('"master"')
      );
    });
  });
  ```

- **Integration Tests**:
  - ✅ DO: Test CLI and MCP interfaces with real task data
  - ✅ DO: Verify end-to-end workflows across tag contexts
  - ✅ DO: Test error scenarios and recovery

## Documentation Updates

- **Rule Updates**:
  - ✅ DO: Update relevant `.cursor/rules/*.mdc` files
  - ✅ DO: Include tagged system considerations in architecture docs
  - ✅ DO: Add examples showing multi-context usage
  - ✅ DO: Update workflow documentation as needed

- **User Documentation**:
  - ✅ DO: Add feature documentation to `/docs` folder
  - ✅ DO: Include tagged system usage examples
  - ✅ DO: Update command reference documentation
  - ✅ DO: Provide migration notes if relevant

## Migration Considerations

- **Silent Migration Support**:
  - ✅ DO: Ensure new features trigger migration when needed
  - ✅ DO: Handle migration errors gracefully in feature code
  - ✅ DO: Test feature behavior with pre-migration projects
  - ❌ DON'T: Assume projects are already migrated

- **Tag Context Handling**:
  - ✅ DO: Default to current tag when not specified
  - ✅ DO: Support explicit tag selection in advanced features
  - ✅ DO: Validate tag existence before operations
  - ✅ DO: Provide clear messaging about tag context

## Performance Considerations

- **Efficient Tag Operations**:
  - ✅ DO: Minimize file I/O operations per feature execution
  - ✅ DO: Cache tag resolution results when appropriate
  - ✅ DO: Use streaming for large task datasets
  - ❌ DON'T: Load all tags when only one is needed

- **Memory Management**:
  - ✅ DO: Process large task lists efficiently
  - ✅ DO: Clean up temporary data structures
  - ✅ DO: Avoid keeping all tag data in memory simultaneously

## Deployment and Versioning

- **Changesets**:
  - ✅ DO: Create appropriate changesets for new features
  - ✅ DO: Use semantic versioning (minor for new features)
  - ✅ DO: Include tagged system information in release notes
  - ✅ DO: Document breaking changes if any

- **Feature Flags**:
  - ✅ DO: Consider feature flags for experimental functionality
  - ✅ DO: Ensure tagged system features work with flags
  - ✅ DO: Provide clear documentation about flag usage

By following these guidelines, new features will integrate smoothly with the Task Master ecosystem while supporting the enhanced tagged task lists system for multi-context development workflows.
