Compare commits
16 Commits
chore/impr
...
fix-task-n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b594795238 | ||
|
|
8f97b6aead | ||
|
|
3f31c34f8d | ||
|
|
ef23beac0d | ||
|
|
077cbb99de | ||
|
|
ee2af1760f | ||
|
|
2421c205c4 | ||
|
|
33208388bd | ||
|
|
3fa0c7f7af | ||
|
|
0609b9ae28 | ||
|
|
b79eb4f7a2 | ||
|
|
45a14c323d | ||
|
|
29e67fafa4 | ||
|
|
43e4d7c9d3 | ||
|
|
1bd1e64cac | ||
|
|
dc44ed9de8 |
5
.changeset/eleven-horses-shop.md
Normal file
5
.changeset/eleven-horses-shop.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix for tasks not found when using string IDs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix compatibility with @google/gemini-cli-core v0.1.12+ by updating ai-sdk-provider-gemini-cli to v0.1.1.
|
||||
7
.changeset/fix-tag-complexity-detection.md
Normal file
7
.changeset/fix-tag-complexity-detection.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix tag-specific complexity report detection in expand command
|
||||
|
||||
The expand command now correctly finds and uses tag-specific complexity reports (e.g., `task-complexity-report_feature-xyz.json`) when operating in a tag context. Previously, it would always look for the generic `task-complexity-report.json` file due to a default value in the CLI option definition.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix 'expand --all' and 'show' commands to correctly handle tag contexts for complexity reports and task display.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Clean up remaining automatic task file generation calls
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add comprehensive Kiro IDE integration with autonomous task management hooks
|
||||
|
||||
- **Kiro Profile**: Added full support for Kiro IDE with automatic installation of 7 Taskmaster agent hooks
|
||||
- **Hook-Driven Workflow**: Introduced natural language automation hooks that eliminate manual task status updates
|
||||
- **Automatic Hook Installation**: Hooks are now automatically copied to `.kiro/hooks/` when running `task-master rules add kiro`
|
||||
- **Language-Agnostic Support**: All hooks support multiple programming languages (JS, Python, Go, Rust, Java, etc.)
|
||||
- **Frontmatter Transformation**: Kiro rules use simplified `inclusion: always` format instead of Cursor's complex frontmatter
|
||||
- **Special Rule**: Added `taskmaster_hooks_workflow.md` that guides AI assistants to prefer hook-driven completion
|
||||
|
||||
Key hooks included:
|
||||
|
||||
- Task Dependency Auto-Progression: Automatically starts tasks when dependencies complete
|
||||
- Code Change Task Tracker: Updates task progress as you save files
|
||||
- Test Success Task Completer: Marks tasks done when tests pass
|
||||
- Daily Standup Assistant: Provides personalized task status summaries
|
||||
- PR Readiness Checker: Validates task completion before creating pull requests
|
||||
- Complexity Analyzer: Auto-expands complex tasks into manageable subtasks
|
||||
- Git Commit Task Linker: Links commits to tasks for better traceability
|
||||
|
||||
This creates a truly autonomous development workflow where task management happens naturally as you code!
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"mode": "pre",
|
||||
"tag": "rc",
|
||||
"initialVersions": {
|
||||
"task-master-ai": "0.21.0",
|
||||
"extension": "0.20.0"
|
||||
},
|
||||
"changesets": [
|
||||
"fix-gemini-cli-dependency",
|
||||
"fresh-bugs-squashed",
|
||||
"happy-sites-stay",
|
||||
"orange-pots-add",
|
||||
"quiet-rabbits-bathe",
|
||||
"swift-otters-argue"
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix max_tokens limits for OpenRouter and Groq models
|
||||
|
||||
- Add special handling in config-manager.js for custom OpenRouter models to use a conservative default of 32,768 max_tokens
|
||||
- Update qwen/qwen-turbo model max_tokens from 1,000,000 to 32,768 to match OpenRouter's actual limits
|
||||
- Fix moonshotai/kimi-k2-instruct max_tokens to 16,384 to match Groq's actual limit (fixes #1028)
|
||||
- This prevents "maximum context length exceeded" errors when using OpenRouter models not in our supported models list
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix VSCode profile generation to use correct rule file names (using `.instructions.md` extension instead of `.md`) and front-matter properties (removing the unsupported `alwaysApply` property from instructions files' front-matter).
|
||||
47
CHANGELOG.md
47
CHANGELOG.md
@@ -1,5 +1,52 @@
|
||||
# task-master-ai
|
||||
|
||||
## 0.22.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1043](https://github.com/eyaltoledano/claude-task-master/pull/1043) [`dc44ed9`](https://github.com/eyaltoledano/claude-task-master/commit/dc44ed9de8a57aca5d39d3a87565568bd0a82068) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Prompt to generate a complexity report when it is missing
|
||||
|
||||
- [#1032](https://github.com/eyaltoledano/claude-task-master/pull/1032) [`4423119`](https://github.com/eyaltoledano/claude-task-master/commit/4423119a5ec53958c9dffa8bf564da8be7a2827d) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add comprehensive Kiro IDE integration with autonomous task management hooks
|
||||
- **Kiro Profile**: Added full support for Kiro IDE with automatic installation of 7 Taskmaster agent hooks
|
||||
- **Hook-Driven Workflow**: Introduced natural language automation hooks that eliminate manual task status updates
|
||||
- **Automatic Hook Installation**: Hooks are now automatically copied to `.kiro/hooks/` when running `task-master rules add kiro`
|
||||
- **Language-Agnostic Support**: All hooks support multiple programming languages (JS, Python, Go, Rust, Java, etc.)
|
||||
- **Frontmatter Transformation**: Kiro rules use simplified `inclusion: always` format instead of Cursor's complex frontmatter
|
||||
- **Special Rule**: Added `taskmaster_hooks_workflow.md` that guides AI assistants to prefer hook-driven completion
|
||||
|
||||
Key hooks included:
|
||||
- Task Dependency Auto-Progression: Automatically starts tasks when dependencies complete
|
||||
- Code Change Task Tracker: Updates task progress as you save files
|
||||
- Test Success Task Completer: Marks tasks done when tests pass
|
||||
- Daily Standup Assistant: Provides personalized task status summaries
|
||||
- PR Readiness Checker: Validates task completion before creating pull requests
|
||||
- Complexity Analyzer: Auto-expands complex tasks into manageable subtasks
|
||||
- Git Commit Task Linker: Links commits to tasks for better traceability
|
||||
|
||||
This creates a truly autonomous development workflow where task management happens naturally as you code!
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1033](https://github.com/eyaltoledano/claude-task-master/pull/1033) [`7b90568`](https://github.com/eyaltoledano/claude-task-master/commit/7b9056832653464f934c91c22997077065d738c4) Thanks [@ben-vargas](https://github.com/ben-vargas)! - Fix compatibility with @google/gemini-cli-core v0.1.12+ by updating ai-sdk-provider-gemini-cli to v0.1.1.
|
||||
|
||||
- [#1038](https://github.com/eyaltoledano/claude-task-master/pull/1038) [`77cc5e4`](https://github.com/eyaltoledano/claude-task-master/commit/77cc5e4537397642f2664f61940a101433ee6fb4) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix 'expand --all' and 'show' commands to correctly handle tag contexts for complexity reports and task display.
|
||||
|
||||
- [#1025](https://github.com/eyaltoledano/claude-task-master/pull/1025) [`8781794`](https://github.com/eyaltoledano/claude-task-master/commit/8781794c56d454697fc92c88a3925982d6b81205) Thanks [@joedanz](https://github.com/joedanz)! - Clean up remaining automatic task file generation calls
|
||||
|
||||
- [#1035](https://github.com/eyaltoledano/claude-task-master/pull/1035) [`fb7d588`](https://github.com/eyaltoledano/claude-task-master/commit/fb7d588137e8c53b0d0f54bd1dd8d387648583ee) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix max_tokens limits for OpenRouter and Groq models
|
||||
- Add special handling in config-manager.js for custom OpenRouter models to use a conservative default of 32,768 max_tokens
|
||||
- Update qwen/qwen-turbo model max_tokens from 1,000,000 to 32,768 to match OpenRouter's actual limits
|
||||
- Fix moonshotai/kimi-k2-instruct max_tokens to 16,384 to match Groq's actual limit (fixes #1028)
|
||||
- This prevents "maximum context length exceeded" errors when using OpenRouter models not in our supported models list
|
||||
|
||||
- [#1027](https://github.com/eyaltoledano/claude-task-master/pull/1027) [`6ae66b2`](https://github.com/eyaltoledano/claude-task-master/commit/6ae66b2afbfe911340fa25e0236c3db83deaa7eb) Thanks [@andreswebs](https://github.com/andreswebs)! - Fix VSCode profile generation to use correct rule file names (using `.instructions.md` extension instead of `.md`) and front-matter properties (removing the unsupported `alwaysApply` property from instructions files' front-matter).
|
||||
|
||||
## 0.22.0-rc.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1043](https://github.com/eyaltoledano/claude-task-master/pull/1043) [`dc44ed9`](https://github.com/eyaltoledano/claude-task-master/commit/dc44ed9de8a57aca5d39d3a87565568bd0a82068) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Prompt to generate a complexity report when it is missing
|
||||
|
||||
## 0.22.0-rc.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "task-master-ai",
|
||||
"version": "0.21.0",
|
||||
"version": "0.22.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "task-master-ai",
|
||||
"version": "0.21.0",
|
||||
"version": "0.22.0",
|
||||
"license": "MIT WITH Commons-Clause",
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "task-master-ai",
|
||||
"version": "0.22.0-rc.0",
|
||||
"version": "0.22.0",
|
||||
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
||||
@@ -1564,8 +1564,8 @@ function registerCommands(programInstance) {
|
||||
) // Allow file override
|
||||
.option(
|
||||
'-cr, --complexity-report <file>',
|
||||
'Path to the report file',
|
||||
COMPLEXITY_REPORT_FILE
|
||||
'Path to the complexity report file (use this to specify the complexity report, not --file)'
|
||||
// Removed default value to allow tag-specific auto-detection
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import boxen from 'boxen';
|
||||
import ora from 'ora';
|
||||
import Table from 'cli-table3';
|
||||
import gradient from 'gradient-string';
|
||||
import readline from 'readline';
|
||||
import {
|
||||
log,
|
||||
findTaskById,
|
||||
@@ -1682,18 +1683,15 @@ async function displayComplexityReport(reportPath) {
|
||||
)
|
||||
);
|
||||
|
||||
const readline = require('readline').createInterface({
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
const answer = await new Promise((resolve) => {
|
||||
readline.question(
|
||||
chalk.cyan('Generate complexity report? (y/n): '),
|
||||
resolve
|
||||
);
|
||||
rl.question(chalk.cyan('Generate complexity report? (y/n): '), resolve);
|
||||
});
|
||||
readline.close();
|
||||
rl.close();
|
||||
|
||||
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
|
||||
// Call the analyze-complexity command
|
||||
@@ -1974,8 +1972,6 @@ async function confirmTaskOverwrite(tasksPath) {
|
||||
)
|
||||
);
|
||||
|
||||
// Use dynamic import to get the readline module
|
||||
const readline = await import('readline');
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
@@ -2463,8 +2459,6 @@ async function displayMultipleTasksSummary(
|
||||
)
|
||||
);
|
||||
|
||||
// Use dynamic import for readline
|
||||
const readline = await import('readline');
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
|
||||
@@ -262,6 +262,43 @@ function hasTaggedStructure(data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes task IDs to ensure they are numbers instead of strings
|
||||
* @param {Array} tasks - Array of tasks to normalize
|
||||
*/
|
||||
function normalizeTaskIds(tasks) {
|
||||
if (!Array.isArray(tasks)) return;
|
||||
|
||||
tasks.forEach((task) => {
|
||||
// Convert task ID to number with validation
|
||||
if (task.id !== undefined) {
|
||||
const parsedId = parseInt(task.id, 10);
|
||||
if (!isNaN(parsedId) && parsedId > 0) {
|
||||
task.id = parsedId;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert subtask IDs to numbers with validation
|
||||
if (Array.isArray(task.subtasks)) {
|
||||
task.subtasks.forEach((subtask) => {
|
||||
if (subtask.id !== undefined) {
|
||||
// Check for dot notation (which shouldn't exist in storage)
|
||||
if (typeof subtask.id === 'string' && subtask.id.includes('.')) {
|
||||
// Extract the subtask part after the dot
|
||||
const parts = subtask.id.split('.');
|
||||
subtask.id = parseInt(parts[parts.length - 1], 10);
|
||||
} else {
|
||||
const parsedSubtaskId = parseInt(subtask.id, 10);
|
||||
if (!isNaN(parsedSubtaskId) && parsedSubtaskId > 0) {
|
||||
subtask.id = parsedSubtaskId;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and parses a JSON file
|
||||
* @param {string} filepath - Path to the JSON file
|
||||
@@ -322,6 +359,8 @@ function readJSON(filepath, projectRoot = null, tag = null) {
|
||||
console.log(`File is in legacy format, performing migration...`);
|
||||
}
|
||||
|
||||
normalizeTaskIds(data.tasks);
|
||||
|
||||
// This is legacy format - migrate it to tagged format
|
||||
const migratedData = {
|
||||
master: {
|
||||
@@ -401,6 +440,16 @@ function readJSON(filepath, projectRoot = null, tag = null) {
|
||||
// Store reference to the raw tagged data for functions that need it
|
||||
const originalTaggedData = JSON.parse(JSON.stringify(data));
|
||||
|
||||
// Normalize IDs in all tags before storing as originalTaggedData
|
||||
for (const tagName in originalTaggedData) {
|
||||
if (
|
||||
originalTaggedData[tagName] &&
|
||||
Array.isArray(originalTaggedData[tagName].tasks)
|
||||
) {
|
||||
normalizeTaskIds(originalTaggedData[tagName].tasks);
|
||||
}
|
||||
}
|
||||
|
||||
// Check and auto-switch git tags if enabled (for existing tagged format)
|
||||
// This needs to run synchronously BEFORE tag resolution
|
||||
if (projectRoot) {
|
||||
@@ -448,6 +497,8 @@ function readJSON(filepath, projectRoot = null, tag = null) {
|
||||
// Get the data for the resolved tag
|
||||
const tagData = data[resolvedTag];
|
||||
if (tagData && tagData.tasks) {
|
||||
normalizeTaskIds(tagData.tasks);
|
||||
|
||||
// Add the _rawTaggedData property and the resolved tag to the returned data
|
||||
const result = {
|
||||
...tagData,
|
||||
@@ -464,6 +515,8 @@ function readJSON(filepath, projectRoot = null, tag = null) {
|
||||
// If the resolved tag doesn't exist, fall back to master
|
||||
const masterData = data.master;
|
||||
if (masterData && masterData.tasks) {
|
||||
normalizeTaskIds(masterData.tasks);
|
||||
|
||||
if (isDebug) {
|
||||
console.log(
|
||||
`Tag '${resolvedTag}' not found, falling back to master with ${masterData.tasks.length} tasks`
|
||||
@@ -493,6 +546,7 @@ function readJSON(filepath, projectRoot = null, tag = null) {
|
||||
// If anything goes wrong, try to return master or empty
|
||||
const masterData = data.master;
|
||||
if (masterData && masterData.tasks) {
|
||||
normalizeTaskIds(masterData.tasks);
|
||||
return {
|
||||
...masterData,
|
||||
_rawTaggedData: originalTaggedData
|
||||
@@ -1412,5 +1466,6 @@ export {
|
||||
createStateJson,
|
||||
markMigrationForNotice,
|
||||
flattenTasksWithSubtasks,
|
||||
ensureTagMetadata
|
||||
ensureTagMetadata,
|
||||
normalizeTaskIds
|
||||
};
|
||||
|
||||
@@ -23,6 +23,82 @@ describe('Task Finder', () => {
|
||||
expect(result.originalSubtaskCount).toBeNull();
|
||||
});
|
||||
|
||||
test('should find tasks when JSON contains string IDs (normalized to numbers)', () => {
|
||||
// Simulate tasks loaded from JSON with string IDs and mixed subtask notations
|
||||
const tasksWithStringIds = [
|
||||
{ id: '1', title: 'First Task' },
|
||||
{
|
||||
id: '2',
|
||||
title: 'Second Task',
|
||||
subtasks: [
|
||||
{ id: '1', title: 'Subtask One' },
|
||||
{ id: '2.2', title: 'Subtask Two (with dotted notation)' } // Testing dotted notation
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: 'Fifth Task',
|
||||
subtasks: [
|
||||
{ id: '5.1', title: 'Subtask with dotted ID' }, // Should normalize to 1
|
||||
{ id: '3', title: 'Subtask with simple ID' } // Should stay as 3
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// The readJSON function should normalize these IDs to numbers
|
||||
// For this test, we'll manually normalize them to simulate what happens
|
||||
tasksWithStringIds.forEach((task) => {
|
||||
task.id = parseInt(task.id, 10);
|
||||
if (task.subtasks) {
|
||||
task.subtasks.forEach((subtask) => {
|
||||
// Handle dotted notation like "5.1" -> extract the subtask part
|
||||
if (typeof subtask.id === 'string' && subtask.id.includes('.')) {
|
||||
const parts = subtask.id.split('.');
|
||||
subtask.id = parseInt(parts[parts.length - 1], 10);
|
||||
} else {
|
||||
subtask.id = parseInt(subtask.id, 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Test finding tasks by numeric ID
|
||||
const result1 = findTaskById(tasksWithStringIds, 5);
|
||||
expect(result1.task).toBeDefined();
|
||||
expect(result1.task.id).toBe(5);
|
||||
expect(result1.task.title).toBe('Fifth Task');
|
||||
|
||||
// Test finding tasks by string ID
|
||||
const result2 = findTaskById(tasksWithStringIds, '5');
|
||||
expect(result2.task).toBeDefined();
|
||||
expect(result2.task.id).toBe(5);
|
||||
|
||||
// Test finding subtasks with normalized IDs
|
||||
const result3 = findTaskById(tasksWithStringIds, '2.1');
|
||||
expect(result3.task).toBeDefined();
|
||||
expect(result3.task.id).toBe(1);
|
||||
expect(result3.task.title).toBe('Subtask One');
|
||||
expect(result3.task.isSubtask).toBe(true);
|
||||
|
||||
// Test subtask that was originally "2.2" (should be normalized to 2)
|
||||
const result4 = findTaskById(tasksWithStringIds, '2.2');
|
||||
expect(result4.task).toBeDefined();
|
||||
expect(result4.task.id).toBe(2);
|
||||
expect(result4.task.title).toBe('Subtask Two (with dotted notation)');
|
||||
|
||||
// Test subtask that was originally "5.1" (should be normalized to 1)
|
||||
const result5 = findTaskById(tasksWithStringIds, '5.1');
|
||||
expect(result5.task).toBeDefined();
|
||||
expect(result5.task.id).toBe(1);
|
||||
expect(result5.task.title).toBe('Subtask with dotted ID');
|
||||
|
||||
// Test subtask that was originally "3" (should stay as 3)
|
||||
const result6 = findTaskById(tasksWithStringIds, '5.3');
|
||||
expect(result6.task).toBeDefined();
|
||||
expect(result6.task.id).toBe(3);
|
||||
expect(result6.task.title).toBe('Subtask with simple ID');
|
||||
});
|
||||
|
||||
test('should find a subtask using dot notation', () => {
|
||||
const result = findTaskById(sampleTasks.tasks, '3.1');
|
||||
expect(result.task).toBeDefined();
|
||||
|
||||
Reference in New Issue
Block a user