Compare commits

...

2 Commits

Author SHA1 Message Date
github-actions[bot]
468106af1e docs: auto-update documentation based on changes in next branch
This PR was automatically generated to update documentation based on recent changes.

  Original commit: fix: expand_all now uses complexity analysis recommendations (#1287)\n\nCo-authored-by: Claude <noreply@anthropic.com>\n\n

  Co-authored-by: Claude <claude-assistant@anthropic.com>
2025-10-11 10:01:13 +00:00
Ralph Khreish
90e6bdcf1c fix: expand_all now uses complexity analysis recommendations (#1287)
Co-authored-by: Claude <noreply@anthropic.com>
2025-10-11 11:54:31 +02:00
9 changed files with 171 additions and 10 deletions

View 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.

View File

@@ -124,6 +124,8 @@ sidebarTitle: "CLI Commands"
# Research-backed generation for all tasks
task-master expand --all --research
```
When you run `task-master expand --all` after `task-master analyze-complexity`, the expand operation automatically uses the recommended subtask counts from the complexity analysis instead of applying uniform defaults. This ensures each task is broken down according to its actual complexity level.
</Accordion>
<Accordion title="Clear Subtasks">

View File

@@ -40,7 +40,7 @@ The MCP tools can be categorized in the same way as the core functionalities:
- **`parse_prd`**: Parses a PRD to generate tasks.
- **`expand_task`**: Expands a task into subtasks.
- **`expand_all`**: Expands all eligible tasks.
- **`expand_all`**: Expands all eligible tasks, automatically using complexity analysis recommendations when available.
- **`analyze_project_complexity`**: Analyzes task complexity.
- **`complexity_report`**: Displays the complexity analysis report.

View File

@@ -197,7 +197,7 @@ Task Master will:
task-master analyze-complexity --research
```
Review the complexity report to identify tasks that need expansion.
Review the complexity report to identify tasks that need expansion and determine optimal subtask counts.
### Step 4: Expand Tasks
@@ -205,7 +205,7 @@ Review the complexity report to identify tasks that need expansion.
task-master expand --all --research
```
Break down complex tasks into manageable subtasks while preserving dependency chains.
Break down complex tasks into manageable subtasks while preserving dependency chains. The expand operation automatically uses the complexity analysis recommendations to determine the appropriate number of subtasks for each task based on its complexity level.
---

View File

@@ -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'
);

View File

@@ -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

View 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 }

50
output.txt Normal file

File diff suppressed because one or more lines are too long

View File

@@ -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 = {