feat(analyze): add task ID filtering to analyze-complexity command
Enhance analyze-complexity to support analyzing specific tasks by ID or range: - Add --id option for comma-separated task IDs - Add --from/--to options for analyzing tasks within a range - Implement intelligent merging with existing reports - Update CLI, MCP tools, and direct functions for consistent support - Add changeset documenting the feature
This commit is contained in:
5
.changeset/metal-forks-yawn.md
Normal file
5
.changeset/metal-forks-yawn.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'task-master-ai': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Enhance analyze-complexity to support analyzing specific task IDs. Users can now analyze individual tasks or selected task groups by using the new `--id` option with comma-separated IDs, or `--from` and `--to` options to specify a range of tasks. The feature intelligently merges analysis results with existing reports, allowing incremental analysis while preserving previous results.
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"models": {
|
"models": {
|
||||||
"main": {
|
"main": {
|
||||||
"provider": "ollama",
|
"provider": "anthropic",
|
||||||
"modelId": "devstral:latest",
|
"modelId": "claude-3-7-sonnet-20250219",
|
||||||
"maxTokens": 120000,
|
"maxTokens": 120000,
|
||||||
"temperature": 0.2
|
"temperature": 0.2
|
||||||
},
|
},
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"fallback": {
|
"fallback": {
|
||||||
"provider": "anthropic",
|
"provider": "anthropic",
|
||||||
"modelId": "claude-3-7-sonnet-20250219",
|
"modelId": "claude-3-5-sonnet-20241022",
|
||||||
"maxTokens": 8192,
|
"maxTokens": 8192,
|
||||||
"temperature": 0.2
|
"temperature": 0.2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ import { createLogWrapper } from '../../tools/utils.js'; // Import the new utili
|
|||||||
* @param {string} args.outputPath - Explicit absolute path to save the report.
|
* @param {string} args.outputPath - Explicit absolute path to save the report.
|
||||||
* @param {string|number} [args.threshold] - Minimum complexity score to recommend expansion (1-10)
|
* @param {string|number} [args.threshold] - Minimum complexity score to recommend expansion (1-10)
|
||||||
* @param {boolean} [args.research] - Use Perplexity AI for research-backed complexity analysis
|
* @param {boolean} [args.research] - Use Perplexity AI for research-backed complexity analysis
|
||||||
|
* @param {string} [args.ids] - Comma-separated list of task IDs to analyze
|
||||||
|
* @param {number} [args.from] - Starting task ID in a range to analyze
|
||||||
|
* @param {number} [args.to] - Ending task ID in a range to analyze
|
||||||
* @param {string} [args.projectRoot] - Project root path.
|
* @param {string} [args.projectRoot] - Project root path.
|
||||||
* @param {Object} log - Logger object
|
* @param {Object} log - Logger object
|
||||||
* @param {Object} [context={}] - Context object containing session data
|
* @param {Object} [context={}] - Context object containing session data
|
||||||
@@ -26,7 +29,16 @@ import { createLogWrapper } from '../../tools/utils.js'; // Import the new utili
|
|||||||
*/
|
*/
|
||||||
export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||||
const { session } = context;
|
const { session } = context;
|
||||||
const { tasksJsonPath, outputPath, threshold, research, projectRoot } = args;
|
const {
|
||||||
|
tasksJsonPath,
|
||||||
|
outputPath,
|
||||||
|
threshold,
|
||||||
|
research,
|
||||||
|
projectRoot,
|
||||||
|
ids,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
} = args;
|
||||||
|
|
||||||
const logWrapper = createLogWrapper(log);
|
const logWrapper = createLogWrapper(log);
|
||||||
|
|
||||||
@@ -58,6 +70,14 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
|||||||
log.info(`Analyzing task complexity from: ${tasksPath}`);
|
log.info(`Analyzing task complexity from: ${tasksPath}`);
|
||||||
log.info(`Output report will be saved to: ${resolvedOutputPath}`);
|
log.info(`Output report will be saved to: ${resolvedOutputPath}`);
|
||||||
|
|
||||||
|
if (ids) {
|
||||||
|
log.info(`Analyzing specific task IDs: ${ids}`);
|
||||||
|
} else if (from || to) {
|
||||||
|
const fromStr = from !== undefined ? from : 'first';
|
||||||
|
const toStr = to !== undefined ? to : 'last';
|
||||||
|
log.info(`Analyzing tasks in range: ${fromStr} to ${toStr}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (research) {
|
if (research) {
|
||||||
log.info('Using research role for complexity analysis');
|
log.info('Using research role for complexity analysis');
|
||||||
}
|
}
|
||||||
@@ -68,7 +88,10 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
|||||||
output: outputPath,
|
output: outputPath,
|
||||||
threshold: threshold,
|
threshold: threshold,
|
||||||
research: research === true, // Ensure boolean
|
research: research === true, // Ensure boolean
|
||||||
projectRoot: projectRoot // Pass projectRoot here
|
projectRoot: projectRoot, // Pass projectRoot here
|
||||||
|
id: ids, // Pass the ids parameter to the core function as 'id'
|
||||||
|
from: from, // Pass from parameter
|
||||||
|
to: to // Pass to parameter
|
||||||
};
|
};
|
||||||
// --- End Initial Checks ---
|
// --- End Initial Checks ---
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,24 @@ export function registerAnalyzeProjectComplexityTool(server) {
|
|||||||
.describe(
|
.describe(
|
||||||
'Path to the tasks file relative to project root (default: tasks/tasks.json).'
|
'Path to the tasks file relative to project root (default: tasks/tasks.json).'
|
||||||
),
|
),
|
||||||
|
ids: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.describe('Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").'),
|
||||||
|
from: z
|
||||||
|
.coerce
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe('Starting task ID in a range to analyze.'),
|
||||||
|
to: z
|
||||||
|
.coerce
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.describe('Ending task ID in a range to analyze.'),
|
||||||
projectRoot: z
|
projectRoot: z
|
||||||
.string()
|
.string()
|
||||||
.describe('The directory of the project. Must be an absolute path.')
|
.describe('The directory of the project. Must be an absolute path.')
|
||||||
@@ -107,7 +125,10 @@ export function registerAnalyzeProjectComplexityTool(server) {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
threshold: args.threshold,
|
threshold: args.threshold,
|
||||||
research: args.research,
|
research: args.research,
|
||||||
projectRoot: args.projectRoot
|
projectRoot: args.projectRoot,
|
||||||
|
ids: args.ids,
|
||||||
|
from: args.from,
|
||||||
|
to: args.to
|
||||||
},
|
},
|
||||||
log,
|
log,
|
||||||
{ session }
|
{ session }
|
||||||
|
|||||||
@@ -1211,6 +1211,18 @@ function registerCommands(programInstance) {
|
|||||||
'-r, --research',
|
'-r, --research',
|
||||||
'Use Perplexity AI for research-backed complexity analysis'
|
'Use Perplexity AI for research-backed complexity analysis'
|
||||||
)
|
)
|
||||||
|
.option(
|
||||||
|
'-i, --id <ids>',
|
||||||
|
'Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")'
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'--from <id>',
|
||||||
|
'Starting task ID in a range to analyze'
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'--to <id>',
|
||||||
|
'Ending task ID in a range to analyze'
|
||||||
|
)
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const tasksPath = options.file || 'tasks/tasks.json';
|
const tasksPath = options.file || 'tasks/tasks.json';
|
||||||
const outputPath = options.output;
|
const outputPath = options.output;
|
||||||
@@ -1221,6 +1233,14 @@ function registerCommands(programInstance) {
|
|||||||
console.log(chalk.blue(`Analyzing task complexity from: ${tasksPath}`));
|
console.log(chalk.blue(`Analyzing task complexity from: ${tasksPath}`));
|
||||||
console.log(chalk.blue(`Output report will be saved to: ${outputPath}`));
|
console.log(chalk.blue(`Output report will be saved to: ${outputPath}`));
|
||||||
|
|
||||||
|
if (options.id) {
|
||||||
|
console.log(chalk.blue(`Analyzing specific task IDs: ${options.id}`));
|
||||||
|
} else if (options.from || options.to) {
|
||||||
|
const fromStr = options.from ? options.from : 'first';
|
||||||
|
const toStr = options.to ? options.to : 'last';
|
||||||
|
console.log(chalk.blue(`Analyzing tasks in range: ${fromStr} to ${toStr}`));
|
||||||
|
}
|
||||||
|
|
||||||
if (useResearch) {
|
if (useResearch) {
|
||||||
console.log(
|
console.log(
|
||||||
chalk.blue(
|
chalk.blue(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import boxen from 'boxen';
|
import boxen from 'boxen';
|
||||||
import readline from 'readline';
|
import readline from 'readline';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
import { log, readJSON, writeJSON, isSilentMode } from '../utils.js';
|
import { log, readJSON, writeJSON, isSilentMode } from '../utils.js';
|
||||||
|
|
||||||
@@ -51,6 +52,9 @@ Do not include any explanatory text, markdown formatting, or code block markers
|
|||||||
* @param {string|number} [options.threshold] - Complexity threshold
|
* @param {string|number} [options.threshold] - Complexity threshold
|
||||||
* @param {boolean} [options.research] - Use research role
|
* @param {boolean} [options.research] - Use research role
|
||||||
* @param {string} [options.projectRoot] - Project root path (for MCP/env fallback).
|
* @param {string} [options.projectRoot] - Project root path (for MCP/env fallback).
|
||||||
|
* @param {string} [options.id] - Comma-separated list of task IDs to analyze specifically
|
||||||
|
* @param {number} [options.from] - Starting task ID in a range to analyze
|
||||||
|
* @param {number} [options.to] - Ending task ID in a range to analyze
|
||||||
* @param {Object} [options._filteredTasksData] - Pre-filtered task data (internal use)
|
* @param {Object} [options._filteredTasksData] - Pre-filtered task data (internal use)
|
||||||
* @param {number} [options._originalTaskCount] - Original task count (internal use)
|
* @param {number} [options._originalTaskCount] - Original task count (internal use)
|
||||||
* @param {Object} context - Context object, potentially containing session and mcpLog
|
* @param {Object} context - Context object, potentially containing session and mcpLog
|
||||||
@@ -65,6 +69,10 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
const thresholdScore = parseFloat(options.threshold || '5');
|
const thresholdScore = parseFloat(options.threshold || '5');
|
||||||
const useResearch = options.research || false;
|
const useResearch = options.research || false;
|
||||||
const projectRoot = options.projectRoot;
|
const projectRoot = options.projectRoot;
|
||||||
|
// New parameters for task ID filtering
|
||||||
|
const specificIds = options.id ? options.id.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id)) : null;
|
||||||
|
const fromId = options.from !== undefined ? parseInt(options.from, 10) : null;
|
||||||
|
const toId = options.to !== undefined ? parseInt(options.to, 10) : null;
|
||||||
|
|
||||||
const outputFormat = mcpLog ? 'json' : 'text';
|
const outputFormat = mcpLog ? 'json' : 'text';
|
||||||
|
|
||||||
@@ -88,13 +96,14 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
reportLog(`Reading tasks from ${tasksPath}...`, 'info');
|
reportLog(`Reading tasks from ${tasksPath}...`, 'info');
|
||||||
let tasksData;
|
let tasksData;
|
||||||
let originalTaskCount = 0;
|
let originalTaskCount = 0;
|
||||||
|
let originalData = null;
|
||||||
|
|
||||||
if (options._filteredTasksData) {
|
if (options._filteredTasksData) {
|
||||||
tasksData = options._filteredTasksData;
|
tasksData = options._filteredTasksData;
|
||||||
originalTaskCount = options._originalTaskCount || tasksData.tasks.length;
|
originalTaskCount = options._originalTaskCount || tasksData.tasks.length;
|
||||||
if (!options._originalTaskCount) {
|
if (!options._originalTaskCount) {
|
||||||
try {
|
try {
|
||||||
const originalData = readJSON(tasksPath);
|
originalData = readJSON(tasksPath);
|
||||||
if (originalData && originalData.tasks) {
|
if (originalData && originalData.tasks) {
|
||||||
originalTaskCount = originalData.tasks.length;
|
originalTaskCount = originalData.tasks.length;
|
||||||
}
|
}
|
||||||
@@ -103,22 +112,55 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tasksData = readJSON(tasksPath);
|
originalData = readJSON(tasksPath);
|
||||||
if (
|
if (
|
||||||
!tasksData ||
|
!originalData ||
|
||||||
!tasksData.tasks ||
|
!originalData.tasks ||
|
||||||
!Array.isArray(tasksData.tasks) ||
|
!Array.isArray(originalData.tasks) ||
|
||||||
tasksData.tasks.length === 0
|
originalData.tasks.length === 0
|
||||||
) {
|
) {
|
||||||
throw new Error('No tasks found in the tasks file');
|
throw new Error('No tasks found in the tasks file');
|
||||||
}
|
}
|
||||||
originalTaskCount = tasksData.tasks.length;
|
originalTaskCount = originalData.tasks.length;
|
||||||
|
|
||||||
|
// Filter tasks based on active status
|
||||||
const activeStatuses = ['pending', 'blocked', 'in-progress'];
|
const activeStatuses = ['pending', 'blocked', 'in-progress'];
|
||||||
const filteredTasks = tasksData.tasks.filter((task) =>
|
let filteredTasks = originalData.tasks.filter((task) =>
|
||||||
activeStatuses.includes(task.status?.toLowerCase() || 'pending')
|
activeStatuses.includes(task.status?.toLowerCase() || 'pending')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Apply ID filtering if specified
|
||||||
|
if (specificIds && specificIds.length > 0) {
|
||||||
|
reportLog(`Filtering tasks by specific IDs: ${specificIds.join(', ')}`, 'info');
|
||||||
|
filteredTasks = filteredTasks.filter(task => specificIds.includes(task.id));
|
||||||
|
|
||||||
|
if (outputFormat === 'text') {
|
||||||
|
if (filteredTasks.length === 0 && specificIds.length > 0) {
|
||||||
|
console.log(chalk.yellow(`Warning: No active tasks found with IDs: ${specificIds.join(', ')}`));
|
||||||
|
} else if (filteredTasks.length < specificIds.length) {
|
||||||
|
const foundIds = filteredTasks.map(t => t.id);
|
||||||
|
const missingIds = specificIds.filter(id => !foundIds.includes(id));
|
||||||
|
console.log(chalk.yellow(`Warning: Some requested task IDs were not found or are not active: ${missingIds.join(', ')}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Apply range filtering if specified
|
||||||
|
else if (fromId !== null || toId !== null) {
|
||||||
|
const effectiveFromId = fromId !== null ? fromId : 1;
|
||||||
|
const effectiveToId = toId !== null ? toId : Math.max(...originalData.tasks.map(t => t.id));
|
||||||
|
|
||||||
|
reportLog(`Filtering tasks by ID range: ${effectiveFromId} to ${effectiveToId}`, 'info');
|
||||||
|
filteredTasks = filteredTasks.filter(task =>
|
||||||
|
task.id >= effectiveFromId && task.id <= effectiveToId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (outputFormat === 'text' && filteredTasks.length === 0) {
|
||||||
|
console.log(chalk.yellow(`Warning: No active tasks found in range: ${effectiveFromId}-${effectiveToId}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tasksData = {
|
tasksData = {
|
||||||
...tasksData,
|
...originalData,
|
||||||
tasks: filteredTasks,
|
tasks: filteredTasks,
|
||||||
_originalTaskCount: originalTaskCount
|
_originalTaskCount: originalTaskCount
|
||||||
};
|
};
|
||||||
@@ -129,7 +171,18 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
`Found ${originalTaskCount} total tasks in the task file.`,
|
`Found ${originalTaskCount} total tasks in the task file.`,
|
||||||
'info'
|
'info'
|
||||||
);
|
);
|
||||||
if (skippedCount > 0) {
|
|
||||||
|
// Updated messaging to reflect filtering logic
|
||||||
|
if (specificIds || fromId !== null || toId !== null) {
|
||||||
|
const filterMsg = specificIds
|
||||||
|
? `Analyzing ${tasksData.tasks.length} tasks with specific IDs: ${specificIds.join(', ')}`
|
||||||
|
: `Analyzing ${tasksData.tasks.length} tasks in range: ${fromId || 1} to ${toId || 'end'}`;
|
||||||
|
|
||||||
|
reportLog(filterMsg, 'info');
|
||||||
|
if (outputFormat === 'text') {
|
||||||
|
console.log(chalk.blue(filterMsg));
|
||||||
|
}
|
||||||
|
} else if (skippedCount > 0) {
|
||||||
const skipMessage = `Skipping ${skippedCount} tasks marked as done/cancelled/deferred. Analyzing ${tasksData.tasks.length} active tasks.`;
|
const skipMessage = `Skipping ${skippedCount} tasks marked as done/cancelled/deferred. Analyzing ${tasksData.tasks.length} active tasks.`;
|
||||||
reportLog(skipMessage, 'info');
|
reportLog(skipMessage, 'info');
|
||||||
if (outputFormat === 'text') {
|
if (outputFormat === 'text') {
|
||||||
@@ -137,7 +190,44 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for existing report before doing analysis
|
||||||
|
let existingReport = null;
|
||||||
|
let existingAnalysisMap = new Map(); // For quick lookups by task ID
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(outputPath)) {
|
||||||
|
existingReport = readJSON(outputPath);
|
||||||
|
reportLog(`Found existing complexity report at ${outputPath}`, 'info');
|
||||||
|
|
||||||
|
if (existingReport &&
|
||||||
|
existingReport.complexityAnalysis &&
|
||||||
|
Array.isArray(existingReport.complexityAnalysis)) {
|
||||||
|
// Create lookup map of existing analysis entries
|
||||||
|
existingReport.complexityAnalysis.forEach(item => {
|
||||||
|
existingAnalysisMap.set(item.taskId, item);
|
||||||
|
});
|
||||||
|
reportLog(`Existing report contains ${existingReport.complexityAnalysis.length} task analyses`, 'info');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (readError) {
|
||||||
|
reportLog(`Warning: Could not read existing report: ${readError.message}`, 'warn');
|
||||||
|
existingReport = null;
|
||||||
|
existingAnalysisMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (tasksData.tasks.length === 0) {
|
if (tasksData.tasks.length === 0) {
|
||||||
|
// If using ID filtering but no matching tasks, return existing report or empty
|
||||||
|
if (existingReport && (specificIds || fromId !== null || toId !== null)) {
|
||||||
|
reportLog(`No matching tasks found for analysis. Keeping existing report.`, 'info');
|
||||||
|
if (outputFormat === 'text') {
|
||||||
|
console.log(chalk.yellow(`No matching tasks found for analysis. Keeping existing report.`));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
report: existingReport,
|
||||||
|
telemetryData: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise create empty report
|
||||||
const emptyReport = {
|
const emptyReport = {
|
||||||
meta: {
|
meta: {
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
@@ -146,9 +236,9 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
projectName: getProjectName(session),
|
projectName: getProjectName(session),
|
||||||
usedResearch: useResearch
|
usedResearch: useResearch
|
||||||
},
|
},
|
||||||
complexityAnalysis: []
|
complexityAnalysis: existingReport?.complexityAnalysis || []
|
||||||
};
|
};
|
||||||
reportLog(`Writing empty complexity report to ${outputPath}...`, 'info');
|
reportLog(`Writing complexity report to ${outputPath}...`, 'info');
|
||||||
writeJSON(outputPath, emptyReport);
|
writeJSON(outputPath, emptyReport);
|
||||||
reportLog(
|
reportLog(
|
||||||
`Task complexity analysis complete. Report written to ${outputPath}`,
|
`Task complexity analysis complete. Report written to ${outputPath}`,
|
||||||
@@ -196,9 +286,13 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return emptyReport;
|
return {
|
||||||
|
report: emptyReport,
|
||||||
|
telemetryData: null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Continue with regular analysis path
|
||||||
const prompt = generateInternalComplexityAnalysisPrompt(tasksData);
|
const prompt = generateInternalComplexityAnalysisPrompt(tasksData);
|
||||||
const systemPrompt =
|
const systemPrompt =
|
||||||
'You are an expert software architect and project manager analyzing task complexity. Respond only with the requested valid JSON array.';
|
'You are an expert software architect and project manager analyzing task complexity. Respond only with the requested valid JSON array.';
|
||||||
@@ -326,15 +420,38 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge with existing report
|
||||||
|
let finalComplexityAnalysis = [];
|
||||||
|
|
||||||
|
if (existingReport && Array.isArray(existingReport.complexityAnalysis)) {
|
||||||
|
// Create a map of task IDs that we just analyzed
|
||||||
|
const analyzedTaskIds = new Set(complexityAnalysis.map(item => item.taskId));
|
||||||
|
|
||||||
|
// Keep existing entries that weren't in this analysis run
|
||||||
|
const existingEntriesNotAnalyzed = existingReport.complexityAnalysis.filter(
|
||||||
|
item => !analyzedTaskIds.has(item.taskId)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Combine with new analysis
|
||||||
|
finalComplexityAnalysis = [...existingEntriesNotAnalyzed, ...complexityAnalysis];
|
||||||
|
|
||||||
|
reportLog(`Merged ${complexityAnalysis.length} new analyses with ${existingEntriesNotAnalyzed.length} existing entries`, 'info');
|
||||||
|
} else {
|
||||||
|
// No existing report or invalid format, just use the new analysis
|
||||||
|
finalComplexityAnalysis = complexityAnalysis;
|
||||||
|
}
|
||||||
|
|
||||||
const report = {
|
const report = {
|
||||||
meta: {
|
meta: {
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
tasksAnalyzed: tasksData.tasks.length,
|
tasksAnalyzed: tasksData.tasks.length,
|
||||||
|
totalTasks: originalTaskCount,
|
||||||
|
analysisCount: finalComplexityAnalysis.length,
|
||||||
thresholdScore: thresholdScore,
|
thresholdScore: thresholdScore,
|
||||||
projectName: getProjectName(session),
|
projectName: getProjectName(session),
|
||||||
usedResearch: useResearch
|
usedResearch: useResearch
|
||||||
},
|
},
|
||||||
complexityAnalysis: complexityAnalysis
|
complexityAnalysis: finalComplexityAnalysis
|
||||||
};
|
};
|
||||||
reportLog(`Writing complexity report to ${outputPath}...`, 'info');
|
reportLog(`Writing complexity report to ${outputPath}...`, 'info');
|
||||||
writeJSON(outputPath, report);
|
writeJSON(outputPath, report);
|
||||||
@@ -350,6 +467,7 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
`Task complexity analysis complete. Report written to ${outputPath}`
|
`Task complexity analysis complete. Report written to ${outputPath}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
// Calculate statistics specifically for this analysis run
|
||||||
const highComplexity = complexityAnalysis.filter(
|
const highComplexity = complexityAnalysis.filter(
|
||||||
(t) => t.complexityScore >= 8
|
(t) => t.complexityScore >= 8
|
||||||
).length;
|
).length;
|
||||||
@@ -361,18 +479,21 @@ async function analyzeTaskComplexity(options, context = {}) {
|
|||||||
).length;
|
).length;
|
||||||
const totalAnalyzed = complexityAnalysis.length;
|
const totalAnalyzed = complexityAnalysis.length;
|
||||||
|
|
||||||
console.log('\nComplexity Analysis Summary:');
|
console.log('\nCurrent Analysis Summary:');
|
||||||
console.log('----------------------------');
|
console.log('----------------------------');
|
||||||
console.log(
|
console.log(`Tasks analyzed in this run: ${totalAnalyzed}`);
|
||||||
`Active tasks sent for analysis: ${tasksData.tasks.length}`
|
|
||||||
);
|
|
||||||
console.log(`Tasks successfully analyzed: ${totalAnalyzed}`);
|
|
||||||
console.log(`High complexity tasks: ${highComplexity}`);
|
console.log(`High complexity tasks: ${highComplexity}`);
|
||||||
console.log(`Medium complexity tasks: ${mediumComplexity}`);
|
console.log(`Medium complexity tasks: ${mediumComplexity}`);
|
||||||
console.log(`Low complexity tasks: ${lowComplexity}`);
|
console.log(`Low complexity tasks: ${lowComplexity}`);
|
||||||
console.log(
|
|
||||||
`Sum verification: ${highComplexity + mediumComplexity + lowComplexity} (should equal ${totalAnalyzed})`
|
if (existingReport) {
|
||||||
);
|
console.log('\nUpdated Report Summary:');
|
||||||
|
console.log('----------------------------');
|
||||||
|
console.log(`Total analyses in report: ${finalComplexityAnalysis.length}`);
|
||||||
|
console.log(`Analyses from previous runs: ${finalComplexityAnalysis.length - totalAnalyzed}`);
|
||||||
|
console.log(`New/updated analyses: ${totalAnalyzed}`);
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`Research-backed analysis: ${useResearch ? 'Yes' : 'No'}`);
|
console.log(`Research-backed analysis: ${useResearch ? 'Yes' : 'No'}`);
|
||||||
console.log(
|
console.log(
|
||||||
`\nSee ${outputPath} for the full report and expansion commands.`
|
`\nSee ${outputPath} for the full report and expansion commands.`
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"meta": {
|
"meta": {
|
||||||
"generatedAt": "2025-05-17T22:29:22.179Z",
|
"generatedAt": "2025-05-22T05:48:33.026Z",
|
||||||
"tasksAnalyzed": 40,
|
"tasksAnalyzed": 6,
|
||||||
|
"totalTasks": 88,
|
||||||
|
"analysisCount": 43,
|
||||||
"thresholdScore": 5,
|
"thresholdScore": 5,
|
||||||
"projectName": "Taskmaster",
|
"projectName": "Taskmaster",
|
||||||
"usedResearch": false
|
"usedResearch": true
|
||||||
},
|
},
|
||||||
"complexityAnalysis": [
|
"complexityAnalysis": [
|
||||||
{
|
{
|
||||||
@@ -215,22 +217,6 @@
|
|||||||
"expansionPrompt": "The current 2 subtasks for implementing task creation without PRD appear appropriate. Consider if any additional subtasks are needed for validation, error handling, or integration with existing task management workflows.",
|
"expansionPrompt": "The current 2 subtasks for implementing task creation without PRD appear appropriate. Consider if any additional subtasks are needed for validation, error handling, or integration with existing task management workflows.",
|
||||||
"reasoning": "This task involves a relatively simple modification to allow task creation without requiring a PRD document. The complexity is low as it primarily involves creating a form interface and saving functionality. The 2 existing subtasks cover the main implementation areas of UI design and data saving."
|
"reasoning": "This task involves a relatively simple modification to allow task creation without requiring a PRD document. The complexity is low as it primarily involves creating a form interface and saving functionality. The 2 existing subtasks cover the main implementation areas of UI design and data saving."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"taskId": 69,
|
|
||||||
"taskTitle": "Enhance Analyze Complexity for Specific Task IDs",
|
|
||||||
"complexityScore": 5,
|
|
||||||
"recommendedSubtasks": 4,
|
|
||||||
"expansionPrompt": "The current 4 subtasks for enhancing the analyze-complexity feature appear well-structured. Consider if any additional subtasks are needed for performance optimization with large task sets or visualization improvements.",
|
|
||||||
"reasoning": "This task involves modifying the existing analyze-complexity feature to support analyzing specific task IDs and updating reports. The complexity is moderate as it requires careful handling of report merging and filtering logic. The 4 existing subtasks cover the main implementation areas from core logic to testing."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"taskId": 70,
|
|
||||||
"taskTitle": "Implement 'diagram' command for Mermaid diagram generation",
|
|
||||||
"complexityScore": 6,
|
|
||||||
"recommendedSubtasks": 4,
|
|
||||||
"expansionPrompt": "The current 4 subtasks for implementing the 'diagram' command appear well-structured. Consider if any additional subtasks are needed for handling large dependency graphs, additional output formats, or integration with existing visualization tools.",
|
|
||||||
"reasoning": "This task involves creating a new command that generates Mermaid diagrams to visualize task dependencies. The complexity is moderate as it requires parsing task relationships, generating proper Mermaid syntax, and handling various output options. The 4 existing subtasks cover the main implementation areas from interface design to documentation."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"taskId": 72,
|
"taskId": 72,
|
||||||
"taskTitle": "Implement PDF Generation for Project Progress and Dependency Overview",
|
"taskTitle": "Implement PDF Generation for Project Progress and Dependency Overview",
|
||||||
@@ -303,29 +289,69 @@
|
|||||||
"expansionPrompt": "This task appears well-defined enough to be implemented without further subtasks. Focus on implementing accurate token counting for different models and proper fallback mechanisms.",
|
"expansionPrompt": "This task appears well-defined enough to be implemented without further subtasks. Focus on implementing accurate token counting for different models and proper fallback mechanisms.",
|
||||||
"reasoning": "This task involves creating a utility function to count tokens for different AI models. The complexity is moderate as it requires integration with the tiktoken library and handling different tokenization schemes. No subtasks are necessary as the task is well-defined and focused."
|
"reasoning": "This task involves creating a utility function to count tokens for different AI models. The complexity is moderate as it requires integration with the tiktoken library and handling different tokenization schemes. No subtasks are necessary as the task is well-defined and focused."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"taskId": 69,
|
||||||
|
"taskTitle": "Enhance Analyze Complexity for Specific Task IDs",
|
||||||
|
"complexityScore": 7,
|
||||||
|
"recommendedSubtasks": 6,
|
||||||
|
"expansionPrompt": "Break down the task 'Enhance Analyze Complexity for Specific Task IDs' into 6 subtasks focusing on: 1) Core logic modification to accept ID parameters, 2) Report merging functionality, 3) CLI interface updates, 4) MCP tool integration, 5) Documentation updates, and 6) Comprehensive testing across all components.",
|
||||||
|
"reasoning": "This task involves modifying existing functionality across multiple components (core logic, CLI, MCP) with complex logic for filtering tasks and merging reports. The implementation requires careful handling of different parameter combinations and edge cases. The task has interdependent components that need to work together seamlessly, and the report merging functionality adds significant complexity."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"taskId": 70,
|
||||||
|
"taskTitle": "Implement 'diagram' command for Mermaid diagram generation",
|
||||||
|
"complexityScore": 6,
|
||||||
|
"recommendedSubtasks": 5,
|
||||||
|
"expansionPrompt": "Break down the 'diagram' command implementation into 5 subtasks: 1) Command interface and parameter handling, 2) Task data extraction and transformation to Mermaid syntax, 3) Diagram rendering with status color coding, 4) Output formatting and file export functionality, and 5) Error handling and edge case management.",
|
||||||
|
"reasoning": "This task requires implementing a new feature rather than modifying existing code, which reduces complexity from integration challenges. However, it involves working with visualization logic, dependency mapping, and multiple output formats. The color coding based on status and handling of dependency relationships adds moderate complexity. The task is well-defined but requires careful attention to diagram formatting and error handling."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"taskId": 85,
|
"taskId": 85,
|
||||||
"taskTitle": "Update ai-services-unified.js for dynamic token limits",
|
"taskTitle": "Update ai-services-unified.js for dynamic token limits",
|
||||||
"complexityScore": 6,
|
"complexityScore": 7,
|
||||||
"recommendedSubtasks": 1,
|
"recommendedSubtasks": 5,
|
||||||
"expansionPrompt": "This task appears well-defined enough to be implemented without further subtasks. Focus on implementing dynamic token limit adjustment based on input length and model capabilities.",
|
"expansionPrompt": "Break down the update of ai-services-unified.js for dynamic token limits into subtasks such as: (1) Import and integrate the token counting utility, (2) Refactor _unifiedServiceRunner to calculate and enforce dynamic token limits, (3) Update error handling for token limit violations, (4) Add and verify logging for token usage, (5) Write and execute tests for various prompt and model scenarios.",
|
||||||
"reasoning": "This task involves modifying the AI service runner to use the new token counting utility and dynamically adjust output token limits. The complexity is moderate to high as it requires careful integration with existing code and handling various edge cases. No subtasks are necessary as the task is well-defined and focused."
|
"reasoning": "This task involves significant code changes to a core function, integration of a new utility, dynamic logic for multiple models, and robust error handling. It also requires comprehensive testing for edge cases and integration, making it moderately complex and best managed by splitting into focused subtasks."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskId": 86,
|
"taskId": 86,
|
||||||
"taskTitle": "Update .taskmasterconfig schema and user guide",
|
"taskTitle": "Update .taskmasterconfig schema and user guide",
|
||||||
"complexityScore": 4,
|
"complexityScore": 6,
|
||||||
"recommendedSubtasks": 1,
|
"recommendedSubtasks": 4,
|
||||||
"expansionPrompt": "This task appears straightforward enough to be implemented without further subtasks. Focus on creating clear migration guidance and updating documentation.",
|
"expansionPrompt": "Expand this task into subtasks: (1) Draft a migration guide for users, (2) Update user documentation to explain new config fields, (3) Modify schema validation logic in config-manager.js, (4) Test and validate backward compatibility and error messaging.",
|
||||||
"reasoning": "This task involves creating a migration guide for users to update their configuration files and documenting the new token limit options. The complexity is relatively low as it primarily involves documentation and schema validation. No subtasks are necessary as the task is well-defined and focused."
|
"reasoning": "The task spans documentation, schema changes, migration guidance, and validation logic. While not algorithmically complex, it requires careful coordination and thorough testing to ensure a smooth user transition and robust validation."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskId": 87,
|
"taskId": 87,
|
||||||
"taskTitle": "Implement validation and error handling",
|
"taskTitle": "Implement validation and error handling",
|
||||||
"complexityScore": 5,
|
"complexityScore": 5,
|
||||||
"recommendedSubtasks": 1,
|
"recommendedSubtasks": 4,
|
||||||
"expansionPrompt": "This task appears well-defined enough to be implemented without further subtasks. Focus on comprehensive validation and helpful error messages throughout the system.",
|
"expansionPrompt": "Decompose this task into: (1) Add validation logic for model and config loading, (2) Implement error handling and fallback mechanisms, (3) Enhance logging and reporting for token usage, (4) Develop helper functions for configuration suggestions and improvements.",
|
||||||
"reasoning": "This task involves adding validation and error handling for token limits throughout the system. The complexity is moderate as it requires careful integration with multiple components and creating helpful error messages. No subtasks are necessary as the task is well-defined and focused."
|
"reasoning": "This task is primarily about adding validation, error handling, and logging. While important for robustness, the logic is straightforward and can be modularized into a few clear subtasks."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"taskId": 89,
|
||||||
|
"taskTitle": "Introduce Prioritize Command with Enhanced Priority Levels",
|
||||||
|
"complexityScore": 6,
|
||||||
|
"recommendedSubtasks": 5,
|
||||||
|
"expansionPrompt": "Expand this task into: (1) Implement the prioritize command with all required flags and shorthands, (2) Update CLI output and help documentation for new priority levels, (3) Ensure backward compatibility with existing commands, (4) Add error handling for invalid inputs, (5) Write and run tests for all command scenarios.",
|
||||||
|
"reasoning": "This CLI feature requires command parsing, updating internal logic for new priority levels, documentation, and robust error handling. The complexity is moderate due to the need for backward compatibility and comprehensive testing."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"taskId": 90,
|
||||||
|
"taskTitle": "Implement Subtask Progress Analyzer and Reporting System",
|
||||||
|
"complexityScore": 8,
|
||||||
|
"recommendedSubtasks": 6,
|
||||||
|
"expansionPrompt": "Break down the analyzer implementation into: (1) Design and implement progress tracking logic, (2) Develop status validation and issue detection, (3) Build the reporting system with multiple output formats, (4) Integrate analyzer with the existing task management system, (5) Optimize for performance and scalability, (6) Write unit, integration, and performance tests.",
|
||||||
|
"reasoning": "This is a complex, multi-faceted feature involving data analysis, reporting, integration, and performance optimization. It touches many parts of the system and requires careful design, making it one of the most complex tasks in the list."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"taskId": 91,
|
||||||
|
"taskTitle": "Implement Move Command for Tasks and Subtasks",
|
||||||
|
"complexityScore": 7,
|
||||||
|
"recommendedSubtasks": 5,
|
||||||
|
"expansionPrompt": "Expand this task into: (1) Implement move logic for tasks and subtasks, (2) Handle edge cases (invalid ids, non-existent parents, circular dependencies), (3) Update CLI to support move command with flags, (4) Ensure data integrity and update relationships, (5) Write and execute tests for various move scenarios.",
|
||||||
|
"reasoning": "Moving tasks and subtasks requires careful handling of hierarchical data, edge cases, and data integrity. The command must be robust and user-friendly, necessitating multiple focused subtasks for safe implementation."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,79 +3,91 @@
|
|||||||
# Status: pending
|
# Status: pending
|
||||||
# Dependencies: None
|
# Dependencies: None
|
||||||
# Priority: medium
|
# Priority: medium
|
||||||
# Description: Modify the analyze-complexity feature (CLI and MCP) to allow analyzing only specified task IDs and append/update results in the report.
|
# Description: Modify the analyze-complexity feature (CLI and MCP) to allow analyzing only specified task IDs or ranges, and append/update results in the report.
|
||||||
# Details:
|
# Details:
|
||||||
|
|
||||||
Implementation Plan:
|
Implementation Plan:
|
||||||
|
|
||||||
1. **Core Logic (`scripts/modules/task-manager/analyze-task-complexity.js`):**
|
1. **Core Logic (`scripts/modules/task-manager/analyze-task-complexity.js`)**
|
||||||
* Modify the function signature to accept an optional `options.ids` parameter (string, comma-separated IDs).
|
* Modify function signature to accept optional parameters: `options.ids` (string, comma-separated IDs) and range parameters `options.from` and `options.to`.
|
||||||
* If `options.ids` is present:
|
* If `options.ids` is present:
|
||||||
* Parse the `ids` string into an array of target IDs.
|
* Parse the `ids` string into an array of target IDs.
|
||||||
* Filter `tasksData.tasks` to *only* include tasks matching the target IDs. Use this filtered list for analysis.
|
* Filter `tasksData.tasks` to include only tasks matching the target IDs.
|
||||||
* Handle cases where provided IDs don't exist in `tasks.json`.
|
* Handle cases where provided IDs don't exist in `tasks.json`.
|
||||||
* If `options.ids` is *not* present: Continue with existing logic (filtering by active status).
|
* If range parameters (`options.from` and `options.to`) are present:
|
||||||
|
* Parse these values into integers.
|
||||||
|
* Filter tasks within the specified ID range (inclusive).
|
||||||
|
* If neither `options.ids` nor range parameters are present: Continue with existing logic (filtering by active status).
|
||||||
|
* Maintain existing logic for skipping completed tasks.
|
||||||
* **Report Handling:**
|
* **Report Handling:**
|
||||||
* Before generating the analysis, check if the `outputPath` report file exists.
|
* Before generating analysis, check if the `outputPath` report file exists.
|
||||||
* If it exists, read the existing `complexityAnalysis` array.
|
* If it exists:
|
||||||
* Generate the new analysis *only* for the target tasks (filtered by ID or status).
|
* Read the existing `complexityAnalysis` array.
|
||||||
* Merge the results: Remove any entries from the *existing* array that match the IDs analyzed in the *current run*. Then, append the *new* analysis results to the array.
|
* Generate new analysis only for target tasks (filtered by ID or range).
|
||||||
* Update the `meta` section (`generatedAt`, `tasksAnalyzed` should reflect *this run*).
|
* Merge results: Remove entries from the existing array that match IDs analyzed in the current run, then append new analysis results to the array.
|
||||||
* Write the *merged* `complexityAnalysis` array and updated `meta` back to the report file.
|
* Update the `meta` section (`generatedAt`, `tasksAnalyzed`).
|
||||||
* If the report file doesn't exist, create it as usual.
|
* Write merged `complexityAnalysis` and updated `meta` back to report file.
|
||||||
* **Prompt Generation:** Ensure `generateInternalComplexityAnalysisPrompt` receives the correctly filtered list of tasks.
|
* If the report file doesn't exist: Create it as usual.
|
||||||
|
* **Prompt Generation:** Ensure `generateInternalComplexityAnalysisPrompt` receives correctly filtered list of tasks.
|
||||||
|
|
||||||
2. **CLI (`scripts/modules/commands.js`):**
|
2. **CLI (`scripts/modules/commands.js`)**
|
||||||
* Add a new option `--id <ids>` to the `analyze-complexity` command definition. Description: "Comma-separated list of specific task IDs to analyze".
|
* Add new options to the `analyze-complexity` command:
|
||||||
|
* `--id/-i <ids>`: "Comma-separated list of specific task IDs to analyze"
|
||||||
|
* `--from/-f <startId>`: "Start ID for range analysis (inclusive)"
|
||||||
|
* `--to/-t <endId>`: "End ID for range analysis (inclusive)"
|
||||||
* In the `.action` handler:
|
* In the `.action` handler:
|
||||||
* Check if `options.id` is provided.
|
* Check if `options.id`, `options.from`, or `options.to` are provided.
|
||||||
* If yes, pass `options.id` (as the comma-separated string) to the `analyzeTaskComplexity` core function via the `options` object.
|
* If yes, pass appropriate values to the `analyzeTaskComplexity` core function via the `options` object.
|
||||||
* Update user feedback messages to indicate specific task analysis.
|
* Update user feedback messages to indicate specific task analysis.
|
||||||
|
|
||||||
3. **MCP Tool (`mcp-server/src/tools/analyze.js`):**
|
3. **MCP Tool (`mcp-server/src/tools/analyze.js`)**
|
||||||
* Add a new optional parameter `ids: z.string().optional().describe("Comma-separated list of task IDs to analyze specifically")` to the Zod schema for the `analyze_project_complexity` tool.
|
* Add new optional parameters to Zod schema for `analyze_project_complexity` tool:
|
||||||
* In the `execute` method, pass `args.ids` to the `analyzeTaskComplexityDirect` function within its `args` object.
|
* `ids: z.string().optional().describe("Comma-separated list of task IDs to analyze specifically")`
|
||||||
|
* `from: z.number().optional().describe("Start ID for range analysis (inclusive)")`
|
||||||
|
* `to: z.number().optional().describe("End ID for range analysis (inclusive)")`
|
||||||
|
* In the `execute` method, pass `args.ids`, `args.from`, and `args.to` to the `analyzeTaskComplexityDirect` function within its `args` object.
|
||||||
|
|
||||||
4. **Direct Function (`mcp-server/src/core/direct-functions/analyze-task-complexity.js`):**
|
4. **Direct Function (`mcp-server/src/core/direct-functions/analyze-task-complexity.js`)**
|
||||||
* Update the function to receive the `ids` string within the `args` object.
|
* Update function to receive `ids`, `from`, and `to` values within the `args` object.
|
||||||
* Pass the `ids` string along to the core `analyzeTaskComplexity` function within its `options` object.
|
* Pass these values along to the core `analyzeTaskComplexity` function within its `options` object.
|
||||||
|
|
||||||
5. **Documentation:** Update relevant rule files (`commands.mdc`, `taskmaster.mdc`) to reflect the new `--id` option/parameter.
|
|
||||||
|
|
||||||
|
5. **Documentation:** Update relevant rule files (`commands.mdc`, `taskmaster.mdc`) to reflect new `--id/-i`, `--from/-f`, and `--to/-t` options/parameters.
|
||||||
|
|
||||||
# Test Strategy:
|
# Test Strategy:
|
||||||
|
|
||||||
1. **CLI:**
|
1. **CLI:**
|
||||||
* Run `task-master analyze-complexity --id=<id1>` (where report doesn't exist). Verify report created with only task id1.
|
* Run `task-master analyze-complexity -i=<id1>` (where report doesn't exist). Verify report created with only task id1.
|
||||||
* Run `task-master analyze-complexity --id=<id2>` (where report exists). Verify report updated, containing analysis for both id1 and id2 (id2 replaces any previous id2 analysis).
|
* Run `task-master analyze-complexity -i=<id2>` (where report exists). Verify report updated, containing analysis for both id1 and id2 (id2 replaces any previous id2 analysis).
|
||||||
* Run `task-master analyze-complexity --id=<id1>,<id3>`. Verify report updated, containing id1, id2, id3.
|
* Run `task-master analyze-complexity -i=<id1>,<id3>`. Verify report updated, containing id1, id2, id3.
|
||||||
* Run `task-master analyze-complexity` (no id). Verify it analyzes *all* active tasks and updates the report accordingly, merging with previous specific analyses.
|
* Run `task-master analyze-complexity -f=50 -t=60`. Verify report created/updated with tasks in the range 50-60.
|
||||||
* Test with invalid/non-existent IDs.
|
* Run `task-master analyze-complexity` (no flags). Verify it analyzes all active tasks and updates the report accordingly, merging with previous specific analyses.
|
||||||
|
* Test with invalid/non-existent IDs or ranges.
|
||||||
|
* Verify that completed tasks are still skipped in all scenarios, maintaining existing behavior.
|
||||||
2. **MCP:**
|
2. **MCP:**
|
||||||
* Call `analyze_project_complexity` tool with `ids: "<id1>"`. Verify report creation/update.
|
* Call `analyze_project_complexity` tool with `ids: "<id1>"`. Verify report creation/update.
|
||||||
* Call `analyze_project_complexity` tool with `ids: "<id1>,<id2>"`. Verify report merging.
|
* Call `analyze_project_complexity` tool with `ids: "<id1>,<id2>,<id3>"`. Verify report created/updated with multiple specific tasks.
|
||||||
* Call `analyze_project_complexity` tool without `ids`. Verify full analysis and merging.
|
* Call `analyze_project_complexity` tool with `from: 50, to: 60`. Verify report created/updated for tasks in range.
|
||||||
|
* Call `analyze_project_complexity` tool without parameters. Verify full analysis and merging.
|
||||||
3. Verify report `meta` section is updated correctly on each run.
|
3. Verify report `meta` section is updated correctly on each run.
|
||||||
|
|
||||||
|
|
||||||
# Subtasks:
|
# Subtasks:
|
||||||
## 1. Modify core complexity analysis logic [pending]
|
## 1. Modify core complexity analysis logic [pending]
|
||||||
### Dependencies: None
|
### Dependencies: None
|
||||||
### Description: Update the core complexity analysis function to accept specific task IDs as input parameters
|
### Description: Update the core complexity analysis function to accept specific task IDs or ranges as input parameters
|
||||||
### Details:
|
### Details:
|
||||||
Refactor the existing complexity analysis module to allow filtering by task IDs. This involves modifying the data processing pipeline to filter tasks before analysis, ensuring the complexity metrics are calculated only for the specified tasks while maintaining context awareness.
|
Refactor the existing complexity analysis module to allow filtering by task IDs or ranges. This involves modifying the data processing pipeline to filter tasks before analysis, ensuring the complexity metrics are calculated only for the specified tasks while maintaining context awareness.
|
||||||
|
|
||||||
## 2. Update CLI interface for task-specific complexity analysis [pending]
|
## 2. Update CLI interface for task-specific complexity analysis [pending]
|
||||||
### Dependencies: 69.1
|
### Dependencies: 69.1
|
||||||
### Description: Extend the CLI to accept task IDs as parameters for the complexity analysis command
|
### Description: Extend the CLI to accept task IDs or ranges as parameters for the complexity analysis command
|
||||||
### Details:
|
### Details:
|
||||||
Add a new flag or parameter to the CLI that allows users to specify task IDs for targeted complexity analysis. Update the command parser, help documentation, and ensure proper validation of the provided task IDs.
|
Add new flags `--id/-i`, `--from/-f`, and `--to/-t` to the CLI that allow users to specify task IDs or ranges for targeted complexity analysis. Update the command parser, help documentation, and ensure proper validation of the provided values.
|
||||||
|
|
||||||
## 3. Integrate task-specific analysis with MCP tool [pending]
|
## 3. Integrate task-specific analysis with MCP tool [pending]
|
||||||
### Dependencies: 69.1
|
### Dependencies: 69.1
|
||||||
### Description: Update the MCP tool interface to support analyzing complexity for specific tasks
|
### Description: Update the MCP tool interface to support analyzing complexity for specific tasks or ranges
|
||||||
### Details:
|
### Details:
|
||||||
Modify the MCP tool's API endpoints and UI components to allow users to select specific tasks for complexity analysis. Ensure the UI provides clear feedback about which tasks are being analyzed and update the visualization components to properly display partial analysis results.
|
Modify the MCP tool's API endpoints and UI components to allow users to select specific tasks or ranges for complexity analysis. Ensure the UI provides clear feedback about which tasks are being analyzed and update the visualization components to properly display partial analysis results.
|
||||||
|
|
||||||
## 4. Create comprehensive tests for task-specific complexity analysis [pending]
|
## 4. Create comprehensive tests for task-specific complexity analysis [pending]
|
||||||
### Dependencies: 69.1, 69.2, 69.3
|
### Dependencies: 69.1, 69.2, 69.3
|
||||||
|
|||||||
@@ -4544,39 +4544,39 @@
|
|||||||
{
|
{
|
||||||
"id": 69,
|
"id": 69,
|
||||||
"title": "Enhance Analyze Complexity for Specific Task IDs",
|
"title": "Enhance Analyze Complexity for Specific Task IDs",
|
||||||
"description": "Modify the analyze-complexity feature (CLI and MCP) to allow analyzing only specified task IDs and append/update results in the report.",
|
"description": "Modify the analyze-complexity feature (CLI and MCP) to allow analyzing only specified task IDs or ranges, and append/update results in the report.",
|
||||||
"details": "\nImplementation Plan:\n\n1. **Core Logic (`scripts/modules/task-manager/analyze-task-complexity.js`):**\n * Modify the function signature to accept an optional `options.ids` parameter (string, comma-separated IDs).\n * If `options.ids` is present:\n * Parse the `ids` string into an array of target IDs.\n * Filter `tasksData.tasks` to *only* include tasks matching the target IDs. Use this filtered list for analysis.\n * Handle cases where provided IDs don't exist in `tasks.json`.\n * If `options.ids` is *not* present: Continue with existing logic (filtering by active status).\n * **Report Handling:**\n * Before generating the analysis, check if the `outputPath` report file exists.\n * If it exists, read the existing `complexityAnalysis` array.\n * Generate the new analysis *only* for the target tasks (filtered by ID or status).\n * Merge the results: Remove any entries from the *existing* array that match the IDs analyzed in the *current run*. Then, append the *new* analysis results to the array.\n * Update the `meta` section (`generatedAt`, `tasksAnalyzed` should reflect *this run*).\n * Write the *merged* `complexityAnalysis` array and updated `meta` back to the report file.\n * If the report file doesn't exist, create it as usual.\n * **Prompt Generation:** Ensure `generateInternalComplexityAnalysisPrompt` receives the correctly filtered list of tasks.\n\n2. **CLI (`scripts/modules/commands.js`):**\n * Add a new option `--id <ids>` to the `analyze-complexity` command definition. Description: \"Comma-separated list of specific task IDs to analyze\".\n * In the `.action` handler:\n * Check if `options.id` is provided.\n * If yes, pass `options.id` (as the comma-separated string) to the `analyzeTaskComplexity` core function via the `options` object.\n * Update user feedback messages to indicate specific task analysis.\n\n3. **MCP Tool (`mcp-server/src/tools/analyze.js`):**\n * Add a new optional parameter `ids: z.string().optional().describe(\"Comma-separated list of task IDs to analyze specifically\")` to the Zod schema for the `analyze_project_complexity` tool.\n * In the `execute` method, pass `args.ids` to the `analyzeTaskComplexityDirect` function within its `args` object.\n\n4. **Direct Function (`mcp-server/src/core/direct-functions/analyze-task-complexity.js`):**\n * Update the function to receive the `ids` string within the `args` object.\n * Pass the `ids` string along to the core `analyzeTaskComplexity` function within its `options` object.\n\n5. **Documentation:** Update relevant rule files (`commands.mdc`, `taskmaster.mdc`) to reflect the new `--id` option/parameter.\n",
|
|
||||||
"testStrategy": "\n1. **CLI:**\n * Run `task-master analyze-complexity --id=<id1>` (where report doesn't exist). Verify report created with only task id1.\n * Run `task-master analyze-complexity --id=<id2>` (where report exists). Verify report updated, containing analysis for both id1 and id2 (id2 replaces any previous id2 analysis).\n * Run `task-master analyze-complexity --id=<id1>,<id3>`. Verify report updated, containing id1, id2, id3.\n * Run `task-master analyze-complexity` (no id). Verify it analyzes *all* active tasks and updates the report accordingly, merging with previous specific analyses.\n * Test with invalid/non-existent IDs.\n2. **MCP:**\n * Call `analyze_project_complexity` tool with `ids: \"<id1>\"`. Verify report creation/update.\n * Call `analyze_project_complexity` tool with `ids: \"<id1>,<id2>\"`. Verify report merging.\n * Call `analyze_project_complexity` tool without `ids`. Verify full analysis and merging.\n3. Verify report `meta` section is updated correctly on each run.\n",
|
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"priority": "medium",
|
"priority": "medium",
|
||||||
|
"details": "\nImplementation Plan:\n\n1. **Core Logic (`scripts/modules/task-manager/analyze-task-complexity.js`)**\n * Modify function signature to accept optional parameters: `options.ids` (string, comma-separated IDs) and range parameters `options.from` and `options.to`.\n * If `options.ids` is present:\n * Parse the `ids` string into an array of target IDs.\n * Filter `tasksData.tasks` to include only tasks matching the target IDs.\n * Handle cases where provided IDs don't exist in `tasks.json`.\n * If range parameters (`options.from` and `options.to`) are present:\n * Parse these values into integers.\n * Filter tasks within the specified ID range (inclusive).\n * If neither `options.ids` nor range parameters are present: Continue with existing logic (filtering by active status).\n * Maintain existing logic for skipping completed tasks.\n * **Report Handling:**\n * Before generating analysis, check if the `outputPath` report file exists.\n * If it exists:\n * Read the existing `complexityAnalysis` array.\n * Generate new analysis only for target tasks (filtered by ID or range).\n * Merge results: Remove entries from the existing array that match IDs analyzed in the current run, then append new analysis results to the array.\n * Update the `meta` section (`generatedAt`, `tasksAnalyzed`).\n * Write merged `complexityAnalysis` and updated `meta` back to report file.\n * If the report file doesn't exist: Create it as usual.\n * **Prompt Generation:** Ensure `generateInternalComplexityAnalysisPrompt` receives correctly filtered list of tasks.\n\n2. **CLI (`scripts/modules/commands.js`)**\n * Add new options to the `analyze-complexity` command:\n * `--id/-i <ids>`: \"Comma-separated list of specific task IDs to analyze\"\n * `--from/-f <startId>`: \"Start ID for range analysis (inclusive)\"\n * `--to/-t <endId>`: \"End ID for range analysis (inclusive)\"\n * In the `.action` handler:\n * Check if `options.id`, `options.from`, or `options.to` are provided.\n * If yes, pass appropriate values to the `analyzeTaskComplexity` core function via the `options` object.\n * Update user feedback messages to indicate specific task analysis.\n\n3. **MCP Tool (`mcp-server/src/tools/analyze.js`)**\n * Add new optional parameters to Zod schema for `analyze_project_complexity` tool:\n * `ids: z.string().optional().describe(\"Comma-separated list of task IDs to analyze specifically\")`\n * `from: z.number().optional().describe(\"Start ID for range analysis (inclusive)\")`\n * `to: z.number().optional().describe(\"End ID for range analysis (inclusive)\")`\n * In the `execute` method, pass `args.ids`, `args.from`, and `args.to` to the `analyzeTaskComplexityDirect` function within its `args` object.\n\n4. **Direct Function (`mcp-server/src/core/direct-functions/analyze-task-complexity.js`)**\n * Update function to receive `ids`, `from`, and `to` values within the `args` object.\n * Pass these values along to the core `analyzeTaskComplexity` function within its `options` object.\n\n5. **Documentation:** Update relevant rule files (`commands.mdc`, `taskmaster.mdc`) to reflect new `--id/-i`, `--from/-f`, and `--to/-t` options/parameters.",
|
||||||
|
"testStrategy": "\n1. **CLI:**\n * Run `task-master analyze-complexity -i=<id1>` (where report doesn't exist). Verify report created with only task id1.\n * Run `task-master analyze-complexity -i=<id2>` (where report exists). Verify report updated, containing analysis for both id1 and id2 (id2 replaces any previous id2 analysis).\n * Run `task-master analyze-complexity -i=<id1>,<id3>`. Verify report updated, containing id1, id2, id3.\n * Run `task-master analyze-complexity -f=50 -t=60`. Verify report created/updated with tasks in the range 50-60.\n * Run `task-master analyze-complexity` (no flags). Verify it analyzes all active tasks and updates the report accordingly, merging with previous specific analyses.\n * Test with invalid/non-existent IDs or ranges.\n * Verify that completed tasks are still skipped in all scenarios, maintaining existing behavior.\n2. **MCP:**\n * Call `analyze_project_complexity` tool with `ids: \"<id1>\"`. Verify report creation/update.\n * Call `analyze_project_complexity` tool with `ids: \"<id1>,<id2>,<id3>\"`. Verify report created/updated with multiple specific tasks.\n * Call `analyze_project_complexity` tool with `from: 50, to: 60`. Verify report created/updated for tasks in range.\n * Call `analyze_project_complexity` tool without parameters. Verify full analysis and merging.\n3. Verify report `meta` section is updated correctly on each run.",
|
||||||
"subtasks": [
|
"subtasks": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"title": "Modify core complexity analysis logic",
|
"title": "Modify core complexity analysis logic",
|
||||||
"description": "Update the core complexity analysis function to accept specific task IDs as input parameters",
|
"description": "Update the core complexity analysis function to accept specific task IDs or ranges as input parameters",
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"details": "Refactor the existing complexity analysis module to allow filtering by task IDs. This involves modifying the data processing pipeline to filter tasks before analysis, ensuring the complexity metrics are calculated only for the specified tasks while maintaining context awareness.",
|
"details": "Refactor the existing complexity analysis module to allow filtering by task IDs or ranges. This involves modifying the data processing pipeline to filter tasks before analysis, ensuring the complexity metrics are calculated only for the specified tasks while maintaining context awareness.",
|
||||||
"status": "pending"
|
"status": "pending"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"title": "Update CLI interface for task-specific complexity analysis",
|
"title": "Update CLI interface for task-specific complexity analysis",
|
||||||
"description": "Extend the CLI to accept task IDs as parameters for the complexity analysis command",
|
"description": "Extend the CLI to accept task IDs or ranges as parameters for the complexity analysis command",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
"details": "Add a new flag or parameter to the CLI that allows users to specify task IDs for targeted complexity analysis. Update the command parser, help documentation, and ensure proper validation of the provided task IDs.",
|
"details": "Add new flags `--id/-i`, `--from/-f`, and `--to/-t` to the CLI that allow users to specify task IDs or ranges for targeted complexity analysis. Update the command parser, help documentation, and ensure proper validation of the provided values.",
|
||||||
"status": "pending"
|
"status": "pending"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"title": "Integrate task-specific analysis with MCP tool",
|
"title": "Integrate task-specific analysis with MCP tool",
|
||||||
"description": "Update the MCP tool interface to support analyzing complexity for specific tasks",
|
"description": "Update the MCP tool interface to support analyzing complexity for specific tasks or ranges",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
1
|
1
|
||||||
],
|
],
|
||||||
"details": "Modify the MCP tool's API endpoints and UI components to allow users to select specific tasks for complexity analysis. Ensure the UI provides clear feedback about which tasks are being analyzed and update the visualization components to properly display partial analysis results.",
|
"details": "Modify the MCP tool's API endpoints and UI components to allow users to select specific tasks or ranges for complexity analysis. Ensure the UI provides clear feedback about which tasks are being analyzed and update the visualization components to properly display partial analysis results.",
|
||||||
"status": "pending"
|
"status": "pending"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user