Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .changeset/add-mcpb-bundle.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/add-modifyjson-utils.md

This file was deleted.

9 changes: 9 additions & 0 deletions .changeset/complexity-tag-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@tm/core": patch
---
Comment on lines +1 to +3
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Changeset package name breaks validation.

CI reports this changeset references an invalid package. Please switch the frontmatter to an allowed package (likely task-master-ai).

πŸ› οΈ Suggested fix
---
-"@tm/core": patch
+"task-master-ai": patch
---
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---
"@tm/core": patch
---
---
"task-master-ai": patch
---
🧰 Tools
πŸͺ› GitHub Actions: CI

[error] 1-1: Changeset validation failed during 'node .github/scripts/validate-changesets.mjs': complexity-tag-fix.md references invalid package '@tm/core'. Only allowed packages: task-master-ai, extension.

πŸ€– Prompt for AI Agents
In @.changeset/complexity-tag-fix.md around lines 1 - 3, The changeset
frontmatter currently lists an invalid package ("@tm/core") which breaks CI
validation; open .changeset/complexity-tag-fix.md and update the frontmatter
package name value to an allowed package (e.g., replace "@tm/core" with
"task-master-ai") so the top YAML block references a valid package; ensure the
triple-dash YAML block remains intact and save the file.


Fix: Ensure ComplexityReportManager uses resolved tag consistently when loading reports

This fixes a potential bug where the cache key and file path could use different tag values when loading complexity reports. The fix ensures that when tag is undefined, both the cache lookup and file path resolution use 'master' consistently.

Fixes #1614
9 changes: 0 additions & 9 deletions .changeset/cuddly-wings-drop.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/fair-heads-report.md

This file was deleted.

40 changes: 0 additions & 40 deletions .changeset/task-metadata-field.md

This file was deleted.

60 changes: 60 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,65 @@
# task-master-ai

## 0.43.0

### Minor Changes

- [#1599](https://github.com/eyaltoledano/claude-task-master/pull/1599) [`e689fcf`](https://github.com/eyaltoledano/claude-task-master/commit/e689fcf2a20cada4a19ee31fed723b6f35f2c13d) Thanks [@triepod-ai](https://github.com/triepod-ai)! - Add MCPB bundle for single-click Claude Desktop installation
- Added `manifest.json` for MCP Bundle (MCPB) specification v0.3
- Added `.mcpbignore` to exclude development files from bundle
- Added `icon.png` (512x512) for Claude Desktop display
- Enables users to install Task Master MCP server directly in Claude Desktop without manual configuration

- [#1605](https://github.com/eyaltoledano/claude-task-master/pull/1605) [`efedc85`](https://github.com/eyaltoledano/claude-task-master/commit/efedc85cb1110a75748f3df0e530f3c9e27d2155) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add verbose output mode to loop command with `--verbose` flag
- New `-v, --verbose` flag shows Claude's work in real-time (thinking, tool calls) rather than waiting until the iteration completes
- New `--no-output` flag excludes full Claude output from iteration results to save memory
- Improved error handling with proper validation for incompatible options (verbose + sandbox)

- [#1611](https://github.com/eyaltoledano/claude-task-master/pull/1611) [`c798639`](https://github.com/eyaltoledano/claude-task-master/commit/c798639d1a6b492de1b7cc82a28a13ddfba23eb8) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add optional `metadata` field to tasks for storing user-defined custom data

Tasks and subtasks now support an optional `metadata` field that allows storing arbitrary JSON data such as:
- External IDs (GitHub issues, Jira tickets, Linear issues)
- Workflow data (sprints, story points, custom statuses)
- Integration data (sync timestamps, external system references)
- Custom tracking (UUIDs, version numbers, audit information)

Key features:
- **AI-Safe**: Metadata is preserved through all AI operations (update-task, expand, etc.) because AI schemas intentionally exclude this field
- **Flexible Schema**: Store any JSON-serializable data without schema changes
- **Backward Compatible**: The field is optional; existing tasks work without modification
- **Subtask Support**: Both tasks and subtasks can have their own metadata
- **MCP Tool Support**: Use `update_task` and `update_subtask` with the `metadata` parameter to update metadata (requires `TASK_MASTER_ALLOW_METADATA_UPDATES=true` in MCP server environment)

Example usage:

```json
{
"id": 1,
"title": "Implement authentication",
"metadata": {
"githubIssue": 42,
"sprint": "Q1-S3",
"storyPoints": 5
}
}
```

MCP metadata update example:

```javascript
// With TASK_MASTER_ALLOW_METADATA_UPDATES=true set in MCP env
update_task({
id: "1",
metadata: '{"githubIssue": 42, "sprint": "Q1-S3"}',
});
```

### Patch Changes

- [#1587](https://github.com/eyaltoledano/claude-task-master/pull/1587) [`0d628ca`](https://github.com/eyaltoledano/claude-task-master/commit/0d628ca9514f22607c0a6495b701e4cde743b45c) Thanks [@bjcoombs](https://github.com/bjcoombs)! - Add modifyJSON function for safer file updates

- [#1600](https://github.com/eyaltoledano/claude-task-master/pull/1600) [`712a078`](https://github.com/eyaltoledano/claude-task-master/commit/712a0789d6d584adf5dbb27732c783cd240014b2) Thanks [@esumerfd](https://github.com/esumerfd)! - Add --no-banner to suppress the startup banner.

## 0.42.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": "0.3",
"name": "Claude Task Master",
"version": "0.42.0",
"version": "0.43.0",
"description": "AI-powered task management for structured development workflows. Parse PRDs, generate tasks with AI, track dependencies, and manage complexity.",
"author": {
"name": "Eyal Toledano",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "task-master-ai",
"version": "0.42.0",
"version": "0.43.0",
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
"main": "index.js",
"type": "module",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class ComplexityReportManager {
return this.reportCache.get(cacheKey)!;
}

const reportPath = this.getReportPath(tag);
const reportPath = this.getReportPath(resolvedTag);

try {
// Check if file exists
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/**
* @fileoverview Integration test for complexity enrichment in list command
*
* This test reproduces the bug where task complexity is not shown in `list`
* after running `analyze-complexity` with a tag.
*
* Bug: https://github.com/eyaltoledano/claude-task-master/issues/1614
*/

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import fs from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
import { FileStorage } from '../../../src/modules/storage/adapters/file-storage/file-storage.js';
import type { Task, ComplexityReport } from '../../../src/common/types/index.js';

describe('Complexity Enrichment Integration Test', () => {
let tempDir: string;
let storage: FileStorage;

beforeEach(async () => {
// Create a temporary directory for testing
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'tm-complexity-test-'));

// Initialize storage
storage = new FileStorage(tempDir);
await storage.initialize();
});

afterEach(async () => {
// Cleanup
await storage.close();
await fs.rm(tempDir, { recursive: true, force: true });
});

it('should enrich tasks with complexity data for tagged tasks', async () => {
const tag = 'foo';

// Step 1: Create tasks with the 'foo' tag
const tasks: Task[] = [
{
id: '1',
title: 'Implement authentication',
description: 'Add JWT-based auth',
status: 'pending',
priority: 'high',
dependencies: [],
subtasks: [],
tags: [tag]
},
{
id: '2',
title: 'Create API endpoints',
description: 'Build REST API',
status: 'pending',
priority: 'medium',
dependencies: [],
subtasks: [],
tags: [tag]
}
];

await storage.saveTasks(tasks, tag);

// Step 2: Create a complexity report for the 'foo' tag
const reportsDir = path.join(tempDir, '.taskmaster', 'reports');
await fs.mkdir(reportsDir, { recursive: true });

const complexityReport: ComplexityReport = {
meta: {
generatedAt: new Date().toISOString(),
tasksAnalyzed: 2,
thresholdScore: 5,
usedResearch: false
},
complexityAnalysis: [
{
taskId: '1',
taskTitle: 'Implement authentication',
complexityScore: 8,
recommendedSubtasks: 5,
complexityReasoning: 'High complexity due to security concerns',
expansionPrompt: 'Break down auth into smaller tasks'
},
{
taskId: '2',
taskTitle: 'Create API endpoints',
complexityScore: 6,
recommendedSubtasks: 4,
complexityReasoning: 'Moderate complexity',
expansionPrompt: 'Split by endpoint functionality'
}
]
};

const reportPath = path.join(reportsDir, `task-complexity-report_${tag}.json`);
await fs.writeFile(reportPath, JSON.stringify(complexityReport, null, 2), 'utf-8');

// Step 3: Load tasks with the tag - complexity should be enriched
const loadedTasks = await storage.loadTasks(tag);

// Verify tasks were loaded
expect(loadedTasks).toHaveLength(2);

// Step 4: Verify complexity data was enriched
const task1 = loadedTasks.find(t => t.id === '1');
const task2 = loadedTasks.find(t => t.id === '2');

expect(task1).toBeDefined();
expect(task2).toBeDefined();

// BUG: These assertions should pass but currently fail
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated comment misleadingly describes passing tests as failing

Low Severity

The comment // BUG: These assertions should pass but currently fail is misleading. Since the fix for issue #1614 is included in this same PR, these assertions will pass after the PR merges. The comment reads as if the tests are expected to fail, which could confuse future developers reviewing the test or investigating test failures. The comment documents historical context but is stale by the time this PR lands.

Fix in CursorΒ Fix in Web

expect(task1!.complexity).toBe(8);
expect(task1!.recommendedSubtasks).toBe(5);
expect(task1!.expansionPrompt).toBe('Break down auth into smaller tasks');

expect(task2!.complexity).toBe(6);
expect(task2!.recommendedSubtasks).toBe(4);
expect(task2!.expansionPrompt).toBe('Split by endpoint functionality');
});

it('should handle master tag complexity enrichment', async () => {
// Test with default 'master' tag (no suffix in report filename)
const tasks: Task[] = [
{
id: '1',
title: 'Setup project',
description: 'Initialize project structure',
status: 'pending',
priority: 'high',
dependencies: [],
subtasks: [],
tags: []
}
];

await storage.saveTasks(tasks);

// Create complexity report for master tag (no suffix)
const reportsDir = path.join(tempDir, '.taskmaster', 'reports');
await fs.mkdir(reportsDir, { recursive: true });

const complexityReport: ComplexityReport = {
meta: {
generatedAt: new Date().toISOString(),
tasksAnalyzed: 1,
thresholdScore: 5,
usedResearch: false
},
complexityAnalysis: [
{
taskId: '1',
taskTitle: 'Setup project',
complexityScore: 3,
recommendedSubtasks: 2,
complexityReasoning: 'Low complexity',
expansionPrompt: 'Simple setup tasks'
}
]
};

const reportPath = path.join(reportsDir, 'task-complexity-report.json');
await fs.writeFile(reportPath, JSON.stringify(complexityReport, null, 2), 'utf-8');

// Load tasks without specifying tag (defaults to master)
const loadedTasks = await storage.loadTasks();

expect(loadedTasks).toHaveLength(1);
expect(loadedTasks[0].complexity).toBe(3);
expect(loadedTasks[0].recommendedSubtasks).toBe(2);
});

it('should return tasks without complexity when no report exists', async () => {
const tag = 'no-report';
const tasks: Task[] = [
{
id: '1',
title: 'Test task',
description: 'A test',
status: 'pending',
priority: 'medium',
dependencies: [],
subtasks: [],
tags: [tag]
}
];

await storage.saveTasks(tasks, tag);
const loadedTasks = await storage.loadTasks(tag);

expect(loadedTasks).toHaveLength(1);
expect(loadedTasks[0].complexity).toBeUndefined();
expect(loadedTasks[0].recommendedSubtasks).toBeUndefined();
});
});
Comment on lines +1 to +195
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

CI formatting failure needs to be addressed.

The pipeline reports the formatter would change this file; please run the formatter (e.g., biome format .) before merging.

🧰 Tools
πŸͺ› GitHub Actions: CI

[error] 15-18: Formatter would have printed changes for complexity-enrichment.test.ts. Run the format tool (e.g., biome format .) to fix code style issues.

πŸ€– Prompt for AI Agents
In `@packages/tm-core/tests/integration/storage/complexity-enrichment.test.ts`
around lines 1 - 195, The file fails CI formatting; run the project formatter
(e.g., `biome format .` or the repo's configured formatter) and commit the
result so the test file (the describe/it/beforeEach/afterEach blocks that use
FileStorage, saveTasks, loadTasks) matches the repo style; ensure whitespace,
imports, and trailing newlines are fixed and re-run tests to confirm formatting
is clean before merging.

Binary file modified taskmaster.mcpb
Binary file not shown.
Loading