fix: expand_all now uses complexity analysis recommendations (#1287)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
16
.changeset/smart-owls-relax.md
Normal file
16
.changeset/smart-owls-relax.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Enhance `expand_all` to intelligently use complexity analysis recommendations when expanding tasks.
|
||||
|
||||
The expand-all operation now automatically leverages recommendations from `analyze-complexity` to determine optimal subtask counts for each task, resulting in more accurate and context-aware task breakdowns.
|
||||
|
||||
Key improvements:
|
||||
- Automatic integration with complexity analysis reports
|
||||
- Tag-aware complexity report path resolution
|
||||
- Intelligent subtask count determination based on task complexity
|
||||
- Falls back to defaults when complexity analysis is unavailable
|
||||
- Enhanced logging for better visibility into expansion decisions
|
||||
|
||||
When you run `task-master expand --all` after `task-master analyze-complexity`, Task Master now uses the recommended subtask counts from the complexity analysis instead of applying uniform defaults, ensuring each task is broken down according to its actual complexity.
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
import { resolveComplexityReportOutputPath } from '../../../../src/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Expand all pending tasks with subtasks (Direct Function Wrapper)
|
||||
@@ -25,13 +26,30 @@ import { createLogWrapper } from '../../tools/utils.js';
|
||||
*/
|
||||
export async function expandAllTasksDirect(args, log, context = {}) {
|
||||
const { session } = context; // Extract session
|
||||
// Destructure expected args, including projectRoot
|
||||
const { tasksJsonPath, num, research, prompt, force, projectRoot, tag } =
|
||||
args;
|
||||
// Destructure expected args, including projectRoot and complexityReportPath
|
||||
const {
|
||||
tasksJsonPath,
|
||||
num,
|
||||
research,
|
||||
prompt,
|
||||
force,
|
||||
projectRoot,
|
||||
tag,
|
||||
complexityReportPath: providedComplexityReportPath
|
||||
} = args;
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
// Use provided complexity report path or compute it
|
||||
const complexityReportPath =
|
||||
providedComplexityReportPath ||
|
||||
resolveComplexityReportOutputPath(null, { projectRoot, tag }, log);
|
||||
|
||||
log.info(
|
||||
`Expand all tasks will use complexity report at: ${complexityReportPath}`
|
||||
);
|
||||
|
||||
if (!tasksJsonPath) {
|
||||
log.error('expandAllTasksDirect called without tasksJsonPath');
|
||||
return {
|
||||
@@ -55,14 +73,14 @@ export async function expandAllTasksDirect(args, log, context = {}) {
|
||||
const additionalContext = prompt || '';
|
||||
const forceFlag = force === true;
|
||||
|
||||
// Call the core function, passing options and the context object { session, mcpLog, projectRoot }
|
||||
// Call the core function, passing options and the context object { session, mcpLog, projectRoot, tag, complexityReportPath }
|
||||
const result = await expandAllTasks(
|
||||
tasksJsonPath,
|
||||
numSubtasks,
|
||||
useResearch,
|
||||
additionalContext,
|
||||
forceFlag,
|
||||
{ session, mcpLog, projectRoot, tag },
|
||||
{ session, mcpLog, projectRoot, tag, complexityReportPath },
|
||||
'json'
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
findTasksPath as coreFindTasksPath,
|
||||
findPRDPath as coreFindPrdPath,
|
||||
findComplexityReportPath as coreFindComplexityReportPath,
|
||||
resolveComplexityReportOutputPath as coreResolveComplexityReportOutputPath,
|
||||
findProjectRoot as coreFindProjectRoot,
|
||||
normalizeProjectRoot
|
||||
} from '../../../../src/utils/path-utils.js';
|
||||
@@ -224,6 +225,21 @@ export function findComplexityReportPath(args, log = silentLogger) {
|
||||
return resolveComplexityReportPath(args, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve complexity report output path (create if needed) - primary MCP function
|
||||
* @param {string|null} [explicitPath] - Explicit path to complexity report
|
||||
* @param {Object} args - Arguments object containing projectRoot and tag
|
||||
* @param {Object} [log] - Log function to prevent console logging
|
||||
* @returns {string} - Resolved output path for complexity report
|
||||
*/
|
||||
export function resolveComplexityReportOutputPath(
|
||||
explicitPath,
|
||||
args,
|
||||
log = silentLogger
|
||||
) {
|
||||
return coreResolveComplexityReportOutputPath(explicitPath, args, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find PRD path - primary MCP function
|
||||
* @param {string} [explicitPath] - Explicit path to PRD file
|
||||
|
||||
@@ -10,7 +10,10 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { expandAllTasksDirect } from '../core/task-master-core.js';
|
||||
import { findTasksPath } from '../core/utils/path-utils.js';
|
||||
import {
|
||||
findTasksPath,
|
||||
resolveComplexityReportOutputPath
|
||||
} from '../core/utils/path-utils.js';
|
||||
import { resolveTag } from '../../../scripts/modules/utils.js';
|
||||
|
||||
/**
|
||||
@@ -85,6 +88,14 @@ export function registerExpandAllTool(server) {
|
||||
);
|
||||
}
|
||||
|
||||
// Resolve complexity report path to use recommendations from analyze-complexity
|
||||
const complexityReportPath = resolveComplexityReportOutputPath(
|
||||
null,
|
||||
{ projectRoot: args.projectRoot, tag: resolvedTag },
|
||||
log
|
||||
);
|
||||
log.info(`Using complexity report path: ${complexityReportPath}`);
|
||||
|
||||
const result = await expandAllTasksDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
@@ -93,7 +104,8 @@ export function registerExpandAllTool(server) {
|
||||
prompt: args.prompt,
|
||||
force: args.force,
|
||||
projectRoot: args.projectRoot,
|
||||
tag: resolvedTag
|
||||
tag: resolvedTag,
|
||||
complexityReportPath
|
||||
},
|
||||
log,
|
||||
{ session }
|
||||
|
||||
@@ -244,6 +244,53 @@ describe('expandAllTasks', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('should pass complexityReportPath to expandTask when provided in context', async () => {
|
||||
// Arrange
|
||||
const mockComplexityReportPath =
|
||||
'/test/project/.taskmaster/reports/task-complexity-report.json';
|
||||
mockExpandTask.mockResolvedValue({
|
||||
telemetryData: { commandName: 'expand-task', totalCost: 0.05 }
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await expandAllTasks(
|
||||
mockTasksPath,
|
||||
undefined, // numSubtasks not specified, should use complexity report
|
||||
false,
|
||||
'',
|
||||
false,
|
||||
{
|
||||
session: mockSession,
|
||||
mcpLog: mockMcpLog,
|
||||
projectRoot: mockProjectRoot,
|
||||
tag: 'master',
|
||||
complexityReportPath: mockComplexityReportPath
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.expandedCount).toBe(2); // Tasks 1 and 2
|
||||
|
||||
// Verify expandTask was called with complexityReportPath in context
|
||||
expect(mockExpandTask).toHaveBeenCalledWith(
|
||||
mockTasksPath,
|
||||
expect.any(Number), // task id
|
||||
undefined, // numSubtasks
|
||||
false, // useResearch
|
||||
'', // additionalContext
|
||||
expect.objectContaining({
|
||||
session: mockSession,
|
||||
mcpLog: mockMcpLog,
|
||||
projectRoot: mockProjectRoot,
|
||||
tag: 'master',
|
||||
complexityReportPath: mockComplexityReportPath
|
||||
}),
|
||||
false // force
|
||||
);
|
||||
});
|
||||
|
||||
test('should return success with message when no tasks are eligible', async () => {
|
||||
// Arrange - Mock tasks data with no eligible tasks
|
||||
const noEligibleTasksData = {
|
||||
|
||||
Reference in New Issue
Block a user