feat(move-tasks): Implement move command for tasks and subtasks

Adds a new CLI command and MCP tool to reorganize tasks and subtasks within the hierarchy. Features include:
- Moving tasks between different positions in the task list
- Converting tasks to subtasks and vice versa
- Moving subtasks between parents
- Moving multiple tasks at once with comma-separated IDs
- Creating placeholder tasks when moving to new IDs
- Validation to prevent accidental data loss

This is particularly useful for resolving merge conflicts when multiple team members create tasks on different branches.
This commit is contained in:
Eyal Toledano
2025-05-22 04:14:22 -04:00
parent edf0f23005
commit 04af16de27
18 changed files with 1201 additions and 29 deletions

View File

@@ -35,6 +35,47 @@ function generateTaskFiles(tasksPath, outputDir, options = {}) {
log('info', `Validating and fixing dependencies`);
validateAndFixDependencies(data, tasksPath);
// Get valid task IDs from tasks.json
const validTaskIds = data.tasks.map(task => task.id);
// Cleanup orphaned task files
log('info', 'Checking for orphaned task files to clean up...');
try {
// Get all task files in the output directory
const files = fs.readdirSync(outputDir);
const taskFilePattern = /^task_(\d+)\.txt$/;
// Filter for task files and check if they match a valid task ID
const orphanedFiles = files.filter(file => {
const match = file.match(taskFilePattern);
if (match) {
const fileTaskId = parseInt(match[1], 10);
return !validTaskIds.includes(fileTaskId);
}
return false;
});
// Delete orphaned files
if (orphanedFiles.length > 0) {
log('info', `Found ${orphanedFiles.length} orphaned task files to remove`);
orphanedFiles.forEach(file => {
const filePath = path.join(outputDir, file);
try {
fs.unlinkSync(filePath);
log('info', `Removed orphaned task file: ${file}`);
} catch (err) {
log('warn', `Failed to remove orphaned task file ${file}: ${err.message}`);
}
});
} else {
log('info', 'No orphaned task files found');
}
} catch (err) {
log('warn', `Error cleaning up orphaned task files: ${err.message}`);
// Continue with file generation even if cleanup fails
}
// Generate task files
log('info', 'Generating individual task files...');
data.tasks.forEach((task) => {