Compare commits
146 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c2e6b2466 | ||
|
|
f07945734d | ||
|
|
d5360f625f | ||
|
|
2e2d290c63 | ||
|
|
d3edd24b5a | ||
|
|
60c0f26f3c | ||
|
|
be0bf18f41 | ||
|
|
32236a0bc5 | ||
|
|
668b22e615 | ||
|
|
4901908f5d | ||
|
|
a047886910 | ||
|
|
92234323d7 | ||
|
|
514fdb0b78 | ||
|
|
932825c2d6 | ||
|
|
3c8c62434f | ||
|
|
9d755b9e79 | ||
|
|
fcc2351b3d | ||
|
|
3db62b5b88 | ||
|
|
6b929fa9fa | ||
|
|
ddaa1dceef | ||
|
|
cac8c234d6 | ||
|
|
b205e52d08 | ||
|
|
4585a6bbc7 | ||
|
|
b3ec151b27 | ||
|
|
5d9748af89 | ||
|
|
b28479a09d | ||
|
|
9efbd38f10 | ||
|
|
dc7a5414c0 | ||
|
|
75e017e371 | ||
|
|
a84cd1a492 | ||
|
|
3888ef41d4 | ||
|
|
83d6405b17 | ||
|
|
bb775e3180 | ||
|
|
2328efe482 | ||
|
|
f3fe481f3f | ||
|
|
f43b5fdd75 | ||
|
|
153b190e0d | ||
|
|
0be5ae59fe | ||
|
|
f1d593f887 | ||
|
|
efd14544f0 | ||
|
|
ef9439d441 | ||
|
|
a49071a6b8 | ||
|
|
c2d83690a1 | ||
|
|
b40a94c4ac | ||
|
|
05a389e171 | ||
|
|
3352a6a99f | ||
|
|
d391f3b5b3 | ||
|
|
f2c5911e58 | ||
|
|
bb5a0211f4 | ||
|
|
4234cc3d87 | ||
|
|
d942db4868 | ||
|
|
3cf718a718 | ||
|
|
a2ff8a97b7 | ||
|
|
b1b888a5f3 | ||
|
|
f817de9da6 | ||
|
|
806c505aac | ||
|
|
6f225cf81a | ||
|
|
74eb9907f3 | ||
|
|
5c29969741 | ||
|
|
8e794e18ac | ||
|
|
3ce4d2cc74 | ||
|
|
2d85fcc6a7 | ||
|
|
0102be4f3b | ||
|
|
b6f1376625 | ||
|
|
d4f21be1a3 | ||
|
|
f28de8b729 | ||
|
|
e50230f9ce | ||
|
|
01992ebd0b | ||
|
|
af652978a0 | ||
|
|
54005d5486 | ||
|
|
65b70d746a | ||
|
|
f533fd0931 | ||
|
|
7db7cf3859 | ||
|
|
2434b97247 | ||
|
|
bac58c606d | ||
|
|
89f8bff219 | ||
|
|
366cd161da | ||
|
|
a346dd5020 | ||
|
|
c2709edd78 | ||
|
|
e53006066e | ||
|
|
2d11b94804 | ||
|
|
a5e36cf7b4 | ||
|
|
9cd18caa3c | ||
|
|
9058d7dfdd | ||
|
|
199e32c2d1 | ||
|
|
a874a12e17 | ||
|
|
eb343287ae | ||
|
|
94eeb5117b | ||
|
|
87c85d3d66 | ||
|
|
0b8f594ac7 | ||
|
|
15b190b87b | ||
|
|
9ae255ccb4 | ||
|
|
518f73eefa | ||
|
|
40a52385ba | ||
|
|
8a86ec538e | ||
|
|
9e7387952d | ||
|
|
ab05f550b3 | ||
|
|
d2bcbee0c2 | ||
|
|
72171bd4ba | ||
|
|
9ad517231a | ||
|
|
7db3b47a47 | ||
|
|
3de785a99c | ||
|
|
8188fdd832 | ||
|
|
3fadc2f1ef | ||
|
|
dd36111367 | ||
|
|
c58ab8963c | ||
|
|
3eeb4721aa | ||
|
|
7ea905f2c5 | ||
|
|
51dd4f625b | ||
|
|
2e55757b26 | ||
|
|
54bfc72baa | ||
|
|
faae0b419d | ||
|
|
27edbd8f3f | ||
|
|
b1390e4ddf | ||
|
|
cc04d53720 | ||
|
|
bfd86eb9cc | ||
|
|
9eb3842f04 | ||
|
|
bf2053e140 | ||
|
|
ee0be04302 | ||
|
|
c0707fc399 | ||
|
|
1ece6f1904 | ||
|
|
f4a9ad1095 | ||
|
|
cba86510d3 | ||
|
|
86ea6d1dbc | ||
|
|
a22d2a45b5 | ||
|
|
d73c8e17ec | ||
|
|
4f23751d25 | ||
|
|
7d5c028ca0 | ||
|
|
f18df6da19 | ||
|
|
1754a31372 | ||
|
|
3096ccdfb3 | ||
|
|
6464bb11e5 | ||
|
|
edaa5fe0d5 | ||
|
|
41d9dbbe6d | ||
|
|
6e0d866756 | ||
|
|
926aa61a4e | ||
|
|
9b4168bb4e | ||
|
|
ad612763ff | ||
|
|
293b59bac6 | ||
|
|
1809c4ed7b | ||
|
|
6e406958c1 | ||
|
|
074b7ec0bc | ||
|
|
e0438c8fb8 | ||
|
|
1f6694fb3d | ||
|
|
b0dfcf345e | ||
|
|
3f64202c9f |
@@ -1,5 +1,5 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add comprehensive AI-powered research command with intelligent context gathering and interactive follow-ups.
|
||||
@@ -7,6 +7,7 @@ Add comprehensive AI-powered research command with intelligent context gathering
|
||||
The new `research` command provides AI-powered research capabilities that automatically gather relevant project context to answer your questions. The command intelligently selects context from multiple sources and supports interactive follow-up questions in CLI mode.
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- **Intelligent Task Discovery**: Automatically finds relevant tasks and subtasks using fuzzy search based on your query keywords, supplementing any explicitly provided task IDs
|
||||
- **Multi-Source Context**: Gathers context from tasks, files, project structure, and custom text to provide comprehensive answers
|
||||
- **Interactive Follow-ups**: CLI users can ask follow-up questions that build on the conversation history while allowing fresh context discovery for each question
|
||||
@@ -15,6 +16,7 @@ The new `research` command provides AI-powered research capabilities that automa
|
||||
- **Enhanced Display**: Syntax-highlighted code blocks and structured output with clear visual separation
|
||||
|
||||
**Usage Examples:**
|
||||
|
||||
```bash
|
||||
# Basic research with auto-discovered context
|
||||
task-master research "How should I implement user authentication?"
|
||||
@@ -30,15 +32,46 @@ task-master research "Quick implementation steps?" --context="Using JWT tokens"
|
||||
```
|
||||
|
||||
**Context Sources:**
|
||||
|
||||
- **Tasks**: Automatically discovers relevant tasks/subtasks via fuzzy search, plus any explicitly specified via `--id`
|
||||
- **Files**: Include specific files via `--files` for code-aware responses
|
||||
- **Project Tree**: Add `--tree` to include project structure overview
|
||||
- **Custom Context**: Provide additional context via `--context` for domain-specific information
|
||||
|
||||
**Interactive Features (CLI only):**
|
||||
|
||||
- Follow-up questions that maintain conversation history
|
||||
- Fresh fuzzy search for each follow-up to discover newly relevant tasks
|
||||
- Cumulative context building across the conversation
|
||||
- Clean visual separation between exchanges
|
||||
- **Save to Tasks**: Save entire research conversations (including follow-ups) directly to task or subtask details with timestamps
|
||||
- **Clean Menu Interface**: Streamlined inquirer-based menu for follow-up actions without redundant UI elements
|
||||
|
||||
The research command integrates with the existing AI service layer and supports all configured AI providers. MCP integration provides the same functionality for programmatic access without interactive features.
|
||||
**Save Functionality:**
|
||||
|
||||
The research command now supports saving complete conversation threads to tasks or subtasks:
|
||||
|
||||
- Save research results and follow-up conversations to any task (e.g., "15") or subtask (e.g., "15.2")
|
||||
- Automatic timestamping and formatting of conversation history
|
||||
- Validation of task/subtask existence before saving
|
||||
- Appends to existing task details without overwriting content
|
||||
- Supports both CLI interactive mode and MCP programmatic access via `--save-to` flag
|
||||
|
||||
**Enhanced CLI Options:**
|
||||
|
||||
```bash
|
||||
# Auto-save research results to a task
|
||||
task-master research "Implementation approach?" --save-to=15
|
||||
|
||||
# Combine auto-save with context gathering
|
||||
task-master research "How to optimize this?" --id=23 --save-to=23.1
|
||||
```
|
||||
|
||||
**MCP Integration:**
|
||||
|
||||
- `saveTo` parameter for automatic saving to specified task/subtask ID
|
||||
- Structured response format with telemetry data
|
||||
- Silent operation mode for programmatic usage
|
||||
- Full feature parity with CLI except interactive follow-ups
|
||||
|
||||
The research command integrates with the existing AI service layer and supports all configured AI providers. Both CLI and MCP interfaces provide comprehensive research capabilities with intelligent context gathering and flexible output options.
|
||||
|
||||
5
.changeset/chatty-rats-talk.md
Normal file
5
.changeset/chatty-rats-talk.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix Cursor deeplink installation by providing copy-paste instructions for GitHub compatibility
|
||||
5
.changeset/curly-dragons-design.md
Normal file
5
.changeset/curly-dragons-design.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
improve findTasks algorithm for resolving tasks path
|
||||
5
.changeset/eleven-news-check.md
Normal file
5
.changeset/eleven-news-check.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix update tool on MCP giving `No valid tasks found`
|
||||
5
.changeset/fluffy-waves-allow.md
Normal file
5
.changeset/fluffy-waves-allow.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Adds ability to automatically create/switch tags to match the current git branch. The configuration to enable the git workflow and then use the auto switching is in config.json."
|
||||
39
.changeset/four-cups-enter.md
Normal file
39
.changeset/four-cups-enter.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Enhanced add-task fuzzy search intelligence and improved user experience
|
||||
|
||||
**Smarter Task Discovery:**
|
||||
|
||||
- Remove hardcoded category system that always matched "Task management"
|
||||
- Eliminate arbitrary limits on fuzzy search results (5→25 high relevance, 3→10 medium relevance, 8→20 detailed tasks)
|
||||
- Improve semantic weighting in Fuse.js search (details=3, description=2, title=1.5) for better relevance
|
||||
- Generate context-driven task recommendations based on true semantic similarity
|
||||
|
||||
**Enhanced Terminal Experience:**
|
||||
|
||||
- Fix duplicate banner display issue that was "eating" terminal history (closes #553)
|
||||
- Remove console.clear() and redundant displayBanner() calls from UI functions
|
||||
- Preserve command history for better development workflow
|
||||
- Streamline banner display across all commands (list, next, show, set-status, clear-subtasks, dependency commands)
|
||||
|
||||
**Visual Improvements:**
|
||||
|
||||
- Replace emoji complexity indicators with clean filled circle characters (●) for professional appearance
|
||||
- Improve consistency and readability of task complexity display
|
||||
|
||||
**AI Provider Compatibility:**
|
||||
|
||||
- Change generateObject mode from 'tool' to 'auto' for better cross-provider compatibility
|
||||
- Add qwen3-235n-a22b:free model support (closes #687)
|
||||
- Add smart warnings for free OpenRouter models with limitations (rate limits, restricted context, no tool_use)
|
||||
|
||||
**Technical Improvements:**
|
||||
|
||||
- Enhanced context generation in add-task to rely on semantic similarity rather than rigid pattern matching
|
||||
- Improved dependency analysis and common pattern detection
|
||||
- Better handling of task relationships and relevance scoring
|
||||
- More intelligent task suggestion algorithms
|
||||
|
||||
The add-task system now provides truly relevant task context based on semantic understanding rather than arbitrary categories and limits, while maintaining a cleaner and more professional terminal experience.
|
||||
18
.changeset/free-pants-rescue.md
Normal file
18
.changeset/free-pants-rescue.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Enhance update-task with --append flag for timestamped task updates
|
||||
|
||||
Adds the `--append` flag to `update-task` command, enabling it to behave like `update-subtask` with timestamped information appending. This provides more flexible task updating options:
|
||||
|
||||
**CLI Enhancement:**
|
||||
- `task-master update-task --id=5 --prompt="New info"` - Full task update (existing behavior)
|
||||
- `task-master update-task --id=5 --append --prompt="Progress update"` - Append timestamped info to task details
|
||||
|
||||
**Full MCP Integration:**
|
||||
- MCP tool `update_task` now supports `append` parameter
|
||||
- Seamless integration with Cursor and other MCP clients
|
||||
- Consistent behavior between CLI and MCP interfaces
|
||||
|
||||
Instead of requiring separate subtask creation for progress tracking, you can now append timestamped information directly to parent tasks while preserving the option for comprehensive task updates.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
Add AWS bedrock support
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
# Add Google Vertex AI Provider Integration
|
||||
|
||||
- Implemented `VertexAIProvider` class extending BaseAIProvider
|
||||
- Added authentication and configuration handling for Vertex AI
|
||||
- Updated configuration manager with Vertex-specific getters
|
||||
- Modified AI services unified system to integrate the provider
|
||||
- Added documentation for Vertex AI setup and configuration
|
||||
- Updated environment variable examples for Vertex AI support
|
||||
- Implemented specialized error handling for Vertex-specific issues
|
||||
5
.changeset/large-wolves-strive.md
Normal file
5
.changeset/large-wolves-strive.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Update o3 model price
|
||||
11
.changeset/late-dryers-relax.md
Normal file
11
.changeset/late-dryers-relax.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add --tag flag support to core commands for multi-context task management. Commands like parse-prd, analyze-complexity, and others now support targeting specific task lists, enabling rapid prototyping and parallel development workflows.
|
||||
|
||||
Key features:
|
||||
- parse-prd --tag=feature-name: Parse PRDs into separate task contexts on the fly
|
||||
- analyze-complexity --tag=branch: Generate tag-specific complexity reports
|
||||
- All task operations can target specific contexts while preserving other lists
|
||||
- Non-existent tags are created automatically for seamless workflow
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
Add support for Azure
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
Add comprehensive `research` MCP tool for AI-powered research queries
|
||||
|
||||
- **New MCP Tool**: `research` tool enables AI-powered research with project context
|
||||
- **Context Integration**: Supports task IDs, file paths, custom context, and project tree
|
||||
- **Fuzzy Task Discovery**: Automatically finds relevant tasks using semantic search
|
||||
- **Token Management**: Detailed token counting and breakdown by context type
|
||||
- **Multiple Detail Levels**: Support for low, medium, and high detail research responses
|
||||
- **Telemetry Integration**: Full cost tracking and usage analytics
|
||||
- **Direct Function**: `researchDirect` with comprehensive parameter validation
|
||||
- **Silent Mode**: Prevents console output interference with MCP JSON responses
|
||||
- **Error Handling**: Robust error handling with proper MCP response formatting
|
||||
|
||||
This completes subtasks 94.5 (Direct Function) and 94.6 (MCP Tool) for the research command implementation, providing a powerful research interface for integrated development environments like Cursor.
|
||||
8
.changeset/nasty-chefs-add.md
Normal file
8
.changeset/nasty-chefs-add.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fixes issue with expand CLI command "Complexity report not found"
|
||||
|
||||
- Closes #735
|
||||
- Closes #728
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Increased minimum required node version to > 18 (was > 14)
|
||||
7
.changeset/pink-houses-lay.md
Normal file
7
.changeset/pink-houses-lay.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix double .taskmaster directory paths in file resolution utilities
|
||||
|
||||
- Closes #636
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
Renamed baseUrl to baseURL
|
||||
5
.changeset/polite-areas-shave.md
Normal file
5
.changeset/polite-areas-shave.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Add one-click MCP server installation for Cursor
|
||||
11
.changeset/pre.json
Normal file
11
.changeset/pre.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"mode": "exit",
|
||||
"tag": "rc",
|
||||
"initialVersions": {
|
||||
"task-master-ai": "0.16.1"
|
||||
},
|
||||
"changesets": [
|
||||
"pink-houses-lay",
|
||||
"polite-areas-shave"
|
||||
]
|
||||
}
|
||||
5
.changeset/quick-flies-sniff.md
Normal file
5
.changeset/quick-flies-sniff.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Fix issue with generate command which was creating tasks in the legacy tasks location.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'task-master-ai': patch
|
||||
---
|
||||
|
||||
Fix max_tokens error when trying to use claude-sonnet-4 and claude-opus-4
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'task-master-ai': minor
|
||||
---
|
||||
|
||||
Add TASK_MASTER_PROJECT_ROOT env variable supported in mcp.json and .env for project root resolution
|
||||
|
||||
- Some users were having issues where the MCP wasn't able to detect the location of their project root, you can now set the `TASK_MASTER_PROJECT_ROOT` environment variable to the root of your project.
|
||||
136
.changeset/six-cups-see.md
Normal file
136
.changeset/six-cups-see.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Introduces Tagged Lists: AI Multi-Context Task Management System
|
||||
|
||||
This major release introduces Tagged Lists, a comprehensive system that transforms Task Master into a multi-context task management powerhouse. You can now organize tasks into completely isolated contexts, enabling parallel (agentic) development workflows, team collaboration, and project experimentation without conflicts.
|
||||
|
||||
**🏷️ Tagged Task Lists Architecture:**
|
||||
|
||||
The new tagged system fundamentally changes how tasks are organized:
|
||||
- **Legacy Format**: `{ "tasks": [...] }`
|
||||
- **New Tagged Format**: `{ "master": { "tasks": [...], "metadata": {...} }, "feature-xyz": { "tasks": [...], "metadata": {...} } }`
|
||||
- **Automatic Migration**: Existing projects seamlessly migrate to tagged format with zero user intervention
|
||||
- **State Management**: New `.taskmaster/state.json` tracks current tag, last switched time, and migration status
|
||||
- **Configuration Integration**: Enhanced `.taskmaster/config.json` with tag-specific settings and defaults
|
||||
|
||||
**🚀 Complete Tag Management Suite:**
|
||||
|
||||
**Core Tag Commands:**
|
||||
- `task-master tags [--show-metadata]` - List all tags with task counts, completion stats, and metadata
|
||||
- `task-master add-tag <name> [options]` - Create new tag contexts with optional task copying
|
||||
- `task-master delete-tag <name> [--yes]` - Delete tags with double confirmation protection
|
||||
- `task-master use-tag <name>` - Switch contexts and immediately see next available task
|
||||
- `task-master rename-tag <old> <new>` - Rename tags with automatic current tag reference updates
|
||||
- `task-master copy-tag <source> <target> [options]` - Duplicate tag contexts for experimentation
|
||||
|
||||
**🤖 Full MCP Integration for Tag Management:**
|
||||
|
||||
Task Master's multi-context capabilities are now fully exposed through the MCP server, enabling powerful agentic workflows:
|
||||
- **`list_tags`**: List all available tag contexts.
|
||||
- **`add_tag`**: Programmatically create new tags.
|
||||
- **`delete_tag`**: Remove tag contexts.
|
||||
- **`use_tag`**: Switch the agent's active task context.
|
||||
- **`rename_tag`**: Rename existing tags.
|
||||
- **`copy_tag`**: Duplicate entire task contexts for experimentation.
|
||||
|
||||
**Tag Creation Options:**
|
||||
- `--copy-from-current` - Copy tasks from currently active tag
|
||||
- `--copy-from=<tag>` - Copy tasks from specific tag
|
||||
- `--from-branch` - Creates a new tag usin active git branch name (for `add-tag` only)
|
||||
- `--description="<text>"` - Add custom tag descriptions
|
||||
- Empty tag creation for fresh contexts
|
||||
|
||||
**🎯 Universal --tag Flag Support:**
|
||||
|
||||
Every task operation now supports tag-specific execution:
|
||||
- `task-master list --tag=feature-branch` - View tasks in specific context
|
||||
- `task-master add-task --tag=experiment --prompt="..."` - Create tasks in specific tag
|
||||
- `task-master parse-prd document.txt --tag=v2-redesign` - Parse PRDs into dedicated contexts
|
||||
- `task-master analyze-complexity --tag=performance-work` - Generate tag-specific reports
|
||||
- `task-master set-status --tag=hotfix --id=5 --status=done` - Update tasks in specific contexts
|
||||
- `task-master expand --tag=research --id=3` - Break down tasks within tag contexts
|
||||
|
||||
**📊 Enhanced Workflow Features:**
|
||||
|
||||
**Smart Context Switching:**
|
||||
- `use-tag` command shows immediate next task after switching
|
||||
- Automatic tag creation when targeting non-existent tags
|
||||
- Current tag persistence across terminal sessions
|
||||
- Branch-tag mapping for future Git integration
|
||||
|
||||
**Intelligent File Management:**
|
||||
- Tag-specific complexity reports: `task-complexity-report_tagname.json`
|
||||
- Master tag uses default filenames: `task-complexity-report.json`
|
||||
- Automatic file isolation prevents cross-tag contamination
|
||||
|
||||
**Advanced Confirmation Logic:**
|
||||
- Commands only prompt when target tag has existing tasks
|
||||
- Empty tags allow immediate operations without confirmation
|
||||
- Smart append vs overwrite detection
|
||||
|
||||
**🔄 Seamless Migration & Compatibility:**
|
||||
|
||||
**Zero-Disruption Migration:**
|
||||
- Existing `tasks.json` files automatically migrate on first command
|
||||
- Master tag receives proper metadata (creation date, description)
|
||||
- Migration notice shown once with helpful explanation
|
||||
- All existing commands work identically to before
|
||||
|
||||
**State Management:**
|
||||
- `.taskmaster/state.json` tracks current tag and migration status
|
||||
- Automatic state creation and maintenance
|
||||
- Branch-tag mapping foundation for Git integration
|
||||
- Migration notice tracking to avoid repeated notifications
|
||||
- Grounds for future context additions
|
||||
|
||||
**Backward Compatibility:**
|
||||
- All existing workflows continue unchanged
|
||||
- Legacy commands work exactly as before
|
||||
- Gradual adoption - users can ignore tags entirely if desired
|
||||
- No breaking changes to existing tasks or file formats
|
||||
|
||||
**💡 Real-World Use Cases:**
|
||||
|
||||
**Team Collaboration:**
|
||||
- `task-master add-tag alice --copy-from-current` - Create teammate-specific contexts
|
||||
- `task-master add-tag bob --copy-from=master` - Onboard new team members
|
||||
- `task-master use-tag alice` - Switch to teammate's work context
|
||||
|
||||
**Feature Development:**
|
||||
- `task-master parse-prd feature-spec.txt --tag=user-auth` - Dedicated feature planning
|
||||
- `task-master add-tag experiment --copy-from=user-auth` - Safe experimentation
|
||||
- `task-master analyze-complexity --tag=user-auth` - Feature-specific analysis
|
||||
|
||||
**Release Management:**
|
||||
- `task-master add-tag v2.0 --description="Next major release"` - Version-specific planning
|
||||
- `task-master copy-tag master v2.1` - Release branch preparation
|
||||
- `task-master use-tag hotfix` - Emergency fix context
|
||||
|
||||
**Project Phases:**
|
||||
- `task-master add-tag research --description="Discovery phase"` - Research tasks
|
||||
- `task-master add-tag implementation --copy-from=research` - Development phase
|
||||
- `task-master add-tag testing --copy-from=implementation` - QA phase
|
||||
|
||||
**🛠️ Technical Implementation:**
|
||||
|
||||
**Data Structure:**
|
||||
- Tagged format with complete isolation between contexts
|
||||
- Rich metadata per tag (creation date, description, update tracking)
|
||||
- Automatic metadata enhancement for existing tags
|
||||
- Clean separation of tag data and internal state
|
||||
|
||||
**Performance Optimizations:**
|
||||
- Dynamic task counting without stored counters
|
||||
- Efficient tag resolution and caching
|
||||
- Minimal file I/O with smart data loading
|
||||
- Responsive table layouts adapting to terminal width
|
||||
|
||||
**Error Handling:**
|
||||
- Comprehensive validation for tag names (alphanumeric, hyphens, underscores)
|
||||
- Reserved name protection (master, main, default)
|
||||
- Graceful handling of missing tags and corrupted data
|
||||
- Detailed error messages with suggested corrections
|
||||
|
||||
This release establishes the foundation for advanced multi-context workflows while maintaining the simplicity and power that makes Task Master effective for individual developers.
|
||||
24
.changeset/slick-webs-lead.md
Normal file
24
.changeset/slick-webs-lead.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Research Save-to-File Feature & Critical MCP Tag Corruption Fix
|
||||
|
||||
**🔬 New Research Save-to-File Functionality:**
|
||||
|
||||
Added comprehensive save-to-file capability to the research command, enabling users to preserve research sessions for future reference and documentation.
|
||||
|
||||
**CLI Integration:**
|
||||
- New `--save-file` flag for `task-master research` command
|
||||
- Consistent with existing `--save` and `--save-to` flags for intuitive usage
|
||||
- Interactive "Save to file" option in follow-up questions menu
|
||||
|
||||
**MCP Integration:**
|
||||
- New `saveToFile` boolean parameter for the `research` MCP tool
|
||||
- Enables programmatic research saving for AI agents and integrated tools
|
||||
|
||||
**File Management:**
|
||||
- Automatically creates `.taskmaster/docs/research/` directory structure
|
||||
- Generates timestamped, slugified filenames (e.g., `2025-01-13_what-is-typescript.md`)
|
||||
- Comprehensive Markdown format with metadata headers including query, timestamp, and context sources
|
||||
- Clean conversation history formatting without duplicate information
|
||||
5
.changeset/slow-lies-make.md
Normal file
5
.changeset/slow-lies-make.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
No longer automatically creates individual task files as they are not used by the applicatoin. You can still generate them anytime using the `generate` command.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'task-master-ai': patch
|
||||
---
|
||||
|
||||
Fix add-task MCP command causing an error
|
||||
7
.changeset/tiny-ads-decide.md
Normal file
7
.changeset/tiny-ads-decide.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Adds support for filtering tasks by multiple statuses at once using comma-separated statuses.
|
||||
|
||||
Example: `cancelled,deferred`
|
||||
5
.changeset/two-lies-start.md
Normal file
5
.changeset/two-lies-start.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Improves dependency management when moving tasks by updating subtask dependencies that reference sibling subtasks by their old parent-based ID
|
||||
22
.changeset/vast-shrimps-happen.md
Normal file
22
.changeset/vast-shrimps-happen.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Add sync-readme command for a task export to GitHub README
|
||||
|
||||
Introduces a new `sync-readme` command that exports your task list to your project's README.md file.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Flexible filtering**: Supports `--status` filtering (e.g., pending, done) and `--with-subtasks` flag
|
||||
- **Smart content management**: Automatically replaces existing exports or appends to new READMEs
|
||||
- **Metadata display**: Shows export timestamp, subtask inclusion status, and filter settings
|
||||
|
||||
**Usage:**
|
||||
|
||||
- `task-master sync-readme` - Export tasks without subtasks
|
||||
- `task-master sync-readme --with-subtasks` - Include subtasks in export
|
||||
- `task-master sync-readme --status=pending` - Only export pending tasks
|
||||
- `task-master sync-readme --status=done --with-subtasks` - Export completed tasks with subtasks
|
||||
|
||||
Perfect for showcasing project progress on GitHub. Experimental. Open to feedback.
|
||||
5
.changeset/yellow-olives-admire.md
Normal file
5
.changeset/yellow-olives-admire.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Adds tag to CLI output so you know which tag you are performing operations on. Already supported in the MCP response.
|
||||
@@ -12,7 +12,8 @@
|
||||
"OPENROUTER_API_KEY": "OPENROUTER_API_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "MISTRAL_API_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "AZURE_OPENAI_API_KEY_HERE",
|
||||
"OLLAMA_API_KEY": "OLLAMA_API_KEY_HERE"
|
||||
"OLLAMA_API_KEY": "OLLAMA_API_KEY_HERE",
|
||||
"GITHUB_API_KEY": "GITHUB_API_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,19 +20,21 @@ alwaysApply: false
|
||||
- **[`task-manager.js`](mdc:scripts/modules/task-manager.js) & `task-manager/` directory: Task Data & Core Logic**
|
||||
- **Purpose**: Contains core functions for task data manipulation (CRUD), AI interactions, and related logic.
|
||||
- **Responsibilities**:
|
||||
- Reading/writing `tasks.json`.
|
||||
- Reading/writing `tasks.json` with tagged task lists support.
|
||||
- Implementing functions for task CRUD, parsing PRDs, expanding tasks, updating status, etc.
|
||||
- **Tagged Task Lists**: Handles task organization across multiple contexts (tags) like "master", branch names, or project phases.
|
||||
- **Tag Resolution**: Provides backward compatibility by resolving tagged format to legacy format transparently.
|
||||
- **Delegating AI interactions** to the `ai-services-unified.js` layer.
|
||||
- Accessing non-AI configuration via `config-manager.js` getters.
|
||||
- **Key Files**: Individual files within `scripts/modules/task-manager/` handle specific actions (e.g., `add-task.js`, `expand-task.js`).
|
||||
|
||||
- **[`dependency-manager.js`](mdc:scripts/modules/dependency-manager.js): Dependency Management**
|
||||
- **Purpose**: Manages task dependencies.
|
||||
- **Responsibilities**: Add/remove/validate/fix dependencies.
|
||||
- **Responsibilities**: Add/remove/validate/fix dependencies across tagged task contexts.
|
||||
|
||||
- **[`ui.js`](mdc:scripts/modules/ui.js): User Interface Components**
|
||||
- **Purpose**: Handles CLI output formatting (tables, colors, boxes, spinners).
|
||||
- **Responsibilities**: Displaying tasks, reports, progress, suggestions.
|
||||
- **Responsibilities**: Displaying tasks, reports, progress, suggestions, and migration notices for tagged systems.
|
||||
|
||||
- **[`ai-services-unified.js`](mdc:scripts/modules/ai-services-unified.js): Unified AI Service Layer**
|
||||
- **Purpose**: Centralized interface for all LLM interactions using Vercel AI SDK.
|
||||
@@ -53,6 +55,7 @@ alwaysApply: false
|
||||
- **Responsibilities** (See also: [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)):
|
||||
- Reads and merges `.taskmasterconfig` with defaults.
|
||||
- Provides getters (e.g., `getMainProvider`, `getLogLevel`, `getDefaultSubtasks`) for accessing settings.
|
||||
- **Tag Configuration**: Manages `global.defaultTag` and `tags` section for tag system settings.
|
||||
- **Note**: Does **not** store or directly handle API keys (keys are in `.env` or MCP `session.env`).
|
||||
|
||||
- **[`utils.js`](mdc:scripts/modules/utils.js): Core Utility Functions**
|
||||
@@ -62,6 +65,8 @@ alwaysApply: false
|
||||
- Task utils (`findTaskById`), Dependency utils (`findCycles`).
|
||||
- API Key Resolution (`resolveEnvVariable`).
|
||||
- Silent Mode Control (`enableSilentMode`, `disableSilentMode`).
|
||||
- **Tagged Task Lists**: Silent migration system, tag resolution, current tag management.
|
||||
- **Migration System**: `performCompleteTagMigration`, `migrateConfigJson`, `createStateJson`.
|
||||
|
||||
- **[`mcp-server/`](mdc:mcp-server/): MCP Server Integration**
|
||||
- **Purpose**: Provides MCP interface using FastMCP.
|
||||
@@ -71,16 +76,42 @@ alwaysApply: false
|
||||
- Tool `execute` methods call **direct function wrappers** (`mcp-server/src/core/direct-functions/*.js`), passing the normalized `projectRoot` and other args.
|
||||
- Direct functions use path utilities (`mcp-server/src/core/utils/`) to resolve paths based on `projectRoot` from session.
|
||||
- Direct functions implement silent mode, logger wrappers, and call core logic functions from `scripts/modules/`.
|
||||
- **Tagged Task Lists**: MCP tools fully support the tagged format with complete tag management capabilities.
|
||||
- Manages MCP caching and response formatting.
|
||||
|
||||
- **[`init.js`](mdc:scripts/init.js): Project Initialization Logic**
|
||||
- **Purpose**: Sets up new Task Master project structure.
|
||||
- **Responsibilities**: Creates directories, copies templates, manages `package.json`, sets up `.cursor/mcp.json`.
|
||||
- **Responsibilities**: Creates directories, copies templates, manages `package.json`, sets up `.cursor/mcp.json`, initializes state.json for tagged system.
|
||||
|
||||
## Tagged Task Lists System Architecture
|
||||
|
||||
**Data Structure**: Task Master now uses a tagged task lists system where the `tasks.json` file contains multiple named task lists as top-level keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"master": {
|
||||
"tasks": [/* standard task objects */]
|
||||
},
|
||||
"feature-branch": {
|
||||
"tasks": [/* separate task context */]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Components:**
|
||||
|
||||
- **Silent Migration**: Automatically transforms legacy `{"tasks": [...]}` format to tagged format `{"master": {"tasks": [...]}}` on first read
|
||||
- **Tag Resolution Layer**: Provides 100% backward compatibility by intercepting tagged format and returning legacy format to existing code
|
||||
- **Configuration Integration**: `global.defaultTag` and `tags` section in config.json manage tag system settings
|
||||
- **State Management**: `.taskmaster/state.json` tracks current tag, migration status, and tag-branch mappings
|
||||
- **Migration Notice**: User-friendly notification system for seamless migration experience
|
||||
|
||||
**Backward Compatibility**: All existing CLI commands and MCP tools continue to work unchanged. The tag resolution layer ensures that existing code receives the expected legacy format while the underlying storage uses the new tagged structure.
|
||||
|
||||
- **Data Flow and Module Dependencies (Updated)**:
|
||||
|
||||
- **CLI**: `bin/task-master.js` -> `scripts/dev.js` (loads `.env`) -> `scripts/modules/commands.js` -> Core Logic (`scripts/modules/*`) -> Unified AI Service (`ai-services-unified.js`) -> Provider Adapters -> LLM API.
|
||||
- **MCP**: External Tool -> `mcp-server/server.js` -> Tool (`mcp-server/src/tools/*`) -> Direct Function (`mcp-server/src/core/direct-functions/*`) -> Core Logic (`scripts/modules/*`) -> Unified AI Service (`ai-services-unified.js`) -> Provider Adapters -> LLM API.
|
||||
- **CLI**: `bin/task-master.js` -> `scripts/dev.js` (loads `.env`) -> `scripts/modules/commands.js` -> Core Logic (`scripts/modules/*`) -> **Tag Resolution Layer** -> Unified AI Service (`ai-services-unified.js`) -> Provider Adapters -> LLM API.
|
||||
- **MCP**: External Tool -> `mcp-server/server.js` -> Tool (`mcp-server/src/tools/*`) -> Direct Function (`mcp-server/src/core/direct-functions/*`) -> Core Logic (`scripts/modules/*`) -> **Tag Resolution Layer** -> Unified AI Service (`ai-services-unified.js`) -> Provider Adapters -> LLM API.
|
||||
- **Configuration**: Core logic needing non-AI settings calls `config-manager.js` getters (passing `session.env` via `explicitRoot` if from MCP). Unified AI Service internally calls `config-manager.js` getters (using `role`) for AI params and `utils.js` (`resolveEnvVariable` with `session.env`) for API keys.
|
||||
|
||||
## Silent Mode Implementation Pattern in MCP Direct Functions
|
||||
@@ -197,6 +228,7 @@ By following these patterns consistently, direct functions will properly manage
|
||||
- **Integration Tests**: Located in `tests/integration/`, test interactions between modules
|
||||
- **End-to-End Tests**: Located in `tests/e2e/`, test complete workflows from a user perspective
|
||||
- **Test Fixtures**: Located in `tests/fixtures/`, provide reusable test data
|
||||
- **Tagged System Tests**: Test migration, tag resolution, and multi-context functionality
|
||||
|
||||
- **Module Design for Testability**:
|
||||
- **Explicit Dependencies**: Functions accept their dependencies as parameters rather than using globals
|
||||
@@ -205,12 +237,14 @@ By following these patterns consistently, direct functions will properly manage
|
||||
- **Clear Module Interfaces**: Each module has well-defined exports that can be mocked in tests
|
||||
- **Callback Isolation**: Callbacks are defined as separate functions for easier testing
|
||||
- **Stateless Design**: Modules avoid maintaining internal state where possible
|
||||
- **Tag Resolution Testing**: Test both tagged and legacy format handling
|
||||
|
||||
- **Mock Integration Patterns**:
|
||||
- **External Libraries**: Libraries like `fs`, `commander`, and `@anthropic-ai/sdk` are mocked at module level
|
||||
- **Internal Modules**: Application modules are mocked with appropriate spy functions
|
||||
- **Testing Function Callbacks**: Callbacks are extracted from mock call arguments and tested in isolation
|
||||
- **UI Elements**: Output functions from `ui.js` are mocked to verify display calls
|
||||
- **Tagged Data Mocking**: Test both legacy and tagged task data structures
|
||||
|
||||
- **Testing Flow**:
|
||||
- Module dependencies are mocked (following Jest's hoisting behavior)
|
||||
@@ -218,6 +252,7 @@ By following these patterns consistently, direct functions will properly manage
|
||||
- Spy functions are set up on module methods
|
||||
- Tests call the functions under test and verify behavior
|
||||
- Mocks are reset between test cases to maintain isolation
|
||||
- Tagged system behavior is tested for both migration and normal operation
|
||||
|
||||
- **Benefits of this Architecture**:
|
||||
|
||||
@@ -226,8 +261,11 @@ By following these patterns consistently, direct functions will properly manage
|
||||
- **Mocking Support**: The clear dependency boundaries make mocking straightforward
|
||||
- **Test Isolation**: Each component can be tested without affecting others
|
||||
- **Callback Testing**: Function callbacks can be extracted and tested independently
|
||||
- **Multi-Context Testing**: Tagged system enables testing different task contexts independently
|
||||
- **Reusability**: Utility functions and UI components can be reused across different parts of the application.
|
||||
- **Scalability**: New features can be added as new modules or by extending existing ones without significantly impacting other parts of the application.
|
||||
- **Multi-Context Support**: Tagged task lists enable working across different contexts (branches, environments, phases) without conflicts.
|
||||
- **Backward Compatibility**: Seamless migration and tag resolution ensure existing workflows continue unchanged.
|
||||
- **Clarity**: The modular structure provides a clear separation of concerns, making the codebase easier to navigate and understand for developers.
|
||||
|
||||
This architectural overview should help AI models understand the structure and organization of the Task Master CLI codebase, enabling them to more effectively assist with code generation, modification, and understanding.
|
||||
@@ -249,6 +287,7 @@ Follow these steps to add MCP support for an existing Task Master command (see [
|
||||
- Call core logic.
|
||||
- Return `{ success: true/false, data/error, fromCache: boolean }`.
|
||||
- Export the wrapper function.
|
||||
- **Note**: Tag-aware MCP tools are fully implemented with complete tag management support.
|
||||
|
||||
3. **Update `task-master-core.js` with Import/Export**: Add imports/exports for the new `*Direct` function.
|
||||
|
||||
@@ -275,12 +314,8 @@ The `initialize_project` command provides a way to set up a new Task Master proj
|
||||
- **MCP Tool**: `initialize_project`
|
||||
- **Functionality**:
|
||||
- Creates necessary directories and files for a new project
|
||||
- Sets up `tasks.json` and initial task files
|
||||
- Configures project metadata (name, description, version)
|
||||
- Handles shell alias creation if requested
|
||||
- Works in both interactive and non-interactive modes
|
||||
- Creates necessary directories and files for a new project
|
||||
- Sets up `tasks.json` and initial task files
|
||||
- Sets up `tasks.json` with tagged structure and initial task files
|
||||
- Configures project metadata (name, description, version)
|
||||
- Initializes state.json for tag system
|
||||
- Handles shell alias creation if requested
|
||||
- Works in both interactive and non-interactive modes
|
||||
@@ -18,6 +18,7 @@ Task Master offers two primary ways to interact:
|
||||
- Refer to [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) for details on the MCP architecture and available tools.
|
||||
- A comprehensive list and description of MCP tools and their corresponding CLI commands can be found in [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc).
|
||||
- **Restart the MCP server** if core logic in `scripts/modules` or MCP tool/direct function definitions change.
|
||||
- **Note**: MCP tools fully support tagged task lists with complete tag management capabilities.
|
||||
|
||||
2. **`task-master` CLI (For Users & Fallback)**:
|
||||
- The global `task-master` command provides a user-friendly interface for direct terminal interaction.
|
||||
@@ -25,10 +26,43 @@ Task Master offers two primary ways to interact:
|
||||
- Install globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`.
|
||||
- The CLI commands often mirror the MCP tools (e.g., `task-master list` corresponds to `get_tasks`).
|
||||
- Refer to [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc) for a detailed command reference.
|
||||
- **Tagged Task Lists**: CLI fully supports the new tagged system with seamless migration.
|
||||
|
||||
## Tagged Task Lists System
|
||||
|
||||
Task Master now supports **tagged task lists** for multi-context task management:
|
||||
|
||||
- **Data Structure**: Tasks are organized into separate contexts (tags) like "master", "feature-branch", or "v2.0"
|
||||
- **Seamless Migration**: Existing projects automatically migrate to use a "master" tag with zero disruption
|
||||
- **Backward Compatibility**: All existing commands continue to work exactly as before
|
||||
- **Context Isolation**: Tasks in different tags are completely separate and isolated
|
||||
- **Silent Migration**: The first time you run any Task Master command, your existing tasks.json will be automatically migrated to the new tagged format
|
||||
- **Migration Notice**: You'll see a friendly FYI notice after migration explaining the new system
|
||||
|
||||
**Migration Example**:
|
||||
```json
|
||||
// Before (legacy format)
|
||||
{
|
||||
"tasks": [
|
||||
{ "id": 1, "title": "Setup API", ... }
|
||||
]
|
||||
}
|
||||
|
||||
// After (tagged format - automatic)
|
||||
{
|
||||
"master": {
|
||||
"tasks": [
|
||||
{ "id": 1, "title": "Setup API", ... }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Tag Management**: CLI commands for tag management (`add-tag`, `use-tag`, `list-tags`, `delete-tag`, `rename-tag`, `copy-tag`) are now available with manual git integration via `--from-branch` option.
|
||||
|
||||
## Standard Development Workflow Process
|
||||
|
||||
- Start new projects by running `initialize_project` tool / `task-master init` or `parse_prd` / `task-master parse-prd --input='<prd-file.txt>'` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to generate initial tasks.json
|
||||
- Start new projects by running `initialize_project` tool / `task-master init` or `parse_prd` / `task-master parse-prd --input='<prd-file.txt>'` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to generate initial tasks.json with tagged structure
|
||||
- Begin coding sessions with `get_tasks` / `task-master list` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to see current tasks, status, and IDs
|
||||
- Determine the next task to work on using `next_task` / `task-master next` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)).
|
||||
- Analyze task complexity with `analyze_project_complexity` / `task-master analyze-complexity --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) before breaking down tasks
|
||||
@@ -104,12 +138,13 @@ Task Master offers two primary ways to interact:
|
||||
|
||||
Taskmaster configuration is managed through two main mechanisms:
|
||||
|
||||
1. **`.taskmasterconfig` File (Primary):**
|
||||
1. **`.taskmaster/config.json` File (Primary):**
|
||||
* Located in the project root directory.
|
||||
* Stores most configuration settings: AI model selections (main, research, fallback), parameters (max tokens, temperature), logging level, default subtasks/priority, project name, etc.
|
||||
* **Tagged System Settings**: Includes `global.defaultTag` (defaults to "master") and `tags` section for tag management configuration.
|
||||
* **Managed via `task-master models --setup` command.** Do not edit manually unless you know what you are doing.
|
||||
* **View/Set specific models via `task-master models` command or `models` MCP tool.**
|
||||
* Created automatically when you run `task-master models --setup` for the first time.
|
||||
* Created automatically when you run `task-master models --setup` for the first time or during tagged system migration.
|
||||
|
||||
2. **Environment Variables (`.env` / `mcp.json`):**
|
||||
* Used **only** for sensitive API keys and specific endpoint URLs.
|
||||
@@ -117,6 +152,11 @@ Taskmaster configuration is managed through two main mechanisms:
|
||||
* For MCP/Cursor integration, configure these keys in the `env` section of `.cursor/mcp.json`.
|
||||
* Available keys/variables: See `assets/env.example` or the Configuration section in the command reference (previously linked to `taskmaster.mdc`).
|
||||
|
||||
3. **`.taskmaster/state.json` File (Tagged System State):**
|
||||
* Tracks current tag context and migration status.
|
||||
* Automatically created during tagged system migration.
|
||||
* Contains: `currentTag`, `lastSwitched`, `migrationNoticeShown`.
|
||||
|
||||
**Important:** Non-API key settings (like model selections, `MAX_TOKENS`, `TASKMASTER_LOG_LEVEL`) are **no longer configured via environment variables**. Use the `task-master models` command (or `--setup` for interactive configuration) or the `models` MCP tool.
|
||||
**If AI commands FAIL in MCP** verify that the API key for the selected provider is present in the `env` section of `.cursor/mcp.json`.
|
||||
**If AI commands FAIL in CLI** verify that the API key for the selected provider is present in the `.env` file in the root of the project.
|
||||
|
||||
@@ -3,7 +3,6 @@ description: Git workflow integrated with Task Master for feature development an
|
||||
globs: "**/*"
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Git Workflow with Task Master Integration
|
||||
|
||||
## **Branch Strategy**
|
||||
@@ -27,6 +26,26 @@ fix-database-issue
|
||||
random-branch-name
|
||||
```
|
||||
|
||||
## **Tagged Task Lists Integration**
|
||||
|
||||
Task Master's **tagged task lists system** provides significant benefits for Git workflows:
|
||||
|
||||
### **Multi-Context Development**
|
||||
- **Branch-Specific Tasks**: Each branch can have its own task context using tags
|
||||
- **Merge Conflict Prevention**: Tasks in different tags are completely isolated
|
||||
- **Context Switching**: Seamlessly switch between different development contexts
|
||||
- **Parallel Development**: Multiple team members can work on separate task contexts
|
||||
|
||||
### **Migration and Compatibility**
|
||||
- **Seamless Migration**: Existing projects automatically migrate to use a "master" tag
|
||||
- **Zero Disruption**: All existing Git workflows continue unchanged
|
||||
- **Backward Compatibility**: Legacy projects work exactly as before
|
||||
|
||||
### **Manual Git Integration**
|
||||
- **Manual Tag Creation**: Use `--from-branch` option to create tags from current git branch
|
||||
- **Manual Context Switching**: Explicitly switch tag contexts as needed for different branches
|
||||
- **Simplified Integration**: Focused on manual control rather than automatic workflows
|
||||
|
||||
## **Workflow Overview**
|
||||
|
||||
```mermaid
|
||||
@@ -34,7 +53,7 @@ flowchart TD
|
||||
A[Start: On main branch] --> B[Pull latest changes]
|
||||
B --> C[Create task branch<br/>git checkout -b task-XXX]
|
||||
C --> D[Set task status: in-progress]
|
||||
D --> E[Get task context & expand if needed]
|
||||
D --> E[Get task context & expand if needed<br/>Tasks automatically use current tag]
|
||||
E --> F[Identify next subtask]
|
||||
|
||||
F --> G[Set subtask: in-progress]
|
||||
@@ -79,13 +98,13 @@ git branch # Verify you're on main
|
||||
# 3. Create task-specific branch
|
||||
git checkout -b task-004 # For Task 4
|
||||
|
||||
# 4. Set task status in Task Master
|
||||
# 4. Set task status in Task Master (tasks automatically use current tag context)
|
||||
# Use: set_task_status tool or `task-master set-status --id=4 --status=in-progress`
|
||||
```
|
||||
|
||||
### **Phase 2: Task Analysis & Planning**
|
||||
```bash
|
||||
# 5. Get task context and expand if needed
|
||||
# 5. Get task context and expand if needed (uses current tag automatically)
|
||||
# Use: get_task tool or `task-master show 4`
|
||||
# Use: expand_task tool or `task-master expand --id=4 --research --force` (if complex)
|
||||
|
||||
@@ -215,7 +234,7 @@ Task 4: Setup Express.js Server Project - Testing complete"
|
||||
|
||||
### **Essential Commands for Git Workflow**
|
||||
```bash
|
||||
# Task management
|
||||
# Task management (uses current tag context automatically)
|
||||
task-master show <id> # Get task/subtask details
|
||||
task-master next # Find next task to work on
|
||||
task-master set-status --id=<id> --status=<status>
|
||||
@@ -302,16 +321,17 @@ Mention any dependent tasks or follow-up work needed.
|
||||
|
||||
## **Conflict Resolution**
|
||||
|
||||
### **Task Conflicts**
|
||||
### **Task Conflicts with Tagged System**
|
||||
```bash
|
||||
# If multiple people work on overlapping tasks:
|
||||
# 1. Use Task Master's move functionality to reorganize
|
||||
task-master move --from=5 --to=25 # Move conflicting task
|
||||
# With tagged task lists, merge conflicts are significantly reduced:
|
||||
# 1. Different branches can use different tag contexts
|
||||
# 2. Tasks in separate tags are completely isolated
|
||||
# 3. Use Task Master's move functionality to reorganize if needed
|
||||
|
||||
# 2. Update task dependencies
|
||||
task-master add-dependency --id=6 --depends-on=5
|
||||
|
||||
# 3. Coordinate through PR comments and task updates
|
||||
# Manual git integration available:
|
||||
# - Use `task-master add-tag --from-branch` to create tags from current branch
|
||||
# - Manually switch contexts with `task-master use-tag <name>`
|
||||
# - Simple, predictable workflow without automatic behavior
|
||||
```
|
||||
|
||||
### **Code Conflicts**
|
||||
@@ -359,6 +379,23 @@ git push origin --delete task-<id>
|
||||
task-master update-task --id=<id> --prompt="Task cancelled due to..."
|
||||
```
|
||||
|
||||
## **Tagged System Benefits for Git Workflows**
|
||||
|
||||
### **Multi-Team Development**
|
||||
- **Isolated Contexts**: Different teams can work on separate tag contexts without conflicts
|
||||
- **Feature Branches**: Each feature branch can have its own task context
|
||||
- **Release Management**: Separate tags for different release versions or environments
|
||||
|
||||
### **Merge Conflict Prevention**
|
||||
- **Context Separation**: Tasks in different tags don't interfere with each other
|
||||
- **Clean Merges**: Reduced likelihood of task-related merge conflicts
|
||||
- **Parallel Development**: Multiple developers can work simultaneously without task conflicts
|
||||
|
||||
### **Manual Git Integration**
|
||||
- **Branch-Based Tag Creation**: Use `--from-branch` option to create tags from current git branch
|
||||
- **Manual Context Management**: Explicitly switch tag contexts as needed
|
||||
- **Predictable Workflow**: Simple, manual control without automatic behavior
|
||||
|
||||
---
|
||||
|
||||
**References:**
|
||||
|
||||
@@ -7,20 +7,20 @@ alwaysApply: true
|
||||
|
||||
This file provides a quick reference to the purpose of each rule file located in the `.cursor/rules` directory.
|
||||
|
||||
- **[`architecture.mdc`](mdc:.cursor/rules/architecture.mdc)**: Describes the high-level architecture of the Task Master CLI application.
|
||||
- **[`architecture.mdc`](mdc:.cursor/rules/architecture.mdc)**: Describes the high-level architecture of the Task Master CLI application, including the new tagged task lists system.
|
||||
- **[`changeset.mdc`](mdc:.cursor/rules/changeset.mdc)**: Guidelines for using Changesets (npm run changeset) to manage versioning and changelogs.
|
||||
- **[`commands.mdc`](mdc:.cursor/rules/commands.mdc)**: Guidelines for implementing CLI commands using Commander.js.
|
||||
- **[`cursor_rules.mdc`](mdc:.cursor/rules/cursor_rules.mdc)**: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness.
|
||||
- **[`dependencies.mdc`](mdc:.cursor/rules/dependencies.mdc)**: Guidelines for managing task dependencies and relationships.
|
||||
- **[`dev_workflow.mdc`](mdc:.cursor/rules/dev_workflow.mdc)**: Guide for using Task Master to manage task-driven development workflows.
|
||||
- **[`dependencies.mdc`](mdc:.cursor/rules/dependencies.mdc)**: Guidelines for managing task dependencies and relationships across tagged task contexts.
|
||||
- **[`dev_workflow.mdc`](mdc:.cursor/rules/dev_workflow.mdc)**: Guide for using Task Master to manage task-driven development workflows with tagged task lists support.
|
||||
- **[`glossary.mdc`](mdc:.cursor/rules/glossary.mdc)**: This file; provides a glossary of other Cursor rules.
|
||||
- **[`mcp.mdc`](mdc:.cursor/rules/mcp.mdc)**: Guidelines for implementing and interacting with the Task Master MCP Server.
|
||||
- **[`new_features.mdc`](mdc:.cursor/rules/new_features.mdc)**: Guidelines for integrating new features into the Task Master CLI.
|
||||
- **[`new_features.mdc`](mdc:.cursor/rules/new_features.mdc)**: Guidelines for integrating new features into the Task Master CLI with tagged system considerations.
|
||||
- **[`self_improve.mdc`](mdc:.cursor/rules/self_improve.mdc)**: Guidelines for continuously improving Cursor rules based on emerging code patterns and best practices.
|
||||
- **[`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)**: Comprehensive reference for Taskmaster MCP tools and CLI commands.
|
||||
- **[`tasks.mdc`](mdc:.cursor/rules/tasks.mdc)**: Guidelines for implementing task management operations.
|
||||
- **[`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)**: Comprehensive reference for Taskmaster MCP tools and CLI commands with tagged task lists information.
|
||||
- **[`tasks.mdc`](mdc:.cursor/rules/tasks.mdc)**: Guidelines for implementing task management operations with tagged task lists system support.
|
||||
- **[`tests.mdc`](mdc:.cursor/rules/tests.mdc)**: Guidelines for implementing and maintaining tests for Task Master CLI.
|
||||
- **[`ui.mdc`](mdc:.cursor/rules/ui.mdc)**: Guidelines for implementing and maintaining user interface components.
|
||||
- **[`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)**: Guidelines for implementing utility functions.
|
||||
- **[`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)**: Guidelines for implementing utility functions including tagged task lists utilities.
|
||||
- **[`telemetry.mdc`](mdc:.cursor/rules/telemetry.mdc)**: Guidelines for integrating AI usage telemetry across Task Master.
|
||||
|
||||
|
||||
@@ -634,3 +634,287 @@ When implementing project initialization commands:
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Feature Planning
|
||||
|
||||
- **Core Logic First**:
|
||||
- ✅ DO: Implement core logic in `scripts/modules/` before CLI or MCP interfaces
|
||||
- ✅ DO: Consider tagged task lists system compatibility from the start
|
||||
- ✅ DO: Design functions to work with both legacy and tagged data formats
|
||||
- ✅ DO: Use tag resolution functions (`getTasksForTag`, `setTasksForTag`) for task data access
|
||||
- ❌ DON'T: Directly manipulate tagged data structure in new features
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Design tagged-aware core functions
|
||||
async function newFeatureCore(tasksPath, featureParams, options = {}) {
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
// Perform feature logic on tasks array
|
||||
const result = performFeatureLogic(tasks, featureParams);
|
||||
|
||||
// Save back using tag resolution
|
||||
setTasksForTag(tasksData, currentTag, tasks);
|
||||
writeJSON(tasksPath, tasksData);
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
- **Backward Compatibility**:
|
||||
- ✅ DO: Ensure new features work with existing projects seamlessly
|
||||
- ✅ DO: Test with both legacy and tagged task data formats
|
||||
- ✅ DO: Support silent migration during feature usage
|
||||
- ❌ DON'T: Break existing workflows when adding tagged system features
|
||||
|
||||
## CLI Command Implementation
|
||||
|
||||
- **Command Structure**:
|
||||
- ✅ DO: Follow the established pattern in [`commands.js`](mdc:scripts/modules/commands.js)
|
||||
- ✅ DO: Use Commander.js for argument parsing
|
||||
- ✅ DO: Include comprehensive help text and examples
|
||||
- ✅ DO: Support tagged task context awareness
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement CLI commands with tagged system awareness
|
||||
program
|
||||
.command('new-feature')
|
||||
.description('Description of the new feature with tagged task lists support')
|
||||
.option('-t, --tag <tag>', 'Specify tag context (defaults to current tag)')
|
||||
.option('-p, --param <value>', 'Feature-specific parameter')
|
||||
.option('--force', 'Force operation without confirmation')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const projectRoot = findProjectRoot();
|
||||
if (!projectRoot) {
|
||||
console.error('Not in a Task Master project directory');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Use specified tag or current tag
|
||||
const targetTag = options.tag || getCurrentTag() || 'master';
|
||||
|
||||
const result = await newFeatureCore(
|
||||
path.join(projectRoot, '.taskmaster', 'tasks', 'tasks.json'),
|
||||
{ param: options.param },
|
||||
{
|
||||
force: options.force,
|
||||
targetTag: targetTag,
|
||||
outputFormat: 'text'
|
||||
}
|
||||
);
|
||||
|
||||
console.log('Feature executed successfully');
|
||||
} catch (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
- **Error Handling**:
|
||||
- ✅ DO: Provide clear error messages for common failures
|
||||
- ✅ DO: Handle tagged system migration errors gracefully
|
||||
- ✅ DO: Include suggestion for resolution when possible
|
||||
- ✅ DO: Exit with appropriate codes for scripting
|
||||
|
||||
## MCP Tool Implementation
|
||||
|
||||
- **Direct Function Pattern**:
|
||||
- ✅ DO: Create direct function wrappers in `mcp-server/src/core/direct-functions/`
|
||||
- ✅ DO: Follow silent mode patterns to prevent console output interference
|
||||
- ✅ DO: Use `findTasksJsonPath` for consistent path resolution
|
||||
- ✅ DO: Ensure tagged system compatibility
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement MCP direct functions with tagged awareness
|
||||
export async function newFeatureDirect(args, log, context = {}) {
|
||||
try {
|
||||
const tasksPath = findTasksJsonPath(args, log);
|
||||
|
||||
// Enable silent mode for clean MCP responses
|
||||
enableSilentMode();
|
||||
|
||||
try {
|
||||
const result = await newFeatureCore(
|
||||
tasksPath,
|
||||
{ param: args.param },
|
||||
{
|
||||
force: args.force,
|
||||
targetTag: args.tag || 'master', // Support tag specification
|
||||
mcpLog: log,
|
||||
session: context.session,
|
||||
outputFormat: 'json'
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: result,
|
||||
fromCache: false
|
||||
};
|
||||
} finally {
|
||||
disableSilentMode();
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Error in newFeatureDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'FEATURE_ERROR', message: error.message },
|
||||
fromCache: false
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Tool Registration**:
|
||||
- ✅ DO: Create tool definitions in `mcp-server/src/tools/`
|
||||
- ✅ DO: Use Zod for parameter validation
|
||||
- ✅ DO: Include optional tag parameter for multi-context support
|
||||
- ✅ DO: Follow established naming conventions
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Register MCP tools with tagged system support
|
||||
export function registerNewFeatureTool(server) {
|
||||
server.addTool({
|
||||
name: "new_feature",
|
||||
description: "Description of the new feature with tagged task lists support",
|
||||
inputSchema: z.object({
|
||||
param: z.string().describe("Feature-specific parameter"),
|
||||
tag: z.string().optional().describe("Target tag context (defaults to current tag)"),
|
||||
force: z.boolean().optional().describe("Force operation without confirmation"),
|
||||
projectRoot: z.string().optional().describe("Project root directory")
|
||||
}),
|
||||
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
|
||||
try {
|
||||
const result = await newFeatureDirect(
|
||||
{ ...args, projectRoot: args.projectRoot },
|
||||
log,
|
||||
{ session }
|
||||
);
|
||||
return handleApiResult(result, log);
|
||||
} catch (error) {
|
||||
return handleApiResult({
|
||||
success: false,
|
||||
error: { code: 'EXECUTION_ERROR', message: error.message }
|
||||
}, log);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
- **Unit Tests**:
|
||||
- ✅ DO: Test core logic independently with both data formats
|
||||
- ✅ DO: Mock file system operations appropriately
|
||||
- ✅ DO: Test tag resolution behavior
|
||||
- ✅ DO: Verify migration compatibility
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Test new features with tagged system awareness
|
||||
describe('newFeature', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should work with legacy task format', async () => {
|
||||
const legacyData = { tasks: [/* test data */] };
|
||||
fs.readFileSync.mockReturnValue(JSON.stringify(legacyData));
|
||||
|
||||
const result = await newFeatureCore('/test/tasks.json', { param: 'test' });
|
||||
|
||||
expect(result).toBeDefined();
|
||||
// Test legacy format handling
|
||||
});
|
||||
|
||||
it('should work with tagged task format', async () => {
|
||||
const taggedData = {
|
||||
master: { tasks: [/* test data */] },
|
||||
feature: { tasks: [/* test data */] }
|
||||
};
|
||||
fs.readFileSync.mockReturnValue(JSON.stringify(taggedData));
|
||||
|
||||
const result = await newFeatureCore('/test/tasks.json', { param: 'test' });
|
||||
|
||||
expect(result).toBeDefined();
|
||||
// Test tagged format handling
|
||||
});
|
||||
|
||||
it('should handle tag migration during feature usage', async () => {
|
||||
const legacyData = { tasks: [/* test data */] };
|
||||
fs.readFileSync.mockReturnValue(JSON.stringify(legacyData));
|
||||
|
||||
await newFeatureCore('/test/tasks.json', { param: 'test' });
|
||||
|
||||
// Verify migration occurred
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(
|
||||
'/test/tasks.json',
|
||||
expect.stringContaining('"master"')
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- **Integration Tests**:
|
||||
- ✅ DO: Test CLI and MCP interfaces with real task data
|
||||
- ✅ DO: Verify end-to-end workflows across tag contexts
|
||||
- ✅ DO: Test error scenarios and recovery
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
- **Rule Updates**:
|
||||
- ✅ DO: Update relevant `.cursor/rules/*.mdc` files
|
||||
- ✅ DO: Include tagged system considerations in architecture docs
|
||||
- ✅ DO: Add examples showing multi-context usage
|
||||
- ✅ DO: Update workflow documentation as needed
|
||||
|
||||
- **User Documentation**:
|
||||
- ✅ DO: Add feature documentation to `/docs` folder
|
||||
- ✅ DO: Include tagged system usage examples
|
||||
- ✅ DO: Update command reference documentation
|
||||
- ✅ DO: Provide migration notes if relevant
|
||||
|
||||
## Migration Considerations
|
||||
|
||||
- **Silent Migration Support**:
|
||||
- ✅ DO: Ensure new features trigger migration when needed
|
||||
- ✅ DO: Handle migration errors gracefully in feature code
|
||||
- ✅ DO: Test feature behavior with pre-migration projects
|
||||
- ❌ DON'T: Assume projects are already migrated
|
||||
|
||||
- **Tag Context Handling**:
|
||||
- ✅ DO: Default to current tag when not specified
|
||||
- ✅ DO: Support explicit tag selection in advanced features
|
||||
- ✅ DO: Validate tag existence before operations
|
||||
- ✅ DO: Provide clear messaging about tag context
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- **Efficient Tag Operations**:
|
||||
- ✅ DO: Minimize file I/O operations per feature execution
|
||||
- ✅ DO: Cache tag resolution results when appropriate
|
||||
- ✅ DO: Use streaming for large task datasets
|
||||
- ❌ DON'T: Load all tags when only one is needed
|
||||
|
||||
- **Memory Management**:
|
||||
- ✅ DO: Process large task lists efficiently
|
||||
- ✅ DO: Clean up temporary data structures
|
||||
- ✅ DO: Avoid keeping all tag data in memory simultaneously
|
||||
|
||||
## Deployment and Versioning
|
||||
|
||||
- **Changesets**:
|
||||
- ✅ DO: Create appropriate changesets for new features
|
||||
- ✅ DO: Use semantic versioning (minor for new features)
|
||||
- ✅ DO: Include tagged system information in release notes
|
||||
- ✅ DO: Document breaking changes if any
|
||||
|
||||
- **Feature Flags**:
|
||||
- ✅ DO: Consider feature flags for experimental functionality
|
||||
- ✅ DO: Ensure tagged system features work with flags
|
||||
- ✅ DO: Provide clear documentation about flag usage
|
||||
|
||||
By following these guidelines, new features will integrate smoothly with the Task Master ecosystem while supporting the enhanced tagged task lists system for multi-context development workflows.
|
||||
|
||||
229
.cursor/rules/tags.mdc
Normal file
229
.cursor/rules/tags.mdc
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
description:
|
||||
globs: scripts/modules/*
|
||||
alwaysApply: false
|
||||
---
|
||||
# Tagged Task Lists Command Patterns
|
||||
|
||||
This document outlines the standardized patterns that **ALL** Task Master commands must follow to properly support the tagged task lists system.
|
||||
|
||||
## Core Principles
|
||||
|
||||
- **Every command** that reads or writes tasks.json must be tag-aware
|
||||
- **Consistent tag resolution** across all commands using `getCurrentTag(projectRoot)`
|
||||
- **Proper context passing** to core functions with `{ projectRoot, tag }`
|
||||
- **Standardized CLI options** with `--tag <tag>` flag
|
||||
|
||||
## Required Imports
|
||||
|
||||
All command files must import `getCurrentTag`:
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Import getCurrentTag in commands.js
|
||||
import {
|
||||
log,
|
||||
readJSON,
|
||||
writeJSON,
|
||||
findProjectRoot,
|
||||
getCurrentTag
|
||||
} from './utils.js';
|
||||
|
||||
// ✅ DO: Import getCurrentTag in task-manager files
|
||||
import {
|
||||
readJSON,
|
||||
writeJSON,
|
||||
getCurrentTag
|
||||
} from '../utils.js';
|
||||
```
|
||||
|
||||
## CLI Command Pattern
|
||||
|
||||
Every CLI command that operates on tasks must follow this exact pattern:
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Standard tag-aware CLI command pattern
|
||||
programInstance
|
||||
.command('command-name')
|
||||
.description('Command description')
|
||||
.option('-f, --file <file>', 'Path to the tasks file', TASKMASTER_TASKS_FILE)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations') // REQUIRED
|
||||
.action(async (options) => {
|
||||
// 1. Find project root
|
||||
const projectRoot = findProjectRoot();
|
||||
if (!projectRoot) {
|
||||
console.error(chalk.red('Error: Could not find project root.'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 2. Resolve tag using standard pattern
|
||||
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||
|
||||
// 3. Call core function with proper context
|
||||
await coreFunction(
|
||||
tasksPath,
|
||||
// ... other parameters ...
|
||||
{ projectRoot, tag } // REQUIRED context object
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## Core Function Pattern
|
||||
|
||||
All core functions in `scripts/modules/task-manager/` must follow this pattern:
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Standard tag-aware core function pattern
|
||||
async function coreFunction(
|
||||
tasksPath,
|
||||
// ... other parameters ...
|
||||
context = {} // REQUIRED context parameter
|
||||
) {
|
||||
const { projectRoot, tag } = context;
|
||||
|
||||
// Use tag-aware readJSON/writeJSON
|
||||
const data = readJSON(tasksPath, projectRoot, tag);
|
||||
|
||||
// ... function logic ...
|
||||
|
||||
writeJSON(tasksPath, data, projectRoot, tag);
|
||||
}
|
||||
```
|
||||
|
||||
## Tag Resolution Priority
|
||||
|
||||
The tag resolution follows this exact priority order:
|
||||
|
||||
1. **Explicit `--tag` flag**: `options.tag`
|
||||
2. **Current active tag**: `getCurrentTag(projectRoot)`
|
||||
3. **Default fallback**: `'master'`
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Standard tag resolution pattern
|
||||
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||
```
|
||||
|
||||
## Commands Requiring Updates
|
||||
|
||||
### High Priority (Core Task Operations)
|
||||
- [x] `add-task` - ✅ Fixed
|
||||
- [x] `list` - ✅ Fixed
|
||||
- [x] `update-task` - ✅ Fixed
|
||||
- [x] `update-subtask` - ✅ Fixed
|
||||
- [x] `set-status` - ✅ Already correct
|
||||
- [x] `remove-task` - ✅ Already correct
|
||||
- [x] `remove-subtask` - ✅ Fixed
|
||||
- [x] `add-subtask` - ✅ Already correct
|
||||
- [x] `clear-subtasks` - ✅ Fixed
|
||||
- [x] `move-task` - ✅ Already correct
|
||||
|
||||
### Medium Priority (Analysis & Expansion)
|
||||
- [x] `expand` - ✅ Fixed
|
||||
- [ ] `next` - ✅ Fixed
|
||||
- [ ] `show` (get-task) - Needs checking
|
||||
- [ ] `analyze-complexity` - Needs checking
|
||||
- [ ] `generate` - ✅ Fixed
|
||||
|
||||
### Lower Priority (Utilities)
|
||||
- [ ] `research` - Needs checking
|
||||
- [ ] `complexity-report` - Needs checking
|
||||
- [ ] `validate-dependencies` - ✅ Fixed
|
||||
- [ ] `fix-dependencies` - ✅ Fixed
|
||||
- [ ] `add-dependency` - ✅ Fixed
|
||||
- [ ] `remove-dependency` - ✅ Fixed
|
||||
|
||||
## MCP Integration Pattern
|
||||
|
||||
MCP direct functions must also follow the tag-aware pattern:
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Tag-aware MCP direct function
|
||||
export async function coreActionDirect(args, log, context = {}) {
|
||||
const { session } = context;
|
||||
const { projectRoot, tag } = args; // MCP passes these in args
|
||||
|
||||
try {
|
||||
const result = await coreAction(
|
||||
tasksPath,
|
||||
// ... other parameters ...
|
||||
{ projectRoot, tag, session, mcpLog: logWrapper }
|
||||
);
|
||||
|
||||
return { success: true, data: result };
|
||||
} catch (error) {
|
||||
return { success: false, error: { code: 'ERROR_CODE', message: error.message } };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## File Generation Tag-Aware Naming
|
||||
|
||||
The `generate` command must use tag-aware file naming:
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Tag-aware file naming
|
||||
const taskFileName = targetTag === 'master'
|
||||
? `task_${task.id.toString().padStart(3, '0')}.txt`
|
||||
: `task_${task.id.toString().padStart(3, '0')}_${targetTag}.txt`;
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
- Master tag: `task_001.txt`, `task_002.txt`
|
||||
- Other tags: `task_001_feature.txt`, `task_002_feature.txt`
|
||||
|
||||
## Common Anti-Patterns
|
||||
|
||||
```javascript
|
||||
// ❌ DON'T: Missing getCurrentTag import
|
||||
import { readJSON, writeJSON } from '../utils.js'; // Missing getCurrentTag
|
||||
|
||||
// ❌ DON'T: Hard-coded tag resolution
|
||||
const tag = options.tag || 'master'; // Missing getCurrentTag
|
||||
|
||||
// ❌ DON'T: Missing --tag option
|
||||
.option('-f, --file <file>', 'Path to tasks file') // Missing --tag option
|
||||
|
||||
// ❌ DON'T: Missing context parameter
|
||||
await coreFunction(tasksPath, param1, param2); // Missing { projectRoot, tag }
|
||||
|
||||
// ❌ DON'T: Incorrect readJSON/writeJSON calls
|
||||
const data = readJSON(tasksPath); // Missing projectRoot and tag
|
||||
writeJSON(tasksPath, data); // Missing projectRoot and tag
|
||||
```
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
For each command, verify:
|
||||
|
||||
- [ ] Imports `getCurrentTag` from utils.js
|
||||
- [ ] Has `--tag <tag>` CLI option
|
||||
- [ ] Uses standard tag resolution: `options.tag || getCurrentTag(projectRoot) || 'master'`
|
||||
- [ ] Finds `projectRoot` with error handling
|
||||
- [ ] Passes `{ projectRoot, tag }` context to core functions
|
||||
- [ ] Core functions accept and use context parameter
|
||||
- [ ] Uses `readJSON(tasksPath, projectRoot, tag)` and `writeJSON(tasksPath, data, projectRoot, tag)`
|
||||
|
||||
## Testing Tag Resolution
|
||||
|
||||
Test each command with:
|
||||
|
||||
```bash
|
||||
# Test with explicit tag
|
||||
node bin/task-master command-name --tag test-tag
|
||||
|
||||
# Test with active tag (should use current active tag)
|
||||
node bin/task-master use-tag test-tag
|
||||
node bin/task-master command-name
|
||||
|
||||
# Test with master tag (default)
|
||||
node bin/task-master use-tag master
|
||||
node bin/task-master command-name
|
||||
```
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
1. **Audit Phase**: Systematically check each command against the checklist
|
||||
2. **Fix Phase**: Apply the standard patterns to non-compliant commands
|
||||
3. **Test Phase**: Verify tag resolution works correctly
|
||||
4. **Document Phase**: Update command documentation with tag support
|
||||
|
||||
This ensures consistent, predictable behavior across all Task Master commands and prevents tag deletion bugs.
|
||||
@@ -11,6 +11,8 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
|
||||
**Important:** Several MCP tools involve AI processing... The AI-powered tools include `parse_prd`, `analyze_project_complexity`, `update_subtask`, `update_task`, `update`, `expand_all`, `expand_task`, and `add_task`.
|
||||
|
||||
**🏷️ Tagged Task Lists System:** Task Master now supports **tagged task lists** for multi-context task management. This allows you to maintain separate, isolated lists of tasks for different features, branches, or experiments. Existing projects are seamlessly migrated to use a default "master" tag. Most commands now support a `--tag <name>` flag to specify which context to operate on. If omitted, commands use the currently active tag.
|
||||
|
||||
---
|
||||
|
||||
## Initialization & Setup
|
||||
@@ -36,7 +38,8 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* `addAliases`: `Add shell aliases tm and taskmaster. Default is false.` (CLI: `--aliases`)
|
||||
* `yes`: `Skip prompts and use defaults/provided arguments. Default is false.` (CLI: `-y, --yes`)
|
||||
* **Usage:** Run this once at the beginning of a new project, typically via an integrated tool like Cursor. Operates on the current working directory of the MCP server.
|
||||
* **Important:** Once complete, you *MUST* parse a prd in order to generate tasks. There will be no tasks files until then. The next step after initializing should be to create a PRD using the example PRD in scripts/example_prd.txt.
|
||||
* **Important:** Once complete, you *MUST* parse a prd in order to generate tasks. There will be no tasks files until then. The next step after initializing should be to create a PRD using the example PRD in .taskmaster/templates/example_prd.txt.
|
||||
* **Tagging:** Use the `--tag` option to parse the PRD into a specific, non-default tag context. If the tag doesn't exist, it will be created automatically. Example: `task-master parse-prd spec.txt --tag=new-feature`.
|
||||
|
||||
### 2. Parse PRD (`parse_prd`)
|
||||
|
||||
@@ -45,12 +48,14 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **Description:** `Parse a Product Requirements Document, PRD, or text file with Taskmaster to automatically generate an initial set of tasks in tasks.json.`
|
||||
* **Key Parameters/Options:**
|
||||
* `input`: `Path to your PRD or requirements text file that Taskmaster should parse for tasks.` (CLI: `[file]` positional or `-i, --input <file>`)
|
||||
* `output`: `Specify where Taskmaster should save the generated 'tasks.json' file. Defaults to 'tasks/tasks.json'.` (CLI: `-o, --output <file>`)
|
||||
* `output`: `Specify where Taskmaster should save the generated 'tasks.json' file. Defaults to '.taskmaster/tasks/tasks.json'.` (CLI: `-o, --output <file>`)
|
||||
* `output`: `Specify where Taskmaster should save the generated 'tasks.json' file. Defaults to '.taskmaster/tasks/tasks.json'.` (CLI: `-o, --output <file>`)
|
||||
* `numTasks`: `Approximate number of top-level tasks Taskmaster should aim to generate from the document.` (CLI: `-n, --num-tasks <number>`)
|
||||
* `force`: `Use this to allow Taskmaster to overwrite an existing 'tasks.json' without asking for confirmation.` (CLI: `-f, --force`)
|
||||
* **Usage:** Useful for bootstrapping a project from an existing requirements document.
|
||||
* **Notes:** Task Master will strictly adhere to any specific requirements mentioned in the PRD, such as libraries, database schemas, frameworks, tech stacks, etc., while filling in any gaps where the PRD isn't fully specified. Tasks are designed to provide the most direct implementation path while avoiding over-engineering.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress. If the user does not have a PRD, suggest discussing their idea and then use the example PRD in `scripts/example_prd.txt` as a template for creating the PRD based on their idea, for use with `parse-prd`.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress. If the user does not have a PRD, suggest discussing their idea and then use the example PRD in `.taskmaster/templates/example_prd.txt` as a template for creating the PRD based on their idea, for use with `parse-prd`.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress. If the user does not have a PRD, suggest discussing their idea and then use the example PRD in `.taskmaster/templates/example_prd.txt` as a template for creating the PRD based on their idea, for use with `parse-prd`.
|
||||
|
||||
---
|
||||
|
||||
@@ -77,10 +82,12 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* `--setup`: `Run interactive setup to configure models, including custom Ollama/OpenRouter IDs.`
|
||||
* **Usage (MCP):** Call without set flags to get current config. Use `setMain`, `setResearch`, or `setFallback` with a valid model ID to update the configuration. Use `listAvailableModels: true` to get a list of unassigned models. To set a custom model, provide the model ID and set `ollama: true` or `openrouter: true`.
|
||||
* **Usage (CLI):** Run without flags to view current configuration and available models. Use set flags to update specific roles. Use `--setup` for guided configuration, including custom models. To set a custom model via flags, use `--set-<role>=<model_id>` along with either `--ollama` or `--openrouter`.
|
||||
* **Notes:** Configuration is stored in `.taskmasterconfig` in the project root. This command/tool modifies that file. Use `listAvailableModels` or `task-master models` to see internally supported models. OpenRouter custom models are validated against their live API. Ollama custom models are not validated live.
|
||||
* **Notes:** Configuration is stored in `.taskmaster/config.json` in the project root. This command/tool modifies that file. Use `listAvailableModels` or `task-master models` to see internally supported models. OpenRouter custom models are validated against their live API. Ollama custom models are not validated live.
|
||||
* **Notes:** Configuration is stored in `.taskmaster/config.json` in the project root. This command/tool modifies that file. Use `listAvailableModels` or `task-master models` to see internally supported models. OpenRouter custom models are validated against their live API. Ollama custom models are not validated live.
|
||||
* **API note:** API keys for selected AI providers (based on their model) need to exist in the mcp.json file to be accessible in MCP context. The API keys must be present in the local .env file for the CLI to be able to read them.
|
||||
* **Model costs:** The costs in supported models are expressed in dollars. An input/output value of 3 is $3.00. A value of 0.8 is $0.80.
|
||||
* **Warning:** DO NOT MANUALLY EDIT THE .taskmasterconfig FILE. Use the included commands either in the MCP or CLI format as needed. Always prioritize MCP tools when available and use the CLI as a fallback.
|
||||
* **Warning:** DO NOT MANUALLY EDIT THE .taskmaster/config.json FILE. Use the included commands either in the MCP or CLI format as needed. Always prioritize MCP tools when available and use the CLI as a fallback.
|
||||
* **Warning:** DO NOT MANUALLY EDIT THE .taskmaster/config.json FILE. Use the included commands either in the MCP or CLI format as needed. Always prioritize MCP tools when available and use the CLI as a fallback.
|
||||
|
||||
---
|
||||
|
||||
@@ -92,8 +99,9 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **CLI Command:** `task-master list [options]`
|
||||
* **Description:** `List your Taskmaster tasks, optionally filtering by status and showing subtasks.`
|
||||
* **Key Parameters/Options:**
|
||||
* `status`: `Show only Taskmaster tasks matching this status, e.g., 'pending' or 'done'.` (CLI: `-s, --status <status>`)
|
||||
* `status`: `Show only Taskmaster tasks matching this status (or multiple statuses, comma-separated), e.g., 'pending' or 'done,in-progress'.` (CLI: `-s, --status <status>`)
|
||||
* `withSubtasks`: `Include subtasks indented under their parent tasks in the list.` (CLI: `--with-subtasks`)
|
||||
* `tag`: `Specify which tag context to list tasks from. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Get an overview of the project status, often used at the start of a work session.
|
||||
|
||||
@@ -110,11 +118,12 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
|
||||
* **MCP Tool:** `get_task`
|
||||
* **CLI Command:** `task-master show [id] [options]`
|
||||
* **Description:** `Display detailed information for a specific Taskmaster task or subtask by its ID.`
|
||||
* **Description:** `Display detailed information for one or more specific Taskmaster tasks or subtasks by ID.`
|
||||
* **Key Parameters/Options:**
|
||||
* `id`: `Required. The ID of the Taskmaster task, e.g., '15', or subtask, e.g., '15.2', you want to view.` (CLI: `[id]. Supports comma-separated list of tasks to get multiple tasks at once.` positional or `-i, --id <id>`)
|
||||
* `id`: `Required. The ID of the Taskmaster task (e.g., '15'), subtask (e.g., '15.2'), or a comma-separated list of IDs ('1,5,10.2') you want to view.` (CLI: `[id]` positional or `-i, --id <id>`)
|
||||
* `tag`: `Specify which tag context to get the task(s) from. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Understand the full details, implementation notes, and test strategy for a specific task before starting work.
|
||||
* **Usage:** Understand the full details for a specific task. When multiple IDs are provided, a summary table is shown.
|
||||
* **CRITICAL INFORMATION** If you need to collect information from multiple tasks, use comma-separated IDs (i.e. 1,2,3) to receive an array of tasks. Do not needlessly get tasks one at a time if you need to get many as that is wasteful.
|
||||
|
||||
---
|
||||
@@ -169,13 +178,15 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
|
||||
* **MCP Tool:** `update_task`
|
||||
* **CLI Command:** `task-master update-task [options]`
|
||||
* **Description:** `Modify a specific Taskmaster task or subtask by its ID, incorporating new information or changes.`
|
||||
* **Description:** `Modify a specific Taskmaster task by ID, incorporating new information or changes. By default, this replaces the existing task details.`
|
||||
* **Key Parameters/Options:**
|
||||
* `id`: `Required. The specific ID of the Taskmaster task, e.g., '15', or subtask, e.g., '15.2', you want to update.` (CLI: `-i, --id <id>`)
|
||||
* `id`: `Required. The specific ID of the Taskmaster task, e.g., '15', you want to update.` (CLI: `-i, --id <id>`)
|
||||
* `prompt`: `Required. Explain the specific changes or provide the new information Taskmaster should incorporate into this task.` (CLI: `-p, --prompt <text>`)
|
||||
* `append`: `If true, appends the prompt content to the task's details with a timestamp, rather than replacing them. Behaves like update-subtask.` (CLI: `--append`)
|
||||
* `research`: `Enable Taskmaster to use the research role for more informed updates. Requires appropriate API key.` (CLI: `-r, --research`)
|
||||
* `tag`: `Specify which tag context the task belongs to. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Refine a specific task based on new understanding or feedback. Example CLI: `task-master update-task --id='15' --prompt='Clarification: Use PostgreSQL instead of MySQL.\nUpdate schema details...'`
|
||||
* **Usage:** Refine a specific task based on new understanding. Use `--append` to log progress without creating subtasks.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress.
|
||||
|
||||
### 10. Update Subtask (`update_subtask`)
|
||||
@@ -184,12 +195,12 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **CLI Command:** `task-master update-subtask [options]`
|
||||
* **Description:** `Append timestamped notes or details to a specific Taskmaster subtask without overwriting existing content. Intended for iterative implementation logging.`
|
||||
* **Key Parameters/Options:**
|
||||
* `id`: `Required. The specific ID of the Taskmaster subtask, e.g., '15.2', you want to add information to.` (CLI: `-i, --id <id>`)
|
||||
* `prompt`: `Required. Provide the information or notes Taskmaster should append to the subtask's details. Ensure this adds *new* information not already present.` (CLI: `-p, --prompt <text>`)
|
||||
* `research`: `Enable Taskmaster to use the research role for more informed updates. Requires appropriate API key.` (CLI: `-r, --research`)
|
||||
* `id`: `Required. The ID of the Taskmaster task, e.g., '5', or subtask, e.g., '5.2', to permanently remove.` (CLI: `-i, --id <id>`)
|
||||
* `yes`: `Skip the confirmation prompt and immediately delete the task.` (CLI: `-y, --yes`)
|
||||
* `tag`: `Specify which tag context to remove the task from. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Add implementation notes, code snippets, or clarifications to a subtask during development. Before calling, review the subtask's current details to append only fresh insights, helping to build a detailed log of the implementation journey and avoid redundancy. Example CLI: `task-master update-subtask --id='15.2' --prompt='Discovered that the API requires header X.\nImplementation needs adjustment...'`
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress.
|
||||
* **Usage:** Permanently delete tasks or subtasks that are no longer needed in the project.
|
||||
* **Notes:** Use with caution as this operation cannot be undone. Consider using 'blocked', 'cancelled', or 'deferred' status instead if you just want to exclude a task from active planning but keep it for reference. The command automatically cleans up dependency references in other tasks.
|
||||
|
||||
### 11. Set Task Status (`set_task_status`)
|
||||
|
||||
@@ -229,6 +240,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* `research`: `Enable Taskmaster to use the research role for more informed subtask generation. Requires appropriate API key.` (CLI: `-r, --research`)
|
||||
* `prompt`: `Optional: Provide extra context or specific instructions to Taskmaster for generating the subtasks.` (CLI: `-p, --prompt <text>`)
|
||||
* `force`: `Optional: If true, clear existing subtasks before generating new ones. Default is false (append).` (CLI: `--force`)
|
||||
* `tag`: `Specify which tag context the task belongs to. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Generate a detailed implementation plan for a complex task before starting coding. Automatically uses complexity report recommendations if available and `num` is not specified.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress.
|
||||
@@ -243,6 +255,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* `research`: `Enable research role for more informed subtask generation. Requires appropriate API key.` (CLI: `-r, --research`)
|
||||
* `prompt`: `Optional: Provide extra context for Taskmaster to apply generally during expansion.` (CLI: `-p, --prompt <text>`)
|
||||
* `force`: `Optional: If true, clear existing subtasks before generating new ones for each eligible task. Default is false (append).` (CLI: `--force`)
|
||||
* `tag`: `Specify which tag context to expand. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Useful after initial task generation or complexity analysis to break down multiple tasks at once.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress.
|
||||
@@ -336,6 +349,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **CLI Command:** `task-master fix-dependencies [options]`
|
||||
* **Description:** `Automatically fix dependency issues (like circular references or links to non-existent tasks) in your Taskmaster tasks.`
|
||||
* **Key Parameters/Options:**
|
||||
* `tag`: `Specify which tag context to fix dependencies in. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Clean up dependency errors automatically.
|
||||
|
||||
@@ -349,9 +363,10 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **CLI Command:** `task-master analyze-complexity [options]`
|
||||
* **Description:** `Have Taskmaster analyze your tasks to determine their complexity and suggest which ones need to be broken down further.`
|
||||
* **Key Parameters/Options:**
|
||||
* `output`: `Where to save the complexity analysis report (default: 'scripts/task-complexity-report.json').` (CLI: `-o, --output <file>`)
|
||||
* `output`: `Where to save the complexity analysis report. Default is '.taskmaster/reports/task-complexity-report.json' (or '..._tagname.json' if a tag is used).` (CLI: `-o, --output <file>`)
|
||||
* `threshold`: `The minimum complexity score (1-10) that should trigger a recommendation to expand a task.` (CLI: `-t, --threshold <number>`)
|
||||
* `research`: `Enable research role for more accurate complexity analysis. Requires appropriate API key.` (CLI: `-r, --research`)
|
||||
* `tag`: `Specify which tag context to analyze. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Used before breaking down tasks to identify which ones need the most attention.
|
||||
* **Important:** This MCP tool makes AI calls and can take up to a minute to complete. Please inform users to hang tight while the operation is in progress.
|
||||
@@ -362,11 +377,27 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **CLI Command:** `task-master complexity-report [options]`
|
||||
* **Description:** `Display the task complexity analysis report in a readable format.`
|
||||
* **Key Parameters/Options:**
|
||||
* `file`: `Path to the complexity report (default: 'scripts/task-complexity-report.json').` (CLI: `-f, --file <file>`)
|
||||
* `file`: `Path to the complexity report (default: '.taskmaster/reports/task-complexity-report.json').` (CLI: `-f, --file <file>`)
|
||||
* `file`: `Path to the complexity report (default: '.taskmaster/reports/task-complexity-report.json').` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Review and understand the complexity analysis results after running analyze-complexity.
|
||||
|
||||
---
|
||||
|
||||
## File Management
|
||||
|
||||
### 24. Generate Task Files (`generate`)
|
||||
|
||||
* **MCP Tool:** `generate`
|
||||
* **CLI Command:** `task-master generate [options]`
|
||||
* **Description:** `Create or update individual Markdown files for each task based on your tasks.json.`
|
||||
* **Key Parameters/Options:**
|
||||
* `output`: `The directory where Taskmaster should save the task files (default: in a 'tasks' directory).` (CLI: `-o, --output <directory>`)
|
||||
* `tag`: `Specify which tag context to generate files for. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Run this after making changes to tasks.json to keep individual task files up to date. This command is now manual and no longer runs automatically.
|
||||
|
||||
---
|
||||
|
||||
## AI-Powered Research
|
||||
|
||||
### 25. Research (`research`)
|
||||
@@ -376,11 +407,15 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
* **Description:** `Perform AI-powered research queries with project context to get fresh, up-to-date information beyond the AI's knowledge cutoff.`
|
||||
* **Key Parameters/Options:**
|
||||
* `query`: `Required. Research query/prompt (e.g., "What are the latest best practices for React Query v5?").` (CLI: `[query]` positional or `-q, --query <text>`)
|
||||
* `taskIds`: `Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17").` (CLI: `-i, --id <ids>`)
|
||||
* `taskIds`: `Comma-separated list of task/subtask IDs from the current tag context (e.g., "15,16.2,17").` (CLI: `-i, --id <ids>`)
|
||||
* `filePaths`: `Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md").` (CLI: `-f, --files <paths>`)
|
||||
* `customContext`: `Additional custom context text to include in the research.` (CLI: `-c, --context <text>`)
|
||||
* `includeProjectTree`: `Include project file tree structure in context (default: false).` (CLI: `--tree`)
|
||||
* `detailLevel`: `Detail level for the research response: 'low', 'medium', 'high' (default: medium).` (CLI: `--detail <level>`)
|
||||
* `saveTo`: `Task or subtask ID (e.g., "15", "15.2") to automatically save the research conversation to.` (CLI: `--save-to <id>`)
|
||||
* `saveFile`: `If true, saves the research conversation to a markdown file in '.taskmaster/docs/research/'.` (CLI: `--save-file`)
|
||||
* `noFollowup`: `Disables the interactive follow-up question menu in the CLI.` (CLI: `--no-followup`)
|
||||
* `tag`: `Specify which tag context to use for task-based context gathering. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
* `projectRoot`: `The directory of the project. Must be an absolute path.` (CLI: Determined automatically)
|
||||
* **Usage:** **This is a POWERFUL tool that agents should use FREQUENTLY** to:
|
||||
* Get fresh information beyond knowledge cutoff dates
|
||||
@@ -404,23 +439,86 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
||||
|
||||
---
|
||||
|
||||
## File Management
|
||||
## Tag Management
|
||||
|
||||
### 24. Generate Task Files (`generate`)
|
||||
This new suite of commands allows you to manage different task contexts (tags).
|
||||
|
||||
* **MCP Tool:** `generate`
|
||||
* **CLI Command:** `task-master generate [options]`
|
||||
* **Description:** `Create or update individual Markdown files for each task based on your tasks.json.`
|
||||
### 26. List Tags (`tags`)
|
||||
|
||||
* **MCP Tool:** `list_tags`
|
||||
* **CLI Command:** `task-master tags [options]`
|
||||
* **Description:** `List all available tags with task counts, completion status, and other metadata.`
|
||||
* **Key Parameters/Options:**
|
||||
* `output`: `The directory where Taskmaster should save the task files (default: in a 'tasks' directory).` (CLI: `-o, --output <directory>`)
|
||||
* `file`: `Path to your Taskmaster 'tasks.json' file. Default relies on auto-detection.` (CLI: `-f, --file <file>`)
|
||||
* **Usage:** Run this after making changes to tasks.json to keep individual task files up to date.
|
||||
* `--show-metadata`: `Include detailed metadata in the output (e.g., creation date, description).` (CLI: `--show-metadata`)
|
||||
|
||||
### 27. Add Tag (`add_tag`)
|
||||
|
||||
* **MCP Tool:** `add_tag`
|
||||
* **CLI Command:** `task-master add-tag <tagName> [options]`
|
||||
* **Description:** `Create a new, empty tag context, or copy tasks from another tag.`
|
||||
* **Key Parameters/Options:**
|
||||
* `tagName`: `Name of the new tag to create (alphanumeric, hyphens, underscores).` (CLI: `<tagName>` positional)
|
||||
* `--from-branch`: `Creates a tag with a name derived from the current git branch, ignoring the <tagName> argument.` (CLI: `--from-branch`)
|
||||
* `--copy-from-current`: `Copy tasks from the currently active tag to the new tag.` (CLI: `--copy-from-current`)
|
||||
* `--copy-from <tag>`: `Copy tasks from a specific source tag to the new tag.` (CLI: `--copy-from <tag>`)
|
||||
* `--description <text>`: `Provide an optional description for the new tag.` (CLI: `-d, --description <text>`)
|
||||
|
||||
### 28. Delete Tag (`delete_tag`)
|
||||
|
||||
* **MCP Tool:** `delete_tag`
|
||||
* **CLI Command:** `task-master delete-tag <tagName> [options]`
|
||||
* **Description:** `Permanently delete a tag and all of its associated tasks.`
|
||||
* **Key Parameters/Options:**
|
||||
* `tagName`: `Name of the tag to delete.` (CLI: `<tagName>` positional)
|
||||
* `--yes`: `Skip the confirmation prompt.` (CLI: `-y, --yes`)
|
||||
|
||||
### 29. Use Tag (`use_tag`)
|
||||
|
||||
* **MCP Tool:** `use_tag`
|
||||
* **CLI Command:** `task-master use-tag <tagName>`
|
||||
* **Description:** `Switch your active task context to a different tag.`
|
||||
* **Key Parameters/Options:**
|
||||
* `tagName`: `Name of the tag to switch to.` (CLI: `<tagName>` positional)
|
||||
|
||||
### 30. Rename Tag (`rename_tag`)
|
||||
|
||||
* **MCP Tool:** `rename_tag`
|
||||
* **CLI Command:** `task-master rename-tag <oldName> <newName>`
|
||||
* **Description:** `Rename an existing tag.`
|
||||
* **Key Parameters/Options:**
|
||||
* `oldName`: `The current name of the tag.` (CLI: `<oldName>` positional)
|
||||
* `newName`: `The new name for the tag.` (CLI: `<newName>` positional)
|
||||
|
||||
### 31. Copy Tag (`copy_tag`)
|
||||
|
||||
* **MCP Tool:** `copy_tag`
|
||||
* **CLI Command:** `task-master copy-tag <sourceName> <targetName> [options]`
|
||||
* **Description:** `Copy an entire tag context, including all its tasks and metadata, to a new tag.`
|
||||
* **Key Parameters/Options:**
|
||||
* `sourceName`: `Name of the tag to copy from.` (CLI: `<sourceName>` positional)
|
||||
* `targetName`: `Name of the new tag to create.` (CLI: `<targetName>` positional)
|
||||
* `--description <text>`: `Optional description for the new tag.` (CLI: `-d, --description <text>`)
|
||||
|
||||
---
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### 32. Sync Readme (`sync-readme`) -- experimental
|
||||
|
||||
* **MCP Tool:** N/A
|
||||
* **CLI Command:** `task-master sync-readme [options]`
|
||||
* **Description:** `Exports your task list to your project's README.md file, useful for showcasing progress.`
|
||||
* **Key Parameters/Options:**
|
||||
* `status`: `Filter tasks by status (e.g., 'pending', 'done').` (CLI: `-s, --status <status>`)
|
||||
* `withSubtasks`: `Include subtasks in the export.` (CLI: `--with-subtasks`)
|
||||
* `tag`: `Specify which tag context to export from. Defaults to the current active tag.` (CLI: `--tag <name>`)
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables Configuration (Updated)
|
||||
|
||||
Taskmaster primarily uses the **`.taskmasterconfig`** file (in project root) for configuration (models, parameters, logging level, etc.), managed via `task-master models --setup`.
|
||||
Taskmaster primarily uses the **`.taskmaster/config.json`** file (in project root) for configuration (models, parameters, logging level, etc.), managed via `task-master models --setup`.
|
||||
Taskmaster primarily uses the **`.taskmaster/config.json`** file (in project root) for configuration (models, parameters, logging level, etc.), managed via `task-master models --setup`.
|
||||
|
||||
Environment variables are used **only** for sensitive API keys related to AI providers and specific overrides like the Ollama base URL:
|
||||
|
||||
@@ -433,12 +531,15 @@ Environment variables are used **only** for sensitive API keys related to AI pro
|
||||
* `AZURE_OPENAI_API_KEY` (Requires `AZURE_OPENAI_ENDPOINT` too)
|
||||
* `OPENROUTER_API_KEY`
|
||||
* `XAI_API_KEY`
|
||||
* `OLLANA_API_KEY` (Requires `OLLAMA_BASE_URL` too)
|
||||
* **Endpoints (Optional/Provider Specific inside .taskmasterconfig):**
|
||||
* `OLLAMA_API_KEY` (Requires `OLLAMA_BASE_URL` too)
|
||||
* **Endpoints (Optional/Provider Specific inside .taskmaster/config.json):**
|
||||
* `OLLAMA_API_KEY` (Requires `OLLAMA_BASE_URL` too)
|
||||
* **Endpoints (Optional/Provider Specific inside .taskmaster/config.json):**
|
||||
* `AZURE_OPENAI_ENDPOINT`
|
||||
* `OLLAMA_BASE_URL` (Default: `http://localhost:11434/api`)
|
||||
|
||||
**Set API keys** in your **`.env`** file in the project root (for CLI use) or within the `env` section of your **`.cursor/mcp.json`** file (for MCP/Cursor integration). All other settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in `.taskmasterconfig` via `task-master models` command or `models` MCP tool.
|
||||
**Set API keys** in your **`.env`** file in the project root (for CLI use) or within the `env` section of your **`.cursor/mcp.json`** file (for MCP/Cursor integration). All other settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in `.taskmaster/config.json` via `task-master models` command or `models` MCP tool.
|
||||
**Set API keys** in your **`.env`** file in the project root (for CLI use) or within the `env` section of your **`.cursor/mcp.json`** file (for MCP/Cursor integration). All other settings (model choice, max tokens, temperature, log level, custom endpoints) are managed in `.taskmaster/config.json` via `task-master models` command or `models` MCP tool.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,9 +3,19 @@ description: Guidelines for implementing task management operations
|
||||
globs: scripts/modules/task-manager.js
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Task Management Guidelines
|
||||
|
||||
## Tagged Task Lists System
|
||||
|
||||
Task Master now uses a **tagged task lists system** for multi-context task management:
|
||||
|
||||
- **Data Structure**: Tasks are organized into separate contexts (tags) within `tasks.json`
|
||||
- **Legacy Format**: `{"tasks": [...]}`
|
||||
- **Tagged Format**: `{"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}`
|
||||
- **Silent Migration**: Legacy format automatically converts to tagged format on first use
|
||||
- **Tag Resolution**: Core functions receive legacy format for 100% backward compatibility
|
||||
- **Default Tag**: "master" is used for all existing and new tasks unless otherwise specified
|
||||
|
||||
## Task Structure Standards
|
||||
|
||||
- **Core Task Properties**:
|
||||
@@ -28,6 +38,25 @@ alwaysApply: false
|
||||
};
|
||||
```
|
||||
|
||||
- **Tagged Data Structure**:
|
||||
- ✅ DO: Access tasks through tag resolution layer
|
||||
- ✅ DO: Use `getTasksForTag(data, tagName)` to retrieve tasks for a specific tag
|
||||
- ✅ DO: Use `setTasksForTag(data, tagName, tasks)` to update tasks for a specific tag
|
||||
- ❌ DON'T: Directly manipulate the tagged structure in core functions
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Use tag resolution functions
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
// Manipulate tasks as normal...
|
||||
|
||||
// Save back to the tagged structure
|
||||
setTasksForTag(tasksData, currentTag, tasks);
|
||||
writeJSON(tasksPath, tasksData);
|
||||
```
|
||||
|
||||
- **Subtask Structure**:
|
||||
- ✅ DO: Use consistent properties across subtasks
|
||||
- ✅ DO: Maintain simple numeric IDs within parent tasks
|
||||
@@ -48,53 +77,56 @@ alwaysApply: false
|
||||
## Task Creation and Parsing
|
||||
|
||||
- **ID Management**:
|
||||
- ✅ DO: Assign unique sequential IDs to tasks
|
||||
- ✅ DO: Calculate the next ID based on existing tasks
|
||||
- ❌ DON'T: Hardcode or reuse IDs
|
||||
- ✅ DO: Assign unique sequential IDs to tasks within each tag context
|
||||
- ✅ DO: Calculate the next ID based on existing tasks in the current tag
|
||||
- ❌ DON'T: Hardcode or reuse IDs within the same tag
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Calculate the next available ID
|
||||
const highestId = Math.max(...data.tasks.map(t => t.id));
|
||||
// ✅ DO: Calculate the next available ID within the current tag
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
const highestId = Math.max(...tasks.map(t => t.id));
|
||||
const nextTaskId = highestId + 1;
|
||||
```
|
||||
|
||||
- **PRD Parsing**:
|
||||
- ✅ DO: Extract tasks from PRD documents using AI
|
||||
- ✅ DO: Create tasks in the current tag context (defaults to "master")
|
||||
- ✅ DO: Provide clear prompts to guide AI task generation
|
||||
- ✅ DO: Validate and clean up AI-generated tasks
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Validate AI responses
|
||||
try {
|
||||
// Parse the JSON response
|
||||
taskData = JSON.parse(jsonContent);
|
||||
// ✅ DO: Parse into current tag context
|
||||
const tasksData = readJSON(tasksPath) || {};
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
|
||||
// Check that we have the required fields
|
||||
if (!taskData.title || !taskData.description) {
|
||||
throw new Error("Missing required fields in the generated task");
|
||||
}
|
||||
} catch (error) {
|
||||
log('error', "Failed to parse AI's response as valid task JSON:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
// Parse tasks and add to current tag
|
||||
const newTasks = await parseTasksFromPRD(prdContent);
|
||||
setTasksForTag(tasksData, currentTag, newTasks);
|
||||
writeJSON(tasksPath, tasksData);
|
||||
```
|
||||
|
||||
## Task Updates and Modifications
|
||||
|
||||
- **Status Management**:
|
||||
- ✅ DO: Provide functions for updating task status
|
||||
- ✅ DO: Provide functions for updating task status within current tag context
|
||||
- ✅ DO: Handle both individual tasks and subtasks
|
||||
- ✅ DO: Consider subtask status when updating parent tasks
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Handle status updates for both tasks and subtasks
|
||||
// ✅ DO: Handle status updates within tagged context
|
||||
async function setTaskStatus(tasksPath, taskIdInput, newStatus) {
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
// Check if it's a subtask (e.g., "1.2")
|
||||
if (taskIdInput.includes('.')) {
|
||||
const [parentId, subtaskId] = taskIdInput.split('.').map(id => parseInt(id, 10));
|
||||
|
||||
// Find the parent task and subtask
|
||||
const parentTask = data.tasks.find(t => t.id === parentId);
|
||||
const parentTask = tasks.find(t => t.id === parentId);
|
||||
const subtask = parentTask.subtasks.find(st => st.id === subtaskId);
|
||||
|
||||
// Update subtask status
|
||||
@@ -109,7 +141,7 @@ alwaysApply: false
|
||||
}
|
||||
} else {
|
||||
// Handle regular task
|
||||
const task = data.tasks.find(t => t.id === parseInt(taskIdInput, 10));
|
||||
const task = tasks.find(t => t.id === parseInt(taskIdInput, 10));
|
||||
task.status = newStatus;
|
||||
|
||||
// If marking as done, also mark subtasks
|
||||
@@ -119,16 +151,24 @@ alwaysApply: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Save updated tasks back to tagged structure
|
||||
setTasksForTag(tasksData, currentTag, tasks);
|
||||
writeJSON(tasksPath, tasksData);
|
||||
}
|
||||
```
|
||||
|
||||
- **Task Expansion**:
|
||||
- ✅ DO: Use AI to generate detailed subtasks
|
||||
- ✅ DO: Use AI to generate detailed subtasks within current tag context
|
||||
- ✅ DO: Consider complexity analysis for subtask counts
|
||||
- ✅ DO: Ensure proper IDs for newly created subtasks
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Generate appropriate subtasks based on complexity
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
if (taskAnalysis) {
|
||||
log('info', `Found complexity analysis for task ${taskId}: Score ${taskAnalysis.complexityScore}/10`);
|
||||
|
||||
@@ -138,6 +178,11 @@ alwaysApply: false
|
||||
log('info', `Using recommended number of subtasks: ${numSubtasks}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate subtasks and save back
|
||||
// ... subtask generation logic ...
|
||||
setTasksForTag(tasksData, currentTag, tasks);
|
||||
writeJSON(tasksPath, tasksData);
|
||||
```
|
||||
|
||||
## Task File Generation
|
||||
@@ -155,67 +200,65 @@ alwaysApply: false
|
||||
|
||||
// Format dependencies with their status
|
||||
if (task.dependencies && task.dependencies.length > 0) {
|
||||
content += `# Dependencies: ${formatDependenciesWithStatus(task.dependencies, data.tasks)}\n`;
|
||||
content += `# Dependencies: ${formatDependenciesWithStatus(task.dependencies, tasks)}\n`;
|
||||
} else {
|
||||
content += '# Dependencies: None\n';
|
||||
}
|
||||
```
|
||||
|
||||
- **Subtask Inclusion**:
|
||||
- ✅ DO: Include subtasks in parent task files
|
||||
- ✅ DO: Use consistent indentation for subtask sections
|
||||
- ✅ DO: Display subtask dependencies with proper formatting
|
||||
- **Tagged Context Awareness**:
|
||||
- ✅ DO: Generate task files from current tag context
|
||||
- ✅ DO: Include tag information in generated files
|
||||
- ❌ DON'T: Mix tasks from different tags in file generation
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Format subtasks correctly in task files
|
||||
if (task.subtasks && task.subtasks.length > 0) {
|
||||
content += '\n# Subtasks:\n';
|
||||
// ✅ DO: Generate files for current tag context
|
||||
async function generateTaskFiles(tasksPath, outputDir) {
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
task.subtasks.forEach(subtask => {
|
||||
content += `## ${subtask.id}. ${subtask.title} [${subtask.status || 'pending'}]\n`;
|
||||
|
||||
// Format subtask dependencies
|
||||
if (subtask.dependencies && subtask.dependencies.length > 0) {
|
||||
// Format the dependencies
|
||||
content += `### Dependencies: ${formattedDeps}\n`;
|
||||
} else {
|
||||
content += '### Dependencies: None\n';
|
||||
}
|
||||
|
||||
content += `### Description: ${subtask.description || ''}\n`;
|
||||
content += '### Details:\n';
|
||||
content += (subtask.details || '').split('\n').map(line => line).join('\n');
|
||||
content += '\n\n';
|
||||
});
|
||||
// Add tag context to file header
|
||||
let content = `# Tag Context: ${currentTag}\n`;
|
||||
content += `# Task ID: ${task.id}\n`;
|
||||
// ... rest of file generation
|
||||
}
|
||||
```
|
||||
|
||||
## Task Listing and Display
|
||||
|
||||
- **Filtering and Organization**:
|
||||
- ✅ DO: Allow filtering tasks by status
|
||||
- ✅ DO: Allow filtering tasks by status within current tag context
|
||||
- ✅ DO: Handle subtask display in lists
|
||||
- ✅ DO: Use consistent table formats
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement clear filtering and organization
|
||||
// ✅ DO: Implement clear filtering within tag context
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
// Filter tasks by status if specified
|
||||
const filteredTasks = statusFilter
|
||||
? data.tasks.filter(task =>
|
||||
? tasks.filter(task =>
|
||||
task.status && task.status.toLowerCase() === statusFilter.toLowerCase())
|
||||
: data.tasks;
|
||||
: tasks;
|
||||
```
|
||||
|
||||
- **Progress Tracking**:
|
||||
- ✅ DO: Calculate and display completion statistics
|
||||
- ✅ DO: Calculate and display completion statistics for current tag
|
||||
- ✅ DO: Track both task and subtask completion
|
||||
- ✅ DO: Use visual progress indicators
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Track and display progress
|
||||
// ✅ DO: Track and display progress within tag context
|
||||
const tasksData = readJSON(tasksPath);
|
||||
const currentTag = getCurrentTag() || 'master';
|
||||
const tasks = getTasksForTag(tasksData, currentTag);
|
||||
|
||||
// Calculate completion statistics
|
||||
const totalTasks = data.tasks.length;
|
||||
const completedTasks = data.tasks.filter(task =>
|
||||
const totalTasks = tasks.length;
|
||||
const completedTasks = tasks.filter(task =>
|
||||
task.status === 'done' || task.status === 'completed').length;
|
||||
const completionPercentage = totalTasks > 0 ? (completedTasks / totalTasks) * 100 : 0;
|
||||
|
||||
@@ -223,7 +266,7 @@ alwaysApply: false
|
||||
let totalSubtasks = 0;
|
||||
let completedSubtasks = 0;
|
||||
|
||||
data.tasks.forEach(task => {
|
||||
tasks.forEach(task => {
|
||||
if (task.subtasks && task.subtasks.length > 0) {
|
||||
totalSubtasks += task.subtasks.length;
|
||||
completedSubtasks += task.subtasks.filter(st =>
|
||||
@@ -232,99 +275,52 @@ alwaysApply: false
|
||||
});
|
||||
```
|
||||
|
||||
## Complexity Analysis
|
||||
## Migration and Compatibility
|
||||
|
||||
- **Scoring System**:
|
||||
- ✅ DO: Use AI to analyze task complexity
|
||||
- ✅ DO: Include complexity scores (1-10)
|
||||
- ✅ DO: Generate specific expansion recommendations
|
||||
- **Silent Migration Handling**:
|
||||
- ✅ DO: Implement silent migration in `readJSON()` function
|
||||
- ✅ DO: Detect legacy format and convert automatically
|
||||
- ✅ DO: Preserve all existing task data during migration
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Handle complexity analysis properly
|
||||
const report = {
|
||||
meta: {
|
||||
generatedAt: new Date().toISOString(),
|
||||
tasksAnalyzed: tasksData.tasks.length,
|
||||
thresholdScore: thresholdScore,
|
||||
projectName: tasksData.meta?.projectName || 'Your Project Name',
|
||||
usedResearch: useResearch
|
||||
},
|
||||
complexityAnalysis: complexityAnalysis
|
||||
};
|
||||
```
|
||||
// ✅ DO: Handle silent migration (implemented in utils.js)
|
||||
function readJSON(filepath) {
|
||||
let data = JSON.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
|
||||
- **Analysis-Based Workflow**:
|
||||
- ✅ DO: Use complexity reports to guide task expansion
|
||||
- ✅ DO: Prioritize complex tasks for more detailed breakdown
|
||||
- ✅ DO: Use expansion prompts from complexity analysis
|
||||
// Silent migration for tasks.json files
|
||||
if (data.tasks && Array.isArray(data.tasks) && !data.master && isTasksFile) {
|
||||
const migratedData = {
|
||||
master: {
|
||||
tasks: data.tasks
|
||||
}
|
||||
};
|
||||
writeJSON(filepath, migratedData);
|
||||
data = migratedData;
|
||||
}
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Apply complexity analysis to workflow
|
||||
// Sort tasks by complexity if report exists, otherwise by ID
|
||||
if (complexityReport && complexityReport.complexityAnalysis) {
|
||||
log('info', 'Sorting tasks by complexity...');
|
||||
|
||||
// Create a map of task IDs to complexity scores
|
||||
const complexityMap = new Map();
|
||||
complexityReport.complexityAnalysis.forEach(analysis => {
|
||||
complexityMap.set(analysis.taskId, analysis.complexityScore);
|
||||
});
|
||||
|
||||
// Sort tasks by complexity score (high to low)
|
||||
tasksToExpand.sort((a, b) => {
|
||||
const scoreA = complexityMap.get(a.id) || 0;
|
||||
const scoreB = complexityMap.get(b.id) || 0;
|
||||
return scoreB - scoreA;
|
||||
});
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
## Next Task Selection
|
||||
|
||||
- **Eligibility Criteria**:
|
||||
- ✅ DO: Consider dependencies when finding next tasks
|
||||
- ✅ DO: Prioritize by task priority and dependency count
|
||||
- ✅ DO: Skip completed tasks
|
||||
- **Tag Resolution**:
|
||||
- ✅ DO: Use tag resolution functions to maintain backward compatibility
|
||||
- ✅ DO: Return legacy format to core functions
|
||||
- ❌ DON'T: Expose tagged structure to existing core logic
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Use proper task prioritization logic
|
||||
function findNextTask(tasks) {
|
||||
// Get all completed task IDs
|
||||
const completedTaskIds = new Set(
|
||||
tasks
|
||||
.filter(t => t.status === 'done' || t.status === 'completed')
|
||||
.map(t => t.id)
|
||||
);
|
||||
// ✅ DO: Use tag resolution layer
|
||||
function getTasksForTag(data, tagName) {
|
||||
if (data.tasks && Array.isArray(data.tasks)) {
|
||||
// Legacy format - return as-is
|
||||
return data.tasks;
|
||||
}
|
||||
|
||||
// Filter for pending tasks whose dependencies are all satisfied
|
||||
const eligibleTasks = tasks.filter(task =>
|
||||
(task.status === 'pending' || task.status === 'in-progress') &&
|
||||
task.dependencies &&
|
||||
task.dependencies.every(depId => completedTaskIds.has(depId))
|
||||
);
|
||||
if (data[tagName] && data[tagName].tasks) {
|
||||
// Tagged format - return tasks for specified tag
|
||||
return data[tagName].tasks;
|
||||
}
|
||||
|
||||
// Sort by priority, dependency count, and ID
|
||||
const priorityValues = { 'high': 3, 'medium': 2, 'low': 1 };
|
||||
|
||||
const nextTask = eligibleTasks.sort((a, b) => {
|
||||
// Priority first
|
||||
const priorityA = priorityValues[a.priority || 'medium'] || 2;
|
||||
const priorityB = priorityValues[b.priority || 'medium'] || 2;
|
||||
|
||||
if (priorityB !== priorityA) {
|
||||
return priorityB - priorityA; // Higher priority first
|
||||
}
|
||||
|
||||
// Dependency count next
|
||||
if (a.dependencies.length !== b.dependencies.length) {
|
||||
return a.dependencies.length - b.dependencies.length; // Fewer dependencies first
|
||||
}
|
||||
|
||||
// ID last
|
||||
return a.id - b.id; // Lower ID first
|
||||
})[0];
|
||||
|
||||
return nextTask;
|
||||
return [];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
description: Guidelines for implementing utility functions
|
||||
globs: scripts/modules/utils.js, mcp-server/src/**/*
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: false
|
||||
---
|
||||
# Utility Function Guidelines
|
||||
@@ -601,3 +601,575 @@ export {
|
||||
- ❌ DON'T: Replace explicit user task selections with fuzzy results
|
||||
|
||||
Refer to [`context_gathering.mdc`](mdc:.cursor/rules/context_gathering.mdc) for detailed implementation patterns, [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) and [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) for more context on MCP server architecture and integration.
|
||||
|
||||
## File System Operations
|
||||
|
||||
- **JSON File Handling**:
|
||||
- ✅ DO: Use `readJSON` and `writeJSON` for all JSON operations
|
||||
- ✅ DO: Include error handling for file operations
|
||||
- ✅ DO: Validate JSON structure after reading
|
||||
- ❌ DON'T: Use raw `fs.readFileSync` or `fs.writeFileSync` for JSON
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Use utility functions with error handling
|
||||
function readJSON(filepath) {
|
||||
try {
|
||||
if (!fs.existsSync(filepath)) {
|
||||
return null; // or appropriate default
|
||||
}
|
||||
|
||||
let data = JSON.parse(fs.readFileSync(filepath, 'utf8'));
|
||||
|
||||
// Silent migration for tasks.json files: Transform old format to tagged format
|
||||
const isTasksFile = filepath.includes('tasks.json') || path.basename(filepath) === 'tasks.json';
|
||||
|
||||
if (data && data.tasks && Array.isArray(data.tasks) && !data.master && isTasksFile) {
|
||||
// Migrate from old format { "tasks": [...] } to new format { "master": { "tasks": [...] } }
|
||||
const migratedData = {
|
||||
master: {
|
||||
tasks: data.tasks
|
||||
}
|
||||
};
|
||||
|
||||
writeJSON(filepath, migratedData);
|
||||
|
||||
// Set global flag for CLI notice and perform complete migration
|
||||
global.taskMasterMigrationOccurred = true;
|
||||
performCompleteTagMigration(filepath);
|
||||
|
||||
data = migratedData;
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
log('error', `Failed to read JSON from ${filepath}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeJSON(filepath, data) {
|
||||
try {
|
||||
const dirPath = path.dirname(filepath);
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(filepath, JSON.stringify(data, null, 2));
|
||||
} catch (error) {
|
||||
log('error', `Failed to write JSON to ${filepath}: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Path Resolution**:
|
||||
- ✅ DO: Use `path.join()` for cross-platform path construction
|
||||
- ✅ DO: Use `path.resolve()` for absolute paths
|
||||
- ✅ DO: Validate paths before file operations
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Handle paths correctly
|
||||
function findProjectRoot(startPath = process.cwd()) {
|
||||
let currentPath = path.resolve(startPath);
|
||||
const rootPath = path.parse(currentPath).root;
|
||||
|
||||
while (currentPath !== rootPath) {
|
||||
const taskMasterPath = path.join(currentPath, '.taskmaster');
|
||||
if (fs.existsSync(taskMasterPath)) {
|
||||
return currentPath;
|
||||
}
|
||||
currentPath = path.dirname(currentPath);
|
||||
}
|
||||
|
||||
return null; // Not found
|
||||
}
|
||||
```
|
||||
|
||||
## Tagged Task Lists System Utilities
|
||||
|
||||
- **Tag Resolution Functions**:
|
||||
- ✅ DO: Use tag resolution layer for all task data access
|
||||
- ✅ DO: Provide backward compatibility with legacy format
|
||||
- ✅ DO: Default to "master" tag when no tag is specified
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement tag resolution functions
|
||||
function getTasksForTag(data, tagName = 'master') {
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Handle legacy format - direct tasks array
|
||||
if (data.tasks && Array.isArray(data.tasks)) {
|
||||
return data.tasks;
|
||||
}
|
||||
|
||||
// Handle tagged format - tasks under specific tag
|
||||
if (data[tagName] && data[tagName].tasks && Array.isArray(data[tagName].tasks)) {
|
||||
return data[tagName].tasks;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function setTasksForTag(data, tagName = 'master', tasks) {
|
||||
// Ensure data object exists
|
||||
if (!data) {
|
||||
data = {};
|
||||
}
|
||||
|
||||
// Create tag structure if it doesn't exist
|
||||
if (!data[tagName]) {
|
||||
data[tagName] = {};
|
||||
}
|
||||
|
||||
// Set tasks for the tag
|
||||
data[tagName].tasks = tasks;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function getCurrentTag() {
|
||||
// Get current tag from state.json or default to 'master'
|
||||
try {
|
||||
const projectRoot = findProjectRoot();
|
||||
if (!projectRoot) return 'master';
|
||||
|
||||
const statePath = path.join(projectRoot, '.taskmaster', 'state.json');
|
||||
if (fs.existsSync(statePath)) {
|
||||
const state = readJSON(statePath);
|
||||
return state.currentTag || 'master';
|
||||
}
|
||||
} catch (error) {
|
||||
log('debug', `Error reading current tag: ${error.message}`);
|
||||
}
|
||||
|
||||
return 'master';
|
||||
}
|
||||
```
|
||||
|
||||
- **Migration Functions**:
|
||||
- ✅ DO: Implement complete migration for all related files
|
||||
- ✅ DO: Handle configuration and state file creation
|
||||
- ✅ DO: Provide migration status tracking
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement complete migration system
|
||||
function performCompleteTagMigration(tasksJsonPath) {
|
||||
try {
|
||||
// Derive project root from tasks.json path
|
||||
const projectRoot = findProjectRoot(path.dirname(tasksJsonPath)) || path.dirname(tasksJsonPath);
|
||||
|
||||
// 1. Migrate config.json - add defaultTag and tags section
|
||||
const configPath = path.join(projectRoot, '.taskmaster', 'config.json');
|
||||
if (fs.existsSync(configPath)) {
|
||||
migrateConfigJson(configPath);
|
||||
}
|
||||
|
||||
// 2. Create state.json if it doesn't exist
|
||||
const statePath = path.join(projectRoot, '.taskmaster', 'state.json');
|
||||
if (!fs.existsSync(statePath)) {
|
||||
createStateJson(statePath);
|
||||
}
|
||||
|
||||
if (getDebugFlag()) {
|
||||
log('debug', 'Completed tagged task lists migration for project');
|
||||
}
|
||||
} catch (error) {
|
||||
if (getDebugFlag()) {
|
||||
log('warn', `Error during complete tag migration: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function migrateConfigJson(configPath) {
|
||||
try {
|
||||
const config = readJSON(configPath);
|
||||
if (!config) return;
|
||||
|
||||
let modified = false;
|
||||
|
||||
// Add global.defaultTag if missing
|
||||
if (!config.global) {
|
||||
config.global = {};
|
||||
}
|
||||
if (!config.global.defaultTag) {
|
||||
config.global.defaultTag = 'master';
|
||||
modified = true;
|
||||
}
|
||||
|
||||
// Add tags section if missing
|
||||
if (!config.tags) {
|
||||
config.tags = {
|
||||
// Git integration settings removed - now manual only
|
||||
};
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
writeJSON(configPath, config);
|
||||
if (getDebugFlag()) {
|
||||
log('debug', 'Updated config.json with tagged task system settings');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (getDebugFlag()) {
|
||||
log('warn', `Error migrating config.json: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createStateJson(statePath) {
|
||||
try {
|
||||
const initialState = {
|
||||
currentTag: 'master',
|
||||
lastSwitched: new Date().toISOString(),
|
||||
migrationNoticeShown: false
|
||||
};
|
||||
|
||||
writeJSON(statePath, initialState);
|
||||
if (getDebugFlag()) {
|
||||
log('debug', 'Created initial state.json for tagged task system');
|
||||
}
|
||||
} catch (error) {
|
||||
if (getDebugFlag()) {
|
||||
log('warn', `Error creating state.json: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markMigrationForNotice() {
|
||||
try {
|
||||
const projectRoot = findProjectRoot();
|
||||
if (!projectRoot) return;
|
||||
|
||||
const statePath = path.join(projectRoot, '.taskmaster', 'state.json');
|
||||
const state = readJSON(statePath) || {};
|
||||
|
||||
state.migrationNoticeShown = false; // Reset to show notice
|
||||
writeJSON(statePath, state);
|
||||
} catch (error) {
|
||||
if (getDebugFlag()) {
|
||||
log('warn', `Error marking migration for notice: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Logging Functions
|
||||
|
||||
- **Consistent Logging**:
|
||||
- ✅ DO: Use the central `log` function for all output
|
||||
- ✅ DO: Use appropriate log levels (info, warn, error, debug)
|
||||
- ✅ DO: Support silent mode for programmatic usage
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement consistent logging with silent mode
|
||||
let silentMode = false;
|
||||
|
||||
function log(level, ...messages) {
|
||||
if (silentMode && level !== 'error') {
|
||||
return; // Suppress non-error logs in silent mode
|
||||
}
|
||||
|
||||
const timestamp = new Date().toISOString();
|
||||
const formattedMessage = messages.join(' ');
|
||||
|
||||
switch (level) {
|
||||
case 'error':
|
||||
console.error(`[ERROR] ${formattedMessage}`);
|
||||
break;
|
||||
case 'warn':
|
||||
console.warn(`[WARN] ${formattedMessage}`);
|
||||
break;
|
||||
case 'info':
|
||||
console.log(`[INFO] ${formattedMessage}`);
|
||||
break;
|
||||
case 'debug':
|
||||
if (getDebugFlag()) {
|
||||
console.log(`[DEBUG] ${formattedMessage}`);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function enableSilentMode() {
|
||||
silentMode = true;
|
||||
}
|
||||
|
||||
function disableSilentMode() {
|
||||
silentMode = false;
|
||||
}
|
||||
|
||||
function isSilentMode() {
|
||||
return silentMode;
|
||||
}
|
||||
```
|
||||
|
||||
## Task Utilities
|
||||
|
||||
- **Task Finding and Manipulation**:
|
||||
- ✅ DO: Use tagged task system aware functions
|
||||
- ✅ DO: Handle both task and subtask operations
|
||||
- ✅ DO: Validate task IDs before operations
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement tag-aware task utilities
|
||||
function findTaskById(tasks, taskId) {
|
||||
if (!Array.isArray(tasks)) {
|
||||
return null;
|
||||
}
|
||||
return tasks.find(task => task.id === taskId) || null;
|
||||
}
|
||||
|
||||
function findSubtaskById(tasks, parentId, subtaskId) {
|
||||
const parentTask = findTaskById(tasks, parentId);
|
||||
if (!parentTask || !parentTask.subtasks) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parentTask.subtasks.find(subtask => subtask.id === subtaskId) || null;
|
||||
}
|
||||
|
||||
function getNextTaskId(tasks) {
|
||||
if (!Array.isArray(tasks) || tasks.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const maxId = Math.max(...tasks.map(task => task.id));
|
||||
return maxId + 1;
|
||||
}
|
||||
|
||||
function getNextSubtaskId(parentTask) {
|
||||
if (!parentTask.subtasks || parentTask.subtasks.length === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const maxId = Math.max(...parentTask.subtasks.map(subtask => subtask.id));
|
||||
return maxId + 1;
|
||||
}
|
||||
```
|
||||
|
||||
## String Utilities
|
||||
|
||||
- **Text Processing**:
|
||||
- ✅ DO: Handle text truncation appropriately
|
||||
- ✅ DO: Provide consistent formatting functions
|
||||
- ✅ DO: Support different output formats
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement useful string utilities
|
||||
function truncate(str, maxLength = 50) {
|
||||
if (!str || typeof str !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (str.length <= maxLength) {
|
||||
return str;
|
||||
}
|
||||
|
||||
return str.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
function formatDuration(ms) {
|
||||
const seconds = Math.floor(ms / 1000);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m ${seconds % 60}s`;
|
||||
} else {
|
||||
return `${seconds}s`;
|
||||
}
|
||||
}
|
||||
|
||||
function capitalizeFirst(str) {
|
||||
if (!str || typeof str !== 'string') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
||||
}
|
||||
```
|
||||
|
||||
## Dependency Management Utilities
|
||||
|
||||
- **Dependency Analysis**:
|
||||
- ✅ DO: Detect circular dependencies
|
||||
- ✅ DO: Validate dependency references
|
||||
- ✅ DO: Support cross-tag dependency checking (future enhancement)
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement dependency utilities
|
||||
function findCycles(tasks) {
|
||||
const cycles = [];
|
||||
const visited = new Set();
|
||||
const recStack = new Set();
|
||||
|
||||
function dfs(taskId, path = []) {
|
||||
if (recStack.has(taskId)) {
|
||||
// Found a cycle
|
||||
const cycleStart = path.indexOf(taskId);
|
||||
const cycle = path.slice(cycleStart).concat([taskId]);
|
||||
cycles.push(cycle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (visited.has(taskId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
visited.add(taskId);
|
||||
recStack.add(taskId);
|
||||
|
||||
const task = findTaskById(tasks, taskId);
|
||||
if (task && task.dependencies) {
|
||||
task.dependencies.forEach(depId => {
|
||||
dfs(depId, path.concat([taskId]));
|
||||
});
|
||||
}
|
||||
|
||||
recStack.delete(taskId);
|
||||
}
|
||||
|
||||
tasks.forEach(task => {
|
||||
if (!visited.has(task.id)) {
|
||||
dfs(task.id);
|
||||
}
|
||||
});
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
function validateDependencies(tasks) {
|
||||
const validationErrors = [];
|
||||
const taskIds = new Set(tasks.map(task => task.id));
|
||||
|
||||
tasks.forEach(task => {
|
||||
if (task.dependencies) {
|
||||
task.dependencies.forEach(depId => {
|
||||
if (!taskIds.has(depId)) {
|
||||
validationErrors.push({
|
||||
taskId: task.id,
|
||||
invalidDependency: depId,
|
||||
message: `Task ${task.id} depends on non-existent task ${depId}`
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return validationErrors;
|
||||
}
|
||||
```
|
||||
|
||||
## Environment and Configuration Utilities
|
||||
|
||||
- **Environment Variable Resolution**:
|
||||
- ✅ DO: Support both `.env` files and MCP session environment
|
||||
- ✅ DO: Provide fallbacks for missing values
|
||||
- ✅ DO: Handle API key resolution correctly
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Implement flexible environment resolution
|
||||
function resolveEnvVariable(key, sessionEnv = null) {
|
||||
// First check session environment (for MCP)
|
||||
if (sessionEnv && sessionEnv[key]) {
|
||||
return sessionEnv[key];
|
||||
}
|
||||
|
||||
// Then check process environment
|
||||
if (process.env[key]) {
|
||||
return process.env[key];
|
||||
}
|
||||
|
||||
// Finally try .env file if in project root
|
||||
try {
|
||||
const projectRoot = findProjectRoot();
|
||||
if (projectRoot) {
|
||||
const envPath = path.join(projectRoot, '.env');
|
||||
if (fs.existsSync(envPath)) {
|
||||
const envContent = fs.readFileSync(envPath, 'utf8');
|
||||
const lines = envContent.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
const [envKey, envValue] = line.split('=');
|
||||
if (envKey && envKey.trim() === key) {
|
||||
return envValue ? envValue.trim().replace(/^["']|["']$/g, '') : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
log('debug', `Error reading .env file: ${error.message}`);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getDebugFlag() {
|
||||
const debugFlag = resolveEnvVariable('TASKMASTER_DEBUG') ||
|
||||
resolveEnvVariable('DEBUG') ||
|
||||
'false';
|
||||
return debugFlag.toLowerCase() === 'true';
|
||||
}
|
||||
```
|
||||
|
||||
## Export Pattern
|
||||
|
||||
- **Module Exports**:
|
||||
- ✅ DO: Export all utility functions explicitly
|
||||
- ✅ DO: Group related functions logically
|
||||
- ✅ DO: Include new tagged system utilities
|
||||
|
||||
```javascript
|
||||
// ✅ DO: Export utilities in logical groups
|
||||
module.exports = {
|
||||
// File system utilities
|
||||
readJSON,
|
||||
writeJSON,
|
||||
findProjectRoot,
|
||||
|
||||
// Tagged task system utilities
|
||||
getTasksForTag,
|
||||
setTasksForTag,
|
||||
getCurrentTag,
|
||||
performCompleteTagMigration,
|
||||
migrateConfigJson,
|
||||
createStateJson,
|
||||
markMigrationForNotice,
|
||||
|
||||
// Logging utilities
|
||||
log,
|
||||
enableSilentMode,
|
||||
disableSilentMode,
|
||||
isSilentMode,
|
||||
|
||||
// Task utilities
|
||||
findTaskById,
|
||||
findSubtaskById,
|
||||
getNextTaskId,
|
||||
getNextSubtaskId,
|
||||
|
||||
// String utilities
|
||||
truncate,
|
||||
formatDuration,
|
||||
capitalizeFirst,
|
||||
|
||||
// Dependency utilities
|
||||
findCycles,
|
||||
validateDependencies,
|
||||
|
||||
// Environment utilities
|
||||
resolveEnvVariable,
|
||||
getDebugFlag,
|
||||
|
||||
// Legacy utilities (maintained for compatibility)
|
||||
aggregateTelemetry
|
||||
};
|
||||
```
|
||||
|
||||
Refer to [`utils.js`](mdc:scripts/modules/utils.js) for implementation examples and [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) for integration patterns.
|
||||
|
||||
@@ -20,13 +20,15 @@
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"userId": "1234567890",
|
||||
"logLevel": "info",
|
||||
"debug": false,
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"projectName": "Taskmaster",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"userId": "1234567890",
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/"
|
||||
"bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com",
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/",
|
||||
"defaultTag": "master"
|
||||
}
|
||||
}
|
||||
@@ -382,25 +382,25 @@ The output report structure is:
|
||||
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"generatedAt": "2023-06-15T12:34:56.789Z",
|
||||
"tasksAnalyzed": 20,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Your Project Name",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 8,
|
||||
"taskTitle": "Develop Implementation Drift Handling",
|
||||
"complexityScore": 9.5,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Create subtasks that handle detecting...",
|
||||
"reasoning": "This task requires sophisticated logic...",
|
||||
"expansionCommand": "node scripts/dev.js expand --id=8 --num=6 --prompt=\"Create subtasks...\" --research"
|
||||
}
|
||||
// More tasks sorted by complexity score (highest first)
|
||||
]
|
||||
"meta": {
|
||||
"generatedAt": "2023-06-15T12:34:56.789Z",
|
||||
"tasksAnalyzed": 20,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Your Project Name",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 8,
|
||||
"taskTitle": "Develop Implementation Drift Handling",
|
||||
"complexityScore": 9.5,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Create subtasks that handle detecting...",
|
||||
"reasoning": "This task requires sophisticated logic...",
|
||||
"expansionCommand": "node scripts/dev.js expand --id=8 --num=6 --prompt=\"Create subtasks...\" --research"
|
||||
}
|
||||
// More tasks sorted by complexity score (highest first)
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
42
.taskmaster/docs/research/2025-06-13_what-is-typescript.md
Normal file
42
.taskmaster/docs/research/2025-06-13_what-is-typescript.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Research Session
|
||||
query: "What is TypeScript?"
|
||||
date: 6/13/2025
|
||||
time: 3:07:41 PM
|
||||
timestamp: 2025-06-13T19:07:41.313Z
|
||||
exchanges: 2
|
||||
---
|
||||
|
||||
# Research Session
|
||||
|
||||
**Query:** What is TypeScript?
|
||||
**Date:** 6/13/2025 3:07:41 PM
|
||||
**Exchanges:** 2
|
||||
|
||||
---
|
||||
|
||||
## Initial Query
|
||||
|
||||
**Question:** What is TypeScript?
|
||||
|
||||
**Response:**
|
||||
|
||||
TypeScript is a strongly typed, object-oriented programming language that builds on JavaScript by adding static typing and type annotations. It is a syntactic superset of JavaScript, meaning all JavaScript code is valid TypeScript, but TypeScript adds extra syntax to specify types, enabling compile-time type checking and better tooling support. This helps catch errors early before running the code and improves code quality, especially in large-scale applications. TypeScript code is transpiled to plain JavaScript, which can run anywhere JavaScript runs, such as browsers, Node.js, or Deno. It is developed and maintained by Microsoft as open-source software under the Apache 2.0 license[1][2][3][4][5].
|
||||
|
||||
---
|
||||
|
||||
## Follow-up 1
|
||||
|
||||
**Question:** And why is the sky blue?
|
||||
|
||||
**Response:**
|
||||
|
||||
- The sky appears blue because sunlight interacts with Earth's atmosphere, and the shorter wavelengths of light (blue and violet) are scattered in all directions by air molecules—a process called Rayleigh scattering[1][2][3][5].
|
||||
- Blue light is scattered more than red light because it has a shorter wavelength, making the sky look blue to our eyes during the day[2][3][5].
|
||||
- If Earth's atmosphere didn't scatter sunlight, the sky would appear dark, as it does on the Moon, which lacks an atmosphere[5].
|
||||
|
||||
|
||||
---
|
||||
|
||||
*Generated by Task Master Research Command*
|
||||
*Timestamp: 2025-06-13T19:07:41.313Z*
|
||||
357
.taskmaster/reports/task-complexity-report.json
Normal file
357
.taskmaster/reports/task-complexity-report.json
Normal file
@@ -0,0 +1,357 @@
|
||||
{
|
||||
"meta": {
|
||||
"generatedAt": "2025-05-22T05:48:33.026Z",
|
||||
"tasksAnalyzed": 6,
|
||||
"totalTasks": 88,
|
||||
"analysisCount": 43,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Taskmaster",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 24,
|
||||
"taskTitle": "Implement AI-Powered Test Generation Command",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "Break down the implementation of the AI-powered test generation command into detailed subtasks covering: command structure setup, AI prompt engineering, test file generation logic, integration with Claude API, and comprehensive error handling.",
|
||||
"reasoning": "This task involves complex integration with an AI service (Claude), requires sophisticated prompt engineering, and needs to generate structured code files. The existing 3 subtasks are a good start but could be expanded to include more detailed steps for AI integration, error handling, and test file formatting."
|
||||
},
|
||||
{
|
||||
"taskId": 26,
|
||||
"taskTitle": "Implement Context Foundation for AI Operations",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 4,
|
||||
"expansionPrompt": "The current 4 subtasks for implementing the context foundation appear comprehensive. Consider if any additional subtasks are needed for testing, documentation, or integration with existing systems.",
|
||||
"reasoning": "This task involves creating a foundation for context integration with several well-defined components. The existing 4 subtasks cover the main implementation areas (context-file flag, cursor rules integration, context extraction utility, and command handler updates). The complexity is moderate as it requires careful integration with existing systems but has clear requirements."
|
||||
},
|
||||
{
|
||||
"taskId": 27,
|
||||
"taskTitle": "Implement Context Enhancements for AI Operations",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 4,
|
||||
"expansionPrompt": "The current 4 subtasks for implementing context enhancements appear well-structured. Consider if any additional subtasks are needed for testing, documentation, or performance optimization.",
|
||||
"reasoning": "This task builds upon the foundation from Task #26 and adds more sophisticated context handling features. The 4 existing subtasks cover the main implementation areas (code context extraction, task history context, PRD context integration, and context formatting). The complexity is higher than the foundation task due to the need for intelligent context selection and optimization."
|
||||
},
|
||||
{
|
||||
"taskId": 28,
|
||||
"taskTitle": "Implement Advanced ContextManager System",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the advanced ContextManager system appear comprehensive. Consider if any additional subtasks are needed for testing, documentation, or backward compatibility with previous context implementations.",
|
||||
"reasoning": "This task represents the most complex phase of the context implementation, requiring a sophisticated class design, optimization algorithms, and integration with multiple systems. The 5 existing subtasks cover the core implementation areas, but the complexity is high due to the need for intelligent context prioritization, token management, and performance monitoring."
|
||||
},
|
||||
{
|
||||
"taskId": 40,
|
||||
"taskTitle": "Implement 'plan' Command for Task Implementation Planning",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 4,
|
||||
"expansionPrompt": "The current 4 subtasks for implementing the 'plan' command appear well-structured. Consider if any additional subtasks are needed for testing, documentation, or integration with existing task management workflows.",
|
||||
"reasoning": "This task involves creating a new command that leverages AI to generate implementation plans. The existing 4 subtasks cover the main implementation areas (retrieving task content, generating plans with AI, formatting in XML, and error handling). The complexity is moderate as it builds on existing patterns for task updates but requires careful AI integration."
|
||||
},
|
||||
{
|
||||
"taskId": 41,
|
||||
"taskTitle": "Implement Visual Task Dependency Graph in Terminal",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 10,
|
||||
"expansionPrompt": "The current 10 subtasks for implementing the visual task dependency graph appear comprehensive. Consider if any additional subtasks are needed for performance optimization with large graphs or additional visualization options.",
|
||||
"reasoning": "This task involves creating a sophisticated visualization system for terminal display, which is inherently complex due to layout algorithms, ASCII/Unicode rendering, and handling complex dependency relationships. The 10 existing subtasks cover all major aspects of implementation, from CLI interface to accessibility features."
|
||||
},
|
||||
{
|
||||
"taskId": 42,
|
||||
"taskTitle": "Implement MCP-to-MCP Communication Protocol",
|
||||
"complexityScore": 9,
|
||||
"recommendedSubtasks": 8,
|
||||
"expansionPrompt": "The current 8 subtasks for implementing the MCP-to-MCP communication protocol appear well-structured. Consider if any additional subtasks are needed for security hardening, performance optimization, or comprehensive documentation.",
|
||||
"reasoning": "This task involves designing and implementing a complex communication protocol between different MCP tools and servers. It requires sophisticated adapter patterns, client-server architecture, and handling of multiple operational modes. The complexity is very high due to the need for standardization, security, and backward compatibility."
|
||||
},
|
||||
{
|
||||
"taskId": 44,
|
||||
"taskTitle": "Implement Task Automation with Webhooks and Event Triggers",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "The current 7 subtasks for implementing task automation with webhooks appear comprehensive. Consider if any additional subtasks are needed for security testing, rate limiting implementation, or webhook monitoring tools.",
|
||||
"reasoning": "This task involves creating a sophisticated event system with webhooks for integration with external services. The complexity is high due to the need for secure authentication, reliable delivery mechanisms, and handling of various webhook formats and protocols. The existing subtasks cover the main implementation areas but security and monitoring could be emphasized more."
|
||||
},
|
||||
{
|
||||
"taskId": 45,
|
||||
"taskTitle": "Implement GitHub Issue Import Feature",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the GitHub issue import feature appear well-structured. Consider if any additional subtasks are needed for handling GitHub API rate limiting, caching, or supporting additional issue metadata.",
|
||||
"reasoning": "This task involves integrating with the GitHub API to import issues as tasks. The complexity is moderate as it requires API authentication, data mapping, and error handling. The existing 5 subtasks cover the main implementation areas from design to end-to-end implementation."
|
||||
},
|
||||
{
|
||||
"taskId": 46,
|
||||
"taskTitle": "Implement ICE Analysis Command for Task Prioritization",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the ICE analysis command appear comprehensive. Consider if any additional subtasks are needed for visualization of ICE scores or integration with other prioritization methods.",
|
||||
"reasoning": "This task involves creating an AI-powered analysis system for task prioritization using the ICE methodology. The complexity is high due to the need for sophisticated scoring algorithms, AI integration, and report generation. The existing subtasks cover the main implementation areas from algorithm design to integration with existing systems."
|
||||
},
|
||||
{
|
||||
"taskId": 47,
|
||||
"taskTitle": "Enhance Task Suggestion Actions Card Workflow",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for enhancing the task suggestion actions card workflow appear well-structured. Consider if any additional subtasks are needed for user testing, accessibility improvements, or performance optimization.",
|
||||
"reasoning": "This task involves redesigning the UI workflow for task expansion and management. The complexity is moderate as it requires careful UX design and state management but builds on existing components. The 6 existing subtasks cover the main implementation areas from design to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 48,
|
||||
"taskTitle": "Refactor Prompts into Centralized Structure",
|
||||
"complexityScore": 4,
|
||||
"recommendedSubtasks": 3,
|
||||
"expansionPrompt": "The current 3 subtasks for refactoring prompts into a centralized structure appear appropriate. Consider if any additional subtasks are needed for prompt versioning, documentation, or testing.",
|
||||
"reasoning": "This task involves a straightforward refactoring to improve code organization. The complexity is relatively low as it primarily involves moving code rather than creating new functionality. The 3 existing subtasks cover the main implementation areas from directory structure to integration."
|
||||
},
|
||||
{
|
||||
"taskId": 49,
|
||||
"taskTitle": "Implement Code Quality Analysis Command",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for implementing the code quality analysis command appear comprehensive. Consider if any additional subtasks are needed for performance optimization with large codebases or integration with existing code quality tools.",
|
||||
"reasoning": "This task involves creating a sophisticated code analysis system with pattern recognition, best practice verification, and AI-powered recommendations. The complexity is high due to the need for code parsing, complex analysis algorithms, and integration with AI services. The existing subtasks cover the main implementation areas from algorithm design to user interface."
|
||||
},
|
||||
{
|
||||
"taskId": 50,
|
||||
"taskTitle": "Implement Test Coverage Tracking System by Task",
|
||||
"complexityScore": 9,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the test coverage tracking system appear well-structured. Consider if any additional subtasks are needed for integration with CI/CD systems, performance optimization, or visualization tools.",
|
||||
"reasoning": "This task involves creating a complex system that maps test coverage to specific tasks and subtasks. The complexity is very high due to the need for sophisticated data structures, integration with coverage tools, and AI-powered test generation. The existing subtasks are comprehensive and cover the main implementation areas from data structure design to AI integration."
|
||||
},
|
||||
{
|
||||
"taskId": 51,
|
||||
"taskTitle": "Implement Perplexity Research Command",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the Perplexity research command appear comprehensive. Consider if any additional subtasks are needed for caching optimization, result formatting, or integration with other research tools.",
|
||||
"reasoning": "This task involves creating a new command that integrates with the Perplexity AI API for research. The complexity is moderate as it requires API integration, context extraction, and result formatting. The 5 existing subtasks cover the main implementation areas from API client to caching system."
|
||||
},
|
||||
{
|
||||
"taskId": 52,
|
||||
"taskTitle": "Implement Task Suggestion Command for CLI",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing the task suggestion command appear well-structured. Consider if any additional subtasks are needed for suggestion quality evaluation, user feedback collection, or integration with existing task workflows.",
|
||||
"reasoning": "This task involves creating a new CLI command that generates contextually relevant task suggestions using AI. The complexity is moderate as it requires AI integration, context collection, and interactive CLI interfaces. The existing subtasks cover the main implementation areas from data collection to user interface."
|
||||
},
|
||||
{
|
||||
"taskId": 53,
|
||||
"taskTitle": "Implement Subtask Suggestion Feature for Parent Tasks",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for implementing the subtask suggestion feature appear comprehensive. Consider if any additional subtasks are needed for suggestion quality metrics, user feedback collection, or performance optimization.",
|
||||
"reasoning": "This task involves creating a feature that suggests contextually relevant subtasks for parent tasks. The complexity is moderate as it builds on existing task management systems but requires sophisticated AI integration and context analysis. The 6 existing subtasks cover the main implementation areas from validation to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 55,
|
||||
"taskTitle": "Implement Positional Arguments Support for CLI Commands",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing positional arguments support appear well-structured. Consider if any additional subtasks are needed for backward compatibility testing, documentation updates, or user experience improvements.",
|
||||
"reasoning": "This task involves modifying the command parsing logic to support positional arguments alongside the existing flag-based syntax. The complexity is moderate as it requires careful handling of different argument styles and edge cases. The 5 existing subtasks cover the main implementation areas from analysis to documentation."
|
||||
},
|
||||
{
|
||||
"taskId": 57,
|
||||
"taskTitle": "Enhance Task-Master CLI User Experience and Interface",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for enhancing the CLI user experience appear comprehensive. Consider if any additional subtasks are needed for accessibility testing, internationalization, or performance optimization.",
|
||||
"reasoning": "This task involves a significant overhaul of the CLI interface to improve user experience. The complexity is high due to the breadth of changes (logging, visual elements, interactive components, etc.) and the need for consistent design across all commands. The 6 existing subtasks cover the main implementation areas from log management to help systems."
|
||||
},
|
||||
{
|
||||
"taskId": 60,
|
||||
"taskTitle": "Implement Mentor System with Round-Table Discussion Feature",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "The current 7 subtasks for implementing the mentor system appear well-structured. Consider if any additional subtasks are needed for mentor personality consistency, discussion quality evaluation, or performance optimization with multiple mentors.",
|
||||
"reasoning": "This task involves creating a sophisticated mentor simulation system with round-table discussions. The complexity is high due to the need for personality simulation, complex LLM integration, and structured discussion management. The 7 existing subtasks cover the main implementation areas from architecture to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 62,
|
||||
"taskTitle": "Add --simple Flag to Update Commands for Direct Text Input",
|
||||
"complexityScore": 4,
|
||||
"recommendedSubtasks": 8,
|
||||
"expansionPrompt": "The current 8 subtasks for implementing the --simple flag appear comprehensive. Consider if any additional subtasks are needed for user experience testing or documentation updates.",
|
||||
"reasoning": "This task involves adding a simple flag option to bypass AI processing for updates. The complexity is relatively low as it primarily involves modifying existing command handlers and adding a flag. The 8 existing subtasks are very detailed and cover all aspects of implementation from command parsing to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 63,
|
||||
"taskTitle": "Add pnpm Support for the Taskmaster Package",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 8,
|
||||
"expansionPrompt": "The current 8 subtasks for adding pnpm support appear comprehensive. Consider if any additional subtasks are needed for CI/CD integration, performance comparison, or documentation updates.",
|
||||
"reasoning": "This task involves ensuring the package works correctly with pnpm as an alternative package manager. The complexity is moderate as it requires careful testing of installation processes and scripts across different environments. The 8 existing subtasks cover all major aspects from documentation to binary verification."
|
||||
},
|
||||
{
|
||||
"taskId": 64,
|
||||
"taskTitle": "Add Yarn Support for Taskmaster Installation",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 9,
|
||||
"expansionPrompt": "The current 9 subtasks for adding Yarn support appear comprehensive. Consider if any additional subtasks are needed for performance testing, CI/CD integration, or compatibility with different Yarn versions.",
|
||||
"reasoning": "This task involves ensuring the package works correctly with Yarn as an alternative package manager. The complexity is moderate as it requires careful testing of installation processes and scripts across different environments. The 9 existing subtasks are very detailed and cover all aspects from configuration to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 65,
|
||||
"taskTitle": "Add Bun Support for Taskmaster Installation",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for adding Bun support appear well-structured. Consider if any additional subtasks are needed for handling Bun-specific issues, performance testing, or documentation updates.",
|
||||
"reasoning": "This task involves adding support for the newer Bun package manager. The complexity is slightly higher than the other package manager tasks due to Bun's differences from Node.js and potential compatibility issues. The 6 existing subtasks cover the main implementation areas from research to documentation."
|
||||
},
|
||||
{
|
||||
"taskId": 67,
|
||||
"taskTitle": "Add CLI JSON output and Cursor keybindings integration",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing JSON output and Cursor keybindings appear well-structured. Consider if any additional subtasks are needed for testing across different operating systems, documentation updates, or user experience improvements.",
|
||||
"reasoning": "This task involves two distinct features: adding JSON output to CLI commands and creating a keybindings installation command. The complexity is moderate as it requires careful handling of different output formats and OS-specific file paths. The 5 existing subtasks cover the main implementation areas for both features."
|
||||
},
|
||||
{
|
||||
"taskId": 68,
|
||||
"taskTitle": "Ability to create tasks without parsing PRD",
|
||||
"complexityScore": 3,
|
||||
"recommendedSubtasks": 2,
|
||||
"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."
|
||||
},
|
||||
{
|
||||
"taskId": 72,
|
||||
"taskTitle": "Implement PDF Generation for Project Progress and Dependency Overview",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for implementing PDF generation appear comprehensive. Consider if any additional subtasks are needed for handling large projects, additional visualization options, or integration with existing reporting tools.",
|
||||
"reasoning": "This task involves creating a feature to generate PDF reports of project progress and dependency visualization. The complexity is high due to the need for PDF generation, data collection, and visualization integration. The 6 existing subtasks cover the main implementation areas from library selection to export options."
|
||||
},
|
||||
{
|
||||
"taskId": 75,
|
||||
"taskTitle": "Integrate Google Search Grounding for Research Role",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 4,
|
||||
"expansionPrompt": "The current 4 subtasks for integrating Google Search Grounding appear well-structured. Consider if any additional subtasks are needed for testing with different query types, error handling, or performance optimization.",
|
||||
"reasoning": "This task involves updating the AI service layer to enable Google Search Grounding for research roles. The complexity is moderate as it requires careful integration with the existing AI service architecture and conditional logic. The 4 existing subtasks cover the main implementation areas from service layer modification to testing."
|
||||
},
|
||||
{
|
||||
"taskId": 76,
|
||||
"taskTitle": "Develop E2E Test Framework for Taskmaster MCP Server (FastMCP over stdio)",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "The current 7 subtasks for developing the E2E test framework appear comprehensive. Consider if any additional subtasks are needed for test result reporting, CI/CD integration, or performance benchmarking.",
|
||||
"reasoning": "This task involves creating a sophisticated end-to-end testing framework for the MCP server. The complexity is high due to the need for subprocess management, protocol handling, and robust test case definition. The 7 existing subtasks cover the main implementation areas from architecture to documentation."
|
||||
},
|
||||
{
|
||||
"taskId": 77,
|
||||
"taskTitle": "Implement AI Usage Telemetry for Taskmaster (with external analytics endpoint)",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 18,
|
||||
"expansionPrompt": "The current 18 subtasks for implementing AI usage telemetry appear very comprehensive. Consider if any additional subtasks are needed for security hardening, privacy compliance, or user feedback collection.",
|
||||
"reasoning": "This task involves creating a telemetry system to track AI usage metrics. The complexity is high due to the need for secure data transmission, comprehensive data collection, and integration across multiple commands. The 18 existing subtasks are extremely detailed and cover all aspects of implementation from core utility to provider-specific updates."
|
||||
},
|
||||
{
|
||||
"taskId": 80,
|
||||
"taskTitle": "Implement Unique User ID Generation and Storage During Installation",
|
||||
"complexityScore": 4,
|
||||
"recommendedSubtasks": 5,
|
||||
"expansionPrompt": "The current 5 subtasks for implementing unique user ID generation appear well-structured. Consider if any additional subtasks are needed for privacy compliance, security auditing, or integration with the telemetry system.",
|
||||
"reasoning": "This task involves generating and storing a unique user identifier during installation. The complexity is relatively low as it primarily involves UUID generation and configuration file management. The 5 existing subtasks cover the main implementation areas from script structure to documentation."
|
||||
},
|
||||
{
|
||||
"taskId": 81,
|
||||
"taskTitle": "Task #81: Implement Comprehensive Local Telemetry System with Future Server Integration Capability",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "The current 6 subtasks for implementing the comprehensive local telemetry system appear well-structured. Consider if any additional subtasks are needed for data migration, storage optimization, or visualization tools.",
|
||||
"reasoning": "This task involves expanding the telemetry system to capture additional metrics and implement local storage with future server integration capability. The complexity is high due to the breadth of data collection, storage requirements, and privacy considerations. The 6 existing subtasks cover the main implementation areas from data collection to user-facing benefits."
|
||||
},
|
||||
{
|
||||
"taskId": 82,
|
||||
"taskTitle": "Update supported-models.json with token limit fields",
|
||||
"complexityScore": 3,
|
||||
"recommendedSubtasks": 1,
|
||||
"expansionPrompt": "This task appears straightforward enough to be implemented without further subtasks. Focus on researching accurate token limit values for each model and ensuring backward compatibility.",
|
||||
"reasoning": "This task involves a simple update to the supported-models.json file to include new token limit fields. The complexity is low as it primarily involves research and data entry. No subtasks are necessary as the task is well-defined and focused."
|
||||
},
|
||||
{
|
||||
"taskId": 83,
|
||||
"taskTitle": "Update config-manager.js defaults and getters",
|
||||
"complexityScore": 4,
|
||||
"recommendedSubtasks": 1,
|
||||
"expansionPrompt": "This task appears straightforward enough to be implemented without further subtasks. Focus on updating the DEFAULTS object and related getter functions while maintaining backward compatibility.",
|
||||
"reasoning": "This task involves updating the config-manager.js module to replace maxTokens with more specific token limit fields. The complexity is relatively low as it primarily involves modifying existing code rather than creating new functionality. No subtasks are necessary as the task is well-defined and focused."
|
||||
},
|
||||
{
|
||||
"taskId": 84,
|
||||
"taskTitle": "Implement token counting utility",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 1,
|
||||
"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."
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"taskTitle": "Update ai-services-unified.js for dynamic token limits",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 5,
|
||||
"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 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,
|
||||
"taskTitle": "Update .taskmasterconfig schema and user guide",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 4,
|
||||
"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": "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,
|
||||
"taskTitle": "Implement validation and error handling",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 4,
|
||||
"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 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."
|
||||
}
|
||||
]
|
||||
}
|
||||
53
.taskmaster/reports/task-complexity-report_test-prd-tag.json
Normal file
53
.taskmaster/reports/task-complexity-report_test-prd-tag.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"meta": {
|
||||
"generatedAt": "2025-06-13T06:52:00.611Z",
|
||||
"tasksAnalyzed": 5,
|
||||
"totalTasks": 5,
|
||||
"analysisCount": 5,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Taskmaster",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 1,
|
||||
"taskTitle": "Setup Project Repository and Node.js Environment",
|
||||
"complexityScore": 4,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Break down the setup process into subtasks such as initializing npm, creating directory structure, installing dependencies, configuring package.json, adding configuration files, and setting up the main entry point.",
|
||||
"reasoning": "This task involves several standard setup steps that are well-defined and sequential, with low algorithmic complexity but moderate procedural detail. Each step is independent and can be assigned as a subtask, making the overall complexity moderate."
|
||||
},
|
||||
{
|
||||
"taskId": 2,
|
||||
"taskTitle": "Implement Core Functionality and CLI Interface",
|
||||
"complexityScore": 7,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "Expand into subtasks for implementing main logic, designing CLI commands, creating the CLI entry point, integrating business logic, adding error handling, formatting output, and ensuring CLI executability.",
|
||||
"reasoning": "This task requires both application logic and user interface (CLI) development, including error handling and integration. The need to coordinate between core logic and CLI, plus ensuring usability, increases complexity and warrants detailed subtasking."
|
||||
},
|
||||
{
|
||||
"taskId": 3,
|
||||
"taskTitle": "Implement Testing Suite and Validation",
|
||||
"complexityScore": 6,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Divide into subtasks for configuring Jest, writing unit tests, writing integration tests, testing CLI commands, setting up coverage reporting, and preparing test fixtures/mocks.",
|
||||
"reasoning": "Comprehensive testing involves multiple types of tests and configuration steps. While each is straightforward, the breadth of coverage and need for automation and validation increases the overall complexity."
|
||||
},
|
||||
{
|
||||
"taskId": 4,
|
||||
"taskTitle": "Setup Node.js Project with CLI Interface",
|
||||
"complexityScore": 5,
|
||||
"recommendedSubtasks": 7,
|
||||
"expansionPrompt": "Break down into subtasks for npm initialization, package.json setup, directory structure creation, dependency installation, CLI entry point creation, package.json bin configuration, and CLI executability.",
|
||||
"reasoning": "This task combines project setup with initial CLI implementation. While each step is standard, the integration of CLI elements adds a layer of complexity beyond a basic setup."
|
||||
},
|
||||
{
|
||||
"taskId": 5,
|
||||
"taskTitle": "Implement Core Functionality with Testing",
|
||||
"complexityScore": 8,
|
||||
"recommendedSubtasks": 8,
|
||||
"expansionPrompt": "Expand into subtasks for implementing each feature (A, B, C), setting up the testing framework, writing tests for each feature, integrating CLI with core logic, and adding coverage reporting.",
|
||||
"reasoning": "This task requires simultaneous development of multiple features, integration with CLI, and comprehensive testing. The coordination and depth required for both implementation and validation make it the most complex among the listed tasks."
|
||||
}
|
||||
]
|
||||
}
|
||||
8
.taskmaster/state.json
Normal file
8
.taskmaster/state.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"currentTag": "master",
|
||||
"lastSwitched": "2025-06-14T00:46:38.351Z",
|
||||
"branchTagMapping": {
|
||||
"v017-adds": "v017-adds"
|
||||
},
|
||||
"migrationNoticeShown": true
|
||||
}
|
||||
149
.taskmaster/tasks/task_095.txt
Normal file
149
.taskmaster/tasks/task_095.txt
Normal file
@@ -0,0 +1,149 @@
|
||||
# Task ID: 95
|
||||
# Title: Implement .taskmaster Directory Structure
|
||||
# Status: done
|
||||
# Dependencies: 1, 3, 4, 17
|
||||
# Priority: high
|
||||
# Description: Consolidate all Task Master-managed files in user projects into a clean, centralized .taskmaster/ directory structure to improve organization and keep user project directories clean, based on GitHub issue #275.
|
||||
# Details:
|
||||
This task involves restructuring how Task Master organizes files within user projects to improve maintainability and keep project directories clean:
|
||||
|
||||
1. Create a new `.taskmaster/` directory structure in user projects:
|
||||
- Move task files from `tasks/` to `.taskmaster/tasks/`
|
||||
- Move PRD files from `scripts/` to `.taskmaster/docs/`
|
||||
- Move analysis reports to `.taskmaster/reports/`
|
||||
- Move configuration from `.taskmasterconfig` to `.taskmaster/config.json`
|
||||
- Create `.taskmaster/templates/` for user templates
|
||||
|
||||
2. Update all Task Master code that creates/reads user files:
|
||||
- Modify task file generation to use `.taskmaster/tasks/`
|
||||
- Update PRD file handling to use `.taskmaster/docs/`
|
||||
- Adjust report generation to save to `.taskmaster/reports/`
|
||||
- Update configuration loading to look for `.taskmaster/config.json`
|
||||
- Modify any path resolution logic in Task Master's codebase
|
||||
|
||||
3. Ensure backward compatibility during migration:
|
||||
- Implement path fallback logic that checks both old and new locations
|
||||
- Add deprecation warnings when old paths are detected
|
||||
- Create a migration command to help users transition to the new structure
|
||||
- Preserve existing user data during migration
|
||||
|
||||
4. Update the project initialization process:
|
||||
- Modify the init command to create the new `.taskmaster/` directory structure
|
||||
- Update default file creation to use new paths
|
||||
|
||||
5. Benefits of the new structure:
|
||||
- Keeps user project directories clean and organized
|
||||
- Clearly separates Task Master files from user project files
|
||||
- Makes it easier to add Task Master to .gitignore if desired
|
||||
- Provides logical grouping of different file types
|
||||
|
||||
6. Test thoroughly to ensure all functionality works with the new structure:
|
||||
- Verify all Task Master commands work with the new paths
|
||||
- Ensure backward compatibility functions correctly
|
||||
- Test migration process preserves all user data
|
||||
|
||||
7. Update documentation:
|
||||
- Update README.md to reflect the new user file structure
|
||||
- Add migration guide for existing users
|
||||
- Document the benefits of the cleaner organization
|
||||
|
||||
# Test Strategy:
|
||||
1. Unit Testing:
|
||||
- Create unit tests for path resolution that verify both new and old paths work
|
||||
- Test configuration loading with both `.taskmasterconfig` and `.taskmaster/config.json`
|
||||
- Verify the migration command correctly moves files and preserves content
|
||||
- Test file creation in all new subdirectories
|
||||
|
||||
2. Integration Testing:
|
||||
- Run all existing integration tests with the new directory structure
|
||||
- Verify that all Task Master commands function correctly with new paths
|
||||
- Test backward compatibility by running commands with old file structure
|
||||
|
||||
3. Migration Testing:
|
||||
- Test the migration process on sample projects with existing tasks and files
|
||||
- Verify all tasks, PRDs, reports, and configurations are correctly moved
|
||||
- Ensure no data loss occurs during migration
|
||||
- Test migration with partial existing structures (e.g., only tasks/ exists)
|
||||
|
||||
4. User Workflow Testing:
|
||||
- Test complete workflows: init → create tasks → generate reports → update PRDs
|
||||
- Verify all generated files go to correct locations in `.taskmaster/`
|
||||
- Test that user project directories remain clean
|
||||
|
||||
5. Manual Testing:
|
||||
- Perform end-to-end testing with the new structure
|
||||
- Create, update, and delete tasks using the new structure
|
||||
- Generate reports and verify they're saved to `.taskmaster/reports/`
|
||||
|
||||
6. Documentation Verification:
|
||||
- Review all documentation to ensure it accurately reflects the new user file structure
|
||||
- Verify the migration guide provides clear instructions
|
||||
|
||||
7. Regression Testing:
|
||||
- Run the full test suite to ensure no regressions were introduced
|
||||
- Verify existing user projects continue to work during transition period
|
||||
|
||||
# Subtasks:
|
||||
## 1. Create .taskmaster directory structure [done]
|
||||
### Dependencies: None
|
||||
### Description: Create the new .taskmaster directory and move existing files to their new locations
|
||||
### Details:
|
||||
Create a new .taskmaster/ directory in the project root. Move the tasks/ directory to .taskmaster/tasks/. Move the scripts/ directory to .taskmaster/scripts/. Move the .taskmasterconfig file to .taskmaster/config.json. Ensure proper file permissions are maintained during the move.
|
||||
<info added on 2025-05-29T15:03:56.912Z>
|
||||
Create the new .taskmaster/ directory structure in user projects with subdirectories for tasks/, docs/, reports/, and templates/. Move the existing .taskmasterconfig file to .taskmaster/config.json. Since this project is also a Task Master user, move this project's current user files (tasks.json, PRD files, etc.) to the new .taskmaster/ structure to test the implementation. This subtask focuses on user project directory structure, not Task Master source code relocation.
|
||||
</info added on 2025-05-29T15:03:56.912Z>
|
||||
|
||||
## 2. Update Task Master code for new user file paths [done]
|
||||
### Dependencies: 95.1
|
||||
### Description: Modify all Task Master code that creates or reads user project files to use the new .taskmaster structure
|
||||
### Details:
|
||||
Update Task Master's file handling code to use the new paths: tasks in .taskmaster/tasks/, PRD files in .taskmaster/docs/, reports in .taskmaster/reports/, and config in .taskmaster/config.json. Modify path resolution logic throughout the Task Master codebase to reference the new user file locations.
|
||||
|
||||
## 3. Update task file generation system [done]
|
||||
### Dependencies: 95.1
|
||||
### Description: Modify the task file generation system to use the new directory structure
|
||||
### Details:
|
||||
Update the task file generation system to create and read task files from .taskmaster/tasks/ instead of tasks/. Ensure all template paths are updated. Modify any path resolution logic specific to task file handling.
|
||||
|
||||
## 4. Implement backward compatibility logic [done]
|
||||
### Dependencies: 95.2, 95.3
|
||||
### Description: Add fallback mechanisms to support both old and new file locations during transition
|
||||
### Details:
|
||||
Implement path fallback logic that checks both old and new locations when files aren't found. Add deprecation warnings when old paths are used, informing users about the new structure. Ensure error messages are clear about the transition.
|
||||
|
||||
## 5. Create migration command for users [done]
|
||||
### Dependencies: 95.1, 95.4
|
||||
### Description: Develop a Task Master command to help users transition their existing projects to the new structure
|
||||
### Details:
|
||||
Create a 'taskmaster migrate' command that automatically moves user files from old locations to the new .taskmaster structure. Move tasks/ to .taskmaster/tasks/, scripts/prd.txt to .taskmaster/docs/, reports to .taskmaster/reports/, and .taskmasterconfig to .taskmaster/config.json. Include backup functionality and validation to ensure migration completed successfully.
|
||||
|
||||
## 6. Update project initialization process [done]
|
||||
### Dependencies: 95.1
|
||||
### Description: Modify the init command to create the new directory structure for new projects
|
||||
### Details:
|
||||
Update the init command to create the .taskmaster directory and its subdirectories (tasks/, docs/, reports/, templates/). Modify default file creation to use the new paths. Ensure new projects are created with the correct structure from the start.
|
||||
|
||||
## 7. Update PRD and report file handling [done]
|
||||
### Dependencies: 95.2, 95.6
|
||||
### Description: Modify PRD file creation and report generation to use the new directory structure
|
||||
### Details:
|
||||
Update PRD file handling to create and read files from .taskmaster/docs/ instead of scripts/. Modify report generation (like task-complexity-report.json) to save to .taskmaster/reports/. Ensure all file operations use the new paths consistently.
|
||||
|
||||
## 8. Update documentation and create migration guide [done]
|
||||
### Dependencies: 95.5, 95.6, 95.7
|
||||
### Description: Update all documentation to reflect the new directory structure and provide migration guidance
|
||||
### Details:
|
||||
Update README.md and other documentation to reflect the new .taskmaster structure for user projects. Create a comprehensive migration guide explaining the benefits of the new structure and how to migrate existing projects. Include examples of the new directory layout and explain how it keeps user project directories clean.
|
||||
|
||||
## 9. Add templates directory support [done]
|
||||
### Dependencies: 95.2, 95.6
|
||||
### Description: Implement support for user templates in the .taskmaster/templates/ directory
|
||||
### Details:
|
||||
Create functionality to support user-defined templates in .taskmaster/templates/. Allow users to store custom task templates, PRD templates, or other reusable files. Update Task Master commands to recognize and use templates from this directory when available.
|
||||
|
||||
## 10. Verify clean user project directories [done]
|
||||
### Dependencies: 95.8, 95.9
|
||||
### Description: Ensure the new structure keeps user project root directories clean and organized
|
||||
### Details:
|
||||
Validate that after implementing the new structure, user project root directories only contain their actual project files plus the single .taskmaster/ directory. Verify that no Task Master files are created outside of .taskmaster/. Test that users can easily add .taskmaster/ to .gitignore if they choose to exclude Task Master files from version control.
|
||||
|
||||
37
.taskmaster/tasks/task_096.txt
Normal file
37
.taskmaster/tasks/task_096.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
# Task ID: 96
|
||||
# Title: Create Export Command for On-Demand Task File and PDF Generation
|
||||
# Status: pending
|
||||
# Dependencies: 2, 4, 95
|
||||
# Priority: medium
|
||||
# Description: Develop an 'export' CLI command that generates task files and comprehensive PDF exports on-demand, replacing automatic file generation and providing users with flexible export options.
|
||||
# Details:
|
||||
Implement a new 'export' command in the CLI that supports two primary modes: (1) generating individual task files on-demand (superseding the current automatic generation system), and (2) producing a comprehensive PDF export. The PDF should include: a first page with the output of 'tm list --with-subtasks', followed by individual pages for each task (using 'tm show <task_id>') and each subtask (using 'tm show <subtask_id>'). Integrate PDF generation using a robust library (e.g., pdfkit, Puppeteer, or jsPDF) to ensure high-quality output and proper pagination. Refactor or disable any existing automatic file generation logic to avoid performance overhead. Ensure the command supports flexible output paths and options for exporting only files, only PDF, or both. Update documentation and help output to reflect the new export capabilities. Consider concurrency and error handling for large projects. Ensure the export process is efficient and does not block the main CLI thread unnecessarily.
|
||||
|
||||
# Test Strategy:
|
||||
1. Run the 'export' command with various options and verify that task files are generated only on-demand, not automatically. 2. Generate a PDF export and confirm that the first page contains the correct 'tm list --with-subtasks' output, and that each subsequent page accurately reflects the output of 'tm show <task_id>' and 'tm show <subtask_id>' for all tasks and subtasks. 3. Test exporting in projects with large numbers of tasks and subtasks to ensure performance and correctness. 4. Attempt exports with invalid paths or missing data to verify robust error handling. 5. Confirm that no automatic file generation occurs during normal task operations. 6. Review CLI help output and documentation for accuracy regarding the new export functionality.
|
||||
|
||||
# Subtasks:
|
||||
## 1. Remove Automatic Task File Generation from Task Operations [pending]
|
||||
### Dependencies: None
|
||||
### Description: Eliminate all calls to generateTaskFiles() from task operations such as add-task, remove-task, set-status, and similar commands to prevent unnecessary performance overhead.
|
||||
### Details:
|
||||
Audit the codebase for any automatic invocations of generateTaskFiles() and remove or refactor them to ensure task files are not generated automatically during task operations.
|
||||
|
||||
## 2. Implement Export Command Infrastructure with On-Demand Task File Generation [pending]
|
||||
### Dependencies: 96.1
|
||||
### Description: Develop the CLI 'export' command infrastructure, enabling users to generate task files on-demand by invoking the preserved generateTaskFiles function only when requested.
|
||||
### Details:
|
||||
Create the export command with options for output paths and modes (files, PDF, or both). Ensure generateTaskFiles is only called within this command and not elsewhere.
|
||||
|
||||
## 3. Implement Comprehensive PDF Export Functionality [pending]
|
||||
### Dependencies: 96.2
|
||||
### Description: Add PDF export capability to the export command, generating a structured PDF with a first page listing all tasks and subtasks, followed by individual pages for each task and subtask, using a robust PDF library.
|
||||
### Details:
|
||||
Integrate a PDF generation library (e.g., pdfkit, Puppeteer, or jsPDF). Ensure the PDF includes the output of 'tm list --with-subtasks' on the first page, and uses 'tm show <task_id>' and 'tm show <subtask_id>' for subsequent pages. Handle pagination, concurrency, and error handling for large projects.
|
||||
|
||||
## 4. Update Documentation, Tests, and CLI Help for Export Workflow [pending]
|
||||
### Dependencies: 96.2, 96.3
|
||||
### Description: Revise all relevant documentation, automated tests, and CLI help output to reflect the new export-based workflow and available options.
|
||||
### Details:
|
||||
Update user guides, README files, and CLI help text. Add or modify tests to cover the new export command and its options. Ensure all documentation accurately describes the new workflow and usage.
|
||||
|
||||
12639
.taskmaster/tasks/tasks.json
Normal file
12639
.taskmaster/tasks/tasks.json
Normal file
File diff suppressed because one or more lines are too long
144
CHANGELOG.md
144
CHANGELOG.md
@@ -1,5 +1,149 @@
|
||||
# task-master-ai
|
||||
|
||||
## 0.16.2-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#655](https://github.com/eyaltoledano/claude-task-master/pull/655) [`edaa5fe`](https://github.com/eyaltoledano/claude-task-master/commit/edaa5fe0d56e0e4e7c4370670a7a388eebd922ac) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix double .taskmaster directory paths in file resolution utilities
|
||||
|
||||
- Closes #636
|
||||
|
||||
- [#671](https://github.com/eyaltoledano/claude-task-master/pull/671) [`86ea6d1`](https://github.com/eyaltoledano/claude-task-master/commit/86ea6d1dbc03eeb39f524f565b50b7017b1d2c9c) Thanks [@joedanz](https://github.com/joedanz)! - Add one-click MCP server installation for Cursor
|
||||
|
||||
## 0.16.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#641](https://github.com/eyaltoledano/claude-task-master/pull/641) [`ad61276`](https://github.com/eyaltoledano/claude-task-master/commit/ad612763ffbdd35aa1b593c9613edc1dc27a8856) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix bedrock issues
|
||||
|
||||
- [#648](https://github.com/eyaltoledano/claude-task-master/pull/648) [`9b4168b`](https://github.com/eyaltoledano/claude-task-master/commit/9b4168bb4e4dfc2f4fb0cf6bd5f81a8565879176) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix MCP tool calls logging errors
|
||||
|
||||
- [#641](https://github.com/eyaltoledano/claude-task-master/pull/641) [`ad61276`](https://github.com/eyaltoledano/claude-task-master/commit/ad612763ffbdd35aa1b593c9613edc1dc27a8856) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Update rules for new directory structure
|
||||
|
||||
- [#648](https://github.com/eyaltoledano/claude-task-master/pull/648) [`9b4168b`](https://github.com/eyaltoledano/claude-task-master/commit/9b4168bb4e4dfc2f4fb0cf6bd5f81a8565879176) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix bug in expand_all mcp tool
|
||||
|
||||
- [#641](https://github.com/eyaltoledano/claude-task-master/pull/641) [`ad61276`](https://github.com/eyaltoledano/claude-task-master/commit/ad612763ffbdd35aa1b593c9613edc1dc27a8856) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix MCP crashing after certain commands due to console logs
|
||||
|
||||
## 0.16.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add AWS bedrock support
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - # Add Google Vertex AI Provider Integration
|
||||
|
||||
- Implemented `VertexAIProvider` class extending BaseAIProvider
|
||||
- Added authentication and configuration handling for Vertex AI
|
||||
- Updated configuration manager with Vertex-specific getters
|
||||
- Modified AI services unified system to integrate the provider
|
||||
- Added documentation for Vertex AI setup and configuration
|
||||
- Updated environment variable examples for Vertex AI support
|
||||
- Implemented specialized error handling for Vertex-specific issues
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add support for Azure
|
||||
|
||||
- [#612](https://github.com/eyaltoledano/claude-task-master/pull/612) [`669b744`](https://github.com/eyaltoledano/claude-task-master/commit/669b744ced454116a7b29de6c58b4b8da977186a) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Increased minimum required node version to > 18 (was > 14)
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Renamed baseUrl to baseURL
|
||||
|
||||
- [#604](https://github.com/eyaltoledano/claude-task-master/pull/604) [`80735f9`](https://github.com/eyaltoledano/claude-task-master/commit/80735f9e60c7dda7207e169697f8ac07b6733634) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add TASK_MASTER_PROJECT_ROOT env variable supported in mcp.json and .env for project root resolution
|
||||
|
||||
- Some users were having issues where the MCP wasn't able to detect the location of their project root, you can now set the `TASK_MASTER_PROJECT_ROOT` environment variable to the root of your project.
|
||||
|
||||
- [#619](https://github.com/eyaltoledano/claude-task-master/pull/619) [`3f64202`](https://github.com/eyaltoledano/claude-task-master/commit/3f64202c9feef83f2bf383c79e4367d337c37e20) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Consolidate Task Master files into unified .taskmaster directory structure
|
||||
|
||||
This release introduces a new consolidated directory structure that organizes all Task Master files under a single `.taskmaster/` directory for better project organization and cleaner workspace management.
|
||||
|
||||
**New Directory Structure:**
|
||||
|
||||
- `.taskmaster/tasks/` - Task files (previously `tasks/`)
|
||||
- `.taskmaster/docs/` - Documentation including PRD files (previously `scripts/`)
|
||||
- `.taskmaster/reports/` - Complexity analysis reports (previously `scripts/`)
|
||||
- `.taskmaster/templates/` - Template files like example PRD
|
||||
- `.taskmaster/config.json` - Configuration (previously `.taskmasterconfig`)
|
||||
|
||||
**Migration & Backward Compatibility:**
|
||||
|
||||
- Existing projects continue to work with legacy file locations
|
||||
- New projects use the consolidated structure automatically
|
||||
- Run `task-master migrate` to move existing projects to the new structure
|
||||
- All CLI commands and MCP tools automatically detect and use appropriate file locations
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Cleaner project root with Task Master files organized in one location
|
||||
- Reduced file scatter across multiple directories
|
||||
- Improved project navigation and maintenance
|
||||
- Consistent file organization across all Task Master projects
|
||||
|
||||
This change maintains full backward compatibility while providing a migration path to the improved structure.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix max_tokens error when trying to use claude-sonnet-4 and claude-opus-4
|
||||
|
||||
- [#625](https://github.com/eyaltoledano/claude-task-master/pull/625) [`2d520de`](https://github.com/eyaltoledano/claude-task-master/commit/2d520de2694da3efe537b475ca52baf3c869edda) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix add-task MCP command causing an error
|
||||
|
||||
## 0.16.0-rc.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add AWS bedrock support
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - # Add Google Vertex AI Provider Integration
|
||||
|
||||
- Implemented `VertexAIProvider` class extending BaseAIProvider
|
||||
- Added authentication and configuration handling for Vertex AI
|
||||
- Updated configuration manager with Vertex-specific getters
|
||||
- Modified AI services unified system to integrate the provider
|
||||
- Added documentation for Vertex AI setup and configuration
|
||||
- Updated environment variable examples for Vertex AI support
|
||||
- Implemented specialized error handling for Vertex-specific issues
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add support for Azure
|
||||
|
||||
- [#612](https://github.com/eyaltoledano/claude-task-master/pull/612) [`669b744`](https://github.com/eyaltoledano/claude-task-master/commit/669b744ced454116a7b29de6c58b4b8da977186a) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Increased minimum required node version to > 18 (was > 14)
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Renamed baseUrl to baseURL
|
||||
|
||||
- [#604](https://github.com/eyaltoledano/claude-task-master/pull/604) [`80735f9`](https://github.com/eyaltoledano/claude-task-master/commit/80735f9e60c7dda7207e169697f8ac07b6733634) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add TASK_MASTER_PROJECT_ROOT env variable supported in mcp.json and .env for project root resolution
|
||||
|
||||
- Some users were having issues where the MCP wasn't able to detect the location of their project root, you can now set the `TASK_MASTER_PROJECT_ROOT` environment variable to the root of your project.
|
||||
|
||||
- [#619](https://github.com/eyaltoledano/claude-task-master/pull/619) [`3f64202`](https://github.com/eyaltoledano/claude-task-master/commit/3f64202c9feef83f2bf383c79e4367d337c37e20) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Consolidate Task Master files into unified .taskmaster directory structure
|
||||
|
||||
This release introduces a new consolidated directory structure that organizes all Task Master files under a single `.taskmaster/` directory for better project organization and cleaner workspace management.
|
||||
|
||||
**New Directory Structure:**
|
||||
|
||||
- `.taskmaster/tasks/` - Task files (previously `tasks/`)
|
||||
- `.taskmaster/docs/` - Documentation including PRD files (previously `scripts/`)
|
||||
- `.taskmaster/reports/` - Complexity analysis reports (previously `scripts/`)
|
||||
- `.taskmaster/templates/` - Template files like example PRD
|
||||
- `.taskmaster/config.json` - Configuration (previously `.taskmasterconfig`)
|
||||
|
||||
**Migration & Backward Compatibility:**
|
||||
|
||||
- Existing projects continue to work with legacy file locations
|
||||
- New projects use the consolidated structure automatically
|
||||
- Run `task-master migrate` to move existing projects to the new structure
|
||||
- All CLI commands and MCP tools automatically detect and use appropriate file locations
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Cleaner project root with Task Master files organized in one location
|
||||
- Reduced file scatter across multiple directories
|
||||
- Improved project navigation and maintenance
|
||||
- Consistent file organization across all Task Master projects
|
||||
|
||||
This change maintains full backward compatibility while providing a migration path to the improved structure.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#607](https://github.com/eyaltoledano/claude-task-master/pull/607) [`6a8a68e`](https://github.com/eyaltoledano/claude-task-master/commit/6a8a68e1a3f34dcdf40b355b4602a08d291f8e38) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Fix max_tokens error when trying to use claude-sonnet-4 and claude-opus-4
|
||||
|
||||
- [#597](https://github.com/eyaltoledano/claude-task-master/pull/597) [`2d520de`](https://github.com/eyaltoledano/claude-task-master/commit/2d520de2694da3efe537b475ca52baf3c869edda) Thanks [@eyaltoledano](https://github.com/eyaltoledano)! - Fix add-task MCP command causing an error
|
||||
|
||||
## 0.15.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -170,7 +170,7 @@ Example:
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 14+
|
||||
- Node.js 18+
|
||||
- npm or yarn
|
||||
|
||||
### Environment Setup
|
||||
|
||||
138
README.md
138
README.md
@@ -2,13 +2,37 @@
|
||||
|
||||
[](https://github.com/eyaltoledano/claude-task-master/actions/workflows/ci.yml) [](https://badge.fury.io/js/task-master-ai) [](https://discord.gg/taskmasterai) [](LICENSE)
|
||||
|
||||
### By [@eyaltoledano](https://x.com/eyaltoledano) & [@RalphEcom](https://x.com/RalphEcom)
|
||||
[](https://www.npmjs.com/package/task-master-ai) [](https://www.npmjs.com/package/task-master-ai) [](https://www.npmjs.com/package/task-master-ai)
|
||||
|
||||
[](https://x.com/eyaltoledano)
|
||||
[](https://x.com/RalphEcom)
|
||||
## By [@eyaltoledano](https://x.com/eyaltoledano), [@RalphEcom](https://x.com/RalphEcom) & [@jasonzhou1993](https://x.com/jasonzhou1993)
|
||||
|
||||
[](https://x.com/eyaltoledano)
|
||||
[](https://x.com/RalphEcom)
|
||||
[](https://x.com/jasonzhou1993)
|
||||
|
||||
A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI.
|
||||
|
||||
## Documentation
|
||||
|
||||
For more detailed information, check out the documentation in the `docs` directory:
|
||||
|
||||
- [Configuration Guide](docs/configuration.md) - Set up environment variables and customize Task Master
|
||||
- [Tutorial](docs/tutorial.md) - Step-by-step guide to getting started with Task Master
|
||||
- [Command Reference](docs/command-reference.md) - Complete list of all available commands
|
||||
- [Task Structure](docs/task-structure.md) - Understanding the task format and features
|
||||
- [Example Interactions](docs/examples.md) - Common Cursor AI interaction examples
|
||||
- [Migration Guide](docs/migration-guide.md) - Guide to migrating to the new project structure
|
||||
|
||||
#### Quick Install for Cursor 1.0+ (One-Click)
|
||||
|
||||
📋 Click the copy button (top-right of code block) then paste into your browser:
|
||||
|
||||
```text
|
||||
cursor://anysphere.cursor-deeplink/mcp/install?name=taskmaster-ai&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIi0tcGFja2FnZT10YXNrLW1hc3Rlci1haSIsInRhc2stbWFzdGVyLWFpIl0sImVudiI6eyJBTlRIUk9QSUNfQVBJX0tFWSI6IllPVVJfQU5USFJPUElDX0FQSV9LRVlfSEVSRSIsIlBFUlBMRVhJVFlfQVBJX0tFWSI6IllPVVJfUEVSUExFWElUWV9BUElfS0VZX0hFUkUiLCJPUEVOQUlfQVBJX0tFWSI6IllPVVJfT1BFTkFJX0tFWV9IRVJFIiwiR09PR0xFX0FQSV9LRVkiOiJZT1VSX0dPT0dMRV9LRVlfSEVSRSIsIk1JU1RSQUxfQVBJX0tFWSI6IllPVVJfTUlTVFJBTF9LRVlfSEVSRSIsIk9QRU5ST1VURVJfQVBJX0tFWSI6IllPVVJfT1BFTlJPVVRFUl9LRVlfSEVSRSIsIlhBSV9BUElfS0VZIjoiWU9VUl9YQUlfS0VZX0hFUkUiLCJBWlVSRV9PUEVOQUlfQVBJX0tFWSI6IllPVVJfQVpVUkVfS0VZX0hFUkUiLCJPTExBTUFfQVBJX0tFWSI6IllPVVJfT0xMQU1BX0FQSV9LRVlfSEVSRSJ9fQo=
|
||||
```
|
||||
|
||||
> **Note:** After clicking the link, you'll still need to add your API keys to the configuration. The link installs the MCP server with placeholder keys that you'll need to replace with your actual API keys.
|
||||
|
||||
## Requirements
|
||||
|
||||
Taskmaster utilizes AI across several commands, and those require a separate API key. You can use a variety of models from different AI providers provided you add your API keys. For example, if you want to use Claude 3.7, you'll need an Anthropic API key.
|
||||
@@ -39,55 +63,57 @@ MCP (Model Control Protocol) lets you run Task Master directly from your editor.
|
||||
| **Cursor** | Global | `~/.cursor/mcp.json` | `%USERPROFILE%\.cursor\mcp.json` | `mcpServers` |
|
||||
| | Project | `<project_folder>/.cursor/mcp.json` | `<project_folder>\.cursor\mcp.json` | `mcpServers` |
|
||||
| **Windsurf** | Global | `~/.codeium/windsurf/mcp_config.json` | `%USERPROFILE%\.codeium\windsurf\mcp_config.json` | `mcpServers` |
|
||||
| **VS Code** | Project | `<project_folder>/.vscode/mcp.json` | `<project_folder>\.vscode\mcp.json` | `servers` |
|
||||
| **VS Code** | Project | `<project_folder>/.vscode/mcp.json` | `<project_folder>\.vscode\mcp.json` | `servers` |
|
||||
|
||||
##### Cursor & Windsurf (`mcpServers`)
|
||||
##### Manual Configuration
|
||||
|
||||
```jsonc
|
||||
###### Cursor & Windsurf (`mcpServers`)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE",
|
||||
"OLLAMA_API_KEY": "YOUR_OLLAMA_API_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
"mcpServers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE",
|
||||
"OLLAMA_API_KEY": "YOUR_OLLAMA_API_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 🔑 Replace `YOUR_…_KEY_HERE` with your real API keys. You can remove keys you don't use.
|
||||
|
||||
##### VS Code (`servers` + `type`)
|
||||
###### VS Code (`servers` + `type`)
|
||||
|
||||
```jsonc
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE"
|
||||
},
|
||||
"type": "stdio"
|
||||
}
|
||||
}
|
||||
"servers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE"
|
||||
},
|
||||
"type": "stdio"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -99,7 +125,7 @@ Open Cursor Settings (Ctrl+Shift+J) ➡ Click on MCP tab on the left ➡ Enable
|
||||
|
||||
#### 3. (Optional) Configure the models you want to use
|
||||
|
||||
In your editor’s AI chat pane, say:
|
||||
In your editor's AI chat pane, say:
|
||||
|
||||
```txt
|
||||
Change the main, research and fallback models to <model_name>, <model_name> and <model_name> respectively.
|
||||
@@ -109,15 +135,21 @@ Change the main, research and fallback models to <model_name>, <model_name> and
|
||||
|
||||
#### 4. Initialize Task Master
|
||||
|
||||
In your editor’s AI chat pane, say:
|
||||
In your editor's AI chat pane, say:
|
||||
|
||||
```txt
|
||||
Initialize taskmaster-ai in my project
|
||||
```
|
||||
|
||||
#### 5. Make sure you have a PRD in `<project_folder>/scripts/prd.txt`
|
||||
#### 5. Make sure you have a PRD (Recommended)
|
||||
|
||||
An example of a PRD is located into `<project_folder>/scripts/example_prd.txt`.
|
||||
For **new projects**: Create your PRD at `.taskmaster/docs/prd.txt`
|
||||
For **existing projects**: You can use `scripts/prd.txt` or migrate with `task-master migrate`
|
||||
|
||||
An example PRD template is available after initialization in `.taskmaster/templates/example_prd.txt`.
|
||||
|
||||
> [!NOTE]
|
||||
> While a PRD is recommended for complex projects, you can always create individual tasks by asking "Can you help me implement [description of what you want to do]?" in chat.
|
||||
|
||||
**Always start with a detailed PRD.**
|
||||
|
||||
@@ -128,7 +160,7 @@ The more detailed your PRD, the better the generated tasks will be.
|
||||
Use your AI assistant to:
|
||||
|
||||
- Parse requirements: `Can you parse my PRD at scripts/prd.txt?`
|
||||
- Plan next step: `What’s the next task I should work on?`
|
||||
- Plan next step: `What's the next task I should work on?`
|
||||
- Implement a task: `Can you help me implement task 3?`
|
||||
- View multiple tasks: `Can you show me tasks 1, 3, and 5?`
|
||||
- Expand a task: `Can you help me expand task 4?`
|
||||
@@ -186,19 +218,9 @@ task-master research "What are the latest best practices for JWT authentication?
|
||||
task-master generate
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For more detailed information, check out the documentation in the `docs` directory:
|
||||
|
||||
- [Configuration Guide](docs/configuration.md) - Set up environment variables and customize Task Master
|
||||
- [Tutorial](docs/tutorial.md) - Step-by-step guide to getting started with Task Master
|
||||
- [Command Reference](docs/command-reference.md) - Complete list of all available commands
|
||||
- [Task Structure](docs/task-structure.md) - Understanding the task format and features
|
||||
- [Example Interactions](docs/examples.md) - Common Cursor AI interaction examples
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### If `task-master init` doesn't respond:
|
||||
### If `task-master init` doesn't respond
|
||||
|
||||
Try running it with Node directly:
|
||||
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
Below you will find a variety of important rules spanning:
|
||||
|
||||
- the dev_workflow
|
||||
- the .windsurfrules document self-improvement workflow
|
||||
- the template to follow when modifying or adding new sections/rules to this document.
|
||||
|
||||
---
|
||||
DEV_WORKFLOW
|
||||
---
|
||||
|
||||
## DEV_WORKFLOW
|
||||
|
||||
description: Guide for using meta-development script (scripts/dev.js) to manage task-driven development workflows
|
||||
globs: **/*
|
||||
filesToApplyRule: **/*
|
||||
globs: **/\*
|
||||
filesToApplyRule: **/\*
|
||||
alwaysApply: true
|
||||
|
||||
---
|
||||
|
||||
- **Global CLI Commands**
|
||||
|
||||
- Task Master now provides a global CLI through the `task-master` command
|
||||
- All functionality from `scripts/dev.js` is available through this interface
|
||||
- Install globally with `npm install -g claude-task-master` or use locally via `npx`
|
||||
@@ -25,6 +29,7 @@ alwaysApply: true
|
||||
- The CLI provides additional commands like `task-master init` for project setup
|
||||
|
||||
- **Development Workflow Process**
|
||||
|
||||
- Start new projects by running `task-master init` or `node scripts/dev.js parse-prd --input=<prd-file.txt>` to generate initial tasks.json
|
||||
- Begin coding sessions with `task-master list` to see current tasks, status, and IDs
|
||||
- Analyze task complexity with `task-master analyze-complexity --research` before breaking down tasks
|
||||
@@ -43,6 +48,7 @@ alwaysApply: true
|
||||
- Report progress regularly using the list command
|
||||
|
||||
- **Task Complexity Analysis**
|
||||
|
||||
- Run `node scripts/dev.js analyze-complexity --research` for comprehensive analysis
|
||||
- Review complexity report in scripts/task-complexity-report.json
|
||||
- Or use `node scripts/dev.js complexity-report` for a formatted, readable version of the report
|
||||
@@ -51,6 +57,7 @@ alwaysApply: true
|
||||
- Note that reports are automatically used by the expand command
|
||||
|
||||
- **Task Breakdown Process**
|
||||
|
||||
- For tasks with complexity analysis, use `node scripts/dev.js expand --id=<id>`
|
||||
- Otherwise use `node scripts/dev.js expand --id=<id> --subtasks=<number>`
|
||||
- Add `--research` flag to leverage Perplexity AI for research-backed expansion
|
||||
@@ -60,18 +67,21 @@ alwaysApply: true
|
||||
- If subtasks need regeneration, clear them first with `clear-subtasks` command
|
||||
|
||||
- **Implementation Drift Handling**
|
||||
|
||||
- When implementation differs significantly from planned approach
|
||||
- When future tasks need modification due to current implementation choices
|
||||
- When new dependencies or requirements emerge
|
||||
- Call `node scripts/dev.js update --from=<futureTaskId> --prompt="<explanation>"` to update tasks.json
|
||||
|
||||
- **Task Status Management**
|
||||
|
||||
- Use 'pending' for tasks ready to be worked on
|
||||
- Use 'done' for completed and verified tasks
|
||||
- Use 'deferred' for postponed tasks
|
||||
- Add custom status values as needed for project-specific workflows
|
||||
|
||||
- **Task File Format Reference**
|
||||
|
||||
```
|
||||
# Task ID: <id>
|
||||
# Title: <title>
|
||||
@@ -87,6 +97,7 @@ alwaysApply: true
|
||||
```
|
||||
|
||||
- **Command Reference: parse-prd**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js parse-prd --input=<prd-file.txt>`
|
||||
- CLI Syntax: `task-master parse-prd --input=<prd-file.txt>`
|
||||
- Description: Parses a PRD document and generates a tasks.json file with structured tasks
|
||||
@@ -96,6 +107,7 @@ alwaysApply: true
|
||||
- Notes: Will overwrite existing tasks.json file. Use with caution.
|
||||
|
||||
- **Command Reference: update**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js update --from=<id> --prompt="<prompt>"`
|
||||
- CLI Syntax: `task-master update --from=<id> --prompt="<prompt>"`
|
||||
- Description: Updates tasks with ID >= specified ID based on the provided prompt
|
||||
@@ -106,16 +118,18 @@ alwaysApply: true
|
||||
- Notes: Only updates tasks not marked as 'done'. Completed tasks remain unchanged.
|
||||
|
||||
- **Command Reference: generate**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js generate`
|
||||
- CLI Syntax: `task-master generate`
|
||||
- Description: Generates individual task files in tasks/ directory based on tasks.json
|
||||
- Description: Generates individual task files based on tasks.json
|
||||
- Parameters:
|
||||
- `--file=<path>, -f`: Use alternative tasks.json file (default: 'tasks/tasks.json')
|
||||
- `--output=<dir>, -o`: Output directory (default: 'tasks')
|
||||
- `--file=<path>, -f`: Use alternative tasks.json file (default: '.taskmaster/tasks/tasks.json')
|
||||
- `--output=<dir>, -o`: Output directory (default: '.taskmaster/tasks')
|
||||
- Example: `task-master generate`
|
||||
- Notes: Overwrites existing task files. Creates tasks/ directory if needed.
|
||||
- Notes: Overwrites existing task files. Creates output directory if needed.
|
||||
|
||||
- **Command Reference: set-status**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js set-status --id=<id> --status=<status>`
|
||||
- CLI Syntax: `task-master set-status --id=<id> --status=<status>`
|
||||
- Description: Updates the status of a specific task in tasks.json
|
||||
@@ -126,6 +140,7 @@ alwaysApply: true
|
||||
- Notes: Common values are 'done', 'pending', and 'deferred', but any string is accepted.
|
||||
|
||||
- **Command Reference: list**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js list`
|
||||
- CLI Syntax: `task-master list`
|
||||
- Description: Lists all tasks in tasks.json with IDs, titles, and status
|
||||
@@ -137,6 +152,7 @@ alwaysApply: true
|
||||
- Notes: Provides quick overview of project progress. Use at start of sessions.
|
||||
|
||||
- **Command Reference: expand**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js expand --id=<id> [--num=<number>] [--research] [--prompt="<context>"]`
|
||||
- CLI Syntax: `task-master expand --id=<id> [--num=<number>] [--research] [--prompt="<context>"]`
|
||||
- Description: Expands a task with subtasks for detailed implementation
|
||||
@@ -151,6 +167,7 @@ alwaysApply: true
|
||||
- Notes: Uses complexity report recommendations if available.
|
||||
|
||||
- **Command Reference: analyze-complexity**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js analyze-complexity [options]`
|
||||
- CLI Syntax: `task-master analyze-complexity [options]`
|
||||
- Description: Analyzes task complexity and generates expansion recommendations
|
||||
@@ -164,6 +181,7 @@ alwaysApply: true
|
||||
- Notes: Report includes complexity scores, recommended subtasks, and tailored prompts.
|
||||
|
||||
- **Command Reference: clear-subtasks**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js clear-subtasks --id=<id>`
|
||||
- CLI Syntax: `task-master clear-subtasks --id=<id>`
|
||||
- Description: Removes subtasks from specified tasks to allow regeneration
|
||||
@@ -180,6 +198,7 @@ alwaysApply: true
|
||||
- Works with both parent tasks and individual subtasks
|
||||
|
||||
- **Task Structure Fields**
|
||||
|
||||
- **id**: Unique identifier for the task (Example: `1`)
|
||||
- **title**: Brief, descriptive title (Example: `"Initialize Repo"`)
|
||||
- **description**: Concise summary of what the task involves (Example: `"Create a new repository, set up initial structure."`)
|
||||
@@ -193,6 +212,7 @@ alwaysApply: true
|
||||
- **subtasks**: List of smaller, more specific tasks (Example: `[{"id": 1, "title": "Configure OAuth", ...}]`)
|
||||
|
||||
- **Environment Variables Configuration**
|
||||
|
||||
- **ANTHROPIC_API_KEY** (Required): Your Anthropic API key for Claude (Example: `ANTHROPIC_API_KEY=sk-ant-api03-...`)
|
||||
- **MODEL** (Default: `"claude-3-7-sonnet-20250219"`): Claude model to use (Example: `MODEL=claude-3-opus-20240229`)
|
||||
- **MAX_TOKENS** (Default: `"4000"`): Maximum tokens for responses (Example: `MAX_TOKENS=8000`)
|
||||
@@ -207,6 +227,7 @@ alwaysApply: true
|
||||
- **PERPLEXITY_MODEL** (Default: `"sonar-medium-online"`): Perplexity model (Example: `PERPLEXITY_MODEL=sonar-large-online`)
|
||||
|
||||
- **Determining the Next Task**
|
||||
|
||||
- Run `task-master next` to show the next task to work on
|
||||
- The next command identifies tasks with all dependencies satisfied
|
||||
- Tasks are prioritized by priority level, dependency count, and ID
|
||||
@@ -221,6 +242,7 @@ alwaysApply: true
|
||||
- Provides ready-to-use commands for common task actions
|
||||
|
||||
- **Viewing Specific Task Details**
|
||||
|
||||
- Run `task-master show <id>` or `task-master show --id=<id>` to view a specific task
|
||||
- Use dot notation for subtasks: `task-master show 1.2` (shows subtask 2 of task 1)
|
||||
- Displays comprehensive information similar to the next command, but for a specific task
|
||||
@@ -230,6 +252,7 @@ alwaysApply: true
|
||||
- Useful for examining task details before implementation or checking status
|
||||
|
||||
- **Managing Task Dependencies**
|
||||
|
||||
- Use `task-master add-dependency --id=<id> --depends-on=<id>` to add a dependency
|
||||
- Use `task-master remove-dependency --id=<id> --depends-on=<id>` to remove a dependency
|
||||
- The system prevents circular dependencies and duplicate dependency entries
|
||||
@@ -238,6 +261,7 @@ alwaysApply: true
|
||||
- Dependencies are visualized with status indicators in task listings and files
|
||||
|
||||
- **Command Reference: add-dependency**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js add-dependency --id=<id> --depends-on=<id>`
|
||||
- CLI Syntax: `task-master add-dependency --id=<id> --depends-on=<id>`
|
||||
- Description: Adds a dependency relationship between two tasks
|
||||
@@ -248,6 +272,7 @@ alwaysApply: true
|
||||
- Notes: Prevents circular dependencies and duplicates; updates task files automatically
|
||||
|
||||
- **Command Reference: remove-dependency**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js remove-dependency --id=<id> --depends-on=<id>`
|
||||
- CLI Syntax: `task-master remove-dependency --id=<id> --depends-on=<id>`
|
||||
- Description: Removes a dependency relationship between two tasks
|
||||
@@ -258,6 +283,7 @@ alwaysApply: true
|
||||
- Notes: Checks if dependency actually exists; updates task files automatically
|
||||
|
||||
- **Command Reference: validate-dependencies**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js validate-dependencies [options]`
|
||||
- CLI Syntax: `task-master validate-dependencies [options]`
|
||||
- Description: Checks for and identifies invalid dependencies in tasks.json and task files
|
||||
@@ -270,6 +296,7 @@ alwaysApply: true
|
||||
- Use before fix-dependencies to audit your task structure
|
||||
|
||||
- **Command Reference: fix-dependencies**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js fix-dependencies [options]`
|
||||
- CLI Syntax: `task-master fix-dependencies [options]`
|
||||
- Description: Finds and fixes all invalid dependencies in tasks.json and task files
|
||||
@@ -283,6 +310,7 @@ alwaysApply: true
|
||||
- Provides detailed report of all fixes made
|
||||
|
||||
- **Command Reference: complexity-report**
|
||||
|
||||
- Legacy Syntax: `node scripts/dev.js complexity-report [options]`
|
||||
- CLI Syntax: `task-master complexity-report [options]`
|
||||
- Description: Displays the task complexity analysis report in a formatted, easy-to-read way
|
||||
@@ -296,6 +324,7 @@ alwaysApply: true
|
||||
- If no report exists, offers to generate one interactively
|
||||
|
||||
- **Command Reference: add-task**
|
||||
|
||||
- CLI Syntax: `task-master add-task [options]`
|
||||
- Description: Add a new task to tasks.json using AI
|
||||
- Parameters:
|
||||
@@ -307,6 +336,7 @@ alwaysApply: true
|
||||
- Notes: Uses AI to convert description into structured task with appropriate details
|
||||
|
||||
- **Command Reference: init**
|
||||
|
||||
- CLI Syntax: `task-master init`
|
||||
- Description: Initialize a new project with Task Master structure
|
||||
- Parameters: None
|
||||
@@ -341,15 +371,20 @@ alwaysApply: true
|
||||
- Check for any unintentional duplications or omissions
|
||||
|
||||
---
|
||||
WINDSURF_RULES
|
||||
---
|
||||
|
||||
## WINDSURF_RULES
|
||||
|
||||
description: Guidelines for creating and maintaining Windsurf rules to ensure consistency and effectiveness.
|
||||
globs: .windsurfrules
|
||||
filesToApplyRule: .windsurfrules
|
||||
alwaysApply: true
|
||||
|
||||
---
|
||||
|
||||
The below describes how you should be structuring new rule sections in this document.
|
||||
|
||||
- **Required Rule Structure:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Clear, one-line description of what the rule enforces
|
||||
@@ -363,11 +398,14 @@ The below describes how you should be structuring new rule sections in this docu
|
||||
```
|
||||
|
||||
- **Section References:**
|
||||
|
||||
- Use `ALL_CAPS_SECTION` to reference files
|
||||
- Example: `WINDSURF_RULES`
|
||||
|
||||
- **Code Examples:**
|
||||
|
||||
- Use language-specific code blocks
|
||||
|
||||
```typescript
|
||||
// ✅ DO: Show good examples
|
||||
const goodExample = true;
|
||||
@@ -377,6 +415,7 @@ The below describes how you should be structuring new rule sections in this docu
|
||||
```
|
||||
|
||||
- **Rule Content Guidelines:**
|
||||
|
||||
- Start with high-level overview
|
||||
- Include specific, actionable requirements
|
||||
- Show examples of correct implementation
|
||||
@@ -384,6 +423,7 @@ The below describes how you should be structuring new rule sections in this docu
|
||||
- Keep rules DRY by referencing other rules
|
||||
|
||||
- **Rule Maintenance:**
|
||||
|
||||
- Update rules when new patterns emerge
|
||||
- Add examples from actual codebase
|
||||
- Remove outdated patterns
|
||||
@@ -397,15 +437,18 @@ The below describes how you should be structuring new rule sections in this docu
|
||||
- Use consistent formatting across rules
|
||||
|
||||
---
|
||||
SELF_IMPROVE
|
||||
---
|
||||
|
||||
## SELF_IMPROVE
|
||||
|
||||
description: Guidelines for continuously improving this rules document based on emerging code patterns and best practices.
|
||||
globs: **/*
|
||||
filesToApplyRule: **/*
|
||||
globs: **/\*
|
||||
filesToApplyRule: **/\*
|
||||
alwaysApply: true
|
||||
|
||||
---
|
||||
|
||||
- **Rule Improvement Triggers:**
|
||||
|
||||
- New code patterns not covered by existing rules
|
||||
- Repeated similar implementations across files
|
||||
- Common error patterns that could be prevented
|
||||
@@ -413,6 +456,7 @@ alwaysApply: true
|
||||
- Emerging best practices in the codebase
|
||||
|
||||
- **Analysis Process:**
|
||||
|
||||
- Compare new code with existing rules
|
||||
- Identify patterns that should be standardized
|
||||
- Look for references to external documentation
|
||||
@@ -420,7 +464,9 @@ alwaysApply: true
|
||||
- Monitor test patterns and coverage
|
||||
|
||||
- **Rule Updates:**
|
||||
|
||||
- **Add New Rules When:**
|
||||
|
||||
- A new technology/pattern is used in 3+ files
|
||||
- Common bugs could be prevented by a rule
|
||||
- Code reviews repeatedly mention the same feedback
|
||||
@@ -433,11 +479,12 @@ alwaysApply: true
|
||||
- Implementation details have changed
|
||||
|
||||
- **Example Pattern Recognition:**
|
||||
|
||||
```typescript
|
||||
// If you see repeated patterns like:
|
||||
const data = await prisma.user.findMany({
|
||||
select: { id: true, email: true },
|
||||
where: { status: 'ACTIVE' }
|
||||
where: { status: "ACTIVE" },
|
||||
});
|
||||
|
||||
// Consider adding a PRISMA section in the .windsurfrules:
|
||||
@@ -447,12 +494,14 @@ alwaysApply: true
|
||||
```
|
||||
|
||||
- **Rule Quality Checks:**
|
||||
|
||||
- Rules should be actionable and specific
|
||||
- Examples should come from actual code
|
||||
- References should be up to date
|
||||
- Patterns should be consistently enforced
|
||||
|
||||
- **Continuous Improvement:**
|
||||
|
||||
- Monitor code review comments
|
||||
- Track common development questions
|
||||
- Update rules after major refactors
|
||||
@@ -460,6 +509,7 @@ alwaysApply: true
|
||||
- Cross-reference related rules
|
||||
|
||||
- **Rule Deprecation:**
|
||||
|
||||
- Mark outdated patterns as deprecated
|
||||
- Remove rules that no longer apply
|
||||
- Update references to deprecated rules
|
||||
|
||||
112
assets/AGENTS.md
112
assets/AGENTS.md
@@ -7,7 +7,7 @@
|
||||
```bash
|
||||
# Project Setup
|
||||
task-master init # Initialize Task Master in current project
|
||||
task-master parse-prd scripts/prd.txt # Generate tasks from PRD document
|
||||
task-master parse-prd .taskmaster/docs/prd.txt # Generate tasks from PRD document
|
||||
task-master models --setup # Configure AI models interactively
|
||||
|
||||
# Daily Development Workflow
|
||||
@@ -39,10 +39,10 @@ task-master generate # Update task markd
|
||||
|
||||
### Core Files
|
||||
|
||||
- `tasks/tasks.json` - Main task data file (auto-managed)
|
||||
- `.taskmasterconfig` - AI model configuration (use `task-master models` to modify)
|
||||
- `scripts/prd.txt` - Product Requirements Document for parsing
|
||||
- `tasks/*.txt` - Individual task files (auto-generated from tasks.json)
|
||||
- `.taskmaster/tasks/tasks.json` - Main task data file (auto-managed)
|
||||
- `.taskmaster/config.json` - AI model configuration (use `task-master models` to modify)
|
||||
- `.taskmaster/docs/prd.txt` - Product Requirements Document for parsing
|
||||
- `.taskmaster/tasks/*.txt` - Individual task files (auto-generated from tasks.json)
|
||||
- `.env` - API keys for CLI usage
|
||||
|
||||
### Claude Code Integration Files
|
||||
@@ -56,20 +56,24 @@ task-master generate # Update task markd
|
||||
|
||||
```
|
||||
project/
|
||||
├── tasks/
|
||||
│ ├── tasks.json # Main task database
|
||||
│ ├── task-1.md # Individual task files
|
||||
│ └── task-2.md
|
||||
├── scripts/
|
||||
│ ├── prd.txt # Product requirements
|
||||
│ └── task-complexity-report.json
|
||||
├── .taskmaster/
|
||||
│ ├── tasks/ # Task files directory
|
||||
│ │ ├── tasks.json # Main task database
|
||||
│ │ ├── task-1.md # Individual task files
|
||||
│ │ └── task-2.md
|
||||
│ ├── docs/ # Documentation directory
|
||||
│ │ ├── prd.txt # Product requirements
|
||||
│ ├── reports/ # Analysis reports directory
|
||||
│ │ └── task-complexity-report.json
|
||||
│ ├── templates/ # Template files
|
||||
│ │ └── example_prd.txt # Example PRD template
|
||||
│ └── config.json # AI models & settings
|
||||
├── .claude/
|
||||
│ ├── settings.json # Claude Code configuration
|
||||
│ └── commands/ # Custom slash commands
|
||||
├── .taskmasterconfig # AI models & settings
|
||||
├── .env # API keys
|
||||
├── .mcp.json # MCP configuration
|
||||
└── CLAUDE.md # This file - auto-loaded by Claude Code
|
||||
│ ├── settings.json # Claude Code configuration
|
||||
│ └── commands/ # Custom slash commands
|
||||
├── .env # API keys
|
||||
├── .mcp.json # MCP configuration
|
||||
└── CLAUDE.md # This file - auto-loaded by Claude Code
|
||||
```
|
||||
|
||||
## MCP Integration
|
||||
@@ -78,23 +82,23 @@ Task Master provides an MCP server that Claude Code can connect to. Configure in
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"task-master-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "your_key_here",
|
||||
"PERPLEXITY_API_KEY": "your_key_here",
|
||||
"OPENAI_API_KEY": "OPENAI_API_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "GOOGLE_API_KEY_HERE",
|
||||
"XAI_API_KEY": "XAI_API_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "OPENROUTER_API_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "MISTRAL_API_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "AZURE_OPENAI_API_KEY_HERE",
|
||||
"OLLAMA_API_KEY": "OLLAMA_API_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
"mcpServers": {
|
||||
"task-master-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "your_key_here",
|
||||
"PERPLEXITY_API_KEY": "your_key_here",
|
||||
"OPENAI_API_KEY": "OPENAI_API_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "GOOGLE_API_KEY_HERE",
|
||||
"XAI_API_KEY": "XAI_API_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "OPENROUTER_API_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "MISTRAL_API_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "AZURE_OPENAI_API_KEY_HERE",
|
||||
"OLLAMA_API_KEY": "OLLAMA_API_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -135,7 +139,7 @@ complexity_report; // = task-master complexity-report
|
||||
task-master init
|
||||
|
||||
# Create or obtain PRD, then parse it
|
||||
task-master parse-prd scripts/prd.txt
|
||||
task-master parse-prd .taskmaster/docs/prd.txt
|
||||
|
||||
# Analyze complexity and expand tasks
|
||||
task-master analyze-complexity --research
|
||||
@@ -208,14 +212,14 @@ Add to `.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"allowedTools": [
|
||||
"Edit",
|
||||
"Bash(task-master *)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(npm run *)",
|
||||
"mcp__task_master_ai__*"
|
||||
]
|
||||
"allowedTools": [
|
||||
"Edit",
|
||||
"Bash(task-master *)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(npm run *)",
|
||||
"mcp__task_master_ai__*"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -268,15 +272,15 @@ task-master models --set-fallback gpt-4o-mini
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "1.2",
|
||||
"title": "Implement user authentication",
|
||||
"description": "Set up JWT-based auth system",
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"dependencies": ["1.1"],
|
||||
"details": "Use bcrypt for hashing, JWT for tokens...",
|
||||
"testStrategy": "Unit tests for auth functions, integration tests for login flow",
|
||||
"subtasks": []
|
||||
"id": "1.2",
|
||||
"title": "Implement user authentication",
|
||||
"description": "Set up JWT-based auth system",
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"dependencies": ["1.1"],
|
||||
"details": "Use bcrypt for hashing, JWT for tokens...",
|
||||
"testStrategy": "Unit tests for auth functions, integration tests for login flow",
|
||||
"subtasks": []
|
||||
}
|
||||
```
|
||||
|
||||
@@ -384,7 +388,7 @@ These commands make AI calls and may take up to a minute:
|
||||
### File Management
|
||||
|
||||
- Never manually edit `tasks.json` - use commands instead
|
||||
- Never manually edit `.taskmasterconfig` - use `task-master models`
|
||||
- Never manually edit `.taskmaster/config.json` - use `task-master models`
|
||||
- Task markdown files in `tasks/` are auto-generated
|
||||
- Run `task-master generate` after manual changes to tasks.json
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"projectName": "Taskmaster",
|
||||
"defaultTag": "master",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"azureOpenaiBaseURL": "https://your-endpoint.openai.azure.com/"
|
||||
"azureOpenaiBaseURL": "https://your-endpoint.openai.azure.com/",
|
||||
"bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com"
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,5 @@ OPENAI_API_KEY="your_openai_api_key_here" # Optional, for OpenAI/Ope
|
||||
GOOGLE_API_KEY="your_google_api_key_here" # Optional, for Google Gemini models.
|
||||
MISTRAL_API_KEY="your_mistral_key_here" # Optional, for Mistral AI models.
|
||||
XAI_API_KEY="YOUR_XAI_KEY_HERE" # Optional, for xAI AI models.
|
||||
AZURE_OPENAI_API_KEY="your_azure_key_here" # Optional, for Azure OpenAI models (requires endpoint in .taskmasterconfig).
|
||||
AZURE_OPENAI_API_KEY="your_azure_key_here" # Optional, for Azure OpenAI models (requires endpoint in .taskmaster/config.json).
|
||||
OLLAMA_API_KEY="your_ollama_api_key_here" # Optional: For remote Ollama servers that require authentication.
|
||||
@@ -23,7 +23,3 @@ node_modules/
|
||||
|
||||
# OS specific
|
||||
.DS_Store
|
||||
|
||||
# Task files
|
||||
tasks.json
|
||||
tasks/
|
||||
@@ -20,7 +20,7 @@ In an AI-driven development process—particularly with tools like [Cursor](http
|
||||
|
||||
Task Master configuration is now managed through two primary methods:
|
||||
|
||||
1. **`.taskmasterconfig` File (Project Root - Primary)**
|
||||
1. **`.taskmaster/config.json` File (Project Root - Primary)**
|
||||
|
||||
- Stores AI model selections (`main`, `research`, `fallback`), model parameters (`maxTokens`, `temperature`), `logLevel`, `defaultSubtasks`, `defaultPriority`, `projectName`, etc.
|
||||
- Managed using the `task-master models --setup` command or the `models` MCP tool.
|
||||
@@ -192,7 +192,7 @@ Notes:
|
||||
## AI Integration (Updated)
|
||||
|
||||
- The script now uses a unified AI service layer (`ai-services-unified.js`).
|
||||
- Model selection (e.g., Claude vs. Perplexity for `--research`) is determined by the configuration in `.taskmasterconfig` based on the requested `role` (`main` or `research`).
|
||||
- Model selection (e.g., Claude vs. Perplexity for `--research`) is determined by the configuration in `.taskmaster/config.json` based on the requested `role` (`main` or `research`).
|
||||
- API keys are automatically resolved from your `.env` file (for CLI) or MCP session environment.
|
||||
- To use the research capabilities (e.g., `expand --research`), ensure you have:
|
||||
1. Configured a model for the `research` role using `task-master models --setup` (Perplexity models are recommended).
|
||||
@@ -357,25 +357,25 @@ The output report structure is:
|
||||
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"generatedAt": "2023-06-15T12:34:56.789Z",
|
||||
"tasksAnalyzed": 20,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Your Project Name",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 8,
|
||||
"taskTitle": "Develop Implementation Drift Handling",
|
||||
"complexityScore": 9.5,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Create subtasks that handle detecting...",
|
||||
"reasoning": "This task requires sophisticated logic...",
|
||||
"expansionCommand": "task-master expand --id=8 --num=6 --prompt=\"Create subtasks...\" --research"
|
||||
}
|
||||
// More tasks sorted by complexity score (highest first)
|
||||
]
|
||||
"meta": {
|
||||
"generatedAt": "2023-06-15T12:34:56.789Z",
|
||||
"tasksAnalyzed": 20,
|
||||
"thresholdScore": 5,
|
||||
"projectName": "Your Project Name",
|
||||
"usedResearch": true
|
||||
},
|
||||
"complexityAnalysis": [
|
||||
{
|
||||
"taskId": 8,
|
||||
"taskTitle": "Develop Implementation Drift Handling",
|
||||
"complexityScore": 9.5,
|
||||
"recommendedSubtasks": 6,
|
||||
"expansionPrompt": "Create subtasks that handle detecting...",
|
||||
"reasoning": "This task requires sophisticated logic...",
|
||||
"expansionCommand": "task-master expand --id=8 --num=6 --prompt=\"Create subtasks...\" --research"
|
||||
}
|
||||
// More tasks sorted by complexity score (highest first)
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
"rules": {
|
||||
"complexity": {
|
||||
"noForEach": "off",
|
||||
"useOptionalChain": "off"
|
||||
"useOptionalChain": "off",
|
||||
"useArrowFunction": "off"
|
||||
},
|
||||
"correctness": {
|
||||
"noConstantCondition": "off",
|
||||
@@ -40,7 +41,9 @@
|
||||
"noUselessElse": "off",
|
||||
"useNodejsImportProtocol": "off",
|
||||
"useNumberNamespace": "off",
|
||||
"noParameterAssign": "off"
|
||||
"noParameterAssign": "off",
|
||||
"useTemplate": "off",
|
||||
"noUnusedTemplateLiteral": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +247,56 @@ task-master add-task --prompt="Description" --dependencies=1,2,3
|
||||
task-master add-task --prompt="Description" --priority=high
|
||||
```
|
||||
|
||||
## Tag Management
|
||||
|
||||
Task Master supports tagged task lists for multi-context task management. Each tag represents a separate, isolated context for tasks.
|
||||
|
||||
```bash
|
||||
# List all available tags with task counts and status
|
||||
task-master tags
|
||||
|
||||
# List tags with detailed metadata
|
||||
task-master tags --show-metadata
|
||||
|
||||
# Create a new empty tag
|
||||
task-master add-tag <tag-name>
|
||||
|
||||
# Create a new tag with a description
|
||||
task-master add-tag <tag-name> --description="Feature development tasks"
|
||||
|
||||
# Create a tag based on current git branch name
|
||||
task-master add-tag --from-branch
|
||||
|
||||
# Create a new tag by copying tasks from the current tag
|
||||
task-master add-tag <new-tag> --copy-from-current
|
||||
|
||||
# Create a new tag by copying from a specific tag
|
||||
task-master add-tag <new-tag> --copy-from=<source-tag>
|
||||
|
||||
# Switch to a different tag context
|
||||
task-master use-tag <tag-name>
|
||||
|
||||
# Rename an existing tag
|
||||
task-master rename-tag <old-name> <new-name>
|
||||
|
||||
# Copy an entire tag to create a new one
|
||||
task-master copy-tag <source-tag> <target-tag>
|
||||
|
||||
# Copy a tag with a description
|
||||
task-master copy-tag <source-tag> <target-tag> --description="Copied for testing"
|
||||
|
||||
# Delete a tag and all its tasks (with confirmation)
|
||||
task-master delete-tag <tag-name>
|
||||
|
||||
# Delete a tag without confirmation prompt
|
||||
task-master delete-tag <tag-name> --yes
|
||||
```
|
||||
|
||||
**Tag Context:**
|
||||
- All task operations (list, show, add, update, etc.) work within the currently active tag
|
||||
- Use `--tag=<name>` flag with most commands to operate on a specific tag context
|
||||
- Tags provide complete isolation - tasks in different tags don't interfere with each other
|
||||
|
||||
## Initialize a Project
|
||||
|
||||
```bash
|
||||
@@ -279,7 +329,9 @@ task-master models --set-research=google/gemini-pro --openrouter
|
||||
task-master models --setup
|
||||
```
|
||||
|
||||
Configuration is stored in `.taskmasterconfig` in your project root. API keys are still managed via `.env` or MCP configuration. Use `task-master models` without flags to see available built-in models. Use `--setup` for a guided experience.
|
||||
Configuration is stored in `.taskmaster/config.json` in your project root (legacy `.taskmasterconfig` files are automatically migrated). API keys are still managed via `.env` or MCP configuration. Use `task-master models` without flags to see available built-in models. Use `--setup` for a guided experience.
|
||||
|
||||
State is stored in `.taskmaster/state.json` in your project root. It maintains important information like the current tag. Do not manually edit this file.
|
||||
|
||||
## Research Fresh Information
|
||||
|
||||
@@ -299,18 +351,34 @@ task-master research "Best practices for error handling" --context="We're using
|
||||
# Research with different detail levels
|
||||
task-master research "React Query v5 migration guide" --detail=high
|
||||
|
||||
# Save research results to a file
|
||||
task-master research "Database optimization techniques" --save=research/db-optimization.md
|
||||
# Disable interactive follow-up questions (useful for scripting, is the default for MCP)
|
||||
# Use a custom tasks file location
|
||||
task-master research "How to implement this feature?" --file=custom-tasks.json
|
||||
|
||||
# Research within a specific tag context
|
||||
task-master research "Database optimization strategies" --tag=feature-branch
|
||||
|
||||
# Save research conversation to .taskmaster/docs/research/ directory (for later reference)
|
||||
task-master research "Database optimization techniques" --save-file
|
||||
|
||||
# Save key findings directly to a task or subtask (recommended for actionable insights)
|
||||
task-master research "How to implement OAuth?" --save-to=15
|
||||
task-master research "API optimization strategies" --save-to=15.2
|
||||
|
||||
# Combine context gathering with automatic saving of findings
|
||||
task-master research "Best practices for this implementation" --id=15,16 --files=src/auth.js --save-to=15.3
|
||||
```
|
||||
|
||||
**The research command is a powerful tool that provides:**
|
||||
**The research command is a powerful exploration tool that provides:**
|
||||
|
||||
- **Fresh information beyond AI knowledge cutoffs**
|
||||
- **Project-aware context** from your tasks and files
|
||||
- **Automatic task discovery** using fuzzy search
|
||||
- **Multiple detail levels** (low, medium, high)
|
||||
- **Token counting and cost tracking**
|
||||
- **Interactive follow-up questions**
|
||||
- **Interactive follow-up questions** for deep exploration
|
||||
- **Flexible save options** (commit findings to tasks or preserve conversations)
|
||||
- **Iterative discovery** through continuous questioning and refinement
|
||||
|
||||
**Use research frequently to:**
|
||||
|
||||
@@ -319,3 +387,12 @@ task-master research "Database optimization techniques" --save=research/db-optim
|
||||
- Find solutions to complex problems
|
||||
- Validate your implementation approaches
|
||||
- Stay updated with latest security recommendations
|
||||
|
||||
**Interactive Features (CLI):**
|
||||
|
||||
- **Follow-up questions** that maintain conversation context and allow deep exploration
|
||||
- **Save menu** during or after research with flexible options:
|
||||
- **Save to task/subtask**: Commit key findings and actionable insights (recommended)
|
||||
- **Save to file**: Preserve entire conversation for later reference if needed
|
||||
- **Continue exploring**: Ask more follow-up questions to dig deeper
|
||||
- **Automatic file naming** with timestamps and query-based slugs when saving conversations
|
||||
|
||||
@@ -2,78 +2,160 @@
|
||||
|
||||
Taskmaster uses two primary methods for configuration:
|
||||
|
||||
1. **`.taskmasterconfig` File (Project Root - Recommended for most settings)**
|
||||
1. **`.taskmaster/config.json` File (Recommended - New Structure)**
|
||||
1. **`.taskmaster/config.json` File (Recommended - New Structure)**
|
||||
|
||||
- This JSON file stores most configuration settings, including AI model selections, parameters, logging levels, and project defaults.
|
||||
- **Location:** This file is created in the root directory of your project when you run the `task-master models --setup` interactive setup. You typically do this during the initialization sequence. Do not manually edit this file beyond adjusting Temperature and Max Tokens depending on your model.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Management:** Use the `task-master models --setup` command (or `models` MCP tool) to interactively create and manage this file. You can also set specific models directly using `task-master models --set-<role>=<model_id>`, adding `--ollama` or `--openrouter` flags for custom models. Manual editing is possible but not recommended unless you understand the structure.
|
||||
- **Example Structure:**
|
||||
```json
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-7-sonnet-20250219",
|
||||
"maxTokens": 64000,
|
||||
"temperature": 0.2,
|
||||
"baseURL": "https://api.anthropic.com/v1"
|
||||
},
|
||||
"research": {
|
||||
"provider": "perplexity",
|
||||
"modelId": "sonar-pro",
|
||||
"maxTokens": 8700,
|
||||
"temperature": 0.1,
|
||||
"baseURL": "https://api.perplexity.ai/v1"
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-5-sonnet",
|
||||
"maxTokens": 64000,
|
||||
"temperature": 0.2
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"logLevel": "info",
|
||||
"debug": false,
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"projectName": "Your Project Name",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/",
|
||||
"vertexProjectId": "your-gcp-project-id",
|
||||
"vertexLocation": "us-central1"
|
||||
}
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-7-sonnet-20250219",
|
||||
"maxTokens": 64000,
|
||||
"temperature": 0.2,
|
||||
"baseURL": "https://api.anthropic.com/v1"
|
||||
},
|
||||
"research": {
|
||||
"provider": "perplexity",
|
||||
"modelId": "sonar-pro",
|
||||
"maxTokens": 8700,
|
||||
"temperature": 0.1,
|
||||
"baseURL": "https://api.perplexity.ai/v1"
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-5-sonnet",
|
||||
"maxTokens": 64000,
|
||||
"temperature": 0.2
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"logLevel": "info",
|
||||
"debug": false,
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"defaultTag": "master",
|
||||
"projectName": "Your Project Name",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/",
|
||||
"vertexProjectId": "your-gcp-project-id",
|
||||
"vertexLocation": "us-central1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Environment Variables (`.env` file or MCP `env` block - For API Keys Only)**
|
||||
- Used **exclusively** for sensitive API keys and specific endpoint URLs.
|
||||
- **Location:**
|
||||
- For CLI usage: Create a `.env` file in your project root.
|
||||
- For MCP/Cursor usage: Configure keys in the `env` section of your `.cursor/mcp.json` file.
|
||||
- **Required API Keys (Depending on configured providers):**
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key.
|
||||
- `PERPLEXITY_API_KEY`: Your Perplexity API key.
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key.
|
||||
- `GOOGLE_API_KEY`: Your Google API key (also used for Vertex AI provider).
|
||||
- `MISTRAL_API_KEY`: Your Mistral API key.
|
||||
- `AZURE_OPENAI_API_KEY`: Your Azure OpenAI API key (also requires `AZURE_OPENAI_ENDPOINT`).
|
||||
- `OPENROUTER_API_KEY`: Your OpenRouter API key.
|
||||
- `XAI_API_KEY`: Your X-AI API key.
|
||||
- **Optional Endpoint Overrides:**
|
||||
- **Per-role `baseURL` in `.taskmasterconfig`:** You can add a `baseURL` property to any model role (`main`, `research`, `fallback`) to override the default API endpoint for that provider. If omitted, the provider's standard endpoint is used.
|
||||
- `AZURE_OPENAI_ENDPOINT`: Required if using Azure OpenAI key (can also be set as `baseURL` for the Azure model role).
|
||||
- `OLLAMA_BASE_URL`: Override the default Ollama API URL (Default: `http://localhost:11434/api`).
|
||||
- `VERTEX_PROJECT_ID`: Your Google Cloud project ID for Vertex AI. Required when using the 'vertex' provider.
|
||||
- `VERTEX_LOCATION`: Google Cloud region for Vertex AI (e.g., 'us-central1'). Default is 'us-central1'.
|
||||
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to service account credentials JSON file for Google Cloud auth (alternative to API key for Vertex AI).
|
||||
2. **Legacy `.taskmasterconfig` File (Backward Compatibility)**
|
||||
|
||||
**Important:** Settings like model ID selections (`main`, `research`, `fallback`), `maxTokens`, `temperature`, `logLevel`, `defaultSubtasks`, `defaultPriority`, and `projectName` are **managed in `.taskmasterconfig`**, not environment variables.
|
||||
- For projects that haven't migrated to the new structure yet.
|
||||
- **Location:** Project root directory.
|
||||
- **Migration:** Use `task-master migrate` to move this to `.taskmaster/config.json`.
|
||||
- **Deprecation:** While still supported, you'll see warnings encouraging migration to the new structure.
|
||||
|
||||
## Environment Variables (`.env` file or MCP `env` block - For API Keys Only)
|
||||
|
||||
- Used **exclusively** for sensitive API keys and specific endpoint URLs.
|
||||
- **Location:**
|
||||
- For CLI usage: Create a `.env` file in your project root.
|
||||
- For MCP/Cursor usage: Configure keys in the `env` section of your `.cursor/mcp.json` file.
|
||||
- **Required API Keys (Depending on configured providers):**
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key.
|
||||
- `PERPLEXITY_API_KEY`: Your Perplexity API key.
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key.
|
||||
- `GOOGLE_API_KEY`: Your Google API key (also used for Vertex AI provider).
|
||||
- `MISTRAL_API_KEY`: Your Mistral API key.
|
||||
- `AZURE_OPENAI_API_KEY`: Your Azure OpenAI API key (also requires `AZURE_OPENAI_ENDPOINT`).
|
||||
- `OPENROUTER_API_KEY`: Your OpenRouter API key.
|
||||
- `XAI_API_KEY`: Your X-AI API key.
|
||||
- **Optional Endpoint Overrides:**
|
||||
- **Per-role `baseURL` in `.taskmasterconfig`:** You can add a `baseURL` property to any model role (`main`, `research`, `fallback`) to override the default API endpoint for that provider. If omitted, the provider's standard endpoint is used.
|
||||
- `AZURE_OPENAI_ENDPOINT`: Required if using Azure OpenAI key (can also be set as `baseURL` for the Azure model role).
|
||||
- `OLLAMA_BASE_URL`: Override the default Ollama API URL (Default: `http://localhost:11434/api`).
|
||||
- `VERTEX_PROJECT_ID`: Your Google Cloud project ID for Vertex AI. Required when using the 'vertex' provider.
|
||||
- `VERTEX_LOCATION`: Google Cloud region for Vertex AI (e.g., 'us-central1'). Default is 'us-central1'.
|
||||
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to service account credentials JSON file for Google Cloud auth (alternative to API key for Vertex AI).
|
||||
2. **Legacy `.taskmasterconfig` File (Backward Compatibility)**
|
||||
|
||||
- For projects that haven't migrated to the new structure yet.
|
||||
- **Location:** Project root directory.
|
||||
- **Migration:** Use `task-master migrate` to move this to `.taskmaster/config.json`.
|
||||
- **Deprecation:** While still supported, you'll see warnings encouraging migration to the new structure.
|
||||
|
||||
## Environment Variables (`.env` file or MCP `env` block - For API Keys Only)
|
||||
|
||||
- Used **exclusively** for sensitive API keys and specific endpoint URLs.
|
||||
- **Location:**
|
||||
- For CLI usage: Create a `.env` file in your project root.
|
||||
- For MCP/Cursor usage: Configure keys in the `env` section of your `.cursor/mcp.json` file.
|
||||
- **Required API Keys (Depending on configured providers):**
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key.
|
||||
- `PERPLEXITY_API_KEY`: Your Perplexity API key.
|
||||
- `OPENAI_API_KEY`: Your OpenAI API key.
|
||||
- `GOOGLE_API_KEY`: Your Google API key (also used for Vertex AI provider).
|
||||
- `MISTRAL_API_KEY`: Your Mistral API key.
|
||||
- `AZURE_OPENAI_API_KEY`: Your Azure OpenAI API key (also requires `AZURE_OPENAI_ENDPOINT`).
|
||||
- `OPENROUTER_API_KEY`: Your OpenRouter API key.
|
||||
- `XAI_API_KEY`: Your X-AI API key.
|
||||
- **Optional Endpoint Overrides:**
|
||||
- **Per-role `baseURL` in `.taskmasterconfig`:** You can add a `baseURL` property to any model role (`main`, `research`, `fallback`) to override the default API endpoint for that provider. If omitted, the provider's standard endpoint is used.
|
||||
- `AZURE_OPENAI_ENDPOINT`: Required if using Azure OpenAI key (can also be set as `baseURL` for the Azure model role).
|
||||
- `OLLAMA_BASE_URL`: Override the default Ollama API URL (Default: `http://localhost:11434/api`).
|
||||
- `VERTEX_PROJECT_ID`: Your Google Cloud project ID for Vertex AI. Required when using the 'vertex' provider.
|
||||
- `VERTEX_LOCATION`: Google Cloud region for Vertex AI (e.g., 'us-central1'). Default is 'us-central1'.
|
||||
- `GOOGLE_APPLICATION_CREDENTIALS`: Path to service account credentials JSON file for Google Cloud auth (alternative to API key for Vertex AI).
|
||||
|
||||
**Important:** Settings like model ID selections (`main`, `research`, `fallback`), `maxTokens`, `temperature`, `logLevel`, `defaultSubtasks`, `defaultPriority`, and `projectName` are **managed in `.taskmaster/config.json`** (or `.taskmasterconfig` for unmigrated projects), not environment variables.
|
||||
|
||||
## Tagged Task Lists Configuration (v0.17+)
|
||||
|
||||
Taskmaster includes a tagged task lists system for multi-context task management.
|
||||
|
||||
### Global Tag Settings
|
||||
|
||||
```json
|
||||
"global": {
|
||||
"defaultTag": "master"
|
||||
}
|
||||
```
|
||||
|
||||
- **`defaultTag`** (string): Default tag context for new operations (default: "master")
|
||||
|
||||
### Git Integration
|
||||
|
||||
Task Master provides manual git integration through the `--from-branch` option:
|
||||
|
||||
- **Manual Tag Creation**: Use `task-master add-tag --from-branch` to create a tag based on your current git branch name
|
||||
- **User Control**: No automatic tag switching - you control when and how tags are created
|
||||
- **Flexible Workflow**: Supports any git workflow without imposing rigid branch-tag mappings
|
||||
|
||||
## State Management File
|
||||
|
||||
Taskmaster uses `.taskmaster/state.json` to track tagged system runtime information:
|
||||
|
||||
```json
|
||||
{
|
||||
"currentTag": "master",
|
||||
"lastSwitched": "2025-06-11T20:26:12.598Z",
|
||||
"migrationNoticeShown": true
|
||||
}
|
||||
```
|
||||
|
||||
- **`currentTag`**: Currently active tag context
|
||||
- **`lastSwitched`**: Timestamp of last tag switch
|
||||
- **`migrationNoticeShown`**: Whether migration notice has been displayed
|
||||
|
||||
This file is automatically created during tagged system migration and should not be manually edited.
|
||||
|
||||
## Example `.env` File (for API Keys)
|
||||
|
||||
```
|
||||
# Required API keys for providers configured in .taskmasterconfig
|
||||
# Required API keys for providers configured in .taskmaster/config.json
|
||||
ANTHROPIC_API_KEY=sk-ant-api03-your-key-here
|
||||
PERPLEXITY_API_KEY=pplx-your-key-here
|
||||
# OPENAI_API_KEY=sk-your-key-here
|
||||
@@ -94,8 +176,12 @@ PERPLEXITY_API_KEY=pplx-your-key-here
|
||||
|
||||
### Configuration Errors
|
||||
|
||||
- If Task Master reports errors about missing configuration or cannot find `.taskmasterconfig`, run `task-master models --setup` in your project root to create or repair the file.
|
||||
- Ensure API keys are correctly placed in your `.env` file (for CLI) or `.cursor/mcp.json` (for MCP) and are valid for the providers selected in `.taskmasterconfig`.
|
||||
- If Task Master reports errors about missing configuration or cannot find the config file, run `task-master models --setup` in your project root to create or repair the file.
|
||||
- For new projects, config will be created at `.taskmaster/config.json`. For legacy projects, you may want to use `task-master migrate` to move to the new structure.
|
||||
- Ensure API keys are correctly placed in your `.env` file (for CLI) or `.cursor/mcp.json` (for MCP) and are valid for the providers selected in your config file.
|
||||
- If Task Master reports errors about missing configuration or cannot find the config file, run `task-master models --setup` in your project root to create or repair the file.
|
||||
- For new projects, config will be created at `.taskmaster/config.json`. For legacy projects, you may want to use `task-master migrate` to move to the new structure.
|
||||
- Ensure API keys are correctly placed in your `.env` file (for CLI) or `.cursor/mcp.json` (for MCP) and are valid for the providers selected in your config file.
|
||||
|
||||
### If `task-master init` doesn't respond:
|
||||
|
||||
@@ -147,7 +233,7 @@ Google Vertex AI is Google Cloud's enterprise AI platform and requires specific
|
||||
VERTEX_LOCATION=us-central1
|
||||
```
|
||||
|
||||
5. **In .taskmasterconfig**:
|
||||
5. **In .taskmaster/config.json**:
|
||||
```json
|
||||
"global": {
|
||||
"vertexProjectId": "my-gcp-project-123",
|
||||
|
||||
@@ -5,7 +5,7 @@ Here are some common interactions with Cursor AI when using Task Master:
|
||||
## Starting a new project
|
||||
|
||||
```
|
||||
I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt.
|
||||
I've just initialized a new project with Claude Task Master. I have a PRD at .taskmaster/docs/prd.txt.
|
||||
Can you help me parse it and set up the initial tasks?
|
||||
```
|
||||
|
||||
@@ -176,3 +176,83 @@ We need to choose between Redis and Memcached for caching. Can you research the
|
||||
```
|
||||
|
||||
(Agent runs: `task-master research "Redis vs Memcached 2024 comparison for session caching" --tree`)
|
||||
|
||||
## Git Integration and Tag Management
|
||||
|
||||
### Creating Tags for Feature Branches
|
||||
|
||||
```
|
||||
I'm starting work on a new feature branch for user authentication. Can you create a matching task tag?
|
||||
```
|
||||
|
||||
(Agent runs: `task-master add-tag --from-branch`)
|
||||
|
||||
### Creating Named Tags
|
||||
|
||||
```
|
||||
Create a new tag called 'api-v2' for our API redesign work.
|
||||
```
|
||||
|
||||
(Agent runs: `task-master add-tag api-v2 --description="API v2 redesign tasks"`)
|
||||
|
||||
### Switching Tag Contexts
|
||||
|
||||
```
|
||||
Switch to the 'testing' tag so I can work on QA tasks.
|
||||
```
|
||||
|
||||
(Agent runs: `task-master use-tag testing`)
|
||||
|
||||
### Copying Tasks Between Tags
|
||||
|
||||
```
|
||||
I need to copy the current tasks to a new 'hotfix' tag for urgent fixes.
|
||||
```
|
||||
|
||||
(Agent runs: `task-master add-tag hotfix --copy-from-current --description="Urgent hotfix tasks"`)
|
||||
|
||||
### Managing Multiple Contexts
|
||||
|
||||
```
|
||||
Show me all available tags and their current status.
|
||||
```
|
||||
|
||||
(Agent runs: `task-master tags --show-metadata`)
|
||||
|
||||
### Tag Cleanup
|
||||
|
||||
```
|
||||
I've finished the 'user-auth' feature and merged the branch. Can you clean up the tag?
|
||||
```
|
||||
|
||||
(Agent runs: `task-master delete-tag user-auth`)
|
||||
|
||||
### Working with Tag-Specific Tasks
|
||||
|
||||
```
|
||||
List all tasks in the 'api-v2' tag context.
|
||||
```
|
||||
|
||||
(Agent runs: `task-master use-tag api-v2` then `task-master list`)
|
||||
|
||||
### Branch-Based Development Workflow
|
||||
|
||||
```
|
||||
I'm switching to work on the 'feature/payments' branch. Can you set up the task context for this?
|
||||
```
|
||||
|
||||
(Agent runs:
|
||||
1. `git checkout feature/payments`
|
||||
2. `task-master add-tag --from-branch --description="Payment system implementation"`
|
||||
3. `task-master list` to show tasks in the new context)
|
||||
|
||||
### Parallel Feature Development
|
||||
|
||||
```
|
||||
I need to work on both authentication and payment features simultaneously. How should I organize the tasks?
|
||||
```
|
||||
|
||||
(Agent suggests and runs:
|
||||
1. `task-master add-tag auth --description="Authentication feature tasks"`
|
||||
2. `task-master add-tag payments --description="Payment system tasks"`
|
||||
3. `task-master use-tag auth` to start with authentication work)
|
||||
|
||||
235
docs/migration-guide.md
Normal file
235
docs/migration-guide.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# Migration Guide: New .taskmaster Directory Structure
|
||||
|
||||
## Overview
|
||||
|
||||
Task Master v0.16.0 introduces a new `.taskmaster/` directory structure to keep your project directories clean and organized. This guide explains the benefits of the new structure and how to migrate existing projects.
|
||||
|
||||
## What's New
|
||||
|
||||
### Before (Legacy Structure)
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── tasks/ # Task files
|
||||
│ ├── tasks.json
|
||||
│ ├── task-1.txt
|
||||
│ └── task-2.txt
|
||||
├── scripts/ # PRD and reports
|
||||
│ ├── prd.txt
|
||||
│ ├── example_prd.txt
|
||||
│ └── task-complexity-report.json
|
||||
├── .taskmasterconfig # Configuration
|
||||
└── ... (your project files)
|
||||
```
|
||||
|
||||
### After (New Structure)
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── .taskmaster/ # Consolidated Task Master files
|
||||
│ ├── config.json # Configuration (was .taskmasterconfig)
|
||||
│ ├── tasks/ # Task files
|
||||
│ │ ├── tasks.json
|
||||
│ │ ├── task-1.txt
|
||||
│ │ └── task-2.txt
|
||||
│ ├── docs/ # Project documentation
|
||||
│ │ └── prd.txt
|
||||
│ ├── reports/ # Generated reports
|
||||
│ │ └── task-complexity-report.json
|
||||
│ └── templates/ # Example/template files
|
||||
│ └── example_prd.txt
|
||||
└── ... (your project files)
|
||||
```
|
||||
|
||||
## Benefits of the New Structure
|
||||
|
||||
✅ **Cleaner Project Root**: No more scattered Task Master files
|
||||
✅ **Better Organization**: Logical separation of tasks, docs, reports, and templates
|
||||
✅ **Hidden by Default**: `.taskmaster/` directory is hidden from most file browsers
|
||||
✅ **Future-Proof**: Centralized location for Task Master extensions
|
||||
✅ **Backward Compatible**: Existing projects continue to work until migrated
|
||||
|
||||
## Migration Options
|
||||
|
||||
### Option 1: Automatic Migration (Recommended)
|
||||
|
||||
Task Master provides a built-in migration command that handles everything automatically:
|
||||
|
||||
#### CLI Migration
|
||||
|
||||
```bash
|
||||
# Dry run to see what would be migrated
|
||||
task-master migrate --dry-run
|
||||
|
||||
# Perform the migration with backup
|
||||
task-master migrate --backup
|
||||
|
||||
# Force migration (overwrites existing files)
|
||||
task-master migrate --force
|
||||
|
||||
# Clean up legacy files after migration
|
||||
task-master migrate --cleanup
|
||||
```
|
||||
|
||||
#### MCP Migration (Cursor/AI Editors)
|
||||
|
||||
Ask your AI assistant:
|
||||
|
||||
```
|
||||
Please migrate my Task Master project to the new .taskmaster directory structure
|
||||
```
|
||||
|
||||
### Option 2: Manual Migration
|
||||
|
||||
If you prefer to migrate manually:
|
||||
|
||||
1. **Create the new directory structure:**
|
||||
|
||||
```bash
|
||||
mkdir -p .taskmaster/{tasks,docs,reports,templates}
|
||||
```
|
||||
|
||||
2. **Move your files:**
|
||||
|
||||
```bash
|
||||
# Move tasks
|
||||
mv tasks/* .taskmaster/tasks/
|
||||
|
||||
# Move configuration
|
||||
mv .taskmasterconfig .taskmaster/config.json
|
||||
|
||||
# Move PRD and documentation
|
||||
mv scripts/prd.txt .taskmaster/docs/
|
||||
mv scripts/example_prd.txt .taskmaster/templates/
|
||||
|
||||
# Move reports (if they exist)
|
||||
mv scripts/task-complexity-report.json .taskmaster/reports/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
3. **Clean up empty directories:**
|
||||
```bash
|
||||
rmdir tasks scripts 2>/dev/null || true
|
||||
```
|
||||
|
||||
## What Gets Migrated
|
||||
|
||||
The migration process handles these file types:
|
||||
|
||||
### Tasks Directory → `.taskmaster/tasks/`
|
||||
|
||||
- `tasks.json`
|
||||
- Individual task text files (`.txt`)
|
||||
|
||||
### Scripts Directory → Multiple Destinations
|
||||
|
||||
- **PRD files** → `.taskmaster/docs/`
|
||||
- `prd.txt`, `requirements.txt`, etc.
|
||||
- **Example/Template files** → `.taskmaster/templates/`
|
||||
- `example_prd.txt`, template files
|
||||
- **Reports** → `.taskmaster/reports/`
|
||||
- `task-complexity-report.json`
|
||||
|
||||
### Configuration
|
||||
|
||||
- `.taskmasterconfig` → `.taskmaster/config.json`
|
||||
|
||||
## After Migration
|
||||
|
||||
Once migrated, Task Master will:
|
||||
|
||||
✅ **Automatically use** the new directory structure
|
||||
✅ **Show deprecation warnings** when legacy files are detected
|
||||
✅ **Create new files** in the proper locations
|
||||
✅ **Fall back gracefully** to legacy locations if new ones don't exist
|
||||
|
||||
### Verification
|
||||
|
||||
After migration, verify everything works:
|
||||
|
||||
1. **List your tasks:**
|
||||
|
||||
```bash
|
||||
task-master list
|
||||
```
|
||||
|
||||
2. **Check your configuration:**
|
||||
|
||||
```bash
|
||||
task-master models
|
||||
```
|
||||
|
||||
3. **Generate new task files:**
|
||||
```bash
|
||||
task-master generate
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Migration Issues
|
||||
|
||||
**Q: Migration says "no files to migrate"**
|
||||
A: Your project may already be using the new structure or have no Task Master files to migrate.
|
||||
|
||||
**Q: Migration fails with permission errors**
|
||||
A: Ensure you have write permissions in your project directory.
|
||||
|
||||
**Q: Some files weren't migrated**
|
||||
A: Check the migration output - some files may not match the expected patterns. You can migrate these manually.
|
||||
|
||||
### Working with Legacy Projects
|
||||
|
||||
If you're working with an older project that hasn't been migrated:
|
||||
|
||||
- Task Master will continue to work with the old structure
|
||||
- You'll see deprecation warnings in the output
|
||||
- New files will still be created in legacy locations
|
||||
- Use the migration command when ready to upgrade
|
||||
|
||||
### New Project Initialization
|
||||
|
||||
New projects automatically use the new structure:
|
||||
|
||||
```bash
|
||||
task-master init # Creates .taskmaster/ structure
|
||||
```
|
||||
|
||||
## Path Changes for Developers
|
||||
|
||||
If you're developing tools or scripts that interact with Task Master files:
|
||||
|
||||
### Configuration File
|
||||
|
||||
- **Old:** `.taskmasterconfig`
|
||||
- **New:** `.taskmaster/config.json`
|
||||
- **Fallback:** Task Master checks both locations
|
||||
|
||||
### Tasks File
|
||||
|
||||
- **Old:** `tasks/tasks.json`
|
||||
- **New:** `.taskmaster/tasks/tasks.json`
|
||||
- **Fallback:** Task Master checks both locations
|
||||
|
||||
### Reports
|
||||
|
||||
- **Old:** `scripts/task-complexity-report.json`
|
||||
- **New:** `.taskmaster/reports/task-complexity-report.json`
|
||||
- **Fallback:** Task Master checks both locations
|
||||
|
||||
### PRD Files
|
||||
|
||||
- **Old:** `scripts/prd.txt`
|
||||
- **New:** `.taskmaster/docs/prd.txt`
|
||||
- **Fallback:** Task Master checks both locations
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter issues during migration:
|
||||
|
||||
1. **Check the logs:** Add `--debug` flag for detailed output
|
||||
2. **Backup first:** Always use `--backup` option for safety
|
||||
3. **Test with dry-run:** Use `--dry-run` to preview changes
|
||||
4. **Ask for help:** Use our Discord community or GitHub issues
|
||||
|
||||
---
|
||||
|
||||
_This migration guide applies to Task Master v0.15.x and later. For older versions, please upgrade to the latest version first._
|
||||
@@ -1,4 +1,4 @@
|
||||
# Available Models as of May 27, 2025
|
||||
# Available Models as of June 13, 2025
|
||||
|
||||
## Main Models
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
| anthropic | claude-3-5-sonnet-20241022 | 0.49 | 3 | 15 |
|
||||
| openai | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| openai | o1 | 0.489 | 15 | 60 |
|
||||
| openai | o3 | 0.5 | 10 | 40 |
|
||||
| openai | o3 | 0.5 | 2 | 8 |
|
||||
| openai | o3-mini | 0.493 | 1.1 | 4.4 |
|
||||
| openai | o4-mini | 0.45 | 1.1 | 4.4 |
|
||||
| openai | o1-mini | 0.4 | 1.1 | 4.4 |
|
||||
@@ -24,6 +24,7 @@
|
||||
| google | gemini-2.5-flash-preview-04-17 | — | — | — |
|
||||
| google | gemini-2.0-flash | 0.754 | 0.15 | 0.6 |
|
||||
| google | gemini-2.0-flash-lite | — | — | — |
|
||||
| perplexity | sonar-pro | — | 3 | 15 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
@@ -70,6 +71,8 @@
|
||||
| perplexity | sonar-pro | — | 3 | 15 |
|
||||
| perplexity | sonar | — | 1 | 1 |
|
||||
| perplexity | deep-research | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
|
||||
@@ -82,7 +85,7 @@
|
||||
| anthropic | claude-3-7-sonnet-20250219 | 0.623 | 3 | 15 |
|
||||
| anthropic | claude-3-5-sonnet-20241022 | 0.49 | 3 | 15 |
|
||||
| openai | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| openai | o3 | 0.5 | 10 | 40 |
|
||||
| openai | o3 | 0.5 | 2 | 8 |
|
||||
| openai | o4-mini | 0.45 | 1.1 | 4.4 |
|
||||
| google | gemini-2.5-pro-preview-05-06 | 0.638 | — | — |
|
||||
| google | gemini-2.5-pro-preview-03-25 | 0.638 | — | — |
|
||||
|
||||
@@ -137,3 +137,290 @@ The `show` command:
|
||||
8. **Communicate context to the agent**: When asking the Cursor agent to help with a task, provide context about what you're trying to achieve.
|
||||
|
||||
9. **Validate dependencies**: Periodically run the validate-dependencies command to check for invalid or circular dependencies.
|
||||
|
||||
# Task Structure Documentation
|
||||
|
||||
Task Master uses a structured JSON format to organize and manage tasks. As of version 0.16.2, Task Master introduces **Tagged Task Lists** for multi-context task management while maintaining full backward compatibility.
|
||||
|
||||
## Tagged Task Lists System
|
||||
|
||||
Task Master now organizes tasks into separate contexts called **tags**. This enables working across multiple contexts such as different branches, environments, or project phases without conflicts.
|
||||
|
||||
### Data Structure Overview
|
||||
|
||||
**Tagged Format (Current)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"master": {
|
||||
"tasks": [
|
||||
{ "id": 1, "title": "Setup API", "status": "pending", ... }
|
||||
]
|
||||
},
|
||||
"feature-branch": {
|
||||
"tasks": [
|
||||
{ "id": 1, "title": "New Feature", "status": "pending", ... }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Legacy Format (Automatically Migrated)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"tasks": [
|
||||
{ "id": 1, "title": "Setup API", "status": "pending", ... }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Tag-based Task Lists (v0.17+) and Compatibility
|
||||
|
||||
- **Seamless Migration**: Existing `tasks.json` files are automatically migrated to use a "master" tag
|
||||
- **Zero Disruption**: All existing commands continue to work exactly as before
|
||||
- **Backward Compatibility**: Existing workflows remain unchanged
|
||||
- **Silent Process**: Migration happens transparently on first use with a friendly notification
|
||||
|
||||
## Core Task Properties
|
||||
|
||||
Each task within a tag context contains the following properties:
|
||||
|
||||
### Required Properties
|
||||
|
||||
- **`id`** (number): Unique identifier within the tag context
|
||||
|
||||
```json
|
||||
"id": 1
|
||||
```
|
||||
|
||||
- **`title`** (string): Brief, descriptive title
|
||||
|
||||
```json
|
||||
"title": "Implement user authentication"
|
||||
```
|
||||
|
||||
- **`description`** (string): Concise summary of what the task involves
|
||||
|
||||
```json
|
||||
"description": "Create a secure authentication system using JWT tokens"
|
||||
```
|
||||
|
||||
- **`status`** (string): Current state of the task
|
||||
- Valid values: `"pending"`, `"in-progress"`, `"done"`, `"review"`, `"deferred"`, `"cancelled"`
|
||||
```json
|
||||
"status": "pending"
|
||||
```
|
||||
|
||||
### Optional Properties
|
||||
|
||||
- **`dependencies`** (array): IDs of prerequisite tasks that must be completed first
|
||||
|
||||
```json
|
||||
"dependencies": [2, 3]
|
||||
```
|
||||
|
||||
- **`priority`** (string): Importance level
|
||||
|
||||
- Valid values: `"high"`, `"medium"`, `"low"`
|
||||
- Default: `"medium"`
|
||||
|
||||
```json
|
||||
"priority": "high"
|
||||
```
|
||||
|
||||
- **`details`** (string): In-depth implementation instructions
|
||||
|
||||
```json
|
||||
"details": "Use GitHub OAuth client ID/secret, handle callback, set session token"
|
||||
```
|
||||
|
||||
- **`testStrategy`** (string): Verification approach
|
||||
|
||||
```json
|
||||
"testStrategy": "Deploy and call endpoint to confirm authentication flow"
|
||||
```
|
||||
|
||||
- **`subtasks`** (array): List of smaller, more specific tasks
|
||||
```json
|
||||
"subtasks": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Configure OAuth",
|
||||
"description": "Set up OAuth configuration",
|
||||
"status": "pending",
|
||||
"dependencies": [],
|
||||
"details": "Configure GitHub OAuth app and store credentials"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Subtask Structure
|
||||
|
||||
Subtasks follow a similar structure to main tasks but with some differences:
|
||||
|
||||
### Subtask Properties
|
||||
|
||||
- **`id`** (number): Unique identifier within the parent task
|
||||
- **`title`** (string): Brief, descriptive title
|
||||
- **`description`** (string): Concise summary of the subtask
|
||||
- **`status`** (string): Current state (same values as main tasks)
|
||||
- **`dependencies`** (array): Can reference other subtasks or main task IDs
|
||||
- **`details`** (string): Implementation instructions and notes
|
||||
|
||||
### Subtask Example
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Handle OAuth callback",
|
||||
"description": "Process the OAuth callback and extract user data",
|
||||
"status": "pending",
|
||||
"dependencies": [1],
|
||||
"details": "Parse callback parameters, exchange code for token, fetch user profile"
|
||||
}
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
Here's a complete example showing the tagged task structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"master": {
|
||||
"tasks": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Setup Express Server",
|
||||
"description": "Initialize and configure Express.js server with middleware",
|
||||
"status": "done",
|
||||
"dependencies": [],
|
||||
"priority": "high",
|
||||
"details": "Create Express app with CORS, body parser, and error handling",
|
||||
"testStrategy": "Start server and verify health check endpoint responds",
|
||||
"subtasks": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Initialize npm project",
|
||||
"description": "Set up package.json and install dependencies",
|
||||
"status": "done",
|
||||
"dependencies": [],
|
||||
"details": "Run npm init, install express, cors, body-parser"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Configure middleware",
|
||||
"description": "Set up CORS and body parsing middleware",
|
||||
"status": "done",
|
||||
"dependencies": [1],
|
||||
"details": "Add app.use() calls for cors() and express.json()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Implement user authentication",
|
||||
"description": "Create secure authentication system",
|
||||
"status": "pending",
|
||||
"dependencies": [1],
|
||||
"priority": "high",
|
||||
"details": "Use JWT tokens for session management",
|
||||
"testStrategy": "Test login/logout flow with valid and invalid credentials",
|
||||
"subtasks": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"feature-auth": {
|
||||
"tasks": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "OAuth Integration",
|
||||
"description": "Add OAuth authentication support",
|
||||
"status": "pending",
|
||||
"dependencies": [],
|
||||
"priority": "medium",
|
||||
"details": "Integrate with GitHub OAuth for user authentication",
|
||||
"testStrategy": "Test OAuth flow with GitHub account",
|
||||
"subtasks": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tag Context Management
|
||||
|
||||
### Current Tag Resolution
|
||||
|
||||
Task Master automatically determines the current tag context based on:
|
||||
|
||||
1. **State Configuration**: Current tag stored in `.taskmaster/state.json`
|
||||
2. **Default Fallback**: "master" tag when no context is specified
|
||||
3. **Future Enhancement**: Git branch-based tag switching (Part 2)
|
||||
|
||||
### Tag Isolation
|
||||
|
||||
- **Context Separation**: Tasks in different tags are completely isolated
|
||||
- **Independent Numbering**: Each tag has its own task ID sequence starting from 1
|
||||
- **Parallel Development**: Multiple team members can work on separate tags without conflicts
|
||||
|
||||
## Data Validation
|
||||
|
||||
Task Master validates the following aspects of task data:
|
||||
|
||||
### Required Validations
|
||||
|
||||
- **Unique IDs**: Task IDs must be unique within each tag context
|
||||
- **Valid Status**: Status values must be from the allowed set
|
||||
- **Dependency References**: Dependencies must reference existing task IDs within the same tag
|
||||
- **Subtask IDs**: Subtask IDs must be unique within their parent task
|
||||
|
||||
### Optional Validations
|
||||
|
||||
- **Circular Dependencies**: System detects and prevents circular dependency chains
|
||||
- **Priority Values**: Priority must be one of the allowed values if specified
|
||||
- **Data Types**: All properties must match their expected data types
|
||||
|
||||
## File Generation
|
||||
|
||||
Task Master can generate individual markdown files for each task based on the JSON structure. These files include:
|
||||
|
||||
- **Task Overview**: ID, title, status, dependencies
|
||||
- **Tag Context**: Which tag the task belongs to
|
||||
- **Implementation Details**: Full task details and test strategy
|
||||
- **Subtask Breakdown**: All subtasks with their current status
|
||||
- **Dependency Status**: Visual indicators showing which dependencies are complete
|
||||
|
||||
## Migration Process
|
||||
|
||||
When Task Master encounters a legacy format `tasks.json` file:
|
||||
|
||||
1. **Detection**: Automatically detects `{"tasks": [...]}` format
|
||||
2. **Transformation**: Converts to `{"master": {"tasks": [...]}}` format
|
||||
3. **Configuration**: Updates `.taskmaster/config.json` with tagged system settings
|
||||
4. **State Creation**: Creates `.taskmaster/state.json` for tag management
|
||||
5. **Notification**: Shows one-time friendly notice about the new system
|
||||
6. **Preservation**: All existing task data is preserved exactly as-is
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Task Organization
|
||||
|
||||
- **Logical Grouping**: Use tags to group related tasks (e.g., by feature, branch, or milestone)
|
||||
- **Clear Titles**: Use descriptive titles that explain the task's purpose
|
||||
- **Proper Dependencies**: Define dependencies to ensure correct execution order
|
||||
- **Detailed Instructions**: Include sufficient detail in the `details` field for implementation
|
||||
|
||||
### Tag Management
|
||||
|
||||
- **Meaningful Names**: Use descriptive tag names that reflect their purpose
|
||||
- **Consistent Naming**: Establish naming conventions for tags (e.g., branch names, feature names)
|
||||
- **Context Switching**: Be aware of which tag context you're working in
|
||||
- **Isolation Benefits**: Leverage tag isolation to prevent merge conflicts
|
||||
|
||||
### Subtask Design
|
||||
|
||||
- **Granular Tasks**: Break down complex tasks into manageable subtasks
|
||||
- **Clear Dependencies**: Define subtask dependencies to show implementation order
|
||||
- **Implementation Notes**: Use subtask details to track progress and decisions
|
||||
- **Status Tracking**: Keep subtask status updated as work progresses
|
||||
|
||||
137
docs/tutorial.md
137
docs/tutorial.md
@@ -20,22 +20,22 @@ npm i -g task-master-ai
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
"mcpServers": {
|
||||
"taskmaster-ai": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "--package=task-master-ai", "task-master-ai"],
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
|
||||
"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "YOUR_GOOGLE_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "YOUR_MISTRAL_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "YOUR_OPENROUTER_KEY_HERE",
|
||||
"XAI_API_KEY": "YOUR_XAI_KEY_HERE",
|
||||
"AZURE_OPENAI_API_KEY": "YOUR_AZURE_KEY_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -60,12 +60,12 @@ The AI will:
|
||||
- Set up initial configuration files
|
||||
- Guide you through the rest of the process
|
||||
|
||||
5. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`)
|
||||
5. Place your PRD document in the `.taskmaster/docs/` directory (e.g., `.taskmaster/docs/prd.txt`)
|
||||
|
||||
6. **Use natural language commands** to interact with Task Master:
|
||||
|
||||
```
|
||||
Can you parse my PRD at scripts/prd.txt?
|
||||
Can you parse my PRD at .taskmaster/docs/prd.txt?
|
||||
What's the next task I should work on?
|
||||
Can you help me implement task 3?
|
||||
```
|
||||
@@ -132,7 +132,7 @@ If you're not using MCP, you can still set up Cursor integration:
|
||||
|
||||
1. After initializing your project, open it in Cursor
|
||||
2. The `.cursor/rules/dev_workflow.mdc` file is automatically loaded by Cursor, providing the AI with knowledge about the task management system
|
||||
3. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`)
|
||||
3. Place your PRD document in the `.taskmaster/docs/` directory (e.g., `.taskmaster/docs/prd.txt`)
|
||||
4. Open Cursor's AI chat and switch to Agent mode
|
||||
|
||||
### Alternative MCP Setup in Cursor
|
||||
@@ -155,13 +155,13 @@ Once configured, you can interact with Task Master's task management commands di
|
||||
In Cursor's AI chat, instruct the agent to generate tasks from your PRD:
|
||||
|
||||
```
|
||||
Please use the task-master parse-prd command to generate tasks from my PRD. The PRD is located at scripts/prd.txt.
|
||||
Please use the task-master parse-prd command to generate tasks from my PRD. The PRD is located at .taskmaster/docs/prd.txt.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
task-master parse-prd scripts/prd.txt
|
||||
task-master parse-prd .taskmaster/docs/prd.txt
|
||||
```
|
||||
|
||||
This will:
|
||||
@@ -397,7 +397,7 @@ task-master expand --id=5 --research
|
||||
### Starting a new project
|
||||
|
||||
```
|
||||
I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt.
|
||||
I've just initialized a new project with Claude Task Master. I have a PRD at .taskmaster/docs/prd.txt.
|
||||
Can you help me parse it and set up the initial tasks?
|
||||
```
|
||||
|
||||
@@ -495,3 +495,96 @@ The agent will:
|
||||
- **When updating dependencies**
|
||||
|
||||
The research tool automatically includes relevant project context and provides fresh information that can significantly improve implementation quality.
|
||||
|
||||
## Git Integration and Tag Management
|
||||
|
||||
Task Master supports tagged task lists for multi-context development, which is particularly useful when working with git branches or different project phases.
|
||||
|
||||
### Working with Tags
|
||||
|
||||
Tags provide isolated task contexts, allowing you to maintain separate task lists for different features, branches, or experiments:
|
||||
|
||||
```
|
||||
I'm starting work on a new feature branch. Can you create a new tag for this work?
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
# Create a tag based on your current git branch
|
||||
task-master add-tag --from-branch
|
||||
```
|
||||
|
||||
Or you can create a tag with a specific name:
|
||||
|
||||
```
|
||||
Create a new tag called 'user-auth' for authentication-related tasks.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
task-master add-tag user-auth --description="User authentication feature tasks"
|
||||
```
|
||||
|
||||
### Switching Between Contexts
|
||||
|
||||
When working on different features or branches:
|
||||
|
||||
```
|
||||
Switch to the 'user-auth' tag context so I can work on authentication tasks.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
task-master use-tag user-auth
|
||||
```
|
||||
|
||||
### Copying Tasks Between Tags
|
||||
|
||||
When you need to duplicate work across contexts:
|
||||
|
||||
```
|
||||
Copy all tasks from the current tag to a new 'testing' tag for QA work.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
task-master add-tag testing --copy-from-current --description="QA and testing tasks"
|
||||
```
|
||||
|
||||
### Tag Management
|
||||
|
||||
View and manage your tag contexts:
|
||||
|
||||
```
|
||||
Show me all available tags and their current status.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
|
||||
```bash
|
||||
task-master tags --show-metadata
|
||||
```
|
||||
|
||||
### Benefits of Tagged Task Lists
|
||||
|
||||
- **Branch Isolation**: Each git branch can have its own task context
|
||||
- **Merge Conflict Prevention**: Tasks in different tags don't interfere with each other
|
||||
- **Parallel Development**: Multiple team members can work on separate contexts
|
||||
- **Context Switching**: Easily switch between different project phases or features
|
||||
- **Experimentation**: Create experimental task lists without affecting main work
|
||||
|
||||
### Git Workflow Integration
|
||||
|
||||
A typical git workflow with Task Master tags:
|
||||
|
||||
1. **Create feature branch**: `git checkout -b feature/user-auth`
|
||||
2. **Create matching tag**: Ask agent to run `task-master add-tag --from-branch`
|
||||
3. **Work in isolated context**: All task operations work within the new tag
|
||||
4. **Switch contexts as needed**: Use `task-master use-tag <name>` to switch between different work streams
|
||||
5. **Merge and cleanup**: After merging the branch, optionally delete the tag with `task-master delete-tag <name>`
|
||||
|
||||
This workflow ensures your task management stays organized and conflicts are minimized when working with teams or multiple features simultaneously.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
``# Taskmaster AI Installation Guide
|
||||
# Taskmaster AI Installation Guide
|
||||
|
||||
This guide helps AI assistants install and configure Taskmaster for users in their development projects.
|
||||
|
||||
|
||||
198
mcp-server/src/core/direct-functions/add-tag.js
Normal file
198
mcp-server/src/core/direct-functions/add-tag.js
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* add-tag.js
|
||||
* Direct function implementation for creating a new tag
|
||||
*/
|
||||
|
||||
import {
|
||||
createTag,
|
||||
createTagFromBranch
|
||||
} from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for creating a new tag with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.name - Name of the new tag to create
|
||||
* @param {boolean} [args.copyFromCurrent=false] - Whether to copy tasks from current tag
|
||||
* @param {string} [args.copyFromTag] - Specific tag to copy tasks from
|
||||
* @param {boolean} [args.fromBranch=false] - Create tag name from current git branch
|
||||
* @param {string} [args.description] - Optional description for the tag
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function addTagDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const {
|
||||
tasksJsonPath,
|
||||
name,
|
||||
copyFromCurrent = false,
|
||||
copyFromTag,
|
||||
fromBranch = false,
|
||||
description,
|
||||
projectRoot
|
||||
} = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('addTagDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Handle --from-branch option
|
||||
if (fromBranch) {
|
||||
log.info('Creating tag from current git branch');
|
||||
|
||||
// Import git utilities
|
||||
const gitUtils = await import(
|
||||
'../../../../scripts/modules/utils/git-utils.js'
|
||||
);
|
||||
|
||||
// Check if we're in a git repository
|
||||
if (!(await gitUtils.isGitRepository(projectRoot))) {
|
||||
log.error('Not in a git repository');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NOT_GIT_REPO',
|
||||
message: 'Not in a git repository. Cannot use fromBranch option.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Get current git branch
|
||||
const currentBranch = await gitUtils.getCurrentBranch(projectRoot);
|
||||
if (!currentBranch) {
|
||||
log.error('Could not determine current git branch');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NO_CURRENT_BRANCH',
|
||||
message: 'Could not determine current git branch.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Prepare options for branch-based tag creation
|
||||
const branchOptions = {
|
||||
copyFromCurrent,
|
||||
copyFromTag,
|
||||
description:
|
||||
description || `Tag created from git branch "${currentBranch}"`
|
||||
};
|
||||
|
||||
// Call the createTagFromBranch function
|
||||
const result = await createTagFromBranch(
|
||||
tasksJsonPath,
|
||||
currentBranch,
|
||||
branchOptions,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
branchName: result.branchName,
|
||||
tagName: result.tagName,
|
||||
created: result.created,
|
||||
mappingUpdated: result.mappingUpdated,
|
||||
message: `Successfully created tag "${result.tagName}" from git branch "${result.branchName}"`
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Check required parameters for regular tag creation
|
||||
if (!name || typeof name !== 'string') {
|
||||
log.error('Missing required parameter: name');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(`Creating new tag: ${name}`);
|
||||
|
||||
// Prepare options
|
||||
const options = {
|
||||
copyFromCurrent,
|
||||
copyFromTag,
|
||||
description
|
||||
};
|
||||
|
||||
// Call the createTag function
|
||||
const result = await createTag(
|
||||
tasksJsonPath,
|
||||
name,
|
||||
options,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
tagName: result.tagName,
|
||||
created: result.created,
|
||||
tasksCopied: result.tasksCopied,
|
||||
sourceTag: result.sourceTag,
|
||||
description: result.description,
|
||||
message: `Successfully created tag "${result.tagName}"`
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in addTagDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'ADD_TAG_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
let manualTaskData = null;
|
||||
let newTaskId;
|
||||
let telemetryData;
|
||||
let tagInfo;
|
||||
|
||||
if (isManualCreation) {
|
||||
// Create manual task data object
|
||||
@@ -129,6 +130,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
);
|
||||
newTaskId = result.newTaskId;
|
||||
telemetryData = result.telemetryData;
|
||||
tagInfo = result.tagInfo;
|
||||
} else {
|
||||
// AI-driven task creation
|
||||
log.info(
|
||||
@@ -154,6 +156,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
);
|
||||
newTaskId = result.newTaskId;
|
||||
telemetryData = result.telemetryData;
|
||||
tagInfo = result.tagInfo;
|
||||
}
|
||||
|
||||
// Restore normal logging
|
||||
@@ -164,7 +167,8 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
data: {
|
||||
taskId: newTaskId,
|
||||
message: `Successfully added new task #${newTaskId}`,
|
||||
telemetryData: telemetryData
|
||||
telemetryData: telemetryData,
|
||||
tagInfo: tagInfo
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -196,7 +196,8 @@ export async function analyzeTaskComplexityDirect(args, log, context = {}) {
|
||||
lowComplexityTasks
|
||||
},
|
||||
fullReport: coreResult.report,
|
||||
telemetryData: coreResult.telemetryData
|
||||
telemetryData: coreResult.telemetryData,
|
||||
tagInfo: coreResult.tagInfo
|
||||
}
|
||||
};
|
||||
} catch (parseError) {
|
||||
|
||||
@@ -28,8 +28,7 @@ export async function complexityReportDirect(args, log) {
|
||||
log.error('complexityReportDirect called without reportPath');
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: 'reportPath is required' },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: 'reportPath is required' }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -111,8 +110,7 @@ export async function complexityReportDirect(args, log) {
|
||||
error: {
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
message: error.message
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
125
mcp-server/src/core/direct-functions/copy-tag.js
Normal file
125
mcp-server/src/core/direct-functions/copy-tag.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* copy-tag.js
|
||||
* Direct function implementation for copying a tag
|
||||
*/
|
||||
|
||||
import { copyTag } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for copying a tag with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.sourceName - Name of the source tag to copy from
|
||||
* @param {string} args.targetName - Name of the new tag to create
|
||||
* @param {string} [args.description] - Optional description for the new tag
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function copyTagDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, sourceName, targetName, description, projectRoot } =
|
||||
args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('copyTagDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check required parameters
|
||||
if (!sourceName || typeof sourceName !== 'string') {
|
||||
log.error('Missing required parameter: sourceName');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Source tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!targetName || typeof targetName !== 'string') {
|
||||
log.error('Missing required parameter: targetName');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Target tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(`Copying tag from "${sourceName}" to "${targetName}"`);
|
||||
|
||||
// Prepare options
|
||||
const options = {
|
||||
description
|
||||
};
|
||||
|
||||
// Call the copyTag function
|
||||
const result = await copyTag(
|
||||
tasksJsonPath,
|
||||
sourceName,
|
||||
targetName,
|
||||
options,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
sourceName: result.sourceName,
|
||||
targetName: result.targetName,
|
||||
copied: result.copied,
|
||||
tasksCopied: result.tasksCopied,
|
||||
description: result.description,
|
||||
message: `Successfully copied tag from "${result.sourceName}" to "${result.targetName}"`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in copyTagDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'COPY_TAG_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
159
mcp-server/src/core/direct-functions/create-tag-from-branch.js
Normal file
159
mcp-server/src/core/direct-functions/create-tag-from-branch.js
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* create-tag-from-branch.js
|
||||
* Direct function implementation for creating tags from git branches
|
||||
*/
|
||||
|
||||
import { createTagFromBranch } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
getCurrentBranch,
|
||||
isGitRepository
|
||||
} from '../../../../scripts/modules/utils/git-utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for creating tags from git branches with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.tasksJsonPath - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.branchName] - Git branch name (optional, uses current branch if not provided)
|
||||
* @param {boolean} [args.copyFromCurrent] - Copy tasks from current tag
|
||||
* @param {string} [args.copyFromTag] - Copy tasks from specific tag
|
||||
* @param {string} [args.description] - Custom description for the tag
|
||||
* @param {boolean} [args.autoSwitch] - Automatically switch to the new tag
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function createTagFromBranchDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const {
|
||||
tasksJsonPath,
|
||||
branchName,
|
||||
copyFromCurrent,
|
||||
copyFromTag,
|
||||
description,
|
||||
autoSwitch,
|
||||
projectRoot
|
||||
} = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('createTagFromBranchDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check if projectRoot was provided
|
||||
if (!projectRoot) {
|
||||
log.error('createTagFromBranchDirect called without projectRoot');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'projectRoot is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check if we're in a git repository
|
||||
if (!(await isGitRepository(projectRoot))) {
|
||||
log.error('Not in a git repository');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NOT_GIT_REPOSITORY',
|
||||
message: 'Not in a git repository. Cannot create tag from branch.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Determine branch name
|
||||
let targetBranch = branchName;
|
||||
if (!targetBranch) {
|
||||
targetBranch = await getCurrentBranch(projectRoot);
|
||||
if (!targetBranch) {
|
||||
log.error('Could not determine current git branch');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'NO_CURRENT_BRANCH',
|
||||
message: 'Could not determine current git branch'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
log.info(`Creating tag from git branch: ${targetBranch}`);
|
||||
|
||||
// Prepare options
|
||||
const options = {
|
||||
copyFromCurrent: copyFromCurrent || false,
|
||||
copyFromTag,
|
||||
description:
|
||||
description || `Tag created from git branch "${targetBranch}"`,
|
||||
autoSwitch: autoSwitch || false
|
||||
};
|
||||
|
||||
// Call the createTagFromBranch function
|
||||
const result = await createTagFromBranch(
|
||||
tasksJsonPath,
|
||||
targetBranch,
|
||||
options,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
branchName: result.branchName,
|
||||
tagName: result.tagName,
|
||||
created: result.created,
|
||||
mappingUpdated: result.mappingUpdated,
|
||||
autoSwitched: result.autoSwitched,
|
||||
message: `Successfully created tag "${result.tagName}" from branch "${result.branchName}"`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in createTagFromBranchDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'CREATE_TAG_FROM_BRANCH_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
110
mcp-server/src/core/direct-functions/delete-tag.js
Normal file
110
mcp-server/src/core/direct-functions/delete-tag.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* delete-tag.js
|
||||
* Direct function implementation for deleting a tag
|
||||
*/
|
||||
|
||||
import { deleteTag } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for deleting a tag with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.name - Name of the tag to delete
|
||||
* @param {boolean} [args.yes=false] - Skip confirmation prompts
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function deleteTagDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, name, yes = false, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('deleteTagDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check required parameters
|
||||
if (!name || typeof name !== 'string') {
|
||||
log.error('Missing required parameter: name');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(`Deleting tag: ${name}`);
|
||||
|
||||
// Prepare options
|
||||
const options = {
|
||||
yes // For MCP, we always skip confirmation prompts
|
||||
};
|
||||
|
||||
// Call the deleteTag function
|
||||
const result = await deleteTag(
|
||||
tasksJsonPath,
|
||||
name,
|
||||
options,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
tagName: result.tagName,
|
||||
deleted: result.deleted,
|
||||
tasksDeleted: result.tasksDeleted,
|
||||
wasCurrentTag: result.wasCurrentTag,
|
||||
switchedToMaster: result.switchedToMaster,
|
||||
message: `Successfully deleted tag "${result.tagName}"`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in deleteTagDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'DELETE_TAG_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,8 @@ export async function expandAllTasksDirect(args, log, context = {}) {
|
||||
useResearch,
|
||||
additionalContext,
|
||||
forceFlag,
|
||||
{ session, mcpLog, projectRoot }
|
||||
{ session, mcpLog, projectRoot },
|
||||
'json'
|
||||
);
|
||||
|
||||
// Core function now returns a summary object including the *aggregated* telemetryData
|
||||
|
||||
@@ -29,7 +29,7 @@ import { createLogWrapper } from '../../tools/utils.js';
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Context object containing session
|
||||
* @param {Object} [context.session] - MCP Session object
|
||||
* @returns {Promise<Object>} - Task expansion result { success: boolean, data?: any, error?: { code: string, message: string }, fromCache: boolean }
|
||||
* @returns {Promise<Object>} - Task expansion result { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function expandTaskDirect(args, log, context = {}) {
|
||||
const { session } = context; // Extract session
|
||||
@@ -54,8 +54,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,8 +72,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'INPUT_VALIDATION_ERROR',
|
||||
message: 'Task ID is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,7 +89,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
|
||||
// Read tasks data
|
||||
log.info(`[expandTaskDirect] Attempting to read JSON from: ${tasksPath}`);
|
||||
const data = readJSON(tasksPath);
|
||||
const data = readJSON(tasksPath, projectRoot);
|
||||
log.info(
|
||||
`[expandTaskDirect] Result of readJSON: ${data ? 'Data read successfully' : 'readJSON returned null or undefined'}`
|
||||
);
|
||||
@@ -105,8 +103,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'INVALID_TASKS_FILE',
|
||||
message: `No valid tasks found in ${tasksPath}. readJSON returned: ${JSON.stringify(data)}`
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -121,8 +118,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'TASK_NOT_FOUND',
|
||||
message: `Task with ID ${taskId} not found`
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,8 +129,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'TASK_COMPLETED',
|
||||
message: `Task ${taskId} is already marked as ${task.status} and cannot be expanded`
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -151,8 +146,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
task,
|
||||
subtasksAdded: 0,
|
||||
hasExistingSubtasks
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -170,10 +164,6 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
// Tracking subtasks count before expansion
|
||||
const subtasksCountBefore = task.subtasks ? task.subtasks.length : 0;
|
||||
|
||||
// Create a backup of the tasks.json file
|
||||
const backupPath = path.join(path.dirname(tasksPath), 'tasks.json.bak');
|
||||
fs.copyFileSync(tasksPath, backupPath);
|
||||
|
||||
// Directly modify the data instead of calling the CLI function
|
||||
if (!task.subtasks) {
|
||||
task.subtasks = [];
|
||||
@@ -213,7 +203,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
if (!wasSilent && isSilentMode()) disableSilentMode();
|
||||
|
||||
// Read the updated data
|
||||
const updatedData = readJSON(tasksPath);
|
||||
const updatedData = readJSON(tasksPath, projectRoot);
|
||||
const updatedTask = updatedData.tasks.find((t) => t.id === taskId);
|
||||
|
||||
// Calculate how many subtasks were added
|
||||
@@ -231,9 +221,9 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
task: coreResult.task,
|
||||
subtasksAdded,
|
||||
hasExistingSubtasks,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
telemetryData: coreResult.telemetryData,
|
||||
tagInfo: coreResult.tagInfo
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
@@ -245,8 +235,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'CORE_FUNCTION_ERROR',
|
||||
message: error.message || 'Failed to expand task'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -256,8 +245,7 @@ export async function expandTaskDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'CORE_FUNCTION_ERROR',
|
||||
message: error.message || 'Failed to expand task'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ export async function generateTaskFilesDirect(args, log) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
if (!outputDir) {
|
||||
@@ -37,8 +36,7 @@ export async function generateTaskFilesDirect(args, log) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,8 +63,7 @@ export async function generateTaskFilesDirect(args, log) {
|
||||
log.error(`Error in generateTaskFiles: ${genError.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'GENERATE_FILES_ERROR', message: genError.message },
|
||||
fromCache: false
|
||||
error: { code: 'GENERATE_FILES_ERROR', message: genError.message }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,8 +76,7 @@ export async function generateTaskFilesDirect(args, log) {
|
||||
outputDir: resolvedOutputDir,
|
||||
taskFiles:
|
||||
'Individual task files have been generated in the output directory'
|
||||
},
|
||||
fromCache: false // This operation always modifies state and should never be cached
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging if an outer error occurs
|
||||
@@ -92,8 +88,7 @@ export async function generateTaskFilesDirect(args, log) {
|
||||
error: {
|
||||
code: 'GENERATE_TASKS_ERROR',
|
||||
message: error.message || 'Unknown error generating task files'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ export async function initializeProjectDirect(args, log, context = {}) {
|
||||
code: 'INVALID_TARGET_DIRECTORY',
|
||||
message: `Cannot initialize project: Invalid target directory '${targetDirectory}' received. Please ensure a valid workspace/folder is open or specified.`,
|
||||
details: `Received args.projectRoot: ${args.projectRoot}` // Show what was received
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,7 +74,7 @@ export async function initializeProjectDirect(args, log, context = {}) {
|
||||
resultData = {
|
||||
message: 'Project initialized successfully.',
|
||||
next_step:
|
||||
'Now that the project is initialized, the next step is to create the tasks by parsing a PRD. This will create the tasks folder and the initial task files (tasks folder will be created when parse-prd is run). The parse-prd tool will require a prd.txt file as input (typically found in the project root directory, scripts/ directory). You can create a prd.txt file by asking the user about their idea, and then using the scripts/example_prd.txt file as a template to genrate a prd.txt file in scripts/. You may skip all of this if the user already has a prd.txt file. You can THEN use the parse-prd tool to create the tasks. So: step 1 after initialization is to create a prd.txt file in scripts/prd.txt or confirm the user already has one. Step 2 is to use the parse-prd tool to create the tasks. Do not bother looking for tasks after initialization, just use the parse-prd tool to create the tasks after creating a prd.txt from which to parse the tasks. You do NOT need to reinitialize the project to parse-prd.',
|
||||
'Now that the project is initialized, the next step is to create the tasks by parsing a PRD. This will create the tasks folder and the initial task files (tasks folder will be created when parse-prd is run). The parse-prd tool will require a prd.txt file as input (typically found in .taskmaster/docs/ directory). You can create a prd.txt file by asking the user about their idea, and then using the .taskmaster/templates/example_prd.txt file as a template to generate a prd.txt file in .taskmaster/docs/. You may skip all of this if the user already has a prd.txt file. You can THEN use the parse-prd tool to create the tasks. So: step 1 after initialization is to create a prd.txt file in .taskmaster/docs/prd.txt or confirm the user already has one. Step 2 is to use the parse-prd tool to create the tasks. Do not bother looking for tasks after initialization, just use the parse-prd tool to create the tasks after creating a prd.txt from which to parse the tasks. You do NOT need to reinitialize the project to parse-prd.',
|
||||
...result
|
||||
};
|
||||
success = true;
|
||||
@@ -97,8 +96,8 @@ export async function initializeProjectDirect(args, log, context = {}) {
|
||||
}
|
||||
|
||||
if (success) {
|
||||
return { success: true, data: resultData, fromCache: false };
|
||||
return { success: true, data: resultData };
|
||||
} else {
|
||||
return { success: false, error: errorResult, fromCache: false };
|
||||
return { success: false, error: errorResult };
|
||||
}
|
||||
}
|
||||
|
||||
132
mcp-server/src/core/direct-functions/list-tags.js
Normal file
132
mcp-server/src/core/direct-functions/list-tags.js
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* list-tags.js
|
||||
* Direct function implementation for listing all tags
|
||||
*/
|
||||
|
||||
import { tags } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for listing all tags with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {boolean} [args.showMetadata=false] - Whether to include metadata in the output
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function listTagsDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, showMetadata = false, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('listTagsDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info('Listing all tags');
|
||||
|
||||
// Prepare options
|
||||
const options = {
|
||||
showMetadata
|
||||
};
|
||||
|
||||
// Call the tags function
|
||||
const result = await tags(
|
||||
tasksJsonPath,
|
||||
options,
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Transform the result to remove full task data and provide summary info
|
||||
const tagsSummary = result.tags.map((tag) => {
|
||||
const tasks = tag.tasks || [];
|
||||
|
||||
// Calculate status breakdown
|
||||
const statusBreakdown = tasks.reduce((acc, task) => {
|
||||
const status = task.status || 'pending';
|
||||
acc[status] = (acc[status] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Calculate subtask counts
|
||||
const subtaskCounts = tasks.reduce(
|
||||
(acc, task) => {
|
||||
if (task.subtasks && task.subtasks.length > 0) {
|
||||
acc.totalSubtasks += task.subtasks.length;
|
||||
task.subtasks.forEach((subtask) => {
|
||||
const subStatus = subtask.status || 'pending';
|
||||
acc.subtasksByStatus[subStatus] =
|
||||
(acc.subtasksByStatus[subStatus] || 0) + 1;
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ totalSubtasks: 0, subtasksByStatus: {} }
|
||||
);
|
||||
|
||||
return {
|
||||
name: tag.name,
|
||||
isCurrent: tag.isCurrent,
|
||||
taskCount: tasks.length,
|
||||
completedTasks: tag.completedTasks,
|
||||
statusBreakdown,
|
||||
subtaskCounts,
|
||||
created: tag.created,
|
||||
description: tag.description
|
||||
};
|
||||
});
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
tags: tagsSummary,
|
||||
currentTag: result.currentTag,
|
||||
totalTags: result.totalTags,
|
||||
message: `Found ${result.totalTags} tag(s)`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in listTagsDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'LIST_TAGS_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,12 @@ import {
|
||||
*
|
||||
* @param {Object} args - Command arguments (now expecting tasksJsonPath explicitly).
|
||||
* @param {Object} log - Logger object.
|
||||
* @returns {Promise<Object>} - Task list result { success: boolean, data?: any, error?: { code: string, message: string }, fromCache: boolean }.
|
||||
* @returns {Promise<Object>} - Task list result { success: boolean, data?: any, error?: { code: string, message: string } }.
|
||||
*/
|
||||
export async function listTasksDirect(args, log) {
|
||||
export async function listTasksDirect(args, log, context = {}) {
|
||||
// Destructure the explicit tasksJsonPath from args
|
||||
const { tasksJsonPath, reportPath, status, withSubtasks } = args;
|
||||
const { tasksJsonPath, reportPath, status, withSubtasks, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
if (!tasksJsonPath) {
|
||||
log.error('listTasksDirect called without tasksJsonPath');
|
||||
@@ -27,8 +28,7 @@ export async function listTasksDirect(args, log) {
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +51,9 @@ export async function listTasksDirect(args, log) {
|
||||
statusFilter,
|
||||
reportPath,
|
||||
withSubtasksFilter,
|
||||
'json'
|
||||
'json',
|
||||
null, // tag
|
||||
{ projectRoot, session } // context
|
||||
);
|
||||
|
||||
if (!resultData || !resultData.tasks) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { moveTask } from '../../../../scripts/modules/task-manager.js';
|
||||
import { findTasksJsonPath } from '../utils/path-utils.js';
|
||||
import { findTasksPath } from '../utils/path-utils.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
@@ -59,7 +59,7 @@ export async function moveTaskDirect(args, log, context = {}) {
|
||||
}
|
||||
};
|
||||
}
|
||||
tasksPath = findTasksJsonPath(args, log);
|
||||
tasksPath = findTasksPath(args, log);
|
||||
}
|
||||
|
||||
// Enable silent mode to prevent console output during MCP operation
|
||||
|
||||
@@ -19,11 +19,12 @@ import {
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.tasksJsonPath - Explicit path to the tasks.json file.
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {Promise<Object>} - Next task result { success: boolean, data?: any, error?: { code: string, message: string }, fromCache: boolean }
|
||||
* @returns {Promise<Object>} - Next task result { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function nextTaskDirect(args, log) {
|
||||
export async function nextTaskDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, reportPath } = args;
|
||||
const { tasksJsonPath, reportPath, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
if (!tasksJsonPath) {
|
||||
log.error('nextTaskDirect called without tasksJsonPath');
|
||||
@@ -32,8 +33,7 @@ export async function nextTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function nextTaskDirect(args, log) {
|
||||
log.info(`Finding next task from ${tasksJsonPath}`);
|
||||
|
||||
// Read tasks data using the provided path
|
||||
const data = readJSON(tasksJsonPath);
|
||||
const data = readJSON(tasksJsonPath, projectRoot);
|
||||
if (!data || !data.tasks) {
|
||||
disableSilentMode(); // Disable before return
|
||||
return {
|
||||
@@ -121,7 +121,7 @@ export async function nextTaskDirect(args, log) {
|
||||
// Use the caching utility
|
||||
try {
|
||||
const result = await coreNextTaskAction();
|
||||
log.info(`nextTaskDirect completed.`);
|
||||
log.info('nextTaskDirect completed.');
|
||||
return result;
|
||||
} catch (error) {
|
||||
log.error(`Unexpected error during nextTask: ${error.message}`);
|
||||
@@ -130,8 +130,7 @@ export async function nextTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
message: error.message
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
import { getDefaultNumTasks } from '../../../../scripts/modules/config-manager.js';
|
||||
import { resolvePrdPath, resolveProjectPath } from '../utils/path-utils.js';
|
||||
import { TASKMASTER_TASKS_FILE } from '../../../../src/constants/paths.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for parsing PRD documents and generating tasks.
|
||||
@@ -49,7 +51,20 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!inputArg) {
|
||||
|
||||
// Resolve input path using path utilities
|
||||
let inputPath;
|
||||
if (inputArg) {
|
||||
try {
|
||||
inputPath = resolvePrdPath({ input: inputArg, projectRoot }, session);
|
||||
} catch (error) {
|
||||
logWrapper.error(`Error resolving PRD path: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'FILE_NOT_FOUND', message: error.message }
|
||||
};
|
||||
}
|
||||
} else {
|
||||
logWrapper.error('parsePRDDirect called without input path');
|
||||
return {
|
||||
success: false,
|
||||
@@ -57,11 +72,13 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
// Resolve input and output paths relative to projectRoot
|
||||
const inputPath = path.resolve(projectRoot, inputArg);
|
||||
// Resolve output path - use new path utilities for default
|
||||
const outputPath = outputArg
|
||||
? path.resolve(projectRoot, outputArg)
|
||||
: path.resolve(projectRoot, 'tasks', 'tasks.json'); // Default output path
|
||||
? path.isAbsolute(outputArg)
|
||||
? outputArg
|
||||
: path.resolve(projectRoot, outputArg)
|
||||
: resolveProjectPath(TASKMASTER_TASKS_FILE, args) ||
|
||||
path.resolve(projectRoot, TASKMASTER_TASKS_FILE);
|
||||
|
||||
// Check if input file exists
|
||||
if (!fs.existsSync(inputPath)) {
|
||||
@@ -79,17 +96,12 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
logWrapper.info(`Creating output directory: ${outputDir}`);
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
} catch (dirError) {
|
||||
logWrapper.error(
|
||||
`Failed to create output directory ${outputDir}: ${dirError.message}`
|
||||
);
|
||||
// Return an error response immediately if dir creation fails
|
||||
} catch (error) {
|
||||
const errorMsg = `Failed to create output directory ${outputDir}: ${error.message}`;
|
||||
logWrapper.error(errorMsg);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'DIRECTORY_CREATION_ERROR',
|
||||
message: `Failed to create output directory: ${dirError.message}`
|
||||
}
|
||||
error: { code: 'DIRECTORY_CREATE_FAILED', message: errorMsg }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -97,7 +109,7 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
if (numTasksArg) {
|
||||
numTasks =
|
||||
typeof numTasksArg === 'string' ? parseInt(numTasksArg, 10) : numTasksArg;
|
||||
if (isNaN(numTasks) || numTasks <= 0) {
|
||||
if (Number.isNaN(numTasks) || numTasks <= 0) {
|
||||
// Ensure positive number
|
||||
numTasks = getDefaultNumTasks(projectRoot); // Fallback to default if parsing fails or invalid
|
||||
logWrapper.warn(
|
||||
@@ -158,7 +170,8 @@ export async function parsePRDDirect(args, log, context = {}) {
|
||||
data: {
|
||||
message: successMsg,
|
||||
outputPath: result.tasksPath,
|
||||
telemetryData: result.telemetryData
|
||||
telemetryData: result.telemetryData,
|
||||
tagInfo: result.tagInfo
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -21,11 +21,12 @@ import {
|
||||
* @param {string} args.tasksJsonPath - Explicit path to the tasks.json file.
|
||||
* @param {string} args.id - The ID(s) of the task(s) or subtask(s) to remove (comma-separated for multiple).
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {Promise<Object>} - Remove task result { success: boolean, data?: any, error?: { code: string, message: string }, fromCache: false }
|
||||
* @returns {Promise<Object>} - Remove task result { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function removeTaskDirect(args, log) {
|
||||
export async function removeTaskDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, id } = args;
|
||||
const { tasksJsonPath, id, projectRoot } = args;
|
||||
const { session } = context;
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
@@ -35,8 +36,7 @@ export async function removeTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,8 +48,7 @@ export async function removeTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'INPUT_VALIDATION_ERROR',
|
||||
message: 'Task ID is required'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,15 +60,14 @@ export async function removeTaskDirect(args, log) {
|
||||
);
|
||||
|
||||
// Validate all task IDs exist before proceeding
|
||||
const data = readJSON(tasksJsonPath);
|
||||
const data = readJSON(tasksJsonPath, projectRoot);
|
||||
if (!data || !data.tasks) {
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'INVALID_TASKS_FILE',
|
||||
message: `No valid tasks found in ${tasksJsonPath}`
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,8 +81,7 @@ export async function removeTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'INVALID_TASK_ID',
|
||||
message: `The following tasks were not found: ${invalidTasks.join(', ')}`
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,8 +130,7 @@ export async function removeTaskDirect(args, log) {
|
||||
details: failedRemovals
|
||||
.map((r) => `${r.taskId}: ${r.error}`)
|
||||
.join('; ')
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -147,8 +143,7 @@ export async function removeTaskDirect(args, log) {
|
||||
failed: failedRemovals.length,
|
||||
results: results,
|
||||
tasksPath: tasksJsonPath
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Ensure silent mode is disabled even if an outer error occurs
|
||||
@@ -161,8 +156,7 @@ export async function removeTaskDirect(args, log) {
|
||||
error: {
|
||||
code: 'UNEXPECTED_ERROR',
|
||||
message: error.message
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
118
mcp-server/src/core/direct-functions/rename-tag.js
Normal file
118
mcp-server/src/core/direct-functions/rename-tag.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* rename-tag.js
|
||||
* Direct function implementation for renaming a tag
|
||||
*/
|
||||
|
||||
import { renameTag } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for renaming a tag with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.oldName - Current name of the tag to rename
|
||||
* @param {string} args.newName - New name for the tag
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function renameTagDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, oldName, newName, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('renameTagDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check required parameters
|
||||
if (!oldName || typeof oldName !== 'string') {
|
||||
log.error('Missing required parameter: oldName');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Old tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!newName || typeof newName !== 'string') {
|
||||
log.error('Missing required parameter: newName');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'New tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(`Renaming tag from "${oldName}" to "${newName}"`);
|
||||
|
||||
// Call the renameTag function
|
||||
const result = await renameTag(
|
||||
tasksJsonPath,
|
||||
oldName,
|
||||
newName,
|
||||
{}, // options (empty for now)
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
oldName: result.oldName,
|
||||
newName: result.newName,
|
||||
renamed: result.renamed,
|
||||
taskCount: result.taskCount,
|
||||
wasCurrentTag: result.wasCurrentTag,
|
||||
message: `Successfully renamed tag from "${result.oldName}" to "${result.newName}"`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in renameTagDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'RENAME_TAG_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
* Direct function implementation for AI-powered research queries
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import { performResearch } from '../../../../scripts/modules/task-manager.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
@@ -20,6 +21,8 @@ import { createLogWrapper } from '../../tools/utils.js';
|
||||
* @param {string} [args.customContext] - Additional custom context text
|
||||
* @param {boolean} [args.includeProjectTree=false] - Include project file tree in context
|
||||
* @param {string} [args.detailLevel='medium'] - Detail level: 'low', 'medium', 'high'
|
||||
* @param {string} [args.saveTo] - Automatically save to task/subtask ID (e.g., "15" or "15.2")
|
||||
* @param {boolean} [args.saveToFile=false] - Save research results to .taskmaster/docs/research/ directory
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
@@ -34,6 +37,8 @@ export async function researchDirect(args, log, context = {}) {
|
||||
customContext,
|
||||
includeProjectTree = false,
|
||||
detailLevel = 'medium',
|
||||
saveTo,
|
||||
saveToFile = false,
|
||||
projectRoot
|
||||
} = args;
|
||||
const { session } = context; // Destructure session from context
|
||||
@@ -105,7 +110,8 @@ export async function researchDirect(args, log, context = {}) {
|
||||
customContext: customContext || '',
|
||||
includeProjectTree,
|
||||
detailLevel,
|
||||
projectRoot
|
||||
projectRoot,
|
||||
saveToFile
|
||||
};
|
||||
|
||||
// Prepare context for the research function
|
||||
@@ -125,6 +131,88 @@ export async function researchDirect(args, log, context = {}) {
|
||||
false // allowFollowUp - disable for MCP calls
|
||||
);
|
||||
|
||||
// Auto-save to task/subtask if requested
|
||||
if (saveTo) {
|
||||
try {
|
||||
const isSubtask = saveTo.includes('.');
|
||||
|
||||
// Format research content for saving
|
||||
const researchContent = `## Research Query: ${query.trim()}
|
||||
|
||||
**Detail Level:** ${result.detailLevel}
|
||||
**Context Size:** ${result.contextSize} characters
|
||||
**Timestamp:** ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}
|
||||
|
||||
### Results
|
||||
|
||||
${result.result}`;
|
||||
|
||||
if (isSubtask) {
|
||||
// Save to subtask
|
||||
const { updateSubtaskById } = await import(
|
||||
'../../../../scripts/modules/task-manager/update-subtask-by-id.js'
|
||||
);
|
||||
|
||||
const tasksPath = path.join(
|
||||
projectRoot,
|
||||
'.taskmaster',
|
||||
'tasks',
|
||||
'tasks.json'
|
||||
);
|
||||
await updateSubtaskById(
|
||||
tasksPath,
|
||||
saveTo,
|
||||
researchContent,
|
||||
false, // useResearch = false for simple append
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
commandName: 'research-save',
|
||||
outputType: 'mcp',
|
||||
projectRoot
|
||||
},
|
||||
'json'
|
||||
);
|
||||
|
||||
log.info(`Research saved to subtask ${saveTo}`);
|
||||
} else {
|
||||
// Save to task
|
||||
const updateTaskById = (
|
||||
await import(
|
||||
'../../../../scripts/modules/task-manager/update-task-by-id.js'
|
||||
)
|
||||
).default;
|
||||
|
||||
const taskIdNum = parseInt(saveTo, 10);
|
||||
const tasksPath = path.join(
|
||||
projectRoot,
|
||||
'.taskmaster',
|
||||
'tasks',
|
||||
'tasks.json'
|
||||
);
|
||||
await updateTaskById(
|
||||
tasksPath,
|
||||
taskIdNum,
|
||||
researchContent,
|
||||
false, // useResearch = false for simple append
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
commandName: 'research-save',
|
||||
outputType: 'mcp',
|
||||
projectRoot
|
||||
},
|
||||
'json',
|
||||
true // appendMode = true
|
||||
);
|
||||
|
||||
log.info(`Research saved to task ${saveTo}`);
|
||||
}
|
||||
} catch (saveError) {
|
||||
log.warn(`Error saving research to task/subtask: ${saveError.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
@@ -140,7 +228,9 @@ export async function researchDirect(args, log, context = {}) {
|
||||
userPromptTokens: result.userPromptTokens,
|
||||
totalInputTokens: result.totalInputTokens,
|
||||
detailLevel: result.detailLevel,
|
||||
telemetryData: result.telemetryData
|
||||
telemetryData: result.telemetryData,
|
||||
tagInfo: result.tagInfo,
|
||||
savedFilePath: result.savedFilePath
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -13,13 +13,15 @@ import { nextTaskDirect } from './next-task.js';
|
||||
/**
|
||||
* Direct function wrapper for setTaskStatus with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments containing id, status and tasksJsonPath.
|
||||
* @param {Object} args - Command arguments containing id, status, tasksJsonPath, and projectRoot.
|
||||
* @param {Object} log - Logger object.
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object with success status and data/error information.
|
||||
*/
|
||||
export async function setTaskStatusDirect(args, log) {
|
||||
// Destructure expected args, including the resolved tasksJsonPath
|
||||
const { tasksJsonPath, id, status, complexityReportPath } = args;
|
||||
export async function setTaskStatusDirect(args, log, context = {}) {
|
||||
// Destructure expected args, including the resolved tasksJsonPath and projectRoot
|
||||
const { tasksJsonPath, id, status, complexityReportPath, projectRoot } = args;
|
||||
const { session } = context;
|
||||
try {
|
||||
log.info(`Setting task status with args: ${JSON.stringify(args)}`);
|
||||
|
||||
@@ -29,8 +31,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,8 +42,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_TASK_ID', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_TASK_ID', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,8 +52,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_STATUS', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_STATUS', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,7 +69,11 @@ export async function setTaskStatusDirect(args, log) {
|
||||
enableSilentMode(); // Enable silent mode before calling core function
|
||||
try {
|
||||
// Call the core function
|
||||
await setTaskStatus(tasksPath, taskId, newStatus, { mcpLog: log });
|
||||
await setTaskStatus(tasksPath, taskId, newStatus, {
|
||||
mcpLog: log,
|
||||
projectRoot,
|
||||
session
|
||||
});
|
||||
|
||||
log.info(`Successfully set task ${taskId} status to ${newStatus}`);
|
||||
|
||||
@@ -82,8 +85,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
taskId,
|
||||
status: newStatus,
|
||||
tasksPath: tasksPath // Return the path used
|
||||
},
|
||||
fromCache: false // This operation always modifies state and should never be cached
|
||||
}
|
||||
};
|
||||
|
||||
// If the task was completed, attempt to fetch the next task
|
||||
@@ -93,9 +95,11 @@ export async function setTaskStatusDirect(args, log) {
|
||||
const nextResult = await nextTaskDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
reportPath: complexityReportPath
|
||||
reportPath: complexityReportPath,
|
||||
projectRoot: projectRoot
|
||||
},
|
||||
log
|
||||
log,
|
||||
{ session }
|
||||
);
|
||||
|
||||
if (nextResult.success) {
|
||||
@@ -126,8 +130,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
error: {
|
||||
code: 'SET_STATUS_ERROR',
|
||||
message: error.message || 'Unknown error setting task status'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
// ALWAYS restore normal logging in finally block
|
||||
@@ -145,8 +148,7 @@ export async function setTaskStatusDirect(args, log) {
|
||||
error: {
|
||||
code: 'SET_STATUS_ERROR',
|
||||
message: error.message || 'Unknown error setting task status'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import {
|
||||
readComplexityReport,
|
||||
readJSON
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { findTasksJsonPath } from '../utils/path-utils.js';
|
||||
import { findTasksPath } from '../utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for getting task details.
|
||||
*
|
||||
* @param {Object} args - Command arguments.
|
||||
* @param {string} args.id - Task ID to show.
|
||||
* @param {string} [args.file] - Optional path to the tasks file (passed to findTasksJsonPath).
|
||||
* @param {string} [args.file] - Optional path to the tasks file (passed to findTasksPath).
|
||||
* @param {string} args.reportPath - Explicit path to the complexity report file.
|
||||
* @param {string} [args.status] - Optional status to filter subtasks by.
|
||||
* @param {string} args.projectRoot - Absolute path to the project root directory (already normalized by tool).
|
||||
@@ -24,8 +24,7 @@ import { findTasksJsonPath } from '../utils/path-utils.js';
|
||||
* @returns {Promise<Object>} - Result object with success status and data/error information.
|
||||
*/
|
||||
export async function showTaskDirect(args, log) {
|
||||
// Destructure session from context if needed later, otherwise ignore
|
||||
// const { session } = context;
|
||||
// This function doesn't need session context since it only reads data
|
||||
// Destructure projectRoot and other args. projectRoot is assumed normalized.
|
||||
const { id, file, reportPath, status, projectRoot } = args;
|
||||
|
||||
@@ -37,7 +36,7 @@ export async function showTaskDirect(args, log) {
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
// Use the projectRoot passed directly from args
|
||||
tasksJsonPath = findTasksJsonPath(
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: projectRoot, file: file },
|
||||
log
|
||||
);
|
||||
@@ -56,7 +55,7 @@ export async function showTaskDirect(args, log) {
|
||||
|
||||
// --- Rest of the function remains the same, using tasksJsonPath ---
|
||||
try {
|
||||
const tasksData = readJSON(tasksJsonPath);
|
||||
const tasksData = readJSON(tasksJsonPath, projectRoot);
|
||||
if (!tasksData || !tasksData.tasks) {
|
||||
return {
|
||||
success: false,
|
||||
|
||||
@@ -42,8 +42,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage }
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID_TYPE', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'INVALID_SUBTASK_ID_TYPE', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID_TYPE', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
log.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_SUBTASK_ID_FORMAT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'INVALID_SUBTASK_ID_FORMAT', message: errorMessage }
|
||||
error: { code: 'INVALID_SUBTASK_ID_FORMAT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(message);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message },
|
||||
fromCache: false
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message }
|
||||
error: { code: 'SUBTASK_NOT_FOUND', message: message }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -145,9 +145,9 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
subtask: coreResult.updatedSubtask,
|
||||
tasksPath,
|
||||
useResearch,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
telemetryData: coreResult.telemetryData,
|
||||
tagInfo: coreResult.tagInfo
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
logWrapper.error(`Error updating subtask by ID: ${error.message}`);
|
||||
@@ -156,8 +156,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'UPDATE_SUBTASK_CORE_ERROR',
|
||||
message: error.message || 'Unknown error updating subtask'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
if (!wasSilent && isSilentMode()) {
|
||||
@@ -174,8 +174,8 @@ export async function updateSubtaskByIdDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'DIRECT_FUNCTION_SETUP_ERROR',
|
||||
message: error.message || 'Unknown setup error'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { createLogWrapper } from '../../tools/utils.js';
|
||||
* @param {string} args.id - Task ID (or subtask ID like "1.2").
|
||||
* @param {string} args.prompt - New information/context prompt.
|
||||
* @param {boolean} [args.research] - Whether to use research role.
|
||||
* @param {boolean} [args.append] - Whether to append timestamped information instead of full update.
|
||||
* @param {string} [args.projectRoot] - Project root path.
|
||||
* @param {Object} log - Logger object.
|
||||
* @param {Object} context - Context object containing session data.
|
||||
@@ -27,7 +28,7 @@ import { createLogWrapper } from '../../tools/utils.js';
|
||||
export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
const { session } = context;
|
||||
// Destructure expected args, including projectRoot
|
||||
const { tasksJsonPath, id, prompt, research, projectRoot } = args;
|
||||
const { tasksJsonPath, id, prompt, research, append, projectRoot } = args;
|
||||
|
||||
const logWrapper = createLogWrapper(log);
|
||||
|
||||
@@ -42,8 +43,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,8 +54,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_TASK_ID', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_TASK_ID', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,8 +64,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'MISSING_PROMPT', message: errorMessage }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,13 +77,12 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
} else {
|
||||
// Parse as integer for main task IDs
|
||||
taskId = parseInt(id, 10);
|
||||
if (isNaN(taskId)) {
|
||||
if (Number.isNaN(taskId)) {
|
||||
const errorMessage = `Invalid task ID: ${id}. Task ID must be a positive integer or subtask ID (e.g., "5.2").`;
|
||||
logWrapper.error(errorMessage);
|
||||
return {
|
||||
success: false,
|
||||
error: { code: 'INVALID_TASK_ID', message: errorMessage },
|
||||
fromCache: false
|
||||
error: { code: 'INVALID_TASK_ID', message: errorMessage }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -122,7 +119,8 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
commandName: 'update-task',
|
||||
outputType: 'mcp'
|
||||
},
|
||||
'json'
|
||||
'json',
|
||||
append || false
|
||||
);
|
||||
|
||||
// Check if the core function returned null or an object without success
|
||||
@@ -136,9 +134,9 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
message: message,
|
||||
taskId: taskId,
|
||||
updated: false,
|
||||
telemetryData: coreResult?.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
telemetryData: coreResult?.telemetryData,
|
||||
tagInfo: coreResult?.tagInfo
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -154,9 +152,9 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
useResearch: useResearch,
|
||||
updated: true,
|
||||
updatedTask: coreResult.updatedTask,
|
||||
telemetryData: coreResult.telemetryData
|
||||
},
|
||||
fromCache: false
|
||||
telemetryData: coreResult.telemetryData,
|
||||
tagInfo: coreResult.tagInfo
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
logWrapper.error(`Error updating task by ID: ${error.message}`);
|
||||
@@ -165,8 +163,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'UPDATE_TASK_CORE_ERROR',
|
||||
message: error.message || 'Unknown error updating task'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
if (!wasSilent && isSilentMode()) {
|
||||
@@ -181,8 +178,7 @@ export async function updateTaskByIdDirect(args, log, context = {}) {
|
||||
error: {
|
||||
code: 'DIRECT_FUNCTION_SETUP_ERROR',
|
||||
message: error.message || 'Unknown setup error'
|
||||
},
|
||||
fromCache: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
*/
|
||||
export async function updateTasksDirect(args, log, context = {}) {
|
||||
const { session } = context;
|
||||
const { from, prompt, research, file: fileArg, projectRoot } = args;
|
||||
const { from, prompt, research, tasksJsonPath, projectRoot } = args;
|
||||
|
||||
// Create the standard logger wrapper
|
||||
const logWrapper = createLogWrapper(log);
|
||||
@@ -60,20 +60,15 @@ export async function updateTasksDirect(args, log, context = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
// Resolve tasks file path
|
||||
const tasksFile = fileArg
|
||||
? path.resolve(projectRoot, fileArg)
|
||||
: path.resolve(projectRoot, 'tasks', 'tasks.json');
|
||||
|
||||
logWrapper.info(
|
||||
`Updating tasks via direct function. From: ${from}, Research: ${research}, File: ${tasksFile}, ProjectRoot: ${projectRoot}`
|
||||
`Updating tasks via direct function. From: ${from}, Research: ${research}, File: ${tasksJsonPath}, ProjectRoot: ${projectRoot}`
|
||||
);
|
||||
|
||||
enableSilentMode(); // Enable silent mode
|
||||
try {
|
||||
// Call the core updateTasks function
|
||||
const result = await updateTasks(
|
||||
tasksFile,
|
||||
tasksJsonPath,
|
||||
from,
|
||||
prompt,
|
||||
research,
|
||||
@@ -93,9 +88,10 @@ export async function updateTasksDirect(args, log, context = {}) {
|
||||
success: true,
|
||||
data: {
|
||||
message: `Successfully updated ${result.updatedTasks.length} tasks.`,
|
||||
tasksFile,
|
||||
tasksPath: tasksJsonPath,
|
||||
updatedCount: result.updatedTasks.length,
|
||||
telemetryData: result.telemetryData
|
||||
telemetryData: result.telemetryData,
|
||||
tagInfo: result.tagInfo
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
103
mcp-server/src/core/direct-functions/use-tag.js
Normal file
103
mcp-server/src/core/direct-functions/use-tag.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* use-tag.js
|
||||
* Direct function implementation for switching to a tag
|
||||
*/
|
||||
|
||||
import { useTag } from '../../../../scripts/modules/task-manager/tag-management.js';
|
||||
import {
|
||||
enableSilentMode,
|
||||
disableSilentMode
|
||||
} from '../../../../scripts/modules/utils.js';
|
||||
import { createLogWrapper } from '../../tools/utils.js';
|
||||
|
||||
/**
|
||||
* Direct function wrapper for switching to a tag with error handling.
|
||||
*
|
||||
* @param {Object} args - Command arguments
|
||||
* @param {string} args.name - Name of the tag to switch to
|
||||
* @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
|
||||
* @param {string} [args.projectRoot] - Project root path
|
||||
* @param {Object} log - Logger object
|
||||
* @param {Object} context - Additional context (session)
|
||||
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
|
||||
*/
|
||||
export async function useTagDirect(args, log, context = {}) {
|
||||
// Destructure expected args
|
||||
const { tasksJsonPath, name, projectRoot } = args;
|
||||
const { session } = context;
|
||||
|
||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||
enableSilentMode();
|
||||
|
||||
// Create logger wrapper using the utility
|
||||
const mcpLog = createLogWrapper(log);
|
||||
|
||||
try {
|
||||
// Check if tasksJsonPath was provided
|
||||
if (!tasksJsonPath) {
|
||||
log.error('useTagDirect called without tasksJsonPath');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_ARGUMENT',
|
||||
message: 'tasksJsonPath is required'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Check required parameters
|
||||
if (!name || typeof name !== 'string') {
|
||||
log.error('Missing required parameter: name');
|
||||
disableSilentMode();
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_PARAMETER',
|
||||
message: 'Tag name is required and must be a string'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
log.info(`Switching to tag: ${name}`);
|
||||
|
||||
// Call the useTag function
|
||||
const result = await useTag(
|
||||
tasksJsonPath,
|
||||
name,
|
||||
{}, // options (empty for now)
|
||||
{
|
||||
session,
|
||||
mcpLog,
|
||||
projectRoot
|
||||
},
|
||||
'json' // outputFormat - use 'json' to suppress CLI UI
|
||||
);
|
||||
|
||||
// Restore normal logging
|
||||
disableSilentMode();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
tagName: result.currentTag,
|
||||
switched: result.switched,
|
||||
previousTag: result.previousTag,
|
||||
taskCount: result.taskCount,
|
||||
message: `Successfully switched to tag "${result.currentTag}"`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
// Make sure to restore normal logging even if there's an error
|
||||
disableSilentMode();
|
||||
|
||||
log.error(`Error in useTagDirect: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: error.code || 'USE_TAG_ERROR',
|
||||
message: error.message
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,15 @@ import { initializeProjectDirect } from './direct-functions/initialize-project.j
|
||||
import { modelsDirect } from './direct-functions/models.js';
|
||||
import { moveTaskDirect } from './direct-functions/move-task.js';
|
||||
import { researchDirect } from './direct-functions/research.js';
|
||||
import { addTagDirect } from './direct-functions/add-tag.js';
|
||||
import { deleteTagDirect } from './direct-functions/delete-tag.js';
|
||||
import { listTagsDirect } from './direct-functions/list-tags.js';
|
||||
import { useTagDirect } from './direct-functions/use-tag.js';
|
||||
import { renameTagDirect } from './direct-functions/rename-tag.js';
|
||||
import { copyTagDirect } from './direct-functions/copy-tag.js';
|
||||
|
||||
// Re-export utility functions
|
||||
export { findTasksJsonPath } from './utils/path-utils.js';
|
||||
export { findTasksPath } from './utils/path-utils.js';
|
||||
|
||||
// Use Map for potential future enhancements like introspection or dynamic dispatch
|
||||
export const directFunctions = new Map([
|
||||
@@ -64,7 +70,13 @@ export const directFunctions = new Map([
|
||||
['initializeProjectDirect', initializeProjectDirect],
|
||||
['modelsDirect', modelsDirect],
|
||||
['moveTaskDirect', moveTaskDirect],
|
||||
['researchDirect', researchDirect]
|
||||
['researchDirect', researchDirect],
|
||||
['addTagDirect', addTagDirect],
|
||||
['deleteTagDirect', deleteTagDirect],
|
||||
['listTagsDirect', listTagsDirect],
|
||||
['useTagDirect', useTagDirect],
|
||||
['renameTagDirect', renameTagDirect],
|
||||
['copyTagDirect', copyTagDirect]
|
||||
]);
|
||||
|
||||
// Re-export all direct function implementations
|
||||
@@ -95,5 +107,11 @@ export {
|
||||
initializeProjectDirect,
|
||||
modelsDirect,
|
||||
moveTaskDirect,
|
||||
researchDirect
|
||||
researchDirect,
|
||||
addTagDirect,
|
||||
deleteTagDirect,
|
||||
listTagsDirect,
|
||||
useTagDirect,
|
||||
renameTagDirect,
|
||||
copyTagDirect
|
||||
};
|
||||
|
||||
@@ -1,436 +1,220 @@
|
||||
/**
|
||||
* path-utils.js
|
||||
* Utility functions for file path operations in Task Master
|
||||
*
|
||||
* This module provides robust path resolution for both:
|
||||
* 1. PACKAGE PATH: Where task-master code is installed
|
||||
* (global node_modules OR local ./node_modules/task-master OR direct from repo)
|
||||
* 2. PROJECT PATH: Where user's tasks.json resides (typically user's project root)
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import os from 'os';
|
||||
|
||||
// Store last found project root to improve performance on subsequent calls (primarily for CLI)
|
||||
export let lastFoundProjectRoot = null;
|
||||
|
||||
// Project marker files that indicate a potential project root
|
||||
export const PROJECT_MARKERS = [
|
||||
// Task Master specific
|
||||
'tasks.json',
|
||||
'tasks/tasks.json',
|
||||
|
||||
// Common version control
|
||||
'.git',
|
||||
'.svn',
|
||||
|
||||
// Common package files
|
||||
'package.json',
|
||||
'pyproject.toml',
|
||||
'Gemfile',
|
||||
'go.mod',
|
||||
'Cargo.toml',
|
||||
|
||||
// Common IDE/editor folders
|
||||
'.cursor',
|
||||
'.vscode',
|
||||
'.idea',
|
||||
|
||||
// Common dependency directories (check if directory)
|
||||
'node_modules',
|
||||
'venv',
|
||||
'.venv',
|
||||
|
||||
// Common config files
|
||||
'.env',
|
||||
'.eslintrc',
|
||||
'tsconfig.json',
|
||||
'babel.config.js',
|
||||
'jest.config.js',
|
||||
'webpack.config.js',
|
||||
|
||||
// Common CI/CD files
|
||||
'.github/workflows',
|
||||
'.gitlab-ci.yml',
|
||||
'.circleci/config.yml'
|
||||
];
|
||||
import {
|
||||
findTasksPath as coreFindTasksPath,
|
||||
findPRDPath as coreFindPrdPath,
|
||||
findComplexityReportPath as coreFindComplexityReportPath,
|
||||
findProjectRoot as coreFindProjectRoot,
|
||||
normalizeProjectRoot
|
||||
} from '../../../../src/utils/path-utils.js';
|
||||
import { PROJECT_MARKERS } from '../../../../src/constants/paths.js';
|
||||
|
||||
/**
|
||||
* Gets the path to the task-master package installation directory
|
||||
* NOTE: This might become unnecessary if CLI fallback in MCP utils is removed.
|
||||
* @returns {string} - Absolute path to the package installation directory
|
||||
* MCP-specific path utilities that extend core path utilities with session support
|
||||
* This module handles session-specific path resolution for the MCP server
|
||||
*/
|
||||
export function getPackagePath() {
|
||||
// When running from source, __dirname is the directory containing this file
|
||||
// When running from npm, we need to find the package root
|
||||
const thisFilePath = fileURLToPath(import.meta.url);
|
||||
const thisFileDir = path.dirname(thisFilePath);
|
||||
|
||||
// Navigate from core/utils up to the package root
|
||||
// In dev: /path/to/task-master/mcp-server/src/core/utils -> /path/to/task-master
|
||||
// In npm: /path/to/node_modules/task-master/mcp-server/src/core/utils -> /path/to/node_modules/task-master
|
||||
return path.resolve(thisFileDir, '../../../../');
|
||||
/**
|
||||
* Silent logger for MCP context to prevent console output
|
||||
*/
|
||||
const silentLogger = {
|
||||
info: () => {},
|
||||
warn: () => {},
|
||||
error: () => {},
|
||||
debug: () => {},
|
||||
success: () => {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cache for last found project root to improve performance
|
||||
*/
|
||||
export const lastFoundProjectRoot = null;
|
||||
|
||||
/**
|
||||
* Find PRD file with MCP support
|
||||
* @param {string} [explicitPath] - Explicit path to PRD file (highest priority)
|
||||
* @param {Object} [args] - Arguments object for context
|
||||
* @param {Object} [log] - Logger object to prevent console logging
|
||||
* @returns {string|null} - Resolved path to PRD file or null if not found
|
||||
*/
|
||||
export function findPrdPath(explicitPath, args = null, log = silentLogger) {
|
||||
return coreFindPrdPath(explicitPath, args, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the absolute path to the tasks.json file based on project root and arguments.
|
||||
* @param {Object} args - Command arguments, potentially including 'projectRoot' and 'file'.
|
||||
* @param {Object} log - Logger object.
|
||||
* @returns {string} - Absolute path to the tasks.json file.
|
||||
* @throws {Error} - If tasks.json cannot be found.
|
||||
* Resolve tasks.json path from arguments
|
||||
* Prioritizes explicit path parameter, then uses fallback logic
|
||||
* @param {Object} args - Arguments object containing projectRoot and optional file path
|
||||
* @param {Object} [log] - Logger object to prevent console logging
|
||||
* @returns {string|null} - Resolved path to tasks.json or null if not found
|
||||
*/
|
||||
export function findTasksJsonPath(args, log) {
|
||||
// PRECEDENCE ORDER for finding tasks.json:
|
||||
// 1. Explicitly provided `projectRoot` in args (Highest priority, expected in MCP context)
|
||||
// 2. Previously found/cached `lastFoundProjectRoot` (primarily for CLI performance)
|
||||
// 3. Search upwards from current working directory (`process.cwd()`) - CLI usage
|
||||
export function resolveTasksPath(args, log = silentLogger) {
|
||||
// Get explicit path from args.file if provided
|
||||
const explicitPath = args?.file;
|
||||
const rawProjectRoot = args?.projectRoot;
|
||||
|
||||
// 1. If project root is explicitly provided (e.g., from MCP session), use it directly
|
||||
if (args.projectRoot) {
|
||||
const projectRoot = args.projectRoot;
|
||||
log.info(`Using explicitly provided project root: ${projectRoot}`);
|
||||
try {
|
||||
// This will throw if tasks.json isn't found within this root
|
||||
return findTasksJsonInDirectory(projectRoot, args.file, log);
|
||||
} catch (error) {
|
||||
// Include debug info in error
|
||||
const debugInfo = {
|
||||
projectRoot,
|
||||
currentDir: process.cwd(),
|
||||
serverDir: path.dirname(process.argv[1]),
|
||||
possibleProjectRoot: path.resolve(
|
||||
path.dirname(process.argv[1]),
|
||||
'../..'
|
||||
),
|
||||
lastFoundProjectRoot,
|
||||
searchedPaths: error.message
|
||||
};
|
||||
|
||||
error.message = `Tasks file not found in any of the expected locations relative to project root "${projectRoot}" (from session).\nDebug Info: ${JSON.stringify(debugInfo, null, 2)}`;
|
||||
throw error;
|
||||
}
|
||||
// If explicit path is provided and absolute, use it directly
|
||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||
return explicitPath;
|
||||
}
|
||||
|
||||
// --- Fallback logic primarily for CLI or when projectRoot isn't passed ---
|
||||
// Normalize project root if provided
|
||||
const projectRoot = rawProjectRoot
|
||||
? normalizeProjectRoot(rawProjectRoot)
|
||||
: null;
|
||||
|
||||
// 2. If we have a last known project root that worked, try it first
|
||||
if (lastFoundProjectRoot) {
|
||||
log.info(`Trying last known project root: ${lastFoundProjectRoot}`);
|
||||
try {
|
||||
// Use the cached root
|
||||
const tasksPath = findTasksJsonInDirectory(
|
||||
lastFoundProjectRoot,
|
||||
args.file,
|
||||
log
|
||||
);
|
||||
return tasksPath; // Return if found in cached root
|
||||
} catch (error) {
|
||||
log.info(
|
||||
`Task file not found in last known project root, continuing search.`
|
||||
);
|
||||
// Continue with search if not found in cache
|
||||
}
|
||||
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||
if (explicitPath && projectRoot) {
|
||||
return path.resolve(projectRoot, explicitPath);
|
||||
}
|
||||
|
||||
// 3. Start search from current directory (most common CLI scenario)
|
||||
const startDir = process.cwd();
|
||||
log.info(
|
||||
`Searching for tasks.json starting from current directory: ${startDir}`
|
||||
);
|
||||
|
||||
// Try to find tasks.json by walking up the directory tree from cwd
|
||||
try {
|
||||
// This will throw if not found in the CWD tree
|
||||
return findTasksJsonWithParentSearch(startDir, args.file, log);
|
||||
} catch (error) {
|
||||
// If all attempts fail, augment and throw the original error from CWD search
|
||||
error.message = `${error.message}\n\nPossible solutions:\n1. Run the command from your project directory containing tasks.json\n2. Use --project-root=/path/to/project to specify the project location (if using CLI)\n3. Ensure the project root is correctly passed from the client (if using MCP)\n\nCurrent working directory: ${startDir}\nLast known project root: ${lastFoundProjectRoot}\nProject root from args: ${args.projectRoot}`;
|
||||
throw error;
|
||||
// Use core findTasksPath with explicit path and normalized projectRoot context
|
||||
if (projectRoot) {
|
||||
return coreFindTasksPath(explicitPath, { projectRoot }, log);
|
||||
}
|
||||
|
||||
// Fallback to core function without projectRoot context
|
||||
return coreFindTasksPath(explicitPath, null, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a directory contains any project marker files or directories
|
||||
* @param {string} dirPath - Directory to check
|
||||
* @returns {boolean} - True if the directory contains any project markers
|
||||
* Resolve PRD path from arguments
|
||||
* @param {Object} args - Arguments object containing projectRoot and optional input path
|
||||
* @param {Object} [log] - Logger object to prevent console logging
|
||||
* @returns {string|null} - Resolved path to PRD file or null if not found
|
||||
*/
|
||||
function hasProjectMarkers(dirPath) {
|
||||
return PROJECT_MARKERS.some((marker) => {
|
||||
const markerPath = path.join(dirPath, marker);
|
||||
// Check if the marker exists as either a file or directory
|
||||
return fs.existsSync(markerPath);
|
||||
});
|
||||
export function resolvePrdPath(args, log = silentLogger) {
|
||||
// Get explicit path from args.input if provided
|
||||
const explicitPath = args?.input;
|
||||
const rawProjectRoot = args?.projectRoot;
|
||||
|
||||
// If explicit path is provided and absolute, use it directly
|
||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||
return explicitPath;
|
||||
}
|
||||
|
||||
// Normalize project root if provided
|
||||
const projectRoot = rawProjectRoot
|
||||
? normalizeProjectRoot(rawProjectRoot)
|
||||
: null;
|
||||
|
||||
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||
if (explicitPath && projectRoot) {
|
||||
return path.resolve(projectRoot, explicitPath);
|
||||
}
|
||||
|
||||
// Use core findPRDPath with explicit path and normalized projectRoot context
|
||||
if (projectRoot) {
|
||||
return coreFindPrdPath(explicitPath, { projectRoot }, log);
|
||||
}
|
||||
|
||||
// Fallback to core function without projectRoot context
|
||||
return coreFindPrdPath(explicitPath, null, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for tasks.json in a specific directory
|
||||
* @param {string} dirPath - Directory to search in
|
||||
* @param {string} explicitFilePath - Optional explicit file path relative to dirPath
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {string} - Absolute path to tasks.json
|
||||
* @throws {Error} - If tasks.json cannot be found
|
||||
* Resolve complexity report path from arguments
|
||||
* @param {Object} args - Arguments object containing projectRoot and optional complexityReport path
|
||||
* @param {Object} [log] - Logger object to prevent console logging
|
||||
* @returns {string|null} - Resolved path to complexity report or null if not found
|
||||
*/
|
||||
function findTasksJsonInDirectory(dirPath, explicitFilePath, log) {
|
||||
const possiblePaths = [];
|
||||
export function resolveComplexityReportPath(args, log = silentLogger) {
|
||||
// Get explicit path from args.complexityReport if provided
|
||||
const explicitPath = args?.complexityReport;
|
||||
const rawProjectRoot = args?.projectRoot;
|
||||
|
||||
// 1. If a file is explicitly provided relative to dirPath
|
||||
if (explicitFilePath) {
|
||||
possiblePaths.push(path.resolve(dirPath, explicitFilePath));
|
||||
// If explicit path is provided and absolute, use it directly
|
||||
if (explicitPath && path.isAbsolute(explicitPath)) {
|
||||
return explicitPath;
|
||||
}
|
||||
|
||||
// 2. Check the standard locations relative to dirPath
|
||||
possiblePaths.push(
|
||||
path.join(dirPath, 'tasks.json'),
|
||||
path.join(dirPath, 'tasks', 'tasks.json')
|
||||
);
|
||||
// Normalize project root if provided
|
||||
const projectRoot = rawProjectRoot
|
||||
? normalizeProjectRoot(rawProjectRoot)
|
||||
: null;
|
||||
|
||||
log.info(`Checking potential task file paths: ${possiblePaths.join(', ')}`);
|
||||
|
||||
// Find the first existing path
|
||||
for (const p of possiblePaths) {
|
||||
log.info(`Checking if exists: ${p}`);
|
||||
const exists = fs.existsSync(p);
|
||||
log.info(`Path ${p} exists: ${exists}`);
|
||||
|
||||
if (exists) {
|
||||
log.info(`Found tasks file at: ${p}`);
|
||||
// Store the project root for future use
|
||||
lastFoundProjectRoot = dirPath;
|
||||
return p;
|
||||
}
|
||||
// If explicit path is relative, resolve it relative to normalized projectRoot
|
||||
if (explicitPath && projectRoot) {
|
||||
return path.resolve(projectRoot, explicitPath);
|
||||
}
|
||||
|
||||
// If no file was found, throw an error
|
||||
const error = new Error(
|
||||
`Tasks file not found in any of the expected locations relative to ${dirPath}: ${possiblePaths.join(', ')}`
|
||||
);
|
||||
error.code = 'TASKS_FILE_NOT_FOUND';
|
||||
throw error;
|
||||
// Use core findComplexityReportPath with explicit path and normalized projectRoot context
|
||||
if (projectRoot) {
|
||||
return coreFindComplexityReportPath(explicitPath, { projectRoot }, log);
|
||||
}
|
||||
|
||||
// Fallback to core function without projectRoot context
|
||||
return coreFindComplexityReportPath(explicitPath, null, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively search for tasks.json in the given directory and parent directories
|
||||
* Also looks for project markers to identify potential project roots
|
||||
* @param {string} startDir - Directory to start searching from
|
||||
* @param {string} explicitFilePath - Optional explicit file path
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {string} - Absolute path to tasks.json
|
||||
* @throws {Error} - If tasks.json cannot be found in any parent directory
|
||||
* Resolve any project-relative path from arguments
|
||||
* @param {string} relativePath - Relative path to resolve
|
||||
* @param {Object} args - Arguments object containing projectRoot
|
||||
* @returns {string} - Resolved absolute path
|
||||
*/
|
||||
function findTasksJsonWithParentSearch(startDir, explicitFilePath, log) {
|
||||
let currentDir = startDir;
|
||||
const rootDir = path.parse(currentDir).root;
|
||||
|
||||
// Keep traversing up until we hit the root directory
|
||||
while (currentDir !== rootDir) {
|
||||
// First check for tasks.json directly
|
||||
try {
|
||||
return findTasksJsonInDirectory(currentDir, explicitFilePath, log);
|
||||
} catch (error) {
|
||||
// If tasks.json not found but the directory has project markers,
|
||||
// log it as a potential project root (helpful for debugging)
|
||||
if (hasProjectMarkers(currentDir)) {
|
||||
log.info(`Found project markers in ${currentDir}, but no tasks.json`);
|
||||
}
|
||||
|
||||
// Move up to parent directory
|
||||
const parentDir = path.dirname(currentDir);
|
||||
|
||||
// Check if we've reached the root
|
||||
if (parentDir === currentDir) {
|
||||
break;
|
||||
}
|
||||
|
||||
log.info(
|
||||
`Tasks file not found in ${currentDir}, searching in parent directory: ${parentDir}`
|
||||
);
|
||||
currentDir = parentDir;
|
||||
}
|
||||
export function resolveProjectPath(relativePath, args) {
|
||||
// Ensure we have a projectRoot from args
|
||||
if (!args?.projectRoot) {
|
||||
throw new Error('projectRoot is required in args to resolve project paths');
|
||||
}
|
||||
|
||||
// If we've searched all the way to the root and found nothing
|
||||
const error = new Error(
|
||||
`Tasks file not found in ${startDir} or any parent directory.`
|
||||
);
|
||||
error.code = 'TASKS_FILE_NOT_FOUND';
|
||||
throw error;
|
||||
}
|
||||
// Normalize the project root to prevent double .taskmaster paths
|
||||
const projectRoot = normalizeProjectRoot(args.projectRoot);
|
||||
|
||||
// Note: findTasksWithNpmConsideration is not used by findTasksJsonPath and might be legacy or used elsewhere.
|
||||
// If confirmed unused, it could potentially be removed in a separate cleanup.
|
||||
function findTasksWithNpmConsideration(startDir, log) {
|
||||
// First try our recursive parent search from cwd
|
||||
try {
|
||||
return findTasksJsonWithParentSearch(startDir, null, log);
|
||||
} catch (error) {
|
||||
// If that fails, try looking relative to the executable location
|
||||
const execPath = process.argv[1];
|
||||
const execDir = path.dirname(execPath);
|
||||
log.info(`Looking for tasks file relative to executable at: ${execDir}`);
|
||||
|
||||
try {
|
||||
return findTasksJsonWithParentSearch(execDir, null, log);
|
||||
} catch (secondError) {
|
||||
// If that also fails, check standard locations in user's home directory
|
||||
const homeDir = os.homedir();
|
||||
log.info(`Looking for tasks file in home directory: ${homeDir}`);
|
||||
|
||||
try {
|
||||
// Check standard locations in home dir
|
||||
return findTasksJsonInDirectory(
|
||||
path.join(homeDir, '.task-master'),
|
||||
null,
|
||||
log
|
||||
);
|
||||
} catch (thirdError) {
|
||||
// If all approaches fail, throw the original error
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
// If already absolute, return as-is
|
||||
if (path.isAbsolute(relativePath)) {
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
// Resolve relative to normalized projectRoot
|
||||
return path.resolve(projectRoot, relativePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds potential PRD document files based on common naming patterns
|
||||
* @param {string} projectRoot - The project root directory
|
||||
* @param {string|null} explicitPath - Optional explicit path provided by the user
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {string|null} - The path to the first found PRD file, or null if none found
|
||||
* Find project root using core utility
|
||||
* @param {string} [startDir] - Directory to start searching from
|
||||
* @returns {string|null} - Project root path or null if not found
|
||||
*/
|
||||
export function findPRDDocumentPath(projectRoot, explicitPath, log) {
|
||||
// If explicit path is provided, check if it exists
|
||||
if (explicitPath) {
|
||||
const fullPath = path.isAbsolute(explicitPath)
|
||||
? explicitPath
|
||||
: path.resolve(projectRoot, explicitPath);
|
||||
|
||||
if (fs.existsSync(fullPath)) {
|
||||
log.info(`Using provided PRD document path: ${fullPath}`);
|
||||
return fullPath;
|
||||
} else {
|
||||
log.warn(
|
||||
`Provided PRD document path not found: ${fullPath}, will search for alternatives`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Common locations and file patterns for PRD documents
|
||||
const commonLocations = [
|
||||
'', // Project root
|
||||
'scripts/'
|
||||
];
|
||||
|
||||
const commonFileNames = ['PRD.md', 'prd.md', 'PRD.txt', 'prd.txt'];
|
||||
|
||||
// Check all possible combinations
|
||||
for (const location of commonLocations) {
|
||||
for (const fileName of commonFileNames) {
|
||||
const potentialPath = path.join(projectRoot, location, fileName);
|
||||
if (fs.existsSync(potentialPath)) {
|
||||
log.info(`Found PRD document at: ${potentialPath}`);
|
||||
return potentialPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.warn(`No PRD document found in common locations within ${projectRoot}`);
|
||||
return null;
|
||||
export function findProjectRoot(startDir) {
|
||||
return coreFindProjectRoot(startDir);
|
||||
}
|
||||
|
||||
export function findComplexityReportPath(projectRoot, explicitPath, log) {
|
||||
// If explicit path is provided, check if it exists
|
||||
if (explicitPath) {
|
||||
const fullPath = path.isAbsolute(explicitPath)
|
||||
? explicitPath
|
||||
: path.resolve(projectRoot, explicitPath);
|
||||
// MAIN EXPORTS FOR MCP TOOLS - these are the functions MCP tools should use
|
||||
|
||||
if (fs.existsSync(fullPath)) {
|
||||
log.info(`Using provided PRD document path: ${fullPath}`);
|
||||
return fullPath;
|
||||
} else {
|
||||
log.warn(
|
||||
`Provided PRD document path not found: ${fullPath}, will search for alternatives`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Common locations and file patterns for PRD documents
|
||||
const commonLocations = [
|
||||
'', // Project root
|
||||
'scripts/'
|
||||
];
|
||||
|
||||
const commonFileNames = [
|
||||
'complexity-report.json',
|
||||
'task-complexity-report.json'
|
||||
];
|
||||
|
||||
// Check all possible combinations
|
||||
for (const location of commonLocations) {
|
||||
for (const fileName of commonFileNames) {
|
||||
const potentialPath = path.join(projectRoot, location, fileName);
|
||||
if (fs.existsSync(potentialPath)) {
|
||||
log.info(`Found PRD document at: ${potentialPath}`);
|
||||
return potentialPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.warn(`No PRD document found in common locations within ${projectRoot}`);
|
||||
return null;
|
||||
/**
|
||||
* Find tasks.json path from arguments - primary MCP function
|
||||
* @param {Object} args - Arguments object containing projectRoot and optional file path
|
||||
* @param {Object} [log] - Log function to prevent console logging
|
||||
* @returns {string|null} - Resolved path to tasks.json or null if not found
|
||||
*/
|
||||
export function findTasksPath(args, log = silentLogger) {
|
||||
return resolveTasksPath(args, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the tasks output directory path
|
||||
* @param {string} projectRoot - The project root directory
|
||||
* @param {string|null} explicitPath - Optional explicit output path provided by the user
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {string} - The resolved tasks directory path
|
||||
* Find complexity report path from arguments - primary MCP function
|
||||
* @param {Object} args - Arguments object containing projectRoot and optional complexityReport path
|
||||
* @param {Object} [log] - Log function to prevent console logging
|
||||
* @returns {string|null} - Resolved path to complexity report or null if not found
|
||||
*/
|
||||
export function resolveTasksOutputPath(projectRoot, explicitPath, log) {
|
||||
// If explicit path is provided, use it
|
||||
if (explicitPath) {
|
||||
const outputPath = path.isAbsolute(explicitPath)
|
||||
? explicitPath
|
||||
: path.resolve(projectRoot, explicitPath);
|
||||
|
||||
log.info(`Using provided tasks output path: ${outputPath}`);
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
// Default output path: tasks/tasks.json in the project root
|
||||
const defaultPath = path.resolve(projectRoot, 'tasks', 'tasks.json');
|
||||
log.info(`Using default tasks output path: ${defaultPath}`);
|
||||
|
||||
// Ensure the directory exists
|
||||
const outputDir = path.dirname(defaultPath);
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
log.info(`Creating tasks directory: ${outputDir}`);
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
return defaultPath;
|
||||
export function findComplexityReportPath(args, log = silentLogger) {
|
||||
return resolveComplexityReportPath(args, log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves various file paths needed for MCP operations based on project root
|
||||
* @param {string} projectRoot - The project root directory
|
||||
* @param {Object} args - Command arguments that may contain explicit paths
|
||||
* @param {Object} log - Logger object
|
||||
* @returns {Object} - An object containing resolved paths
|
||||
* Find PRD path - primary MCP function
|
||||
* @param {string} [explicitPath] - Explicit path to PRD file
|
||||
* @param {Object} [args] - Arguments object for context (not used in current implementation)
|
||||
* @param {Object} [log] - Logger object to prevent console logging
|
||||
* @returns {string|null} - Resolved path to PRD file or null if not found
|
||||
*/
|
||||
export function resolveProjectPaths(projectRoot, args, log) {
|
||||
const prdPath = findPRDDocumentPath(projectRoot, args.input, log);
|
||||
const tasksJsonPath = resolveTasksOutputPath(projectRoot, args.output, log);
|
||||
|
||||
// You can add more path resolutions here as needed
|
||||
|
||||
return {
|
||||
projectRoot,
|
||||
prdPath,
|
||||
tasksJsonPath
|
||||
// Add additional path properties as needed
|
||||
};
|
||||
export function findPRDPath(explicitPath, args = null, log = silentLogger) {
|
||||
return findPrdPath(explicitPath, args, log);
|
||||
}
|
||||
|
||||
// Legacy aliases for backward compatibility - DEPRECATED
|
||||
export const findTasksJsonPath = findTasksPath;
|
||||
export const findComplexityReportJsonPath = findComplexityReportPath;
|
||||
|
||||
// Re-export PROJECT_MARKERS for MCP tools that import it from this module
|
||||
export { PROJECT_MARKERS };
|
||||
|
||||
@@ -7,11 +7,10 @@ import { z } from 'zod';
|
||||
import {
|
||||
handleApiResult,
|
||||
createErrorResponse,
|
||||
getProjectRootFromSession,
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { addDependencyDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import { findTasksPath } from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the addDependency tool with the MCP server
|
||||
@@ -44,7 +43,7 @@ export function registerAddDependencyTool(server) {
|
||||
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
tasksJsonPath = findTasksJsonPath(
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: args.projectRoot, file: args.file },
|
||||
log
|
||||
);
|
||||
@@ -76,7 +75,13 @@ export function registerAddDependencyTool(server) {
|
||||
}
|
||||
|
||||
// Use handleApiResult to format the response
|
||||
return handleApiResult(result, log, 'Error adding dependency');
|
||||
return handleApiResult(
|
||||
result,
|
||||
log,
|
||||
'Error adding dependency',
|
||||
undefined,
|
||||
args.projectRoot
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error in addDependency tool: ${error.message}`);
|
||||
return createErrorResponse(error.message);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { addSubtaskDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import { findTasksPath } from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the addSubtask tool with the MCP server
|
||||
@@ -67,7 +67,7 @@ export function registerAddSubtaskTool(server) {
|
||||
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
tasksJsonPath = findTasksJsonPath(
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: args.projectRoot, file: args.file },
|
||||
log
|
||||
);
|
||||
@@ -88,9 +88,11 @@ export function registerAddSubtaskTool(server) {
|
||||
details: args.details,
|
||||
status: args.status,
|
||||
dependencies: args.dependencies,
|
||||
skipGenerate: args.skipGenerate
|
||||
skipGenerate: args.skipGenerate,
|
||||
projectRoot: args.projectRoot
|
||||
},
|
||||
log
|
||||
log,
|
||||
{ session }
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
@@ -99,7 +101,13 @@ export function registerAddSubtaskTool(server) {
|
||||
log.error(`Failed to add subtask: ${result.error.message}`);
|
||||
}
|
||||
|
||||
return handleApiResult(result, log, 'Error adding subtask');
|
||||
return handleApiResult(
|
||||
result,
|
||||
log,
|
||||
'Error adding subtask',
|
||||
undefined,
|
||||
args.projectRoot
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error in addSubtask tool: ${error.message}`);
|
||||
return createErrorResponse(error.message);
|
||||
|
||||
99
mcp-server/src/tools/add-tag.js
Normal file
99
mcp-server/src/tools/add-tag.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* tools/add-tag.js
|
||||
* Tool to create a new tag
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
createErrorResponse,
|
||||
handleApiResult,
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { addTagDirect } from '../core/task-master-core.js';
|
||||
import { findTasksPath } from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the addTag tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerAddTagTool(server) {
|
||||
server.addTool({
|
||||
name: 'add_tag',
|
||||
description: 'Create a new tag for organizing tasks in different contexts',
|
||||
parameters: z.object({
|
||||
name: z.string().describe('Name of the new tag to create'),
|
||||
copyFromCurrent: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
'Whether to copy tasks from the current tag (default: false)'
|
||||
),
|
||||
copyFromTag: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Specific tag to copy tasks from'),
|
||||
fromBranch: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
'Create tag name from current git branch (ignores name parameter)'
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Optional description for the tag'),
|
||||
file: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Path to the tasks file (default: tasks/tasks.json)'),
|
||||
projectRoot: z
|
||||
.string()
|
||||
.describe('The directory of the project. Must be an absolute path.')
|
||||
}),
|
||||
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
|
||||
try {
|
||||
log.info(`Starting add-tag with args: ${JSON.stringify(args)}`);
|
||||
|
||||
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: args.projectRoot, file: args.file },
|
||||
log
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error finding tasks.json: ${error.message}`);
|
||||
return createErrorResponse(
|
||||
`Failed to find tasks.json: ${error.message}`
|
||||
);
|
||||
}
|
||||
|
||||
// Call the direct function
|
||||
const result = await addTagDirect(
|
||||
{
|
||||
tasksJsonPath: tasksJsonPath,
|
||||
name: args.name,
|
||||
copyFromCurrent: args.copyFromCurrent,
|
||||
copyFromTag: args.copyFromTag,
|
||||
fromBranch: args.fromBranch,
|
||||
description: args.description,
|
||||
projectRoot: args.projectRoot
|
||||
},
|
||||
log,
|
||||
{ session }
|
||||
);
|
||||
|
||||
return handleApiResult(
|
||||
result,
|
||||
log,
|
||||
'Error creating tag',
|
||||
undefined,
|
||||
args.projectRoot
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error in add-tag tool: ${error.message}`);
|
||||
return createErrorResponse(error.message);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
withNormalizedProjectRoot
|
||||
} from './utils.js';
|
||||
import { addTaskDirect } from '../core/task-master-core.js';
|
||||
import { findTasksJsonPath } from '../core/utils/path-utils.js';
|
||||
import { findTasksPath } from '../core/utils/path-utils.js';
|
||||
|
||||
/**
|
||||
* Register the addTask tool with the MCP server
|
||||
@@ -70,7 +70,7 @@ export function registerAddTaskTool(server) {
|
||||
// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
|
||||
let tasksJsonPath;
|
||||
try {
|
||||
tasksJsonPath = findTasksJsonPath(
|
||||
tasksJsonPath = findTasksPath(
|
||||
{ projectRoot: args.projectRoot, file: args.file },
|
||||
log
|
||||
);
|
||||
@@ -99,7 +99,13 @@ export function registerAddTaskTool(server) {
|
||||
{ session }
|
||||
);
|
||||
|
||||
return handleApiResult(result, log);
|
||||
return handleApiResult(
|
||||
result,
|
||||
log,
|
||||
'Error adding task',
|
||||
undefined,
|
||||
args.projectRoot
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(`Error in add-task tool: ${error.message}`);
|
||||
return createErrorResponse(error.message);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user