Simplified the Task Master CLI by organizing code into modules within the directory. **Why:** - **Better Organization:** Code is now grouped by function (AI, commands, dependencies, tasks, UI, utilities). - **Easier to Maintain:** Smaller modules are simpler to update and fix. - **Scalable:** New features can be added more easily in a structured way. **What Changed:** - Moved code from single _____ _ __ __ _ |_ _|_ _ ___| | __ | \/ | __ _ ___| |_ ___ _ __ | |/ _` / __| |/ / | |\/| |/ _` / __| __/ _ \ '__| | | (_| \__ \ < | | | | (_| \__ \ || __/ | |_|\__,_|___/_|\_\ |_| |_|\__,_|___/\__\___|_| by https://x.com/eyaltoledano ╭────────────────────────────────────────────╮ │ │ │ Version: 0.9.16 Project: Task Master │ │ │ ╰────────────────────────────────────────────╯ ╭─────────────────────╮ │ │ │ Task Master CLI │ │ │ ╰─────────────────────╯ ╭───────────────────╮ │ Task Generation │ ╰───────────────────╯ parse-prd --input=<file.txt> [--tasks=10] Generate tasks from a PRD document generate Create individual task files from tasks… ╭───────────────────╮ │ Task Management │ ╰───────────────────╯ list [--status=<status>] [--with-subtas… List all tasks with their status set-status --id=<id> --status=<status> Update task status (done, pending, etc.) update --from=<id> --prompt="<context>" Update tasks based on new requirements add-task --prompt="<text>" [--dependencies=… Add a new task using AI add-dependency --id=<id> --depends-on=<id> Add a dependency to a task remove-dependency --id=<id> --depends-on=<id> Remove a dependency from a task ╭──────────────────────────╮ │ Task Analysis & Detail │ ╰──────────────────────────╯ analyze-complexity [--research] [--threshold=5] Analyze tasks and generate expansion re… complexity-report [--file=<path>] Display the complexity analysis report expand --id=<id> [--num=5] [--research] [… Break down tasks into detailed subtasks expand --all [--force] [--research] Expand all pending tasks with subtasks clear-subtasks --id=<id> Remove subtasks from specified tasks ╭─────────────────────────────╮ │ Task Navigation & Viewing │ ╰─────────────────────────────╯ next Show the next task to work on based on … show <id> Display detailed information about a sp… ╭─────────────────────────╮ │ Dependency Management │ ╰─────────────────────────╯ validate-dependenci… Identify invalid dependencies without f… fix-dependencies Fix invalid dependencies automatically ╭─────────────────────────╮ │ Environment Variables │ ╰─────────────────────────╯ ANTHROPIC_API_KEY Your Anthropic API key Required MODEL Claude model to use Default: claude-3-7-sonn… MAX_TOKENS Maximum tokens for responses Default: 4000 TEMPERATURE Temperature for model responses Default: 0.7 PERPLEXITY_API_KEY Perplexity API key for research Optional PERPLEXITY_MODEL Perplexity model to use Default: sonar-small-onl… DEBUG Enable debug logging Default: false LOG_LEVEL Console output level (debug,info,warn,error) Default: info DEFAULT_SUBTASKS Default number of subtasks to generate Default: 3 DEFAULT_PRIORITY Default task priority Default: medium PROJECT_NAME Project name displayed in UI Default: Task Master file into these new modules: - : AI interactions (Claude, Perplexity) - : CLI command definitions (Commander.js) - : Task dependency handling - : Core task operations (create, list, update, etc.) - : User interface elements (display, formatting) - : Utility functions and configuration - : Exports all modules - Replaced direct use of _____ _ __ __ _ |_ _|_ _ ___| | __ | \/ | __ _ ___| |_ ___ _ __ | |/ _` / __| |/ / | |\/| |/ _` / __| __/ _ \ '__| | | (_| \__ \ < | | | | (_| \__ \ || __/ | |_|\__,_|___/_|\_\ |_| |_|\__,_|___/\__\___|_| by https://x.com/eyaltoledano ╭────────────────────────────────────────────╮ │ │ │ Version: 0.9.16 Project: Task Master │ │ │ ╰────────────────────────────────────────────╯ ╭─────────────────────╮ │ │ │ Task Master CLI │ │ │ ╰─────────────────────╯ ╭───────────────────╮ │ Task Generation │ ╰───────────────────╯ parse-prd --input=<file.txt> [--tasks=10] Generate tasks from a PRD document generate Create individual task files from tasks… ╭───────────────────╮ │ Task Management │ ╰───────────────────╯ list [--status=<status>] [--with-subtas… List all tasks with their status set-status --id=<id> --status=<status> Update task status (done, pending, etc.) update --from=<id> --prompt="<context>" Update tasks based on new requirements add-task --prompt="<text>" [--dependencies=… Add a new task using AI add-dependency --id=<id> --depends-on=<id> Add a dependency to a task remove-dependency --id=<id> --depends-on=<id> Remove a dependency from a task ╭──────────────────────────╮ │ Task Analysis & Detail │ ╰──────────────────────────╯ analyze-complexity [--research] [--threshold=5] Analyze tasks and generate expansion re… complexity-report [--file=<path>] Display the complexity analysis report expand --id=<id> [--num=5] [--research] [… Break down tasks into detailed subtasks expand --all [--force] [--research] Expand all pending tasks with subtasks clear-subtasks --id=<id> Remove subtasks from specified tasks ╭─────────────────────────────╮ │ Task Navigation & Viewing │ ╰─────────────────────────────╯ next Show the next task to work on based on … show <id> Display detailed information about a sp… ╭─────────────────────────╮ │ Dependency Management │ ╰─────────────────────────╯ validate-dependenci… Identify invalid dependencies without f… fix-dependencies Fix invalid dependencies automatically ╭─────────────────────────╮ │ Environment Variables │ ╰─────────────────────────╯ ANTHROPIC_API_KEY Your Anthropic API key Required MODEL Claude model to use Default: claude-3-7-sonn… MAX_TOKENS Maximum tokens for responses Default: 4000 TEMPERATURE Temperature for model responses Default: 0.7 PERPLEXITY_API_KEY Perplexity API key for research Optional PERPLEXITY_MODEL Perplexity model to use Default: sonar-small-onl… DEBUG Enable debug logging Default: false LOG_LEVEL Console output level (debug,info,warn,error) Default: info DEFAULT_SUBTASKS Default number of subtasks to generate Default: 3 DEFAULT_PRIORITY Default task priority Default: medium PROJECT_NAME Project name displayed in UI Default: Task Master with the global command (see ). - Updated documentation () to reflect the new command. **Benefits:** Code is now cleaner, easier to work with, and ready for future growth. Use the command (or ) to run the CLI. See for command details.
224 lines
7.5 KiB
Plaintext
224 lines
7.5 KiB
Plaintext
---
|
|
description: Guidelines for managing task dependencies and relationships
|
|
globs: scripts/modules/dependency-manager.js
|
|
alwaysApply: false
|
|
---
|
|
|
|
# Dependency Management Guidelines
|
|
|
|
## Dependency Structure Principles
|
|
|
|
- **Dependency References**:
|
|
- ✅ DO: Represent task dependencies as arrays of task IDs
|
|
- ✅ DO: Use numeric IDs for direct task references
|
|
- ✅ DO: Use string IDs with dot notation (e.g., "1.2") for subtask references
|
|
- ❌ DON'T: Mix reference types without proper conversion
|
|
|
|
```javascript
|
|
// ✅ DO: Use consistent dependency formats
|
|
// For main tasks
|
|
task.dependencies = [1, 2, 3]; // Dependencies on other main tasks
|
|
|
|
// For subtasks
|
|
subtask.dependencies = [1, "3.2"]; // Dependency on main task 1 and subtask 2 of task 3
|
|
```
|
|
|
|
- **Subtask Dependencies**:
|
|
- ✅ DO: Allow numeric subtask IDs to reference other subtasks within the same parent
|
|
- ✅ DO: Convert between formats appropriately when needed
|
|
- ❌ DON'T: Create circular dependencies between subtasks
|
|
|
|
```javascript
|
|
// ✅ DO: Properly normalize subtask dependencies
|
|
// When a subtask refers to another subtask in the same parent
|
|
if (typeof depId === 'number' && depId < 100) {
|
|
// It's likely a reference to another subtask in the same parent task
|
|
const fullSubtaskId = `${parentId}.${depId}`;
|
|
// Now use fullSubtaskId for validation
|
|
}
|
|
```
|
|
|
|
## Dependency Validation
|
|
|
|
- **Existence Checking**:
|
|
- ✅ DO: Validate that referenced tasks exist before adding dependencies
|
|
- ✅ DO: Provide clear error messages for non-existent dependencies
|
|
- ✅ DO: Remove references to non-existent tasks during validation
|
|
|
|
```javascript
|
|
// ✅ DO: Check if the dependency exists before adding
|
|
if (!taskExists(data.tasks, formattedDependencyId)) {
|
|
log('error', `Dependency target ${formattedDependencyId} does not exist in tasks.json`);
|
|
process.exit(1);
|
|
}
|
|
```
|
|
|
|
- **Circular Dependency Prevention**:
|
|
- ✅ DO: Check for circular dependencies before adding new relationships
|
|
- ✅ DO: Use graph traversal algorithms (DFS) to detect cycles
|
|
- ✅ DO: Provide clear error messages explaining the circular chain
|
|
|
|
```javascript
|
|
// ✅ DO: Check for circular dependencies before adding
|
|
const dependencyChain = [formattedTaskId];
|
|
if (isCircularDependency(data.tasks, formattedDependencyId, dependencyChain)) {
|
|
log('error', `Cannot add dependency ${formattedDependencyId} to task ${formattedTaskId} as it would create a circular dependency.`);
|
|
process.exit(1);
|
|
}
|
|
```
|
|
|
|
- **Self-Dependency Prevention**:
|
|
- ✅ DO: Prevent tasks from depending on themselves
|
|
- ✅ DO: Handle both direct and indirect self-dependencies
|
|
|
|
```javascript
|
|
// ✅ DO: Prevent self-dependencies
|
|
if (String(formattedTaskId) === String(formattedDependencyId)) {
|
|
log('error', `Task ${formattedTaskId} cannot depend on itself.`);
|
|
process.exit(1);
|
|
}
|
|
```
|
|
|
|
## Dependency Modification
|
|
|
|
- **Adding Dependencies**:
|
|
- ✅ DO: Format task and dependency IDs consistently
|
|
- ✅ DO: Check for existing dependencies to prevent duplicates
|
|
- ✅ DO: Sort dependencies for better readability
|
|
|
|
```javascript
|
|
// ✅ DO: Format IDs consistently when adding dependencies
|
|
const formattedTaskId = typeof taskId === 'string' && taskId.includes('.')
|
|
? taskId : parseInt(taskId, 10);
|
|
|
|
const formattedDependencyId = formatTaskId(dependencyId);
|
|
```
|
|
|
|
- **Removing Dependencies**:
|
|
- ✅ DO: Check if the dependency exists before removing
|
|
- ✅ DO: Handle different ID formats consistently
|
|
- ✅ DO: Provide feedback about the removal result
|
|
|
|
```javascript
|
|
// ✅ DO: Properly handle dependency removal
|
|
const dependencyIndex = targetTask.dependencies.findIndex(dep => {
|
|
// Convert both to strings for comparison
|
|
let depStr = String(dep);
|
|
|
|
// Handle relative subtask references
|
|
if (typeof dep === 'number' && dep < 100 && isSubtask) {
|
|
const [parentId] = formattedTaskId.split('.');
|
|
depStr = `${parentId}.${dep}`;
|
|
}
|
|
|
|
return depStr === normalizedDependencyId;
|
|
});
|
|
|
|
if (dependencyIndex === -1) {
|
|
log('info', `Task ${formattedTaskId} does not depend on ${formattedDependencyId}, no changes made.`);
|
|
return;
|
|
}
|
|
|
|
// Remove the dependency
|
|
targetTask.dependencies.splice(dependencyIndex, 1);
|
|
```
|
|
|
|
## Dependency Cleanup
|
|
|
|
- **Duplicate Removal**:
|
|
- ✅ DO: Use Set objects to identify and remove duplicates
|
|
- ✅ DO: Handle both numeric and string ID formats
|
|
|
|
```javascript
|
|
// ✅ DO: Remove duplicate dependencies
|
|
const uniqueDeps = new Set();
|
|
const uniqueDependencies = task.dependencies.filter(depId => {
|
|
// Convert to string for comparison to handle both numeric and string IDs
|
|
const depIdStr = String(depId);
|
|
if (uniqueDeps.has(depIdStr)) {
|
|
log('warn', `Removing duplicate dependency from task ${task.id}: ${depId}`);
|
|
return false;
|
|
}
|
|
uniqueDeps.add(depIdStr);
|
|
return true;
|
|
});
|
|
```
|
|
|
|
- **Invalid Reference Cleanup**:
|
|
- ✅ DO: Check for and remove references to non-existent tasks
|
|
- ✅ DO: Check for and remove self-references
|
|
- ✅ DO: Track and report changes made during cleanup
|
|
|
|
```javascript
|
|
// ✅ DO: Filter invalid task dependencies
|
|
task.dependencies = task.dependencies.filter(depId => {
|
|
const numericId = typeof depId === 'string' ? parseInt(depId, 10) : depId;
|
|
if (!validTaskIds.has(numericId)) {
|
|
log('warn', `Removing invalid task dependency from task ${task.id}: ${depId} (task does not exist)`);
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
```
|
|
|
|
## Dependency Visualization
|
|
|
|
- **Status Indicators**:
|
|
- ✅ DO: Use visual indicators to show dependency status (✅/⏱️)
|
|
- ✅ DO: Format dependency lists consistently
|
|
|
|
```javascript
|
|
// ✅ DO: Format dependencies with status indicators
|
|
function formatDependenciesWithStatus(dependencies, allTasks) {
|
|
if (!dependencies || dependencies.length === 0) {
|
|
return 'None';
|
|
}
|
|
|
|
return dependencies.map(depId => {
|
|
const depTask = findTaskById(allTasks, depId);
|
|
if (!depTask) return `${depId} (Not found)`;
|
|
|
|
const isDone = depTask.status === 'done' || depTask.status === 'completed';
|
|
const statusIcon = isDone ? '✅' : '⏱️';
|
|
|
|
return `${statusIcon} ${depId} (${depTask.status})`;
|
|
}).join(', ');
|
|
}
|
|
```
|
|
|
|
## Cycle Detection
|
|
|
|
- **Graph Traversal**:
|
|
- ✅ DO: Use depth-first search (DFS) for cycle detection
|
|
- ✅ DO: Track visited nodes and recursion stack
|
|
- ✅ DO: Support both task and subtask dependencies
|
|
|
|
```javascript
|
|
// ✅ DO: Use proper cycle detection algorithms
|
|
function findCycles(subtaskId, dependencyMap, visited = new Set(), recursionStack = new Set()) {
|
|
// Mark the current node as visited and part of recursion stack
|
|
visited.add(subtaskId);
|
|
recursionStack.add(subtaskId);
|
|
|
|
const cyclesToBreak = [];
|
|
const dependencies = dependencyMap.get(subtaskId) || [];
|
|
|
|
for (const depId of dependencies) {
|
|
if (!visited.has(depId)) {
|
|
const cycles = findCycles(depId, dependencyMap, visited, recursionStack);
|
|
cyclesToBreak.push(...cycles);
|
|
}
|
|
else if (recursionStack.has(depId)) {
|
|
// Found a cycle, add the edge to break
|
|
cyclesToBreak.push(depId);
|
|
}
|
|
}
|
|
|
|
// Remove the node from recursion stack before returning
|
|
recursionStack.delete(subtaskId);
|
|
|
|
return cyclesToBreak;
|
|
}
|
|
```
|
|
|
|
Refer to [`dependency-manager.js`](mdc:scripts/modules/dependency-manager.js) for implementation examples and [`new_features.mdc`](mdc:.cursor/rules/new_features.mdc) for integration guidelines. |