Unify and streamline profile system architecture (#853)
* move claude rules and commands to assets/claude * update claude profile to copy assets/claude to .claude * fix formatting * feat(profiles): Implement unified profile system - Convert Claude and Codex profiles to use createProfile() factory - Remove simple vs complex profile distinction in rule transformer - Unify convertAllRulesToProfileRules() to handle all profiles consistently - Fix mcpConfigPath construction in base-profile.js for null mcpConfigName - Update terminology from 'simpleProfiles' to 'assetOnlyProfiles' throughout - Ensure Claude .claude directory copying works in both CLI and MCP contexts - All profiles now follow same execution flow with proper lifecycle functions Changes: - src/profiles/claude.js: Convert to createProfile() factory pattern - src/profiles/codex.js: Convert to createProfile() factory pattern - src/utils/rule-transformer.js: Unified profile handling logic - src/utils/profiles.js: Remove simple profile categorization - src/profiles/base-profile.js: Fix mcpConfigPath construction - scripts/modules/commands.js: Update variable naming - tests/: Update all tests for unified system and terminology Fixes Claude profile asset copying issue in MCP context. All tests passing (617 passed, 11 skipped). * re-checkin claude files * fix formatting * chore: clean up test Claude rules files * chore: add changeset for unified profile system * add claude files back * add changeset * restore proper gitignore * remove claude agents file from root * remove incorrect doc * simplify profiles and update tests * update changeset * update changeset * remove profile specific code * streamline profiles with defaults and update tests * update changeset * add newline at end of gitignore * restore changes * streamline profiles with defaults; update tests and add vscode test * update rule profile tests * update wording for clearer profile management * refactor and clarify terminology * use original projectRoot var name * revert param desc * use updated claude assets from neno * add "YOUR_" before api key here * streamline codex profile * add gemini profile * update gemini profile * update tests * relocate function * update rules interactive setup Gemini desc * remove duplicative code * add comma
This commit is contained in:
5
.changeset/spicy-badgers-fail.md
Normal file
5
.changeset/spicy-badgers-fail.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Unify and streamline profile system architecture for improved maintainability
|
||||
147
assets/claude/TM_COMMANDS_GUIDE.md
Normal file
147
assets/claude/TM_COMMANDS_GUIDE.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Task Master Commands for Claude Code
|
||||
|
||||
Complete guide to using Task Master through Claude Code's slash commands.
|
||||
|
||||
## Overview
|
||||
|
||||
All Task Master functionality is available through the `/project:tm/` namespace with natural language support and intelligent features.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install Task Master
|
||||
/project:tm/setup/quick-install
|
||||
|
||||
# Initialize project
|
||||
/project:tm/init/quick
|
||||
|
||||
# Parse requirements
|
||||
/project:tm/parse-prd requirements.md
|
||||
|
||||
# Start working
|
||||
/project:tm/next
|
||||
```
|
||||
|
||||
## Command Structure
|
||||
|
||||
Commands are organized hierarchically to match Task Master's CLI:
|
||||
- Main commands at `/project:tm/[command]`
|
||||
- Subcommands for specific operations `/project:tm/[command]/[subcommand]`
|
||||
- Natural language arguments accepted throughout
|
||||
|
||||
## Complete Command Reference
|
||||
|
||||
### Setup & Configuration
|
||||
- `/project:tm/setup/install` - Full installation guide
|
||||
- `/project:tm/setup/quick-install` - One-line install
|
||||
- `/project:tm/init` - Initialize project
|
||||
- `/project:tm/init/quick` - Quick init with -y
|
||||
- `/project:tm/models` - View AI config
|
||||
- `/project:tm/models/setup` - Configure AI
|
||||
|
||||
### Task Generation
|
||||
- `/project:tm/parse-prd` - Generate from PRD
|
||||
- `/project:tm/parse-prd/with-research` - Enhanced parsing
|
||||
- `/project:tm/generate` - Create task files
|
||||
|
||||
### Task Management
|
||||
- `/project:tm/list` - List with natural language filters
|
||||
- `/project:tm/list/with-subtasks` - Hierarchical view
|
||||
- `/project:tm/list/by-status <status>` - Filter by status
|
||||
- `/project:tm/show <id>` - Task details
|
||||
- `/project:tm/add-task` - Create task
|
||||
- `/project:tm/update` - Update tasks
|
||||
- `/project:tm/remove-task` - Delete task
|
||||
|
||||
### Status Management
|
||||
- `/project:tm/set-status/to-pending <id>`
|
||||
- `/project:tm/set-status/to-in-progress <id>`
|
||||
- `/project:tm/set-status/to-done <id>`
|
||||
- `/project:tm/set-status/to-review <id>`
|
||||
- `/project:tm/set-status/to-deferred <id>`
|
||||
- `/project:tm/set-status/to-cancelled <id>`
|
||||
|
||||
### Task Analysis
|
||||
- `/project:tm/analyze-complexity` - AI analysis
|
||||
- `/project:tm/complexity-report` - View report
|
||||
- `/project:tm/expand <id>` - Break down task
|
||||
- `/project:tm/expand/all` - Expand all complex
|
||||
|
||||
### Dependencies
|
||||
- `/project:tm/add-dependency` - Add dependency
|
||||
- `/project:tm/remove-dependency` - Remove dependency
|
||||
- `/project:tm/validate-dependencies` - Check issues
|
||||
- `/project:tm/fix-dependencies` - Auto-fix
|
||||
|
||||
### Workflows
|
||||
- `/project:tm/workflows/smart-flow` - Adaptive workflows
|
||||
- `/project:tm/workflows/pipeline` - Chain commands
|
||||
- `/project:tm/workflows/auto-implement` - AI implementation
|
||||
|
||||
### Utilities
|
||||
- `/project:tm/status` - Project dashboard
|
||||
- `/project:tm/next` - Next task recommendation
|
||||
- `/project:tm/utils/analyze` - Project analysis
|
||||
- `/project:tm/learn` - Interactive help
|
||||
|
||||
## Key Features
|
||||
|
||||
### Natural Language Support
|
||||
All commands understand natural language:
|
||||
```
|
||||
/project:tm/list pending high priority
|
||||
/project:tm/update mark 23 as done
|
||||
/project:tm/add-task implement OAuth login
|
||||
```
|
||||
|
||||
### Smart Context
|
||||
Commands analyze project state and provide intelligent suggestions based on:
|
||||
- Current task status
|
||||
- Dependencies
|
||||
- Team patterns
|
||||
- Project phase
|
||||
|
||||
### Visual Enhancements
|
||||
- Progress bars and indicators
|
||||
- Status badges
|
||||
- Organized displays
|
||||
- Clear hierarchies
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Daily Development
|
||||
```
|
||||
/project:tm/workflows/smart-flow morning
|
||||
/project:tm/next
|
||||
/project:tm/set-status/to-in-progress <id>
|
||||
/project:tm/set-status/to-done <id>
|
||||
```
|
||||
|
||||
### Task Breakdown
|
||||
```
|
||||
/project:tm/show <id>
|
||||
/project:tm/expand <id>
|
||||
/project:tm/list/with-subtasks
|
||||
```
|
||||
|
||||
### Sprint Planning
|
||||
```
|
||||
/project:tm/analyze-complexity
|
||||
/project:tm/workflows/pipeline init → expand/all → status
|
||||
```
|
||||
|
||||
## Migration from Old Commands
|
||||
|
||||
| Old | New |
|
||||
|-----|-----|
|
||||
| `/project:task-master:list` | `/project:tm/list` |
|
||||
| `/project:task-master:complete` | `/project:tm/set-status/to-done` |
|
||||
| `/project:workflows:auto-implement` | `/project:tm/workflows/auto-implement` |
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use `/project:tm/` + Tab for command discovery
|
||||
2. Natural language is supported everywhere
|
||||
3. Commands provide smart defaults
|
||||
4. Chain commands for automation
|
||||
5. Check `/project:tm/learn` for interactive help
|
||||
55
assets/claude/commands/tm/add-dependency/add-dependency.md
Normal file
55
assets/claude/commands/tm/add-dependency/add-dependency.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Add a dependency between tasks.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the task IDs to establish dependency relationship.
|
||||
|
||||
## Adding Dependencies
|
||||
|
||||
Creates a dependency where one task must be completed before another can start.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Parse natural language or IDs:
|
||||
- "make 5 depend on 3" → task 5 depends on task 3
|
||||
- "5 needs 3" → task 5 depends on task 3
|
||||
- "5 3" → task 5 depends on task 3
|
||||
- "5 after 3" → task 5 depends on task 3
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master add-dependency --id=<task-id> --depends-on=<dependency-id>
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Before adding:
|
||||
1. **Verify both tasks exist**
|
||||
2. **Check for circular dependencies**
|
||||
3. **Ensure dependency makes logical sense**
|
||||
4. **Warn if creating complex chains**
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Detect if dependency already exists
|
||||
- Suggest related dependencies
|
||||
- Show impact on task flow
|
||||
- Update task priorities if needed
|
||||
|
||||
## Post-Addition
|
||||
|
||||
After adding dependency:
|
||||
1. Show updated dependency graph
|
||||
2. Identify any newly blocked tasks
|
||||
3. Suggest task order changes
|
||||
4. Update project timeline
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/add-dependency 5 needs 3
|
||||
→ Task #5 now depends on Task #3
|
||||
→ Task #5 is now blocked until #3 completes
|
||||
→ Suggested: Also consider if #5 needs #4
|
||||
```
|
||||
76
assets/claude/commands/tm/add-subtask/add-subtask.md
Normal file
76
assets/claude/commands/tm/add-subtask/add-subtask.md
Normal file
@@ -0,0 +1,76 @@
|
||||
Add a subtask to a parent task.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse arguments to create a new subtask or convert existing task.
|
||||
|
||||
## Adding Subtasks
|
||||
|
||||
Creates subtasks to break down complex parent tasks into manageable pieces.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Flexible natural language:
|
||||
- "add subtask to 5: implement login form"
|
||||
- "break down 5 with: setup, implement, test"
|
||||
- "subtask for 5: handle edge cases"
|
||||
- "5: validate user input" → adds subtask to task 5
|
||||
|
||||
## Execution Modes
|
||||
|
||||
### 1. Create New Subtask
|
||||
```bash
|
||||
task-master add-subtask --parent=<id> --title="<title>" --description="<desc>"
|
||||
```
|
||||
|
||||
### 2. Convert Existing Task
|
||||
```bash
|
||||
task-master add-subtask --parent=<id> --task-id=<existing-id>
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Automatic Subtask Generation**
|
||||
- If title contains "and" or commas, create multiple
|
||||
- Suggest common subtask patterns
|
||||
- Inherit parent's context
|
||||
|
||||
2. **Intelligent Defaults**
|
||||
- Priority based on parent
|
||||
- Appropriate time estimates
|
||||
- Logical dependencies between subtasks
|
||||
|
||||
3. **Validation**
|
||||
- Check parent task complexity
|
||||
- Warn if too many subtasks
|
||||
- Ensure subtask makes sense
|
||||
|
||||
## Creation Process
|
||||
|
||||
1. Parse parent task context
|
||||
2. Generate subtask with ID like "5.1"
|
||||
3. Set appropriate defaults
|
||||
4. Link to parent task
|
||||
5. Update parent's time estimate
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/add-subtask to 5: implement user authentication
|
||||
→ Created subtask #5.1: "implement user authentication"
|
||||
→ Parent task #5 now has 1 subtask
|
||||
→ Suggested next subtasks: tests, documentation
|
||||
|
||||
/project:tm/add-subtask 5: setup, implement, test
|
||||
→ Created 3 subtasks:
|
||||
#5.1: setup
|
||||
#5.2: implement
|
||||
#5.3: test
|
||||
```
|
||||
|
||||
## Post-Creation
|
||||
|
||||
- Show updated task hierarchy
|
||||
- Suggest logical next subtasks
|
||||
- Update complexity estimates
|
||||
- Recommend subtask order
|
||||
@@ -0,0 +1,71 @@
|
||||
Convert an existing task into a subtask.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse parent ID and task ID to convert.
|
||||
|
||||
## Task Conversion
|
||||
|
||||
Converts an existing standalone task into a subtask of another task.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "move task 8 under 5"
|
||||
- "make 8 a subtask of 5"
|
||||
- "nest 8 in 5"
|
||||
- "5 8" → make task 8 a subtask of task 5
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master add-subtask --parent=<parent-id> --task-id=<task-to-convert>
|
||||
```
|
||||
|
||||
## Pre-Conversion Checks
|
||||
|
||||
1. **Validation**
|
||||
- Both tasks exist and are valid
|
||||
- No circular parent relationships
|
||||
- Task isn't already a subtask
|
||||
- Logical hierarchy makes sense
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Dependencies that will be affected
|
||||
- Tasks that depend on converting task
|
||||
- Priority alignment needed
|
||||
- Status compatibility
|
||||
|
||||
## Conversion Process
|
||||
|
||||
1. Change task ID from "8" to "5.1" (next available)
|
||||
2. Update all dependency references
|
||||
3. Inherit parent's context where appropriate
|
||||
4. Adjust priorities if needed
|
||||
5. Update time estimates
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Preserve task history
|
||||
- Maintain dependencies
|
||||
- Update all references
|
||||
- Create conversion log
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/add-subtask/from-task 5 8
|
||||
→ Converting: Task #8 becomes subtask #5.1
|
||||
→ Updated: 3 dependency references
|
||||
→ Parent task #5 now has 1 subtask
|
||||
→ Note: Subtask inherits parent's priority
|
||||
|
||||
Before: #8 "Implement validation" (standalone)
|
||||
After: #5.1 "Implement validation" (subtask of #5)
|
||||
```
|
||||
|
||||
## Post-Conversion
|
||||
|
||||
- Show new task hierarchy
|
||||
- List updated dependencies
|
||||
- Verify project integrity
|
||||
- Suggest related conversions
|
||||
78
assets/claude/commands/tm/add-task/add-task.md
Normal file
78
assets/claude/commands/tm/add-task/add-task.md
Normal file
@@ -0,0 +1,78 @@
|
||||
Add new tasks with intelligent parsing and context awareness.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Smart Task Addition
|
||||
|
||||
Parse natural language to create well-structured tasks.
|
||||
|
||||
### 1. **Input Understanding**
|
||||
|
||||
I'll intelligently parse your request:
|
||||
- Natural language → Structured task
|
||||
- Detect priority from keywords (urgent, ASAP, important)
|
||||
- Infer dependencies from context
|
||||
- Suggest complexity based on description
|
||||
- Determine task type (feature, bug, refactor, test, docs)
|
||||
|
||||
### 2. **Smart Parsing Examples**
|
||||
|
||||
**"Add urgent task to fix login bug"**
|
||||
→ Title: Fix login bug
|
||||
→ Priority: high
|
||||
→ Type: bug
|
||||
→ Suggested complexity: medium
|
||||
|
||||
**"Create task for API documentation after task 23 is done"**
|
||||
→ Title: API documentation
|
||||
→ Dependencies: [23]
|
||||
→ Type: documentation
|
||||
→ Priority: medium
|
||||
|
||||
**"Need to refactor auth module - depends on 12 and 15, high complexity"**
|
||||
→ Title: Refactor auth module
|
||||
→ Dependencies: [12, 15]
|
||||
→ Complexity: high
|
||||
→ Type: refactor
|
||||
|
||||
### 3. **Context Enhancement**
|
||||
|
||||
Based on current project state:
|
||||
- Suggest related existing tasks
|
||||
- Warn about potential conflicts
|
||||
- Recommend dependencies
|
||||
- Propose subtasks if complex
|
||||
|
||||
### 4. **Interactive Refinement**
|
||||
|
||||
```yaml
|
||||
Task Preview:
|
||||
─────────────
|
||||
Title: [Extracted title]
|
||||
Priority: [Inferred priority]
|
||||
Dependencies: [Detected dependencies]
|
||||
Complexity: [Estimated complexity]
|
||||
|
||||
Suggestions:
|
||||
- Similar task #34 exists, consider as dependency?
|
||||
- This seems complex, break into subtasks?
|
||||
- Tasks #45-47 work on same module
|
||||
```
|
||||
|
||||
### 5. **Validation & Creation**
|
||||
|
||||
Before creating:
|
||||
- Validate dependencies exist
|
||||
- Check for duplicates
|
||||
- Ensure logical ordering
|
||||
- Verify task completeness
|
||||
|
||||
### 6. **Smart Defaults**
|
||||
|
||||
Intelligent defaults based on:
|
||||
- Task type patterns
|
||||
- Team conventions
|
||||
- Historical data
|
||||
- Current sprint/phase
|
||||
|
||||
Result: High-quality tasks from minimal input.
|
||||
@@ -0,0 +1,121 @@
|
||||
Analyze task complexity and generate expansion recommendations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Perform deep analysis of task complexity across the project.
|
||||
|
||||
## Complexity Analysis
|
||||
|
||||
Uses AI to analyze tasks and recommend which ones need breakdown.
|
||||
|
||||
## Execution Options
|
||||
|
||||
```bash
|
||||
task-master analyze-complexity [--research] [--threshold=5]
|
||||
```
|
||||
|
||||
## Analysis Parameters
|
||||
|
||||
- `--research` → Use research AI for deeper analysis
|
||||
- `--threshold=5` → Only flag tasks above complexity 5
|
||||
- Default: Analyze all pending tasks
|
||||
|
||||
## Analysis Process
|
||||
|
||||
### 1. **Task Evaluation**
|
||||
For each task, AI evaluates:
|
||||
- Technical complexity
|
||||
- Time requirements
|
||||
- Dependency complexity
|
||||
- Risk factors
|
||||
- Knowledge requirements
|
||||
|
||||
### 2. **Complexity Scoring**
|
||||
Assigns score 1-10 based on:
|
||||
- Implementation difficulty
|
||||
- Integration challenges
|
||||
- Testing requirements
|
||||
- Unknown factors
|
||||
- Technical debt risk
|
||||
|
||||
### 3. **Recommendations**
|
||||
For complex tasks:
|
||||
- Suggest expansion approach
|
||||
- Recommend subtask breakdown
|
||||
- Identify risk areas
|
||||
- Propose mitigation strategies
|
||||
|
||||
## Smart Analysis Features
|
||||
|
||||
1. **Pattern Recognition**
|
||||
- Similar task comparisons
|
||||
- Historical complexity accuracy
|
||||
- Team velocity consideration
|
||||
- Technology stack factors
|
||||
|
||||
2. **Contextual Factors**
|
||||
- Team expertise
|
||||
- Available resources
|
||||
- Timeline constraints
|
||||
- Business criticality
|
||||
|
||||
3. **Risk Assessment**
|
||||
- Technical risks
|
||||
- Timeline risks
|
||||
- Dependency risks
|
||||
- Knowledge gaps
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
Task Complexity Analysis Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
High Complexity Tasks (>7):
|
||||
📍 #5 "Implement real-time sync" - Score: 9/10
|
||||
Factors: WebSocket complexity, state management, conflict resolution
|
||||
Recommendation: Expand into 5-7 subtasks
|
||||
Risks: Performance, data consistency
|
||||
|
||||
📍 #12 "Migrate database schema" - Score: 8/10
|
||||
Factors: Data migration, zero downtime, rollback strategy
|
||||
Recommendation: Expand into 4-5 subtasks
|
||||
Risks: Data loss, downtime
|
||||
|
||||
Medium Complexity Tasks (5-7):
|
||||
📍 #23 "Add export functionality" - Score: 6/10
|
||||
Consider expansion if timeline tight
|
||||
|
||||
Low Complexity Tasks (<5):
|
||||
✅ 15 tasks - No expansion needed
|
||||
|
||||
Summary:
|
||||
- Expand immediately: 2 tasks
|
||||
- Consider expanding: 5 tasks
|
||||
- Keep as-is: 15 tasks
|
||||
```
|
||||
|
||||
## Actionable Output
|
||||
|
||||
For each high-complexity task:
|
||||
1. Complexity score with reasoning
|
||||
2. Specific expansion suggestions
|
||||
3. Risk mitigation approaches
|
||||
4. Recommended subtask structure
|
||||
|
||||
## Integration
|
||||
|
||||
Results are:
|
||||
- Saved to `.taskmaster/reports/complexity-analysis.md`
|
||||
- Used by expand command
|
||||
- Inform sprint planning
|
||||
- Guide resource allocation
|
||||
|
||||
## Next Steps
|
||||
|
||||
After analysis:
|
||||
```
|
||||
/project:tm/expand 5 # Expand specific task
|
||||
/project:tm/expand/all # Expand all recommended
|
||||
/project:tm/complexity-report # View detailed report
|
||||
```
|
||||
@@ -0,0 +1,93 @@
|
||||
Clear all subtasks from all tasks globally.
|
||||
|
||||
## Global Subtask Clearing
|
||||
|
||||
Remove all subtasks across the entire project. Use with extreme caution.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master clear-subtasks --all
|
||||
```
|
||||
|
||||
## Pre-Clear Analysis
|
||||
|
||||
1. **Project-Wide Summary**
|
||||
```
|
||||
Global Subtask Summary
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
Total parent tasks: 12
|
||||
Total subtasks: 47
|
||||
- Completed: 15
|
||||
- In-progress: 8
|
||||
- Pending: 24
|
||||
|
||||
Work at risk: ~120 hours
|
||||
```
|
||||
|
||||
2. **Critical Warnings**
|
||||
- In-progress subtasks that will lose work
|
||||
- Completed subtasks with valuable history
|
||||
- Complex dependency chains
|
||||
- Integration test results
|
||||
|
||||
## Double Confirmation
|
||||
|
||||
```
|
||||
⚠️ DESTRUCTIVE OPERATION WARNING ⚠️
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
This will remove ALL 47 subtasks from your project
|
||||
Including 8 in-progress and 15 completed subtasks
|
||||
|
||||
This action CANNOT be undone
|
||||
|
||||
Type 'CLEAR ALL SUBTASKS' to confirm:
|
||||
```
|
||||
|
||||
## Smart Safeguards
|
||||
|
||||
- Require explicit confirmation phrase
|
||||
- Create automatic backup
|
||||
- Log all removed data
|
||||
- Option to export first
|
||||
|
||||
## Use Cases
|
||||
|
||||
Valid reasons for global clear:
|
||||
- Project restructuring
|
||||
- Major pivot in approach
|
||||
- Starting fresh breakdown
|
||||
- Switching to different task organization
|
||||
|
||||
## Process
|
||||
|
||||
1. Full project analysis
|
||||
2. Create backup file
|
||||
3. Show detailed impact
|
||||
4. Require confirmation
|
||||
5. Execute removal
|
||||
6. Generate summary report
|
||||
|
||||
## Alternative Suggestions
|
||||
|
||||
Before clearing all:
|
||||
- Export subtasks to file
|
||||
- Clear only pending subtasks
|
||||
- Clear by task category
|
||||
- Archive instead of delete
|
||||
|
||||
## Post-Clear Report
|
||||
|
||||
```
|
||||
Global Subtask Clear Complete
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Removed: 47 subtasks from 12 tasks
|
||||
Backup saved: .taskmaster/backup/subtasks-20240115.json
|
||||
Parent tasks updated: 12
|
||||
Time estimates adjusted: Yes
|
||||
|
||||
Next steps:
|
||||
- Review updated task list
|
||||
- Re-expand complex tasks as needed
|
||||
- Check project timeline
|
||||
```
|
||||
86
assets/claude/commands/tm/clear-subtasks/clear-subtasks.md
Normal file
86
assets/claude/commands/tm/clear-subtasks/clear-subtasks.md
Normal file
@@ -0,0 +1,86 @@
|
||||
Clear all subtasks from a specific task.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
Remove all subtasks from a parent task at once.
|
||||
|
||||
## Clearing Subtasks
|
||||
|
||||
Bulk removal of all subtasks from a parent task.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master clear-subtasks --id=<task-id>
|
||||
```
|
||||
|
||||
## Pre-Clear Analysis
|
||||
|
||||
1. **Subtask Summary**
|
||||
- Number of subtasks
|
||||
- Completion status of each
|
||||
- Work already done
|
||||
- Dependencies affected
|
||||
|
||||
2. **Impact Assessment**
|
||||
- Data that will be lost
|
||||
- Dependencies to be removed
|
||||
- Effect on project timeline
|
||||
- Parent task implications
|
||||
|
||||
## Confirmation Required
|
||||
|
||||
```
|
||||
Clear Subtasks Confirmation
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Parent Task: #5 "Implement user authentication"
|
||||
Subtasks to remove: 4
|
||||
- #5.1 "Setup auth framework" (done)
|
||||
- #5.2 "Create login form" (in-progress)
|
||||
- #5.3 "Add validation" (pending)
|
||||
- #5.4 "Write tests" (pending)
|
||||
|
||||
⚠️ This will permanently delete all subtask data
|
||||
Continue? (y/n)
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Option to convert to standalone tasks
|
||||
- Backup task data before clearing
|
||||
- Preserve completed work history
|
||||
- Update parent task appropriately
|
||||
|
||||
## Process
|
||||
|
||||
1. List all subtasks for confirmation
|
||||
2. Check for in-progress work
|
||||
3. Remove all subtasks
|
||||
4. Update parent task
|
||||
5. Clean up dependencies
|
||||
|
||||
## Alternative Options
|
||||
|
||||
Suggest alternatives:
|
||||
- Convert important subtasks to tasks
|
||||
- Keep completed subtasks
|
||||
- Archive instead of delete
|
||||
- Export subtask data first
|
||||
|
||||
## Post-Clear
|
||||
|
||||
- Show updated parent task
|
||||
- Recalculate time estimates
|
||||
- Update task complexity
|
||||
- Suggest next steps
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/clear-subtasks 5
|
||||
→ Found 4 subtasks to remove
|
||||
→ Warning: Subtask #5.2 is in-progress
|
||||
→ Cleared all subtasks from task #5
|
||||
→ Updated parent task estimates
|
||||
→ Suggestion: Consider re-expanding with better breakdown
|
||||
```
|
||||
117
assets/claude/commands/tm/complexity-report/complexity-report.md
Normal file
117
assets/claude/commands/tm/complexity-report/complexity-report.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Display the task complexity analysis report.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
View the detailed complexity analysis generated by analyze-complexity command.
|
||||
|
||||
## Viewing Complexity Report
|
||||
|
||||
Shows comprehensive task complexity analysis with actionable insights.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master complexity-report [--file=<path>]
|
||||
```
|
||||
|
||||
## Report Location
|
||||
|
||||
Default: `.taskmaster/reports/complexity-analysis.md`
|
||||
Custom: Specify with --file parameter
|
||||
|
||||
## Report Contents
|
||||
|
||||
### 1. **Executive Summary**
|
||||
```
|
||||
Complexity Analysis Summary
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Analysis Date: 2024-01-15
|
||||
Tasks Analyzed: 32
|
||||
High Complexity: 5 (16%)
|
||||
Medium Complexity: 12 (37%)
|
||||
Low Complexity: 15 (47%)
|
||||
|
||||
Critical Findings:
|
||||
- 5 tasks need immediate expansion
|
||||
- 3 tasks have high technical risk
|
||||
- 2 tasks block critical path
|
||||
```
|
||||
|
||||
### 2. **Detailed Task Analysis**
|
||||
For each complex task:
|
||||
- Complexity score breakdown
|
||||
- Contributing factors
|
||||
- Specific risks identified
|
||||
- Expansion recommendations
|
||||
- Similar completed tasks
|
||||
|
||||
### 3. **Risk Matrix**
|
||||
Visual representation:
|
||||
```
|
||||
Risk vs Complexity Matrix
|
||||
━━━━━━━━━━━━━━━━━━━━━━━
|
||||
High Risk | #5(9) #12(8) | #23(6)
|
||||
Med Risk | #34(7) | #45(5) #67(5)
|
||||
Low Risk | #78(8) | [15 tasks]
|
||||
| High Complex | Med Complex
|
||||
```
|
||||
|
||||
### 4. **Recommendations**
|
||||
|
||||
**Immediate Actions:**
|
||||
1. Expand task #5 - Critical path + high complexity
|
||||
2. Expand task #12 - High risk + dependencies
|
||||
3. Review task #34 - Consider splitting
|
||||
|
||||
**Sprint Planning:**
|
||||
- Don't schedule multiple high-complexity tasks together
|
||||
- Ensure expertise available for complex tasks
|
||||
- Build in buffer time for unknowns
|
||||
|
||||
## Interactive Features
|
||||
|
||||
When viewing report:
|
||||
1. **Quick Actions**
|
||||
- Press 'e' to expand a task
|
||||
- Press 'd' for task details
|
||||
- Press 'r' to refresh analysis
|
||||
|
||||
2. **Filtering**
|
||||
- View by complexity level
|
||||
- Filter by risk factors
|
||||
- Show only actionable items
|
||||
|
||||
3. **Export Options**
|
||||
- Markdown format
|
||||
- CSV for spreadsheets
|
||||
- JSON for tools
|
||||
|
||||
## Report Intelligence
|
||||
|
||||
- Compares with historical data
|
||||
- Shows complexity trends
|
||||
- Identifies patterns
|
||||
- Suggests process improvements
|
||||
|
||||
## Integration
|
||||
|
||||
Use report for:
|
||||
- Sprint planning sessions
|
||||
- Resource allocation
|
||||
- Risk assessment
|
||||
- Team discussions
|
||||
- Client updates
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/project:tm/complexity-report
|
||||
→ Opens latest analysis
|
||||
|
||||
/project:tm/complexity-report --file=archived/2024-01-01.md
|
||||
→ View historical analysis
|
||||
|
||||
After viewing:
|
||||
/project:tm/expand 5
|
||||
→ Expand high-complexity task
|
||||
```
|
||||
51
assets/claude/commands/tm/expand/expand-all-tasks.md
Normal file
51
assets/claude/commands/tm/expand/expand-all-tasks.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Expand all pending tasks that need subtasks.
|
||||
|
||||
## Bulk Task Expansion
|
||||
|
||||
Intelligently expands all tasks that would benefit from breakdown.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master expand --all
|
||||
```
|
||||
|
||||
## Smart Selection
|
||||
|
||||
Only expands tasks that:
|
||||
- Are marked as pending
|
||||
- Have high complexity (>5)
|
||||
- Lack existing subtasks
|
||||
- Would benefit from breakdown
|
||||
|
||||
## Expansion Process
|
||||
|
||||
1. **Analysis Phase**
|
||||
- Identify expansion candidates
|
||||
- Group related tasks
|
||||
- Plan expansion strategy
|
||||
|
||||
2. **Batch Processing**
|
||||
- Expand tasks in logical order
|
||||
- Maintain consistency
|
||||
- Preserve relationships
|
||||
- Optimize for parallelism
|
||||
|
||||
3. **Quality Control**
|
||||
- Ensure subtask quality
|
||||
- Avoid over-decomposition
|
||||
- Maintain task coherence
|
||||
- Update dependencies
|
||||
|
||||
## Options
|
||||
|
||||
- Add `force` to expand all regardless of complexity
|
||||
- Add `research` for enhanced AI analysis
|
||||
|
||||
## Results
|
||||
|
||||
After bulk expansion:
|
||||
- Summary of tasks expanded
|
||||
- New subtask count
|
||||
- Updated complexity metrics
|
||||
- Suggested task order
|
||||
49
assets/claude/commands/tm/expand/expand-task.md
Normal file
49
assets/claude/commands/tm/expand/expand-task.md
Normal file
@@ -0,0 +1,49 @@
|
||||
Break down a complex task into subtasks.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Intelligent Task Expansion
|
||||
|
||||
Analyzes a task and creates detailed subtasks for better manageability.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master expand --id=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Expansion Process
|
||||
|
||||
1. **Task Analysis**
|
||||
- Review task complexity
|
||||
- Identify components
|
||||
- Detect technical challenges
|
||||
- Estimate time requirements
|
||||
|
||||
2. **Subtask Generation**
|
||||
- Create 3-7 subtasks typically
|
||||
- Each subtask 1-4 hours
|
||||
- Logical implementation order
|
||||
- Clear acceptance criteria
|
||||
|
||||
3. **Smart Breakdown**
|
||||
- Setup/configuration tasks
|
||||
- Core implementation
|
||||
- Testing components
|
||||
- Integration steps
|
||||
- Documentation updates
|
||||
|
||||
## Enhanced Features
|
||||
|
||||
Based on task type:
|
||||
- **Feature**: Setup → Implement → Test → Integrate
|
||||
- **Bug Fix**: Reproduce → Diagnose → Fix → Verify
|
||||
- **Refactor**: Analyze → Plan → Refactor → Validate
|
||||
|
||||
## Post-Expansion
|
||||
|
||||
After expansion:
|
||||
1. Show subtask hierarchy
|
||||
2. Update time estimates
|
||||
3. Suggest implementation order
|
||||
4. Highlight critical path
|
||||
@@ -0,0 +1,81 @@
|
||||
Automatically fix dependency issues found during validation.
|
||||
|
||||
## Automatic Dependency Repair
|
||||
|
||||
Intelligently fixes common dependency problems while preserving project logic.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master fix-dependencies
|
||||
```
|
||||
|
||||
## What Gets Fixed
|
||||
|
||||
### 1. **Auto-Fixable Issues**
|
||||
- Remove references to deleted tasks
|
||||
- Break simple circular dependencies
|
||||
- Remove self-dependencies
|
||||
- Clean up duplicate dependencies
|
||||
|
||||
### 2. **Smart Resolutions**
|
||||
- Reorder dependencies to maintain logic
|
||||
- Suggest task merging for over-dependent tasks
|
||||
- Flatten unnecessary dependency chains
|
||||
- Remove redundant transitive dependencies
|
||||
|
||||
### 3. **Manual Review Required**
|
||||
- Complex circular dependencies
|
||||
- Critical path modifications
|
||||
- Business logic dependencies
|
||||
- High-impact changes
|
||||
|
||||
## Fix Process
|
||||
|
||||
1. **Analysis Phase**
|
||||
- Run validation check
|
||||
- Categorize issues by type
|
||||
- Determine fix strategy
|
||||
|
||||
2. **Execution Phase**
|
||||
- Apply automatic fixes
|
||||
- Log all changes made
|
||||
- Preserve task relationships
|
||||
|
||||
3. **Verification Phase**
|
||||
- Re-validate after fixes
|
||||
- Show before/after comparison
|
||||
- Highlight manual fixes needed
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Preserves intended task flow
|
||||
- Minimal disruption approach
|
||||
- Creates fix history/log
|
||||
- Suggests manual interventions
|
||||
|
||||
## Output Example
|
||||
|
||||
```
|
||||
Dependency Auto-Fix Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Fixed Automatically:
|
||||
✅ Removed 2 references to deleted tasks
|
||||
✅ Resolved 1 self-dependency
|
||||
✅ Cleaned 3 redundant dependencies
|
||||
|
||||
Manual Review Needed:
|
||||
⚠️ Complex circular dependency: #12 → #15 → #18 → #12
|
||||
Suggestion: Make #15 not depend on #12
|
||||
⚠️ Task #45 has 8 dependencies
|
||||
Suggestion: Break into subtasks
|
||||
|
||||
Run '/project:tm/validate-dependencies' to verify fixes
|
||||
```
|
||||
|
||||
## Safety
|
||||
|
||||
- Preview mode available
|
||||
- Rollback capability
|
||||
- Change logging
|
||||
- No data loss
|
||||
121
assets/claude/commands/tm/generate/generate-tasks.md
Normal file
121
assets/claude/commands/tm/generate/generate-tasks.md
Normal file
@@ -0,0 +1,121 @@
|
||||
Generate individual task files from tasks.json.
|
||||
|
||||
## Task File Generation
|
||||
|
||||
Creates separate markdown files for each task, perfect for AI agents or documentation.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master generate
|
||||
```
|
||||
|
||||
## What It Creates
|
||||
|
||||
For each task, generates a file like `task_001.txt`:
|
||||
|
||||
```
|
||||
Task ID: 1
|
||||
Title: Implement user authentication
|
||||
Status: pending
|
||||
Priority: high
|
||||
Dependencies: []
|
||||
Created: 2024-01-15
|
||||
Complexity: 7
|
||||
|
||||
## Description
|
||||
Create a secure user authentication system with login, logout, and session management.
|
||||
|
||||
## Details
|
||||
- Use JWT tokens for session management
|
||||
- Implement secure password hashing
|
||||
- Add remember me functionality
|
||||
- Include password reset flow
|
||||
|
||||
## Test Strategy
|
||||
- Unit tests for auth functions
|
||||
- Integration tests for login flow
|
||||
- Security testing for vulnerabilities
|
||||
- Performance tests for concurrent logins
|
||||
|
||||
## Subtasks
|
||||
1.1 Setup authentication framework (pending)
|
||||
1.2 Create login endpoints (pending)
|
||||
1.3 Implement session management (pending)
|
||||
1.4 Add password reset (pending)
|
||||
```
|
||||
|
||||
## File Organization
|
||||
|
||||
Creates structure:
|
||||
```
|
||||
.taskmaster/
|
||||
└── tasks/
|
||||
├── task_001.txt
|
||||
├── task_002.txt
|
||||
├── task_003.txt
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Consistent Formatting**
|
||||
- Standardized structure
|
||||
- Clear sections
|
||||
- AI-readable format
|
||||
- Markdown compatible
|
||||
|
||||
2. **Contextual Information**
|
||||
- Full task details
|
||||
- Related task references
|
||||
- Progress indicators
|
||||
- Implementation notes
|
||||
|
||||
3. **Incremental Updates**
|
||||
- Only regenerate changed tasks
|
||||
- Preserve custom additions
|
||||
- Track generation timestamp
|
||||
- Version control friendly
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **AI Context**: Provide task context to AI assistants
|
||||
- **Documentation**: Standalone task documentation
|
||||
- **Archival**: Task history preservation
|
||||
- **Sharing**: Send specific tasks to team members
|
||||
- **Review**: Easier task review process
|
||||
|
||||
## Generation Options
|
||||
|
||||
Based on arguments:
|
||||
- Filter by status
|
||||
- Include/exclude completed
|
||||
- Custom templates
|
||||
- Different formats
|
||||
|
||||
## Post-Generation
|
||||
|
||||
```
|
||||
Task File Generation Complete
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Generated: 45 task files
|
||||
Location: .taskmaster/tasks/
|
||||
Total size: 156 KB
|
||||
|
||||
New files: 5
|
||||
Updated files: 12
|
||||
Unchanged: 28
|
||||
|
||||
Ready for:
|
||||
- AI agent consumption
|
||||
- Version control
|
||||
- Team distribution
|
||||
```
|
||||
|
||||
## Integration Benefits
|
||||
|
||||
- Git-trackable task history
|
||||
- Easy task sharing
|
||||
- AI tool compatibility
|
||||
- Offline task access
|
||||
- Backup redundancy
|
||||
81
assets/claude/commands/tm/help.md
Normal file
81
assets/claude/commands/tm/help.md
Normal file
@@ -0,0 +1,81 @@
|
||||
Show help for Task Master commands.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Display help for Task Master commands. If arguments provided, show specific command help.
|
||||
|
||||
## Task Master Command Help
|
||||
|
||||
### Quick Navigation
|
||||
|
||||
Type `/project:tm/` and use tab completion to explore all commands.
|
||||
|
||||
### Command Categories
|
||||
|
||||
#### 🚀 Setup & Installation
|
||||
- `/project:tm/setup/install` - Comprehensive installation guide
|
||||
- `/project:tm/setup/quick-install` - One-line global install
|
||||
|
||||
#### 📋 Project Setup
|
||||
- `/project:tm/init` - Initialize new project
|
||||
- `/project:tm/init/quick` - Quick setup with auto-confirm
|
||||
- `/project:tm/models` - View AI configuration
|
||||
- `/project:tm/models/setup` - Configure AI providers
|
||||
|
||||
#### 🎯 Task Generation
|
||||
- `/project:tm/parse-prd` - Generate tasks from PRD
|
||||
- `/project:tm/parse-prd/with-research` - Enhanced parsing
|
||||
- `/project:tm/generate` - Create task files
|
||||
|
||||
#### 📝 Task Management
|
||||
- `/project:tm/list` - List tasks (natural language filters)
|
||||
- `/project:tm/show <id>` - Display task details
|
||||
- `/project:tm/add-task` - Create new task
|
||||
- `/project:tm/update` - Update tasks naturally
|
||||
- `/project:tm/next` - Get next task recommendation
|
||||
|
||||
#### 🔄 Status Management
|
||||
- `/project:tm/set-status/to-pending <id>`
|
||||
- `/project:tm/set-status/to-in-progress <id>`
|
||||
- `/project:tm/set-status/to-done <id>`
|
||||
- `/project:tm/set-status/to-review <id>`
|
||||
- `/project:tm/set-status/to-deferred <id>`
|
||||
- `/project:tm/set-status/to-cancelled <id>`
|
||||
|
||||
#### 🔍 Analysis & Breakdown
|
||||
- `/project:tm/analyze-complexity` - Analyze task complexity
|
||||
- `/project:tm/expand <id>` - Break down complex task
|
||||
- `/project:tm/expand/all` - Expand all eligible tasks
|
||||
|
||||
#### 🔗 Dependencies
|
||||
- `/project:tm/add-dependency` - Add task dependency
|
||||
- `/project:tm/remove-dependency` - Remove dependency
|
||||
- `/project:tm/validate-dependencies` - Check for issues
|
||||
|
||||
#### 🤖 Workflows
|
||||
- `/project:tm/workflows/smart-flow` - Intelligent workflows
|
||||
- `/project:tm/workflows/pipeline` - Command chaining
|
||||
- `/project:tm/workflows/auto-implement` - Auto-implementation
|
||||
|
||||
#### 📊 Utilities
|
||||
- `/project:tm/utils/analyze` - Project analysis
|
||||
- `/project:tm/status` - Project dashboard
|
||||
- `/project:tm/learn` - Interactive learning
|
||||
|
||||
### Natural Language Examples
|
||||
|
||||
```
|
||||
/project:tm/list pending high priority
|
||||
/project:tm/update mark all API tasks as done
|
||||
/project:tm/add-task create login system with OAuth
|
||||
/project:tm/show current
|
||||
```
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. Install: `/project:tm/setup/quick-install`
|
||||
2. Initialize: `/project:tm/init/quick`
|
||||
3. Learn: `/project:tm/learn start`
|
||||
4. Work: `/project:tm/workflows/smart-flow`
|
||||
|
||||
For detailed command info: `/project:tm/help <command-name>`
|
||||
46
assets/claude/commands/tm/init/init-project-quick.md
Normal file
46
assets/claude/commands/tm/init/init-project-quick.md
Normal file
@@ -0,0 +1,46 @@
|
||||
Quick initialization with auto-confirmation.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Initialize a Task Master project without prompts, accepting all defaults.
|
||||
|
||||
## Quick Setup
|
||||
|
||||
```bash
|
||||
task-master init -y
|
||||
```
|
||||
|
||||
## What It Does
|
||||
|
||||
1. Creates `.taskmaster/` directory structure
|
||||
2. Initializes empty `tasks.json`
|
||||
3. Sets up default configuration
|
||||
4. Uses directory name as project name
|
||||
5. Skips all confirmation prompts
|
||||
|
||||
## Smart Defaults
|
||||
|
||||
- Project name: Current directory name
|
||||
- Description: "Task Master Project"
|
||||
- Model config: Existing environment vars
|
||||
- Task structure: Standard format
|
||||
|
||||
## Next Steps
|
||||
|
||||
After quick init:
|
||||
1. Configure AI models if needed:
|
||||
```
|
||||
/project:tm/models/setup
|
||||
```
|
||||
|
||||
2. Parse PRD if available:
|
||||
```
|
||||
/project:tm/parse-prd <file>
|
||||
```
|
||||
|
||||
3. Or create first task:
|
||||
```
|
||||
/project:tm/add-task create initial setup
|
||||
```
|
||||
|
||||
Perfect for rapid project setup!
|
||||
50
assets/claude/commands/tm/init/init-project.md
Normal file
50
assets/claude/commands/tm/init/init-project.md
Normal file
@@ -0,0 +1,50 @@
|
||||
Initialize a new Task Master project.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse arguments to determine initialization preferences.
|
||||
|
||||
## Initialization Process
|
||||
|
||||
1. **Parse Arguments**
|
||||
- PRD file path (if provided)
|
||||
- Project name
|
||||
- Auto-confirm flag (-y)
|
||||
|
||||
2. **Project Setup**
|
||||
```bash
|
||||
task-master init
|
||||
```
|
||||
|
||||
3. **Smart Initialization**
|
||||
- Detect existing project files
|
||||
- Suggest project name from directory
|
||||
- Check for git repository
|
||||
- Verify AI provider configuration
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Based on arguments:
|
||||
- `quick` / `-y` → Skip confirmations
|
||||
- `<file.md>` → Use as PRD after init
|
||||
- `--name=<name>` → Set project name
|
||||
- `--description=<desc>` → Set description
|
||||
|
||||
## Post-Initialization
|
||||
|
||||
After successful init:
|
||||
1. Show project structure created
|
||||
2. Verify AI models configured
|
||||
3. Suggest next steps:
|
||||
- Parse PRD if available
|
||||
- Configure AI providers
|
||||
- Set up git hooks
|
||||
- Create first tasks
|
||||
|
||||
## Integration
|
||||
|
||||
If PRD file provided:
|
||||
```
|
||||
/project:tm/init my-prd.md
|
||||
→ Automatically runs parse-prd after init
|
||||
```
|
||||
103
assets/claude/commands/tm/learn.md
Normal file
103
assets/claude/commands/tm/learn.md
Normal file
@@ -0,0 +1,103 @@
|
||||
Learn about Task Master capabilities through interactive exploration.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Interactive Task Master Learning
|
||||
|
||||
Based on your input, I'll help you discover capabilities:
|
||||
|
||||
### 1. **What are you trying to do?**
|
||||
|
||||
If $ARGUMENTS contains:
|
||||
- "start" / "begin" → Show project initialization workflows
|
||||
- "manage" / "organize" → Show task management commands
|
||||
- "automate" / "auto" → Show automation workflows
|
||||
- "analyze" / "report" → Show analysis tools
|
||||
- "fix" / "problem" → Show troubleshooting commands
|
||||
- "fast" / "quick" → Show efficiency shortcuts
|
||||
|
||||
### 2. **Intelligent Suggestions**
|
||||
|
||||
Based on your project state:
|
||||
|
||||
**No tasks yet?**
|
||||
```
|
||||
You'll want to start with:
|
||||
1. /project:task-master:init <prd-file>
|
||||
→ Creates tasks from requirements
|
||||
|
||||
2. /project:task-master:parse-prd <file>
|
||||
→ Alternative task generation
|
||||
|
||||
Try: /project:task-master:init demo-prd.md
|
||||
```
|
||||
|
||||
**Have tasks?**
|
||||
Let me analyze what you might need...
|
||||
- Many pending tasks? → Learn sprint planning
|
||||
- Complex tasks? → Learn task expansion
|
||||
- Daily work? → Learn workflow automation
|
||||
|
||||
### 3. **Command Discovery**
|
||||
|
||||
**By Category:**
|
||||
- 📋 Task Management: list, show, add, update, complete
|
||||
- 🔄 Workflows: auto-implement, sprint-plan, daily-standup
|
||||
- 🛠️ Utilities: check-health, complexity-report, sync-memory
|
||||
- 🔍 Analysis: validate-deps, show dependencies
|
||||
|
||||
**By Scenario:**
|
||||
- "I want to see what to work on" → `/project:task-master:next`
|
||||
- "I need to break this down" → `/project:task-master:expand <id>`
|
||||
- "Show me everything" → `/project:task-master:status`
|
||||
- "Just do it for me" → `/project:workflows:auto-implement`
|
||||
|
||||
### 4. **Power User Patterns**
|
||||
|
||||
**Command Chaining:**
|
||||
```
|
||||
/project:task-master:next
|
||||
/project:task-master:start <id>
|
||||
/project:workflows:auto-implement
|
||||
```
|
||||
|
||||
**Smart Filters:**
|
||||
```
|
||||
/project:task-master:list pending high
|
||||
/project:task-master:list blocked
|
||||
/project:task-master:list 1-5 tree
|
||||
```
|
||||
|
||||
**Automation:**
|
||||
```
|
||||
/project:workflows:pipeline init → expand-all → sprint-plan
|
||||
```
|
||||
|
||||
### 5. **Learning Path**
|
||||
|
||||
Based on your experience level:
|
||||
|
||||
**Beginner Path:**
|
||||
1. init → Create project
|
||||
2. status → Understand state
|
||||
3. next → Find work
|
||||
4. complete → Finish task
|
||||
|
||||
**Intermediate Path:**
|
||||
1. expand → Break down complex tasks
|
||||
2. sprint-plan → Organize work
|
||||
3. complexity-report → Understand difficulty
|
||||
4. validate-deps → Ensure consistency
|
||||
|
||||
**Advanced Path:**
|
||||
1. pipeline → Chain operations
|
||||
2. smart-flow → Context-aware automation
|
||||
3. Custom commands → Extend the system
|
||||
|
||||
### 6. **Try This Now**
|
||||
|
||||
Based on what you asked about, try:
|
||||
[Specific command suggestion based on $ARGUMENTS]
|
||||
|
||||
Want to learn more about a specific command?
|
||||
Type: /project:help <command-name>
|
||||
39
assets/claude/commands/tm/list/list-tasks-by-status.md
Normal file
39
assets/claude/commands/tm/list/list-tasks-by-status.md
Normal file
@@ -0,0 +1,39 @@
|
||||
List tasks filtered by a specific status.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the status from arguments and list only tasks matching that status.
|
||||
|
||||
## Status Options
|
||||
- `pending` - Not yet started
|
||||
- `in-progress` - Currently being worked on
|
||||
- `done` - Completed
|
||||
- `review` - Awaiting review
|
||||
- `deferred` - Postponed
|
||||
- `cancelled` - Cancelled
|
||||
|
||||
## Execution
|
||||
|
||||
Based on $ARGUMENTS, run:
|
||||
```bash
|
||||
task-master list --status=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Enhanced Display
|
||||
|
||||
For the filtered results:
|
||||
- Group by priority within the status
|
||||
- Show time in current status
|
||||
- Highlight tasks approaching deadlines
|
||||
- Display blockers and dependencies
|
||||
- Suggest next actions for each status group
|
||||
|
||||
## Intelligent Insights
|
||||
|
||||
Based on the status filter:
|
||||
- **Pending**: Show recommended start order
|
||||
- **In-Progress**: Display idle time warnings
|
||||
- **Done**: Show newly unblocked tasks
|
||||
- **Review**: Indicate review duration
|
||||
- **Deferred**: Show reactivation criteria
|
||||
- **Cancelled**: Display impact analysis
|
||||
29
assets/claude/commands/tm/list/list-tasks-with-subtasks.md
Normal file
29
assets/claude/commands/tm/list/list-tasks-with-subtasks.md
Normal file
@@ -0,0 +1,29 @@
|
||||
List all tasks including their subtasks in a hierarchical view.
|
||||
|
||||
This command shows all tasks with their nested subtasks, providing a complete project overview.
|
||||
|
||||
## Execution
|
||||
|
||||
Run the Task Master list command with subtasks flag:
|
||||
```bash
|
||||
task-master list --with-subtasks
|
||||
```
|
||||
|
||||
## Enhanced Display
|
||||
|
||||
I'll organize the output to show:
|
||||
- Parent tasks with clear indicators
|
||||
- Nested subtasks with proper indentation
|
||||
- Status badges for quick scanning
|
||||
- Dependencies and blockers highlighted
|
||||
- Progress indicators for tasks with subtasks
|
||||
|
||||
## Smart Filtering
|
||||
|
||||
Based on the task hierarchy:
|
||||
- Show completion percentage for parent tasks
|
||||
- Highlight blocked subtask chains
|
||||
- Group by functional areas
|
||||
- Indicate critical path items
|
||||
|
||||
This gives you a complete tree view of your project structure.
|
||||
43
assets/claude/commands/tm/list/list-tasks.md
Normal file
43
assets/claude/commands/tm/list/list-tasks.md
Normal file
@@ -0,0 +1,43 @@
|
||||
List tasks with intelligent argument parsing.
|
||||
|
||||
Parse arguments to determine filters and display options:
|
||||
- Status: pending, in-progress, done, review, deferred, cancelled
|
||||
- Priority: high, medium, low (or priority:high)
|
||||
- Special: subtasks, tree, dependencies, blocked
|
||||
- IDs: Direct numbers (e.g., "1,3,5" or "1-5")
|
||||
- Complex: "pending high" = pending AND high priority
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Let me parse your request intelligently:
|
||||
|
||||
1. **Detect Filter Intent**
|
||||
- If arguments contain status keywords → filter by status
|
||||
- If arguments contain priority → filter by priority
|
||||
- If arguments contain "subtasks" → include subtasks
|
||||
- If arguments contain "tree" → hierarchical view
|
||||
- If arguments contain numbers → show specific tasks
|
||||
- If arguments contain "blocked" → show blocked tasks only
|
||||
|
||||
2. **Smart Combinations**
|
||||
Examples of what I understand:
|
||||
- "pending high" → pending tasks with high priority
|
||||
- "done today" → tasks completed today
|
||||
- "blocked" → tasks with unmet dependencies
|
||||
- "1-5" → tasks 1 through 5
|
||||
- "subtasks tree" → hierarchical view with subtasks
|
||||
|
||||
3. **Execute Appropriate Query**
|
||||
Based on parsed intent, run the most specific task-master command
|
||||
|
||||
4. **Enhanced Display**
|
||||
- Group by relevant criteria
|
||||
- Show most important information first
|
||||
- Use visual indicators for quick scanning
|
||||
- Include relevant metrics
|
||||
|
||||
5. **Intelligent Suggestions**
|
||||
Based on what you're viewing, suggest next actions:
|
||||
- Many pending? → Suggest priority order
|
||||
- Many blocked? → Show dependency resolution
|
||||
- Looking at specific tasks? → Show related tasks
|
||||
51
assets/claude/commands/tm/models/setup-models.md
Normal file
51
assets/claude/commands/tm/models/setup-models.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Run interactive setup to configure AI models.
|
||||
|
||||
## Interactive Model Configuration
|
||||
|
||||
Guides you through setting up AI providers for Task Master.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master models --setup
|
||||
```
|
||||
|
||||
## Setup Process
|
||||
|
||||
1. **Environment Check**
|
||||
- Detect existing API keys
|
||||
- Show current configuration
|
||||
- Identify missing providers
|
||||
|
||||
2. **Provider Selection**
|
||||
- Choose main provider (required)
|
||||
- Select research provider (recommended)
|
||||
- Configure fallback (optional)
|
||||
|
||||
3. **API Key Configuration**
|
||||
- Prompt for missing keys
|
||||
- Validate key format
|
||||
- Test connectivity
|
||||
- Save configuration
|
||||
|
||||
## Smart Recommendations
|
||||
|
||||
Based on your needs:
|
||||
- **For best results**: Claude + Perplexity
|
||||
- **Budget conscious**: GPT-3.5 + Perplexity
|
||||
- **Maximum capability**: GPT-4 + Perplexity + Claude fallback
|
||||
|
||||
## Configuration Storage
|
||||
|
||||
Keys can be stored in:
|
||||
1. Environment variables (recommended)
|
||||
2. `.env` file in project
|
||||
3. Global `.taskmaster/config`
|
||||
|
||||
## Post-Setup
|
||||
|
||||
After configuration:
|
||||
- Test each provider
|
||||
- Show usage examples
|
||||
- Suggest next steps
|
||||
- Verify parse-prd works
|
||||
51
assets/claude/commands/tm/models/view-models.md
Normal file
51
assets/claude/commands/tm/models/view-models.md
Normal file
@@ -0,0 +1,51 @@
|
||||
View current AI model configuration.
|
||||
|
||||
## Model Configuration Display
|
||||
|
||||
Shows the currently configured AI providers and models for Task Master.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master models
|
||||
```
|
||||
|
||||
## Information Displayed
|
||||
|
||||
1. **Main Provider**
|
||||
- Model ID and name
|
||||
- API key status (configured/missing)
|
||||
- Usage: Primary task generation
|
||||
|
||||
2. **Research Provider**
|
||||
- Model ID and name
|
||||
- API key status
|
||||
- Usage: Enhanced research mode
|
||||
|
||||
3. **Fallback Provider**
|
||||
- Model ID and name
|
||||
- API key status
|
||||
- Usage: Backup when main fails
|
||||
|
||||
## Visual Status
|
||||
|
||||
```
|
||||
Task Master AI Model Configuration
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Main: ✅ claude-3-5-sonnet (configured)
|
||||
Research: ✅ perplexity-sonar (configured)
|
||||
Fallback: ⚠️ Not configured (optional)
|
||||
|
||||
Available Models:
|
||||
- claude-3-5-sonnet
|
||||
- gpt-4-turbo
|
||||
- gpt-3.5-turbo
|
||||
- perplexity-sonar
|
||||
```
|
||||
|
||||
## Next Actions
|
||||
|
||||
Based on configuration:
|
||||
- If missing API keys → Suggest setup
|
||||
- If no research model → Explain benefits
|
||||
- If all configured → Show usage tips
|
||||
66
assets/claude/commands/tm/next/next-task.md
Normal file
66
assets/claude/commands/tm/next/next-task.md
Normal file
@@ -0,0 +1,66 @@
|
||||
Intelligently determine and prepare the next action based on comprehensive context.
|
||||
|
||||
This enhanced version of 'next' considers:
|
||||
- Current task states
|
||||
- Recent activity
|
||||
- Time constraints
|
||||
- Dependencies
|
||||
- Your working patterns
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Next Action
|
||||
|
||||
### 1. **Context Gathering**
|
||||
Let me analyze the current situation:
|
||||
- Active tasks (in-progress)
|
||||
- Recently completed tasks
|
||||
- Blocked tasks
|
||||
- Time since last activity
|
||||
- Arguments provided: $ARGUMENTS
|
||||
|
||||
### 2. **Smart Decision Tree**
|
||||
|
||||
**If you have an in-progress task:**
|
||||
- Has it been idle > 2 hours? → Suggest resuming or switching
|
||||
- Near completion? → Show remaining steps
|
||||
- Blocked? → Find alternative task
|
||||
|
||||
**If no in-progress tasks:**
|
||||
- Unblocked high-priority tasks? → Start highest
|
||||
- Complex tasks need breakdown? → Suggest expansion
|
||||
- All tasks blocked? → Show dependency resolution
|
||||
|
||||
**Special arguments handling:**
|
||||
- "quick" → Find task < 2 hours
|
||||
- "easy" → Find low complexity task
|
||||
- "important" → Find high priority regardless of complexity
|
||||
- "continue" → Resume last worked task
|
||||
|
||||
### 3. **Preparation Workflow**
|
||||
|
||||
Based on selected task:
|
||||
1. Show full context and history
|
||||
2. Set up development environment
|
||||
3. Run relevant tests
|
||||
4. Open related files
|
||||
5. Show similar completed tasks
|
||||
6. Estimate completion time
|
||||
|
||||
### 4. **Alternative Suggestions**
|
||||
|
||||
Always provide options:
|
||||
- Primary recommendation
|
||||
- Quick alternative (< 1 hour)
|
||||
- Strategic option (unblocks most tasks)
|
||||
- Learning option (new technology/skill)
|
||||
|
||||
### 5. **Workflow Integration**
|
||||
|
||||
Seamlessly connect to:
|
||||
- `/project:task-master:start [selected]`
|
||||
- `/project:workflows:auto-implement`
|
||||
- `/project:task-master:expand` (if complex)
|
||||
- `/project:utils:complexity-report` (if unsure)
|
||||
|
||||
The goal: Zero friction from decision to implementation.
|
||||
@@ -0,0 +1,48 @@
|
||||
Parse PRD with enhanced research mode for better task generation.
|
||||
|
||||
Arguments: $ARGUMENTS (PRD file path)
|
||||
|
||||
## Research-Enhanced Parsing
|
||||
|
||||
Uses the research AI provider (typically Perplexity) for more comprehensive task generation with current best practices.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master parse-prd --input=$ARGUMENTS --research
|
||||
```
|
||||
|
||||
## Research Benefits
|
||||
|
||||
1. **Current Best Practices**
|
||||
- Latest framework patterns
|
||||
- Security considerations
|
||||
- Performance optimizations
|
||||
- Accessibility requirements
|
||||
|
||||
2. **Technical Deep Dive**
|
||||
- Implementation approaches
|
||||
- Library recommendations
|
||||
- Architecture patterns
|
||||
- Testing strategies
|
||||
|
||||
3. **Comprehensive Coverage**
|
||||
- Edge cases consideration
|
||||
- Error handling tasks
|
||||
- Monitoring setup
|
||||
- Deployment tasks
|
||||
|
||||
## Enhanced Output
|
||||
|
||||
Research mode typically:
|
||||
- Generates more detailed tasks
|
||||
- Includes industry standards
|
||||
- Adds compliance considerations
|
||||
- Suggests modern tooling
|
||||
|
||||
## When to Use
|
||||
|
||||
- New technology domains
|
||||
- Complex requirements
|
||||
- Regulatory compliance needed
|
||||
- Best practices crucial
|
||||
49
assets/claude/commands/tm/parse-prd/parse-prd.md
Normal file
49
assets/claude/commands/tm/parse-prd/parse-prd.md
Normal file
@@ -0,0 +1,49 @@
|
||||
Parse a PRD document to generate tasks.
|
||||
|
||||
Arguments: $ARGUMENTS (PRD file path)
|
||||
|
||||
## Intelligent PRD Parsing
|
||||
|
||||
Analyzes your requirements document and generates a complete task breakdown.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master parse-prd --input=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Parsing Process
|
||||
|
||||
1. **Document Analysis**
|
||||
- Extract key requirements
|
||||
- Identify technical components
|
||||
- Detect dependencies
|
||||
- Estimate complexity
|
||||
|
||||
2. **Task Generation**
|
||||
- Create 10-15 tasks by default
|
||||
- Include implementation tasks
|
||||
- Add testing tasks
|
||||
- Include documentation tasks
|
||||
- Set logical dependencies
|
||||
|
||||
3. **Smart Enhancements**
|
||||
- Group related functionality
|
||||
- Set appropriate priorities
|
||||
- Add acceptance criteria
|
||||
- Include test strategies
|
||||
|
||||
## Options
|
||||
|
||||
Parse arguments for modifiers:
|
||||
- Number after filename → `--num-tasks`
|
||||
- `research` → Use research mode
|
||||
- `comprehensive` → Generate more tasks
|
||||
|
||||
## Post-Generation
|
||||
|
||||
After parsing:
|
||||
1. Display task summary
|
||||
2. Show dependency graph
|
||||
3. Suggest task expansion for complex items
|
||||
4. Recommend sprint planning
|
||||
@@ -0,0 +1,62 @@
|
||||
Remove a dependency between tasks.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the task IDs to remove dependency relationship.
|
||||
|
||||
## Removing Dependencies
|
||||
|
||||
Removes a dependency relationship, potentially unblocking tasks.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Parse natural language or IDs:
|
||||
- "remove dependency between 5 and 3"
|
||||
- "5 no longer needs 3"
|
||||
- "unblock 5 from 3"
|
||||
- "5 3" → remove dependency of 5 on 3
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master remove-dependency --id=<task-id> --depends-on=<dependency-id>
|
||||
```
|
||||
|
||||
## Pre-Removal Checks
|
||||
|
||||
1. **Verify dependency exists**
|
||||
2. **Check impact on task flow**
|
||||
3. **Warn if it breaks logical sequence**
|
||||
4. **Show what will be unblocked**
|
||||
|
||||
## Smart Analysis
|
||||
|
||||
Before removing:
|
||||
- Show why dependency might have existed
|
||||
- Check if removal makes tasks executable
|
||||
- Verify no critical path disruption
|
||||
- Suggest alternative dependencies
|
||||
|
||||
## Post-Removal
|
||||
|
||||
After removing:
|
||||
1. Show updated task status
|
||||
2. List newly unblocked tasks
|
||||
3. Update project timeline
|
||||
4. Suggest next actions
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Confirm if removing critical dependency
|
||||
- Show tasks that become immediately actionable
|
||||
- Warn about potential issues
|
||||
- Keep removal history
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/remove-dependency 5 from 3
|
||||
→ Removed: Task #5 no longer depends on #3
|
||||
→ Task #5 is now UNBLOCKED and ready to start
|
||||
→ Warning: Consider if #5 still needs #2 completed first
|
||||
```
|
||||
84
assets/claude/commands/tm/remove-subtask/remove-subtask.md
Normal file
84
assets/claude/commands/tm/remove-subtask/remove-subtask.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Remove a subtask from its parent task.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse subtask ID to remove, with option to convert to standalone task.
|
||||
|
||||
## Removing Subtasks
|
||||
|
||||
Remove a subtask and optionally convert it back to a standalone task.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "remove subtask 5.1"
|
||||
- "delete 5.1"
|
||||
- "convert 5.1 to task" → remove and convert
|
||||
- "5.1 standalone" → convert to standalone
|
||||
|
||||
## Execution Options
|
||||
|
||||
### 1. Delete Subtask
|
||||
```bash
|
||||
task-master remove-subtask --id=<parentId.subtaskId>
|
||||
```
|
||||
|
||||
### 2. Convert to Standalone
|
||||
```bash
|
||||
task-master remove-subtask --id=<parentId.subtaskId> --convert
|
||||
```
|
||||
|
||||
## Pre-Removal Checks
|
||||
|
||||
1. **Validate Subtask**
|
||||
- Verify subtask exists
|
||||
- Check completion status
|
||||
- Review dependencies
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Other subtasks that depend on it
|
||||
- Parent task implications
|
||||
- Data that will be lost
|
||||
|
||||
## Removal Process
|
||||
|
||||
### For Deletion:
|
||||
1. Confirm if subtask has work done
|
||||
2. Update parent task estimates
|
||||
3. Remove subtask and its data
|
||||
4. Clean up dependencies
|
||||
|
||||
### For Conversion:
|
||||
1. Assign new standalone task ID
|
||||
2. Preserve all task data
|
||||
3. Update dependency references
|
||||
4. Maintain task history
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Warn if subtask is in-progress
|
||||
- Show impact on parent task
|
||||
- Preserve important data
|
||||
- Update related estimates
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/remove-subtask 5.1
|
||||
→ Warning: Subtask #5.1 is in-progress
|
||||
→ This will delete all subtask data
|
||||
→ Parent task #5 will be updated
|
||||
Confirm deletion? (y/n)
|
||||
|
||||
/project:tm/remove-subtask 5.1 convert
|
||||
→ Converting subtask #5.1 to standalone task #89
|
||||
→ Preserved: All task data and history
|
||||
→ Updated: 2 dependency references
|
||||
→ New task #89 is now independent
|
||||
```
|
||||
|
||||
## Post-Removal
|
||||
|
||||
- Update parent task status
|
||||
- Recalculate estimates
|
||||
- Show updated hierarchy
|
||||
- Suggest next actions
|
||||
107
assets/claude/commands/tm/remove-task/remove-task.md
Normal file
107
assets/claude/commands/tm/remove-task/remove-task.md
Normal file
@@ -0,0 +1,107 @@
|
||||
Remove a task permanently from the project.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
Delete a task and handle all its relationships properly.
|
||||
|
||||
## Task Removal
|
||||
|
||||
Permanently removes a task while maintaining project integrity.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "remove task 5"
|
||||
- "delete 5"
|
||||
- "5" → remove task 5
|
||||
- Can include "-y" for auto-confirm
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master remove-task --id=<id> [-y]
|
||||
```
|
||||
|
||||
## Pre-Removal Analysis
|
||||
|
||||
1. **Task Details**
|
||||
- Current status
|
||||
- Work completed
|
||||
- Time invested
|
||||
- Associated data
|
||||
|
||||
2. **Relationship Check**
|
||||
- Tasks that depend on this
|
||||
- Dependencies this task has
|
||||
- Subtasks that will be removed
|
||||
- Blocking implications
|
||||
|
||||
3. **Impact Assessment**
|
||||
```
|
||||
Task Removal Impact
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
Task: #5 "Implement authentication" (in-progress)
|
||||
Status: 60% complete (~8 hours work)
|
||||
|
||||
Will affect:
|
||||
- 3 tasks depend on this (will be blocked)
|
||||
- Has 4 subtasks (will be deleted)
|
||||
- Part of critical path
|
||||
|
||||
⚠️ This action cannot be undone
|
||||
```
|
||||
|
||||
## Smart Warnings
|
||||
|
||||
- Warn if task is in-progress
|
||||
- Show dependent tasks that will be blocked
|
||||
- Highlight if part of critical path
|
||||
- Note any completed work being lost
|
||||
|
||||
## Removal Process
|
||||
|
||||
1. Show comprehensive impact
|
||||
2. Require confirmation (unless -y)
|
||||
3. Update dependent task references
|
||||
4. Remove task and subtasks
|
||||
5. Clean up orphaned dependencies
|
||||
6. Log removal with timestamp
|
||||
|
||||
## Alternative Actions
|
||||
|
||||
Suggest before deletion:
|
||||
- Mark as cancelled instead
|
||||
- Convert to documentation
|
||||
- Archive task data
|
||||
- Transfer work to another task
|
||||
|
||||
## Post-Removal
|
||||
|
||||
- List affected tasks
|
||||
- Show broken dependencies
|
||||
- Update project statistics
|
||||
- Suggest dependency fixes
|
||||
- Recalculate timeline
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/remove-task 5
|
||||
→ Task #5 is in-progress with 8 hours logged
|
||||
→ 3 other tasks depend on this
|
||||
→ Suggestion: Mark as cancelled instead?
|
||||
Remove anyway? (y/n)
|
||||
|
||||
/project:tm/remove-task 5 -y
|
||||
→ Removed: Task #5 and 4 subtasks
|
||||
→ Updated: 3 task dependencies
|
||||
→ Warning: Tasks #7, #8, #9 now have missing dependency
|
||||
→ Run /project:tm/fix-dependencies to resolve
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Confirmation required
|
||||
- Impact preview
|
||||
- Removal logging
|
||||
- Suggest alternatives
|
||||
- No cascade delete of dependents
|
||||
55
assets/claude/commands/tm/set-status/to-cancelled.md
Normal file
55
assets/claude/commands/tm/set-status/to-cancelled.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Cancel a task permanently.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Cancelling a Task
|
||||
|
||||
This status indicates a task is no longer needed and won't be completed.
|
||||
|
||||
## Valid Reasons for Cancellation
|
||||
|
||||
- Requirements changed
|
||||
- Feature deprecated
|
||||
- Duplicate of another task
|
||||
- Strategic pivot
|
||||
- Technical approach invalidated
|
||||
|
||||
## Pre-Cancellation Checks
|
||||
|
||||
1. Confirm no critical dependencies
|
||||
2. Check for partial implementation
|
||||
3. Verify cancellation rationale
|
||||
4. Document lessons learned
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=cancelled
|
||||
```
|
||||
|
||||
## Cancellation Impact
|
||||
|
||||
When cancelling:
|
||||
1. **Dependency Updates**
|
||||
- Notify dependent tasks
|
||||
- Update project scope
|
||||
- Recalculate timelines
|
||||
|
||||
2. **Clean-up Actions**
|
||||
- Remove related branches
|
||||
- Archive any work done
|
||||
- Update documentation
|
||||
- Close related issues
|
||||
|
||||
3. **Learning Capture**
|
||||
- Document why cancelled
|
||||
- Note what was learned
|
||||
- Update estimation models
|
||||
- Prevent future duplicates
|
||||
|
||||
## Historical Preservation
|
||||
|
||||
- Keep for reference
|
||||
- Tag with cancellation reason
|
||||
- Link to replacement if any
|
||||
- Maintain audit trail
|
||||
47
assets/claude/commands/tm/set-status/to-deferred.md
Normal file
47
assets/claude/commands/tm/set-status/to-deferred.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Defer a task for later consideration.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Deferring a Task
|
||||
|
||||
This status indicates a task is valid but not currently actionable or prioritized.
|
||||
|
||||
## Valid Reasons for Deferral
|
||||
|
||||
- Waiting for external dependencies
|
||||
- Reprioritized for future sprint
|
||||
- Blocked by technical limitations
|
||||
- Resource constraints
|
||||
- Strategic timing considerations
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=deferred
|
||||
```
|
||||
|
||||
## Deferral Management
|
||||
|
||||
When deferring:
|
||||
1. **Document Reason**
|
||||
- Capture why it's being deferred
|
||||
- Set reactivation criteria
|
||||
- Note any partial work completed
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Check dependent tasks
|
||||
- Update project timeline
|
||||
- Notify affected stakeholders
|
||||
|
||||
3. **Future Planning**
|
||||
- Set review reminders
|
||||
- Tag for specific milestone
|
||||
- Preserve context for reactivation
|
||||
- Link to blocking issues
|
||||
|
||||
## Smart Tracking
|
||||
|
||||
- Monitor deferral duration
|
||||
- Alert when criteria met
|
||||
- Prevent scope creep
|
||||
- Regular review cycles
|
||||
44
assets/claude/commands/tm/set-status/to-done.md
Normal file
44
assets/claude/commands/tm/set-status/to-done.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Mark a task as completed.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Completing a Task
|
||||
|
||||
This command validates task completion and updates project state intelligently.
|
||||
|
||||
## Pre-Completion Checks
|
||||
|
||||
1. Verify test strategy was followed
|
||||
2. Check if all subtasks are complete
|
||||
3. Validate acceptance criteria met
|
||||
4. Ensure code is committed
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=done
|
||||
```
|
||||
|
||||
## Post-Completion Actions
|
||||
|
||||
1. **Update Dependencies**
|
||||
- Identify newly unblocked tasks
|
||||
- Update sprint progress
|
||||
- Recalculate project timeline
|
||||
|
||||
2. **Documentation**
|
||||
- Generate completion summary
|
||||
- Update CLAUDE.md with learnings
|
||||
- Log implementation approach
|
||||
|
||||
3. **Next Steps**
|
||||
- Show newly available tasks
|
||||
- Suggest logical next task
|
||||
- Update velocity metrics
|
||||
|
||||
## Celebration & Learning
|
||||
|
||||
- Show impact of completion
|
||||
- Display unblocked work
|
||||
- Recognize achievement
|
||||
- Capture lessons learned
|
||||
36
assets/claude/commands/tm/set-status/to-in-progress.md
Normal file
36
assets/claude/commands/tm/set-status/to-in-progress.md
Normal file
@@ -0,0 +1,36 @@
|
||||
Start working on a task by setting its status to in-progress.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Starting Work on Task
|
||||
|
||||
This command does more than just change status - it prepares your environment for productive work.
|
||||
|
||||
## Pre-Start Checks
|
||||
|
||||
1. Verify dependencies are met
|
||||
2. Check if another task is already in-progress
|
||||
3. Ensure task details are complete
|
||||
4. Validate test strategy exists
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=in-progress
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
After setting to in-progress:
|
||||
1. Create/checkout appropriate git branch
|
||||
2. Open relevant documentation
|
||||
3. Set up test watchers if applicable
|
||||
4. Display task details and acceptance criteria
|
||||
5. Show similar completed tasks for reference
|
||||
|
||||
## Smart Suggestions
|
||||
|
||||
- Estimated completion time based on complexity
|
||||
- Related files from similar tasks
|
||||
- Potential blockers to watch for
|
||||
- Recommended first steps
|
||||
32
assets/claude/commands/tm/set-status/to-pending.md
Normal file
32
assets/claude/commands/tm/set-status/to-pending.md
Normal file
@@ -0,0 +1,32 @@
|
||||
Set a task's status to pending.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Setting Task to Pending
|
||||
|
||||
This moves a task back to the pending state, useful for:
|
||||
- Resetting erroneously started tasks
|
||||
- Deferring work that was prematurely begun
|
||||
- Reorganizing sprint priorities
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=pending
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Before setting to pending:
|
||||
- Warn if task is currently in-progress
|
||||
- Check if this will block other tasks
|
||||
- Suggest documenting why it's being reset
|
||||
- Preserve any work already done
|
||||
|
||||
## Smart Actions
|
||||
|
||||
After setting to pending:
|
||||
- Update sprint planning if needed
|
||||
- Notify about freed resources
|
||||
- Suggest priority reassessment
|
||||
- Log the status change with context
|
||||
40
assets/claude/commands/tm/set-status/to-review.md
Normal file
40
assets/claude/commands/tm/set-status/to-review.md
Normal file
@@ -0,0 +1,40 @@
|
||||
Set a task's status to review.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Marking Task for Review
|
||||
|
||||
This status indicates work is complete but needs verification before final approval.
|
||||
|
||||
## When to Use Review Status
|
||||
|
||||
- Code complete but needs peer review
|
||||
- Implementation done but needs testing
|
||||
- Documentation written but needs proofreading
|
||||
- Design complete but needs stakeholder approval
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=review
|
||||
```
|
||||
|
||||
## Review Preparation
|
||||
|
||||
When setting to review:
|
||||
1. **Generate Review Checklist**
|
||||
- Link to PR/MR if applicable
|
||||
- Highlight key changes
|
||||
- Note areas needing attention
|
||||
- Include test results
|
||||
|
||||
2. **Documentation**
|
||||
- Update task with review notes
|
||||
- Link relevant artifacts
|
||||
- Specify reviewers if known
|
||||
|
||||
3. **Smart Actions**
|
||||
- Create review reminders
|
||||
- Track review duration
|
||||
- Suggest reviewers based on expertise
|
||||
- Prepare rollback plan if needed
|
||||
117
assets/claude/commands/tm/setup/install-taskmaster.md
Normal file
117
assets/claude/commands/tm/setup/install-taskmaster.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Check if Task Master is installed and install it if needed.
|
||||
|
||||
This command helps you get Task Master set up globally on your system.
|
||||
|
||||
## Detection and Installation Process
|
||||
|
||||
1. **Check Current Installation**
|
||||
```bash
|
||||
# Check if task-master command exists
|
||||
which task-master || echo "Task Master not found"
|
||||
|
||||
# Check npm global packages
|
||||
npm list -g task-master-ai
|
||||
```
|
||||
|
||||
2. **System Requirements Check**
|
||||
```bash
|
||||
# Verify Node.js is installed
|
||||
node --version
|
||||
|
||||
# Verify npm is installed
|
||||
npm --version
|
||||
|
||||
# Check Node version (need 16+)
|
||||
```
|
||||
|
||||
3. **Install Task Master Globally**
|
||||
If not installed, run:
|
||||
```bash
|
||||
npm install -g task-master-ai
|
||||
```
|
||||
|
||||
4. **Verify Installation**
|
||||
```bash
|
||||
# Check version
|
||||
task-master --version
|
||||
|
||||
# Verify command is available
|
||||
which task-master
|
||||
```
|
||||
|
||||
5. **Initial Setup**
|
||||
```bash
|
||||
# Initialize in current directory
|
||||
task-master init
|
||||
```
|
||||
|
||||
6. **Configure AI Provider**
|
||||
Ensure you have at least one AI provider API key set:
|
||||
```bash
|
||||
# Check current configuration
|
||||
task-master models --status
|
||||
|
||||
# If no API keys found, guide setup
|
||||
echo "You'll need at least one API key:"
|
||||
echo "- ANTHROPIC_API_KEY for Claude"
|
||||
echo "- OPENAI_API_KEY for GPT models"
|
||||
echo "- PERPLEXITY_API_KEY for research"
|
||||
echo ""
|
||||
echo "Set them in your shell profile or .env file"
|
||||
```
|
||||
|
||||
7. **Quick Test**
|
||||
```bash
|
||||
# Create a test PRD
|
||||
echo "Build a simple hello world API" > test-prd.txt
|
||||
|
||||
# Try parsing it
|
||||
task-master parse-prd test-prd.txt -n 3
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If installation fails:
|
||||
|
||||
**Permission Errors:**
|
||||
```bash
|
||||
# Try with sudo (macOS/Linux)
|
||||
sudo npm install -g task-master-ai
|
||||
|
||||
# Or fix npm permissions
|
||||
npm config set prefix ~/.npm-global
|
||||
export PATH=~/.npm-global/bin:$PATH
|
||||
```
|
||||
|
||||
**Network Issues:**
|
||||
```bash
|
||||
# Use different registry
|
||||
npm install -g task-master-ai --registry https://registry.npmjs.org/
|
||||
```
|
||||
|
||||
**Node Version Issues:**
|
||||
```bash
|
||||
# Install Node 18+ via nvm
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
```
|
||||
|
||||
## Success Confirmation
|
||||
|
||||
Once installed, you should see:
|
||||
```
|
||||
✅ Task Master v0.16.2 (or higher) installed
|
||||
✅ Command 'task-master' available globally
|
||||
✅ AI provider configured
|
||||
✅ Ready to use slash commands!
|
||||
|
||||
Try: /project:task-master:init your-prd.md
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
After installation:
|
||||
1. Run `/project:utils:check-health` to verify setup
|
||||
2. Configure AI providers with `/project:task-master:models`
|
||||
3. Start using Task Master commands!
|
||||
22
assets/claude/commands/tm/setup/quick-install-taskmaster.md
Normal file
22
assets/claude/commands/tm/setup/quick-install-taskmaster.md
Normal file
@@ -0,0 +1,22 @@
|
||||
Quick install Task Master globally if not already installed.
|
||||
|
||||
Execute this streamlined installation:
|
||||
|
||||
```bash
|
||||
# Check and install in one command
|
||||
task-master --version 2>/dev/null || npm install -g task-master-ai
|
||||
|
||||
# Verify installation
|
||||
task-master --version
|
||||
|
||||
# Quick setup check
|
||||
task-master models --status || echo "Note: You'll need to set up an AI provider API key"
|
||||
```
|
||||
|
||||
If you see "command not found" after installation, you may need to:
|
||||
1. Restart your terminal
|
||||
2. Or add npm global bin to PATH: `export PATH=$(npm bin -g):$PATH`
|
||||
|
||||
Once installed, you can use all the Task Master commands!
|
||||
|
||||
Quick test: Run `/project:help` to see all available commands.
|
||||
82
assets/claude/commands/tm/show/show-task.md
Normal file
82
assets/claude/commands/tm/show/show-task.md
Normal file
@@ -0,0 +1,82 @@
|
||||
Show detailed task information with rich context and insights.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Enhanced Task Display
|
||||
|
||||
Parse arguments to determine what to show and how.
|
||||
|
||||
### 1. **Smart Task Selection**
|
||||
|
||||
Based on $ARGUMENTS:
|
||||
- Number → Show specific task with full context
|
||||
- "current" → Show active in-progress task(s)
|
||||
- "next" → Show recommended next task
|
||||
- "blocked" → Show all blocked tasks with reasons
|
||||
- "critical" → Show critical path tasks
|
||||
- Multiple IDs → Comparative view
|
||||
|
||||
### 2. **Contextual Information**
|
||||
|
||||
For each task, intelligently include:
|
||||
|
||||
**Core Details**
|
||||
- Full task information (id, title, description, details)
|
||||
- Current status with history
|
||||
- Test strategy and acceptance criteria
|
||||
- Priority and complexity analysis
|
||||
|
||||
**Relationships**
|
||||
- Dependencies (what it needs)
|
||||
- Dependents (what needs it)
|
||||
- Parent/subtask hierarchy
|
||||
- Related tasks (similar work)
|
||||
|
||||
**Time Intelligence**
|
||||
- Created/updated timestamps
|
||||
- Time in current status
|
||||
- Estimated vs actual time
|
||||
- Historical completion patterns
|
||||
|
||||
### 3. **Visual Enhancements**
|
||||
|
||||
```
|
||||
📋 Task #45: Implement User Authentication
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Status: 🟡 in-progress (2 hours)
|
||||
Priority: 🔴 High | Complexity: 73/100
|
||||
|
||||
Dependencies: ✅ #41, ✅ #42, ⏳ #43 (blocked)
|
||||
Blocks: #46, #47, #52
|
||||
|
||||
Progress: ████████░░ 80% complete
|
||||
|
||||
Recent Activity:
|
||||
- 2h ago: Status changed to in-progress
|
||||
- 4h ago: Dependency #42 completed
|
||||
- Yesterday: Task expanded with 3 subtasks
|
||||
```
|
||||
|
||||
### 4. **Intelligent Insights**
|
||||
|
||||
Based on task analysis:
|
||||
- **Risk Assessment**: Complexity vs time remaining
|
||||
- **Bottleneck Analysis**: Is this blocking critical work?
|
||||
- **Recommendation**: Suggested approach or concerns
|
||||
- **Similar Tasks**: How others completed similar work
|
||||
|
||||
### 5. **Action Suggestions**
|
||||
|
||||
Context-aware next steps:
|
||||
- If blocked → Show how to unblock
|
||||
- If complex → Suggest expansion
|
||||
- If in-progress → Show completion checklist
|
||||
- If done → Show dependent tasks ready to start
|
||||
|
||||
### 6. **Multi-Task View**
|
||||
|
||||
When showing multiple tasks:
|
||||
- Common dependencies
|
||||
- Optimal completion order
|
||||
- Parallel work opportunities
|
||||
- Combined complexity analysis
|
||||
64
assets/claude/commands/tm/status/project-status.md
Normal file
64
assets/claude/commands/tm/status/project-status.md
Normal file
@@ -0,0 +1,64 @@
|
||||
Enhanced status command with comprehensive project insights.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Status Overview
|
||||
|
||||
### 1. **Executive Summary**
|
||||
Quick dashboard view:
|
||||
- 🏃 Active work (in-progress tasks)
|
||||
- 📊 Progress metrics (% complete, velocity)
|
||||
- 🚧 Blockers and risks
|
||||
- ⏱️ Time analysis (estimated vs actual)
|
||||
- 🎯 Sprint/milestone progress
|
||||
|
||||
### 2. **Contextual Analysis**
|
||||
|
||||
Based on $ARGUMENTS, focus on:
|
||||
- "sprint" → Current sprint progress and burndown
|
||||
- "blocked" → Dependency chains and resolution paths
|
||||
- "team" → Task distribution and workload
|
||||
- "timeline" → Schedule adherence and projections
|
||||
- "risk" → High complexity or overdue items
|
||||
|
||||
### 3. **Smart Insights**
|
||||
|
||||
**Workflow Health:**
|
||||
- Idle tasks (in-progress > 24h without updates)
|
||||
- Bottlenecks (multiple tasks waiting on same dependency)
|
||||
- Quick wins (low complexity, high impact)
|
||||
|
||||
**Predictive Analytics:**
|
||||
- Completion projections based on velocity
|
||||
- Risk of missing deadlines
|
||||
- Recommended task order for optimal flow
|
||||
|
||||
### 4. **Visual Intelligence**
|
||||
|
||||
Dynamic visualization based on data:
|
||||
```
|
||||
Sprint Progress: ████████░░ 80% (16/20 tasks)
|
||||
Velocity Trend: ↗️ +15% this week
|
||||
Blocked Tasks: 🔴 3 critical path items
|
||||
|
||||
Priority Distribution:
|
||||
High: ████████ 8 tasks (2 blocked)
|
||||
Medium: ████░░░░ 4 tasks
|
||||
Low: ██░░░░░░ 2 tasks
|
||||
```
|
||||
|
||||
### 5. **Actionable Recommendations**
|
||||
|
||||
Based on analysis:
|
||||
1. **Immediate actions** (unblock critical path)
|
||||
2. **Today's focus** (optimal task sequence)
|
||||
3. **Process improvements** (recurring patterns)
|
||||
4. **Resource needs** (skills, time, dependencies)
|
||||
|
||||
### 6. **Historical Context**
|
||||
|
||||
Compare to previous periods:
|
||||
- Velocity changes
|
||||
- Pattern recognition
|
||||
- Improvement areas
|
||||
- Success patterns to repeat
|
||||
117
assets/claude/commands/tm/sync-readme/sync-readme.md
Normal file
117
assets/claude/commands/tm/sync-readme/sync-readme.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Export tasks to README.md with professional formatting.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Generate a well-formatted README with current task information.
|
||||
|
||||
## README Synchronization
|
||||
|
||||
Creates or updates README.md with beautifully formatted task information.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Optional filters:
|
||||
- "pending" → Only pending tasks
|
||||
- "with-subtasks" → Include subtask details
|
||||
- "by-priority" → Group by priority
|
||||
- "sprint" → Current sprint only
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master sync-readme [--with-subtasks] [--status=<status>]
|
||||
```
|
||||
|
||||
## README Generation
|
||||
|
||||
### 1. **Project Header**
|
||||
```markdown
|
||||
# Project Name
|
||||
|
||||
## 📋 Task Progress
|
||||
|
||||
Last Updated: 2024-01-15 10:30 AM
|
||||
|
||||
### Summary
|
||||
- Total Tasks: 45
|
||||
- Completed: 15 (33%)
|
||||
- In Progress: 5 (11%)
|
||||
- Pending: 25 (56%)
|
||||
```
|
||||
|
||||
### 2. **Task Sections**
|
||||
Organized by status or priority:
|
||||
- Progress indicators
|
||||
- Task descriptions
|
||||
- Dependencies noted
|
||||
- Time estimates
|
||||
|
||||
### 3. **Visual Elements**
|
||||
- Progress bars
|
||||
- Status badges
|
||||
- Priority indicators
|
||||
- Completion checkmarks
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Intelligent Grouping**
|
||||
- By feature area
|
||||
- By sprint/milestone
|
||||
- By assigned developer
|
||||
- By priority
|
||||
|
||||
2. **Progress Tracking**
|
||||
- Overall completion
|
||||
- Sprint velocity
|
||||
- Burndown indication
|
||||
- Time tracking
|
||||
|
||||
3. **Formatting Options**
|
||||
- GitHub-flavored markdown
|
||||
- Task checkboxes
|
||||
- Collapsible sections
|
||||
- Table format available
|
||||
|
||||
## Example Output
|
||||
|
||||
```markdown
|
||||
## 🚀 Current Sprint
|
||||
|
||||
### In Progress
|
||||
- [ ] 🔄 #5 **Implement user authentication** (60% complete)
|
||||
- Dependencies: API design (#3 ✅)
|
||||
- Subtasks: 4 (2 completed)
|
||||
- Est: 8h / Spent: 5h
|
||||
|
||||
### Pending (High Priority)
|
||||
- [ ] ⚡ #8 **Create dashboard UI**
|
||||
- Blocked by: #5
|
||||
- Complexity: High
|
||||
- Est: 12h
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
Based on arguments:
|
||||
- Include/exclude sections
|
||||
- Detail level control
|
||||
- Custom grouping
|
||||
- Filter by criteria
|
||||
|
||||
## Post-Sync
|
||||
|
||||
After generation:
|
||||
1. Show diff preview
|
||||
2. Backup existing README
|
||||
3. Write new content
|
||||
4. Commit reminder
|
||||
5. Update timestamp
|
||||
|
||||
## Integration
|
||||
|
||||
Works well with:
|
||||
- Git workflows
|
||||
- CI/CD pipelines
|
||||
- Project documentation
|
||||
- Team updates
|
||||
- Client reports
|
||||
146
assets/claude/commands/tm/tm-main.md
Normal file
146
assets/claude/commands/tm/tm-main.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Task Master Command Reference
|
||||
|
||||
Comprehensive command structure for Task Master integration with Claude Code.
|
||||
|
||||
## Command Organization
|
||||
|
||||
Commands are organized hierarchically to match Task Master's CLI structure while providing enhanced Claude Code integration.
|
||||
|
||||
## Project Setup & Configuration
|
||||
|
||||
### `/project:tm/init`
|
||||
- `init-project` - Initialize new project (handles PRD files intelligently)
|
||||
- `init-project-quick` - Quick setup with auto-confirmation (-y flag)
|
||||
|
||||
### `/project:tm/models`
|
||||
- `view-models` - View current AI model configuration
|
||||
- `setup-models` - Interactive model configuration
|
||||
- `set-main` - Set primary generation model
|
||||
- `set-research` - Set research model
|
||||
- `set-fallback` - Set fallback model
|
||||
|
||||
## Task Generation
|
||||
|
||||
### `/project:tm/parse-prd`
|
||||
- `parse-prd` - Generate tasks from PRD document
|
||||
- `parse-prd-with-research` - Enhanced parsing with research mode
|
||||
|
||||
### `/project:tm/generate`
|
||||
- `generate-tasks` - Create individual task files from tasks.json
|
||||
|
||||
## Task Management
|
||||
|
||||
### `/project:tm/list`
|
||||
- `list-tasks` - Smart listing with natural language filters
|
||||
- `list-tasks-with-subtasks` - Include subtasks in hierarchical view
|
||||
- `list-tasks-by-status` - Filter by specific status
|
||||
|
||||
### `/project:tm/set-status`
|
||||
- `to-pending` - Reset task to pending
|
||||
- `to-in-progress` - Start working on task
|
||||
- `to-done` - Mark task complete
|
||||
- `to-review` - Submit for review
|
||||
- `to-deferred` - Defer task
|
||||
- `to-cancelled` - Cancel task
|
||||
|
||||
### `/project:tm/sync-readme`
|
||||
- `sync-readme` - Export tasks to README.md with formatting
|
||||
|
||||
### `/project:tm/update`
|
||||
- `update-task` - Update tasks with natural language
|
||||
- `update-tasks-from-id` - Update multiple tasks from a starting point
|
||||
- `update-single-task` - Update specific task
|
||||
|
||||
### `/project:tm/add-task`
|
||||
- `add-task` - Add new task with AI assistance
|
||||
|
||||
### `/project:tm/remove-task`
|
||||
- `remove-task` - Remove task with confirmation
|
||||
|
||||
## Subtask Management
|
||||
|
||||
### `/project:tm/add-subtask`
|
||||
- `add-subtask` - Add new subtask to parent
|
||||
- `convert-task-to-subtask` - Convert existing task to subtask
|
||||
|
||||
### `/project:tm/remove-subtask`
|
||||
- `remove-subtask` - Remove subtask (with optional conversion)
|
||||
|
||||
### `/project:tm/clear-subtasks`
|
||||
- `clear-subtasks` - Clear subtasks from specific task
|
||||
- `clear-all-subtasks` - Clear all subtasks globally
|
||||
|
||||
## Task Analysis & Breakdown
|
||||
|
||||
### `/project:tm/analyze-complexity`
|
||||
- `analyze-complexity` - Analyze and generate expansion recommendations
|
||||
|
||||
### `/project:tm/complexity-report`
|
||||
- `complexity-report` - Display complexity analysis report
|
||||
|
||||
### `/project:tm/expand`
|
||||
- `expand-task` - Break down specific task
|
||||
- `expand-all-tasks` - Expand all eligible tasks
|
||||
- `with-research` - Enhanced expansion
|
||||
|
||||
## Task Navigation
|
||||
|
||||
### `/project:tm/next`
|
||||
- `next-task` - Intelligent next task recommendation
|
||||
|
||||
### `/project:tm/show`
|
||||
- `show-task` - Display detailed task information
|
||||
|
||||
### `/project:tm/status`
|
||||
- `project-status` - Comprehensive project dashboard
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### `/project:tm/add-dependency`
|
||||
- `add-dependency` - Add task dependency
|
||||
|
||||
### `/project:tm/remove-dependency`
|
||||
- `remove-dependency` - Remove task dependency
|
||||
|
||||
### `/project:tm/validate-dependencies`
|
||||
- `validate-dependencies` - Check for dependency issues
|
||||
|
||||
### `/project:tm/fix-dependencies`
|
||||
- `fix-dependencies` - Automatically fix dependency problems
|
||||
|
||||
## Workflows & Automation
|
||||
|
||||
### `/project:tm/workflows`
|
||||
- `smart-workflow` - Context-aware intelligent workflow execution
|
||||
- `command-pipeline` - Chain multiple commands together
|
||||
- `auto-implement-tasks` - Advanced auto-implementation with code generation
|
||||
|
||||
## Utilities
|
||||
|
||||
### `/project:tm/utils`
|
||||
- `analyze-project` - Deep project analysis and insights
|
||||
|
||||
### `/project:tm/setup`
|
||||
- `install-taskmaster` - Comprehensive installation guide
|
||||
- `quick-install-taskmaster` - One-line global installation
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
### Natural Language
|
||||
Most commands accept natural language arguments:
|
||||
```
|
||||
/project:tm/add-task create user authentication system
|
||||
/project:tm/update mark all API tasks as high priority
|
||||
/project:tm/list show blocked tasks
|
||||
```
|
||||
|
||||
### ID-Based Commands
|
||||
Commands requiring IDs intelligently parse from $ARGUMENTS:
|
||||
```
|
||||
/project:tm/show 45
|
||||
/project:tm/expand 23
|
||||
/project:tm/set-status/to-done 67
|
||||
```
|
||||
|
||||
### Smart Defaults
|
||||
Commands provide intelligent defaults and suggestions based on context.
|
||||
119
assets/claude/commands/tm/update/update-single-task.md
Normal file
119
assets/claude/commands/tm/update/update-single-task.md
Normal file
@@ -0,0 +1,119 @@
|
||||
Update a single specific task with new information.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse task ID and update details.
|
||||
|
||||
## Single Task Update
|
||||
|
||||
Precisely update one task with AI assistance to maintain consistency.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Natural language updates:
|
||||
- "5: add caching requirement"
|
||||
- "update 5 to include error handling"
|
||||
- "task 5 needs rate limiting"
|
||||
- "5 change priority to high"
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master update-task --id=<id> --prompt="<context>"
|
||||
```
|
||||
|
||||
## Update Types
|
||||
|
||||
### 1. **Content Updates**
|
||||
- Enhance description
|
||||
- Add requirements
|
||||
- Clarify details
|
||||
- Update acceptance criteria
|
||||
|
||||
### 2. **Metadata Updates**
|
||||
- Change priority
|
||||
- Adjust time estimates
|
||||
- Update complexity
|
||||
- Modify dependencies
|
||||
|
||||
### 3. **Strategic Updates**
|
||||
- Revise approach
|
||||
- Change test strategy
|
||||
- Update implementation notes
|
||||
- Adjust subtask needs
|
||||
|
||||
## AI-Powered Updates
|
||||
|
||||
The AI:
|
||||
1. **Understands Context**
|
||||
- Reads current task state
|
||||
- Identifies update intent
|
||||
- Maintains consistency
|
||||
- Preserves important info
|
||||
|
||||
2. **Applies Changes**
|
||||
- Updates relevant fields
|
||||
- Keeps style consistent
|
||||
- Adds without removing
|
||||
- Enhances clarity
|
||||
|
||||
3. **Validates Results**
|
||||
- Checks coherence
|
||||
- Verifies completeness
|
||||
- Maintains relationships
|
||||
- Suggests related updates
|
||||
|
||||
## Example Updates
|
||||
|
||||
```
|
||||
/project:tm/update/single 5: add rate limiting
|
||||
→ Updating Task #5: "Implement API endpoints"
|
||||
|
||||
Current: Basic CRUD endpoints
|
||||
Adding: Rate limiting requirements
|
||||
|
||||
Updated sections:
|
||||
✓ Description: Added rate limiting mention
|
||||
✓ Details: Added specific limits (100/min)
|
||||
✓ Test Strategy: Added rate limit tests
|
||||
✓ Complexity: Increased from 5 to 6
|
||||
✓ Time Estimate: Increased by 2 hours
|
||||
|
||||
Suggestion: Also update task #6 (API Gateway) for consistency?
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Incremental Updates**
|
||||
- Adds without overwriting
|
||||
- Preserves work history
|
||||
- Tracks what changed
|
||||
- Shows diff view
|
||||
|
||||
2. **Consistency Checks**
|
||||
- Related task alignment
|
||||
- Subtask compatibility
|
||||
- Dependency validity
|
||||
- Timeline impact
|
||||
|
||||
3. **Update History**
|
||||
- Timestamp changes
|
||||
- Track who/what updated
|
||||
- Reason for update
|
||||
- Previous versions
|
||||
|
||||
## Field-Specific Updates
|
||||
|
||||
Quick syntax for specific fields:
|
||||
- "5 priority:high" → Update priority only
|
||||
- "5 add-time:4h" → Add to time estimate
|
||||
- "5 status:review" → Change status
|
||||
- "5 depends:3,4" → Add dependencies
|
||||
|
||||
## Post-Update
|
||||
|
||||
- Show updated task
|
||||
- Highlight changes
|
||||
- Check related tasks
|
||||
- Update suggestions
|
||||
- Timeline adjustments
|
||||
72
assets/claude/commands/tm/update/update-task.md
Normal file
72
assets/claude/commands/tm/update/update-task.md
Normal file
@@ -0,0 +1,72 @@
|
||||
Update tasks with intelligent field detection and bulk operations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Task Updates
|
||||
|
||||
Parse arguments to determine update intent and execute smartly.
|
||||
|
||||
### 1. **Natural Language Processing**
|
||||
|
||||
Understand update requests like:
|
||||
- "mark 23 as done" → Update status to done
|
||||
- "increase priority of 45" → Set priority to high
|
||||
- "add dependency on 12 to task 34" → Add dependency
|
||||
- "tasks 20-25 need review" → Bulk status update
|
||||
- "all API tasks high priority" → Pattern-based update
|
||||
|
||||
### 2. **Smart Field Detection**
|
||||
|
||||
Automatically detect what to update:
|
||||
- Status keywords: done, complete, start, pause, review
|
||||
- Priority changes: urgent, high, low, deprioritize
|
||||
- Dependency updates: depends on, blocks, after
|
||||
- Assignment: assign to, owner, responsible
|
||||
- Time: estimate, spent, deadline
|
||||
|
||||
### 3. **Bulk Operations**
|
||||
|
||||
Support for multiple task updates:
|
||||
```
|
||||
Examples:
|
||||
- "complete tasks 12, 15, 18"
|
||||
- "all pending auth tasks to in-progress"
|
||||
- "increase priority for tasks blocking 45"
|
||||
- "defer all documentation tasks"
|
||||
```
|
||||
|
||||
### 4. **Contextual Validation**
|
||||
|
||||
Before updating, check:
|
||||
- Status transitions are valid
|
||||
- Dependencies don't create cycles
|
||||
- Priority changes make sense
|
||||
- Bulk updates won't break project flow
|
||||
|
||||
Show preview:
|
||||
```
|
||||
Update Preview:
|
||||
─────────────────
|
||||
Tasks to update: #23, #24, #25
|
||||
Change: status → in-progress
|
||||
Impact: Will unblock tasks #30, #31
|
||||
Warning: Task #24 has unmet dependencies
|
||||
```
|
||||
|
||||
### 5. **Smart Suggestions**
|
||||
|
||||
Based on update:
|
||||
- Completing task? → Show newly unblocked tasks
|
||||
- Changing priority? → Show impact on sprint
|
||||
- Adding dependency? → Check for conflicts
|
||||
- Bulk update? → Show summary of changes
|
||||
|
||||
### 6. **Workflow Integration**
|
||||
|
||||
After updates:
|
||||
- Auto-update dependent task states
|
||||
- Trigger status recalculation
|
||||
- Update sprint/milestone progress
|
||||
- Log changes with context
|
||||
|
||||
Result: Flexible, intelligent task updates with safety checks.
|
||||
108
assets/claude/commands/tm/update/update-tasks-from-id.md
Normal file
108
assets/claude/commands/tm/update/update-tasks-from-id.md
Normal file
@@ -0,0 +1,108 @@
|
||||
Update multiple tasks starting from a specific ID.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse starting task ID and update context.
|
||||
|
||||
## Bulk Task Updates
|
||||
|
||||
Update multiple related tasks based on new requirements or context changes.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "from 5: add security requirements"
|
||||
- "5 onwards: update API endpoints"
|
||||
- "starting at 5: change to use new framework"
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master update --from=<id> --prompt="<context>"
|
||||
```
|
||||
|
||||
## Update Process
|
||||
|
||||
### 1. **Task Selection**
|
||||
Starting from specified ID:
|
||||
- Include the task itself
|
||||
- Include all dependent tasks
|
||||
- Include related subtasks
|
||||
- Smart boundary detection
|
||||
|
||||
### 2. **Context Application**
|
||||
AI analyzes the update context and:
|
||||
- Identifies what needs changing
|
||||
- Maintains consistency
|
||||
- Preserves completed work
|
||||
- Updates related information
|
||||
|
||||
### 3. **Intelligent Updates**
|
||||
- Modify descriptions appropriately
|
||||
- Update test strategies
|
||||
- Adjust time estimates
|
||||
- Revise dependencies if needed
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Scope Detection**
|
||||
- Find natural task groupings
|
||||
- Identify related features
|
||||
- Stop at logical boundaries
|
||||
- Avoid over-updating
|
||||
|
||||
2. **Consistency Maintenance**
|
||||
- Keep naming conventions
|
||||
- Preserve relationships
|
||||
- Update cross-references
|
||||
- Maintain task flow
|
||||
|
||||
3. **Change Preview**
|
||||
```
|
||||
Bulk Update Preview
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
Starting from: Task #5
|
||||
Tasks to update: 8 tasks + 12 subtasks
|
||||
|
||||
Context: "add security requirements"
|
||||
|
||||
Changes will include:
|
||||
- Add security sections to descriptions
|
||||
- Update test strategies for security
|
||||
- Add security-related subtasks where needed
|
||||
- Adjust time estimates (+20% average)
|
||||
|
||||
Continue? (y/n)
|
||||
```
|
||||
|
||||
## Example Updates
|
||||
|
||||
```
|
||||
/project:tm/update/from-id 5: change database to PostgreSQL
|
||||
→ Analyzing impact starting from task #5
|
||||
→ Found 6 related tasks to update
|
||||
→ Updates will maintain consistency
|
||||
→ Preview changes? (y/n)
|
||||
|
||||
Applied updates:
|
||||
✓ Task #5: Updated connection logic references
|
||||
✓ Task #6: Changed migration approach
|
||||
✓ Task #7: Updated query syntax notes
|
||||
✓ Task #8: Revised testing strategy
|
||||
✓ Task #9: Updated deployment steps
|
||||
✓ Task #12: Changed backup procedures
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Preview all changes
|
||||
- Selective confirmation
|
||||
- Rollback capability
|
||||
- Change logging
|
||||
- Validation checks
|
||||
|
||||
## Post-Update
|
||||
|
||||
- Summary of changes
|
||||
- Consistency verification
|
||||
- Suggest review tasks
|
||||
- Update timeline if needed
|
||||
97
assets/claude/commands/tm/utils/analyze-project.md
Normal file
97
assets/claude/commands/tm/utils/analyze-project.md
Normal file
@@ -0,0 +1,97 @@
|
||||
Advanced project analysis with actionable insights and recommendations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Comprehensive Project Analysis
|
||||
|
||||
Multi-dimensional analysis based on requested focus area.
|
||||
|
||||
### 1. **Analysis Modes**
|
||||
|
||||
Based on $ARGUMENTS:
|
||||
- "velocity" → Sprint velocity and trends
|
||||
- "quality" → Code quality metrics
|
||||
- "risk" → Risk assessment and mitigation
|
||||
- "dependencies" → Dependency graph analysis
|
||||
- "team" → Workload and skill distribution
|
||||
- "architecture" → System design coherence
|
||||
- Default → Full spectrum analysis
|
||||
|
||||
### 2. **Velocity Analytics**
|
||||
|
||||
```
|
||||
📊 Velocity Analysis
|
||||
━━━━━━━━━━━━━━━━━━━
|
||||
Current Sprint: 24 points/week ↗️ +20%
|
||||
Rolling Average: 20 points/week
|
||||
Efficiency: 85% (17/20 tasks on time)
|
||||
|
||||
Bottlenecks Detected:
|
||||
- Code review delays (avg 4h wait)
|
||||
- Test environment availability
|
||||
- Dependency on external team
|
||||
|
||||
Recommendations:
|
||||
1. Implement parallel review process
|
||||
2. Add staging environment
|
||||
3. Mock external dependencies
|
||||
```
|
||||
|
||||
### 3. **Risk Assessment**
|
||||
|
||||
**Technical Risks**
|
||||
- High complexity tasks without backup assignee
|
||||
- Single points of failure in architecture
|
||||
- Insufficient test coverage in critical paths
|
||||
- Technical debt accumulation rate
|
||||
|
||||
**Project Risks**
|
||||
- Critical path dependencies
|
||||
- Resource availability gaps
|
||||
- Deadline feasibility analysis
|
||||
- Scope creep indicators
|
||||
|
||||
### 4. **Dependency Intelligence**
|
||||
|
||||
Visual dependency analysis:
|
||||
```
|
||||
Critical Path:
|
||||
#12 → #15 → #23 → #45 → #50 (20 days)
|
||||
↘ #24 → #46 ↗
|
||||
|
||||
Optimization: Parallelize #15 and #24
|
||||
Time Saved: 3 days
|
||||
```
|
||||
|
||||
### 5. **Quality Metrics**
|
||||
|
||||
**Code Quality**
|
||||
- Test coverage trends
|
||||
- Complexity scores
|
||||
- Technical debt ratio
|
||||
- Review feedback patterns
|
||||
|
||||
**Process Quality**
|
||||
- Rework frequency
|
||||
- Bug introduction rate
|
||||
- Time to resolution
|
||||
- Knowledge distribution
|
||||
|
||||
### 6. **Predictive Insights**
|
||||
|
||||
Based on patterns:
|
||||
- Completion probability by deadline
|
||||
- Resource needs projection
|
||||
- Risk materialization likelihood
|
||||
- Suggested interventions
|
||||
|
||||
### 7. **Executive Dashboard**
|
||||
|
||||
High-level summary with:
|
||||
- Health score (0-100)
|
||||
- Top 3 risks
|
||||
- Top 3 opportunities
|
||||
- Recommended actions
|
||||
- Success probability
|
||||
|
||||
Result: Data-driven decisions with clear action paths.
|
||||
@@ -0,0 +1,71 @@
|
||||
Validate all task dependencies for issues.
|
||||
|
||||
## Dependency Validation
|
||||
|
||||
Comprehensive check for dependency problems across the entire project.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master validate-dependencies
|
||||
```
|
||||
|
||||
## Validation Checks
|
||||
|
||||
1. **Circular Dependencies**
|
||||
- A depends on B, B depends on A
|
||||
- Complex circular chains
|
||||
- Self-dependencies
|
||||
|
||||
2. **Missing Dependencies**
|
||||
- References to non-existent tasks
|
||||
- Deleted task references
|
||||
- Invalid task IDs
|
||||
|
||||
3. **Logical Issues**
|
||||
- Completed tasks depending on pending
|
||||
- Cancelled tasks in dependency chains
|
||||
- Impossible sequences
|
||||
|
||||
4. **Complexity Warnings**
|
||||
- Over-complex dependency chains
|
||||
- Too many dependencies per task
|
||||
- Bottleneck tasks
|
||||
|
||||
## Smart Analysis
|
||||
|
||||
The validation provides:
|
||||
- Visual dependency graph
|
||||
- Critical path analysis
|
||||
- Bottleneck identification
|
||||
- Suggested optimizations
|
||||
|
||||
## Report Format
|
||||
|
||||
```
|
||||
Dependency Validation Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ No circular dependencies found
|
||||
⚠️ 2 warnings found:
|
||||
- Task #23 has 7 dependencies (consider breaking down)
|
||||
- Task #45 blocks 5 other tasks (potential bottleneck)
|
||||
❌ 1 error found:
|
||||
- Task #67 depends on deleted task #66
|
||||
|
||||
Critical Path: #1 → #5 → #23 → #45 → #50 (15 days)
|
||||
```
|
||||
|
||||
## Actionable Output
|
||||
|
||||
For each issue found:
|
||||
- Clear description
|
||||
- Impact assessment
|
||||
- Suggested fix
|
||||
- Command to resolve
|
||||
|
||||
## Next Steps
|
||||
|
||||
After validation:
|
||||
- Run `/project:tm/fix-dependencies` to auto-fix
|
||||
- Manually adjust problematic dependencies
|
||||
- Rerun to verify fixes
|
||||
97
assets/claude/commands/tm/workflows/auto-implement-tasks.md
Normal file
97
assets/claude/commands/tm/workflows/auto-implement-tasks.md
Normal file
@@ -0,0 +1,97 @@
|
||||
Enhanced auto-implementation with intelligent code generation and testing.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Auto-Implementation
|
||||
|
||||
Advanced implementation with context awareness and quality checks.
|
||||
|
||||
### 1. **Pre-Implementation Analysis**
|
||||
|
||||
Before starting:
|
||||
- Analyze task complexity and requirements
|
||||
- Check codebase patterns and conventions
|
||||
- Identify similar completed tasks
|
||||
- Assess test coverage needs
|
||||
- Detect potential risks
|
||||
|
||||
### 2. **Smart Implementation Strategy**
|
||||
|
||||
Based on task type and context:
|
||||
|
||||
**Feature Tasks**
|
||||
1. Research existing patterns
|
||||
2. Design component architecture
|
||||
3. Implement with tests
|
||||
4. Integrate with system
|
||||
5. Update documentation
|
||||
|
||||
**Bug Fix Tasks**
|
||||
1. Reproduce issue
|
||||
2. Identify root cause
|
||||
3. Implement minimal fix
|
||||
4. Add regression tests
|
||||
5. Verify side effects
|
||||
|
||||
**Refactoring Tasks**
|
||||
1. Analyze current structure
|
||||
2. Plan incremental changes
|
||||
3. Maintain test coverage
|
||||
4. Refactor step-by-step
|
||||
5. Verify behavior unchanged
|
||||
|
||||
### 3. **Code Intelligence**
|
||||
|
||||
**Pattern Recognition**
|
||||
- Learn from existing code
|
||||
- Follow team conventions
|
||||
- Use preferred libraries
|
||||
- Match style guidelines
|
||||
|
||||
**Test-Driven Approach**
|
||||
- Write tests first when possible
|
||||
- Ensure comprehensive coverage
|
||||
- Include edge cases
|
||||
- Performance considerations
|
||||
|
||||
### 4. **Progressive Implementation**
|
||||
|
||||
Step-by-step with validation:
|
||||
```
|
||||
Step 1/5: Setting up component structure ✓
|
||||
Step 2/5: Implementing core logic ✓
|
||||
Step 3/5: Adding error handling ⚡ (in progress)
|
||||
Step 4/5: Writing tests ⏳
|
||||
Step 5/5: Integration testing ⏳
|
||||
|
||||
Current: Adding try-catch blocks and validation...
|
||||
```
|
||||
|
||||
### 5. **Quality Assurance**
|
||||
|
||||
Automated checks:
|
||||
- Linting and formatting
|
||||
- Test execution
|
||||
- Type checking
|
||||
- Dependency validation
|
||||
- Performance analysis
|
||||
|
||||
### 6. **Smart Recovery**
|
||||
|
||||
If issues arise:
|
||||
- Diagnostic analysis
|
||||
- Suggestion generation
|
||||
- Fallback strategies
|
||||
- Manual intervention points
|
||||
- Learning from failures
|
||||
|
||||
### 7. **Post-Implementation**
|
||||
|
||||
After completion:
|
||||
- Generate PR description
|
||||
- Update documentation
|
||||
- Log lessons learned
|
||||
- Suggest follow-up tasks
|
||||
- Update task relationships
|
||||
|
||||
Result: High-quality, production-ready implementations.
|
||||
77
assets/claude/commands/tm/workflows/command-pipeline.md
Normal file
77
assets/claude/commands/tm/workflows/command-pipeline.md
Normal file
@@ -0,0 +1,77 @@
|
||||
Execute a pipeline of commands based on a specification.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Command Pipeline Execution
|
||||
|
||||
Parse pipeline specification from arguments. Supported formats:
|
||||
|
||||
### Simple Pipeline
|
||||
`init → expand-all → sprint-plan`
|
||||
|
||||
### Conditional Pipeline
|
||||
`status → if:pending>10 → sprint-plan → else → next`
|
||||
|
||||
### Iterative Pipeline
|
||||
`for:pending-tasks → expand → complexity-check`
|
||||
|
||||
### Smart Pipeline Patterns
|
||||
|
||||
**1. Project Setup Pipeline**
|
||||
```
|
||||
init [prd] →
|
||||
expand-all →
|
||||
complexity-report →
|
||||
sprint-plan →
|
||||
show first-sprint
|
||||
```
|
||||
|
||||
**2. Daily Work Pipeline**
|
||||
```
|
||||
standup →
|
||||
if:in-progress → continue →
|
||||
else → next → start
|
||||
```
|
||||
|
||||
**3. Task Completion Pipeline**
|
||||
```
|
||||
complete [id] →
|
||||
git-commit →
|
||||
if:blocked-tasks-freed → show-freed →
|
||||
next
|
||||
```
|
||||
|
||||
**4. Quality Check Pipeline**
|
||||
```
|
||||
list in-progress →
|
||||
for:each → check-idle-time →
|
||||
if:idle>1day → prompt-update
|
||||
```
|
||||
|
||||
### Pipeline Features
|
||||
|
||||
**Variables**
|
||||
- Store results: `status → $count=pending-count`
|
||||
- Use in conditions: `if:$count>10`
|
||||
- Pass between commands: `expand $high-priority-tasks`
|
||||
|
||||
**Error Handling**
|
||||
- On failure: `try:complete → catch:show-blockers`
|
||||
- Skip on error: `optional:test-run`
|
||||
- Retry logic: `retry:3:commit`
|
||||
|
||||
**Parallel Execution**
|
||||
- Parallel branches: `[analyze | test | lint]`
|
||||
- Join results: `parallel → join:report`
|
||||
|
||||
### Execution Flow
|
||||
|
||||
1. Parse pipeline specification
|
||||
2. Validate command sequence
|
||||
3. Execute with state passing
|
||||
4. Handle conditions and loops
|
||||
5. Aggregate results
|
||||
6. Show summary
|
||||
|
||||
This enables complex workflows like:
|
||||
`parse-prd → expand-all → filter:complex>70 → assign:senior → sprint-plan:weighted`
|
||||
55
assets/claude/commands/tm/workflows/smart-workflow.md
Normal file
55
assets/claude/commands/tm/workflows/smart-workflow.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Execute an intelligent workflow based on current project state and recent commands.
|
||||
|
||||
This command analyzes:
|
||||
1. Recent commands you've run
|
||||
2. Current project state
|
||||
3. Time of day / day of week
|
||||
4. Your working patterns
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Workflow Selection
|
||||
|
||||
Based on context, I'll determine the best workflow:
|
||||
|
||||
### Context Analysis
|
||||
- Previous command executed
|
||||
- Current task states
|
||||
- Unfinished work from last session
|
||||
- Your typical patterns
|
||||
|
||||
### Smart Execution
|
||||
|
||||
If last command was:
|
||||
- `status` → Likely starting work → Run daily standup
|
||||
- `complete` → Task finished → Find next task
|
||||
- `list pending` → Planning → Suggest sprint planning
|
||||
- `expand` → Breaking down work → Show complexity analysis
|
||||
- `init` → New project → Show onboarding workflow
|
||||
|
||||
If no recent commands:
|
||||
- Morning? → Daily standup workflow
|
||||
- Many pending tasks? → Sprint planning
|
||||
- Tasks blocked? → Dependency resolution
|
||||
- Friday? → Weekly review
|
||||
|
||||
### Workflow Composition
|
||||
|
||||
I'll chain appropriate commands:
|
||||
1. Analyze current state
|
||||
2. Execute primary workflow
|
||||
3. Suggest follow-up actions
|
||||
4. Prepare environment for coding
|
||||
|
||||
### Learning Mode
|
||||
|
||||
This command learns from your patterns:
|
||||
- Track command sequences
|
||||
- Note time preferences
|
||||
- Remember common workflows
|
||||
- Adapt to your style
|
||||
|
||||
Example flows detected:
|
||||
- Morning: standup → next → start
|
||||
- After lunch: status → continue task
|
||||
- End of day: complete → commit → status
|
||||
@@ -81,7 +81,8 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@anthropic-ai/claude-code": "^1.0.25",
|
||||
"ai-sdk-provider-gemini-cli": "^0.0.4"
|
||||
"ai-sdk-provider-gemini-cli": "^0.0.4",
|
||||
"@biomejs/cli-linux-x64": "^1.9.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -4021,10 +4021,6 @@ Examples:
|
||||
projectRoot,
|
||||
profileConfig
|
||||
);
|
||||
if (typeof profileConfig.onAddRulesProfile === 'function') {
|
||||
const assetsDir = path.join(projectRoot, 'assets');
|
||||
profileConfig.onAddRulesProfile(projectRoot, assetsDir);
|
||||
}
|
||||
console.log(
|
||||
chalk.blue(`Completed adding rules for profile: ${profile}`)
|
||||
);
|
||||
@@ -4054,37 +4050,27 @@ Examples:
|
||||
|
||||
// Print summary for additions
|
||||
if (action === RULES_ACTIONS.ADD && addResults.length > 0) {
|
||||
const {
|
||||
allSuccessfulProfiles,
|
||||
totalSuccess,
|
||||
totalFailed,
|
||||
simpleProfiles
|
||||
} = categorizeProfileResults(addResults);
|
||||
const { allSuccessfulProfiles, totalSuccess, totalFailed } =
|
||||
categorizeProfileResults(addResults);
|
||||
|
||||
if (allSuccessfulProfiles.length > 0) {
|
||||
console.log(
|
||||
chalk.green(
|
||||
`\nSuccessfully added rules for: ${allSuccessfulProfiles.join(', ')}`
|
||||
`\nSuccessfully processed profiles: ${allSuccessfulProfiles.join(', ')}`
|
||||
)
|
||||
);
|
||||
|
||||
// Create a more descriptive summary
|
||||
if (totalSuccess > 0 && simpleProfiles.length > 0) {
|
||||
// Create a descriptive summary
|
||||
if (totalSuccess > 0) {
|
||||
console.log(
|
||||
chalk.green(
|
||||
`Total: ${totalSuccess} rules added, ${totalFailed} failed, ${simpleProfiles.length} integration guide(s) copied.`
|
||||
`Total: ${totalSuccess} files processed, ${totalFailed} failed.`
|
||||
)
|
||||
);
|
||||
} else if (totalSuccess > 0) {
|
||||
} else {
|
||||
console.log(
|
||||
chalk.green(
|
||||
`Total: ${totalSuccess} rules added, ${totalFailed} failed.`
|
||||
)
|
||||
);
|
||||
} else if (simpleProfiles.length > 0) {
|
||||
console.log(
|
||||
chalk.green(
|
||||
`Total: ${simpleProfiles.length} integration guide(s) copied.`
|
||||
`Total: ${allSuccessfulProfiles.length} profile(s) set up successfully.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @typedef {'claude' | 'cline' | 'codex' | 'cursor' | 'roo' | 'trae' | 'windsurf' | 'vscode'} RulesProfile
|
||||
* @typedef {'claude' | 'cline' | 'codex' | 'cursor' | 'gemini' | 'roo' | 'trae' | 'windsurf' | 'vscode'} RulesProfile
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -14,6 +14,7 @@
|
||||
* - cline: Cline IDE rules
|
||||
* - codex: Codex integration
|
||||
* - cursor: Cursor IDE rules
|
||||
* - gemini: Gemini integration
|
||||
* - roo: Roo Code IDE rules
|
||||
* - trae: Trae IDE rules
|
||||
* - vscode: VS Code with GitHub Copilot integration
|
||||
@@ -29,6 +30,7 @@ export const RULE_PROFILES = [
|
||||
'cline',
|
||||
'codex',
|
||||
'cursor',
|
||||
'gemini',
|
||||
'roo',
|
||||
'trae',
|
||||
'vscode',
|
||||
|
||||
@@ -16,8 +16,9 @@ import path from 'path';
|
||||
* @param {string} [editorConfig.targetExtension='.md'] - Target file extension
|
||||
* @param {Object} [editorConfig.toolMappings={}] - Tool name mappings
|
||||
* @param {Array} [editorConfig.customReplacements=[]] - Custom text replacements
|
||||
* @param {Object} [editorConfig.customFileMap={}] - Custom file name mappings
|
||||
* @param {Object} [editorConfig.fileMap={}] - Custom file name mappings
|
||||
* @param {boolean} [editorConfig.supportsRulesSubdirectories=false] - Whether to use taskmaster/ subdirectory for taskmaster-specific rules (only Cursor uses this by default)
|
||||
* @param {boolean} [editorConfig.includeDefaultRules=true] - Whether to include default rule files
|
||||
* @param {Function} [editorConfig.onAdd] - Lifecycle hook for profile addition
|
||||
* @param {Function} [editorConfig.onRemove] - Lifecycle hook for profile removal
|
||||
* @param {Function} [editorConfig.onPostConvert] - Lifecycle hook for post-conversion
|
||||
@@ -29,34 +30,38 @@ export function createProfile(editorConfig) {
|
||||
displayName = name,
|
||||
url,
|
||||
docsUrl,
|
||||
profileDir,
|
||||
profileDir = `.${name.toLowerCase()}`,
|
||||
rulesDir = `${profileDir}/rules`,
|
||||
mcpConfig = true,
|
||||
mcpConfigName = 'mcp.json',
|
||||
mcpConfigName = mcpConfig ? 'mcp.json' : null,
|
||||
fileExtension = '.mdc',
|
||||
targetExtension = '.md',
|
||||
toolMappings = {},
|
||||
customReplacements = [],
|
||||
customFileMap = {},
|
||||
fileMap = {},
|
||||
supportsRulesSubdirectories = false,
|
||||
includeDefaultRules = true,
|
||||
onAdd,
|
||||
onRemove,
|
||||
onPostConvert
|
||||
} = editorConfig;
|
||||
|
||||
const mcpConfigPath = `${profileDir}/${mcpConfigName}`;
|
||||
const mcpConfigPath = mcpConfigName ? `${profileDir}/${mcpConfigName}` : null;
|
||||
|
||||
// Standard file mapping with custom overrides
|
||||
// Use taskmaster subdirectory only if profile supports it
|
||||
const taskmasterPrefix = supportsRulesSubdirectories ? 'taskmaster/' : '';
|
||||
const defaultFileMap = {
|
||||
'cursor_rules.mdc': `${name.toLowerCase()}_rules${targetExtension}`,
|
||||
'dev_workflow.mdc': `${taskmasterPrefix}dev_workflow${targetExtension}`,
|
||||
'self_improve.mdc': `self_improve${targetExtension}`,
|
||||
'taskmaster.mdc': `${taskmasterPrefix}taskmaster${targetExtension}`
|
||||
'rules/cursor_rules.mdc': `${name.toLowerCase()}_rules${targetExtension}`,
|
||||
'rules/dev_workflow.mdc': `${taskmasterPrefix}dev_workflow${targetExtension}`,
|
||||
'rules/self_improve.mdc': `self_improve${targetExtension}`,
|
||||
'rules/taskmaster.mdc': `${taskmasterPrefix}taskmaster${targetExtension}`
|
||||
};
|
||||
|
||||
const fileMap = { ...defaultFileMap, ...customFileMap };
|
||||
// Build final fileMap - merge defaults with custom entries when includeDefaultRules is true
|
||||
const finalFileMap = includeDefaultRules
|
||||
? { ...defaultFileMap, ...fileMap }
|
||||
: fileMap;
|
||||
|
||||
// Base global replacements that work for all editors
|
||||
const baseGlobalReplacements = [
|
||||
@@ -187,7 +192,8 @@ export function createProfile(editorConfig) {
|
||||
replacement: (match, text, filePath) => {
|
||||
const baseName = path.basename(filePath, '.mdc');
|
||||
const newFileName =
|
||||
fileMap[`${baseName}.mdc`] || `${baseName}${targetExtension}`;
|
||||
finalFileMap[`rules/${baseName}.mdc`] ||
|
||||
`${baseName}${targetExtension}`;
|
||||
// Update the link text to match the new filename (strip directory path for display)
|
||||
const newLinkText = path.basename(newFileName);
|
||||
// For Cursor, keep the mdc: protocol; for others, use standard relative paths
|
||||
@@ -201,8 +207,8 @@ export function createProfile(editorConfig) {
|
||||
};
|
||||
|
||||
function getTargetRuleFilename(sourceFilename) {
|
||||
if (fileMap[sourceFilename]) {
|
||||
return fileMap[sourceFilename];
|
||||
if (finalFileMap[sourceFilename]) {
|
||||
return finalFileMap[sourceFilename];
|
||||
}
|
||||
return targetExtension !== fileExtension
|
||||
? sourceFilename.replace(
|
||||
@@ -221,7 +227,8 @@ export function createProfile(editorConfig) {
|
||||
mcpConfigName,
|
||||
mcpConfigPath,
|
||||
supportsRulesSubdirectories,
|
||||
fileMap,
|
||||
includeDefaultRules,
|
||||
fileMap: finalFileMap,
|
||||
globalReplacements: baseGlobalReplacements,
|
||||
conversionConfig,
|
||||
getTargetRuleFilename,
|
||||
|
||||
@@ -2,58 +2,96 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { isSilentMode, log } from '../../scripts/modules/utils.js';
|
||||
import { createProfile } from './base-profile.js';
|
||||
|
||||
// Helper function to recursively copy directory (adopted from Roo profile)
|
||||
function copyRecursiveSync(src, dest) {
|
||||
const exists = fs.existsSync(src);
|
||||
const stats = exists && fs.statSync(src);
|
||||
const isDirectory = exists && stats.isDirectory();
|
||||
if (isDirectory) {
|
||||
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
||||
fs.readdirSync(src).forEach((childItemName) => {
|
||||
copyRecursiveSync(
|
||||
path.join(src, childItemName),
|
||||
path.join(dest, childItemName)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to recursively remove directory
|
||||
function removeDirectoryRecursive(dirPath) {
|
||||
if (fs.existsSync(dirPath)) {
|
||||
try {
|
||||
fs.rmSync(dirPath, { recursive: true, force: true });
|
||||
return true;
|
||||
} catch (err) {
|
||||
log('error', `Failed to remove directory ${dirPath}: ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lifecycle functions for Claude Code profile
|
||||
function onAddRulesProfile(targetDir, assetsDir) {
|
||||
// Use the provided assets directory to find the source file
|
||||
const sourceFile = path.join(assetsDir, 'AGENTS.md');
|
||||
const destFile = path.join(targetDir, 'CLAUDE.md');
|
||||
// Copy .claude directory recursively
|
||||
const claudeSourceDir = path.join(assetsDir, 'claude');
|
||||
const claudeDestDir = path.join(targetDir, '.claude');
|
||||
|
||||
if (fs.existsSync(sourceFile)) {
|
||||
try {
|
||||
fs.copyFileSync(sourceFile, destFile);
|
||||
log('debug', `[Claude] Copied AGENTS.md to ${destFile}`);
|
||||
} catch (err) {
|
||||
log('error', `[Claude] Failed to copy AGENTS.md: ${err.message}`);
|
||||
if (!fs.existsSync(claudeSourceDir)) {
|
||||
log(
|
||||
'error',
|
||||
`[Claude] Source directory does not exist: ${claudeSourceDir}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
copyRecursiveSync(claudeSourceDir, claudeDestDir);
|
||||
log('debug', `[Claude] Copied .claude directory to ${claudeDestDir}`);
|
||||
} catch (err) {
|
||||
log(
|
||||
'error',
|
||||
`[Claude] An error occurred during directory copy: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function onRemoveRulesProfile(targetDir) {
|
||||
const claudeFile = path.join(targetDir, 'CLAUDE.md');
|
||||
if (fs.existsSync(claudeFile)) {
|
||||
try {
|
||||
fs.rmSync(claudeFile, { force: true });
|
||||
log('debug', `[Claude] Removed CLAUDE.md from ${claudeFile}`);
|
||||
} catch (err) {
|
||||
log('error', `[Claude] Failed to remove CLAUDE.md: ${err.message}`);
|
||||
}
|
||||
// Remove .claude directory recursively
|
||||
const claudeDir = path.join(targetDir, '.claude');
|
||||
if (removeDirectoryRecursive(claudeDir)) {
|
||||
log('debug', `[Claude] Removed .claude directory from ${claudeDir}`);
|
||||
}
|
||||
}
|
||||
|
||||
function onPostConvertRulesProfile(targetDir, assetsDir) {
|
||||
// For Claude, post-convert is the same as add since we don't transform rules
|
||||
onAddRulesProfile(targetDir, assetsDir);
|
||||
}
|
||||
|
||||
// Simple filename function
|
||||
function getTargetRuleFilename(sourceFilename) {
|
||||
return sourceFilename;
|
||||
}
|
||||
|
||||
// Simple profile configuration - bypasses base-profile system
|
||||
export const claudeProfile = {
|
||||
profileName: 'claude',
|
||||
// Create and export claude profile using the base factory
|
||||
export const claudeProfile = createProfile({
|
||||
name: 'claude',
|
||||
displayName: 'Claude Code',
|
||||
url: 'claude.ai',
|
||||
docsUrl: 'docs.anthropic.com/en/docs/claude-code',
|
||||
profileDir: '.', // Root directory
|
||||
rulesDir: '.', // No rules directory needed
|
||||
mcpConfig: false, // No MCP config needed
|
||||
rulesDir: '.', // No specific rules directory needed
|
||||
mcpConfig: false,
|
||||
mcpConfigName: null,
|
||||
mcpConfigPath: null,
|
||||
conversionConfig: {},
|
||||
fileMap: {},
|
||||
globalReplacements: [],
|
||||
getTargetRuleFilename,
|
||||
onAddRulesProfile,
|
||||
onRemoveRulesProfile,
|
||||
onPostConvertRulesProfile
|
||||
};
|
||||
includeDefaultRules: false,
|
||||
fileMap: {
|
||||
'AGENTS.md': 'CLAUDE.md'
|
||||
},
|
||||
onAdd: onAddRulesProfile,
|
||||
onRemove: onRemoveRulesProfile,
|
||||
onPostConvert: onPostConvertRulesProfile
|
||||
});
|
||||
|
||||
// Export lifecycle functions separately to avoid naming conflicts
|
||||
export { onAddRulesProfile, onRemoveRulesProfile, onPostConvertRulesProfile };
|
||||
|
||||
@@ -9,12 +9,5 @@ export const clineProfile = createProfile({
|
||||
docsUrl: 'docs.cline.bot',
|
||||
profileDir: '.clinerules',
|
||||
rulesDir: '.clinerules',
|
||||
mcpConfig: false,
|
||||
mcpConfigName: 'cline_mcp_settings.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.md',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.STANDARD, // Cline uses standard tool names
|
||||
customFileMap: {
|
||||
'cursor_rules.mdc': 'cline_rules.md'
|
||||
}
|
||||
mcpConfig: false
|
||||
});
|
||||
|
||||
@@ -1,59 +1,18 @@
|
||||
// Codex profile for rule-transformer
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { isSilentMode, log } from '../../scripts/modules/utils.js';
|
||||
import { createProfile } from './base-profile.js';
|
||||
|
||||
// Lifecycle functions for Codex profile
|
||||
function onAddRulesProfile(targetDir, assetsDir) {
|
||||
// Use the provided assets directory to find the source file
|
||||
const sourceFile = path.join(assetsDir, 'AGENTS.md');
|
||||
const destFile = path.join(targetDir, 'AGENTS.md');
|
||||
|
||||
if (fs.existsSync(sourceFile)) {
|
||||
try {
|
||||
fs.copyFileSync(sourceFile, destFile);
|
||||
log('debug', `[Codex] Copied AGENTS.md to ${destFile}`);
|
||||
} catch (err) {
|
||||
log('error', `[Codex] Failed to copy AGENTS.md: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onRemoveRulesProfile(targetDir) {
|
||||
const agentsFile = path.join(targetDir, 'AGENTS.md');
|
||||
if (fs.existsSync(agentsFile)) {
|
||||
try {
|
||||
fs.rmSync(agentsFile, { force: true });
|
||||
log('debug', `[Codex] Removed AGENTS.md from ${agentsFile}`);
|
||||
} catch (err) {
|
||||
log('error', `[Codex] Failed to remove AGENTS.md: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onPostConvertRulesProfile(targetDir, assetsDir) {
|
||||
onAddRulesProfile(targetDir, assetsDir);
|
||||
}
|
||||
|
||||
// Simple filename function
|
||||
function getTargetRuleFilename(sourceFilename) {
|
||||
return sourceFilename;
|
||||
}
|
||||
|
||||
// Simple profile configuration - bypasses base-profile system
|
||||
export const codexProfile = {
|
||||
profileName: 'codex',
|
||||
// Create and export codex profile using the base factory
|
||||
export const codexProfile = createProfile({
|
||||
name: 'codex',
|
||||
displayName: 'Codex',
|
||||
url: 'codex.ai',
|
||||
docsUrl: 'platform.openai.com/docs/codex',
|
||||
profileDir: '.', // Root directory
|
||||
rulesDir: '.', // No rules directory needed
|
||||
mcpConfig: false, // No MCP config needed
|
||||
rulesDir: '.', // No specific rules directory needed
|
||||
mcpConfig: false,
|
||||
mcpConfigName: null,
|
||||
mcpConfigPath: null,
|
||||
conversionConfig: {},
|
||||
fileMap: {},
|
||||
globalReplacements: [],
|
||||
getTargetRuleFilename,
|
||||
onAddRulesProfile,
|
||||
onRemoveRulesProfile,
|
||||
onPostConvertRulesProfile
|
||||
};
|
||||
includeDefaultRules: false,
|
||||
fileMap: {
|
||||
'AGENTS.md': 'AGENTS.md'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,15 +7,6 @@ export const cursorProfile = createProfile({
|
||||
displayName: 'Cursor',
|
||||
url: 'cursor.so',
|
||||
docsUrl: 'docs.cursor.com',
|
||||
profileDir: '.cursor',
|
||||
rulesDir: '.cursor/rules',
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'mcp.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.mdc', // Cursor keeps .mdc extension
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.STANDARD,
|
||||
supportsRulesSubdirectories: true,
|
||||
customFileMap: {
|
||||
'cursor_rules.mdc': 'cursor_rules.mdc' // Keep the same name for cursor
|
||||
}
|
||||
supportsRulesSubdirectories: true
|
||||
});
|
||||
|
||||
17
src/profiles/gemini.js
Normal file
17
src/profiles/gemini.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// Gemini profile for rule-transformer
|
||||
import { createProfile } from './base-profile.js';
|
||||
|
||||
// Create and export gemini profile using the base factory
|
||||
export const geminiProfile = createProfile({
|
||||
name: 'gemini',
|
||||
displayName: 'Gemini',
|
||||
url: 'codeassist.google',
|
||||
docsUrl: 'github.com/google-gemini/gemini-cli',
|
||||
profileDir: '.gemini', // Keep .gemini for settings.json
|
||||
rulesDir: '.', // Root directory for GEMINI.md
|
||||
mcpConfigName: 'settings.json', // Override default 'mcp.json'
|
||||
includeDefaultRules: false,
|
||||
fileMap: {
|
||||
'AGENTS.md': 'GEMINI.md'
|
||||
}
|
||||
});
|
||||
@@ -3,6 +3,7 @@ export { claudeProfile } from './claude.js';
|
||||
export { clineProfile } from './cline.js';
|
||||
export { codexProfile } from './codex.js';
|
||||
export { cursorProfile } from './cursor.js';
|
||||
export { geminiProfile } from './gemini.js';
|
||||
export { rooProfile } from './roo.js';
|
||||
export { traeProfile } from './trae.js';
|
||||
export { vscodeProfile } from './vscode.js';
|
||||
|
||||
@@ -110,16 +110,7 @@ export const rooProfile = createProfile({
|
||||
displayName: 'Roo Code',
|
||||
url: 'roocode.com',
|
||||
docsUrl: 'docs.roocode.com',
|
||||
profileDir: '.roo',
|
||||
rulesDir: '.roo/rules',
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'mcp.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.md',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.ROO_STYLE,
|
||||
customFileMap: {
|
||||
'cursor_rules.mdc': 'roo_rules.md'
|
||||
},
|
||||
onAdd: onAddRulesProfile,
|
||||
onRemove: onRemoveRulesProfile,
|
||||
onPostConvert: onPostConvertRulesProfile
|
||||
|
||||
@@ -7,11 +7,5 @@ export const traeProfile = createProfile({
|
||||
displayName: 'Trae',
|
||||
url: 'trae.ai',
|
||||
docsUrl: 'docs.trae.ai',
|
||||
profileDir: '.trae',
|
||||
rulesDir: '.trae/rules',
|
||||
mcpConfig: false,
|
||||
mcpConfigName: 'trae_mcp_settings.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.md',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.STANDARD // Trae uses standard tool names
|
||||
mcpConfig: false
|
||||
});
|
||||
|
||||
@@ -7,16 +7,7 @@ export const vscodeProfile = createProfile({
|
||||
displayName: 'VS Code',
|
||||
url: 'code.visualstudio.com',
|
||||
docsUrl: 'code.visualstudio.com/docs',
|
||||
profileDir: '.vscode', // MCP config location
|
||||
rulesDir: '.github/instructions', // VS Code instructions location
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'mcp.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.md',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.STANDARD, // VS Code uses standard tool names
|
||||
customFileMap: {
|
||||
'cursor_rules.mdc': 'vscode_rules.md' // Rename cursor_rules to vscode_rules
|
||||
},
|
||||
customReplacements: [
|
||||
// Core VS Code directory structure changes
|
||||
{ from: /\.cursor\/rules/g, to: '.github/instructions' },
|
||||
|
||||
@@ -6,12 +6,5 @@ export const windsurfProfile = createProfile({
|
||||
name: 'windsurf',
|
||||
displayName: 'Windsurf',
|
||||
url: 'windsurf.com',
|
||||
docsUrl: 'docs.windsurf.com',
|
||||
profileDir: '.windsurf',
|
||||
rulesDir: '.windsurf/rules',
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'mcp.json',
|
||||
fileExtension: '.mdc',
|
||||
targetExtension: '.md',
|
||||
toolMappings: COMMON_TOOL_MAPPINGS.STANDARD // Windsurf uses standard tool names
|
||||
docsUrl: 'docs.windsurf.com'
|
||||
});
|
||||
|
||||
@@ -47,15 +47,15 @@ export function setupMCPConfiguration(projectRoot, mcpConfigPath) {
|
||||
command: 'npx',
|
||||
args: ['-y', '--package=task-master-ai', 'task-master-ai'],
|
||||
env: {
|
||||
ANTHROPIC_API_KEY: 'ANTHROPIC_API_KEY_HERE',
|
||||
PERPLEXITY_API_KEY: 'PERPLEXITY_API_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'
|
||||
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',
|
||||
XAI_API_KEY: 'YOUR_XAI_KEY_HERE',
|
||||
OPENROUTER_API_KEY: 'YOUR_OPENROUTER_KEY_HERE',
|
||||
MISTRAL_API_KEY: 'YOUR_MISTRAL_KEY_HERE',
|
||||
AZURE_OPENAI_API_KEY: 'YOUR_AZURE_KEY_HERE',
|
||||
OLLAMA_API_KEY: 'YOUR_OLLAMA_API_KEY_HERE'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,57 +16,78 @@ import { RULE_PROFILES } from '../constants/profiles.js';
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Detect which profiles are currently installed in the project
|
||||
* @param {string} projectRoot - Project root directory
|
||||
* @returns {string[]} Array of installed profile names
|
||||
* Get the display name for a profile
|
||||
* @param {string} profileName - The profile name
|
||||
* @returns {string} - The display name
|
||||
*/
|
||||
export function getProfileDisplayName(profileName) {
|
||||
try {
|
||||
const profile = getRulesProfile(profileName);
|
||||
return profile.displayName || profileName;
|
||||
} catch (error) {
|
||||
return profileName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get installed profiles in the project directory
|
||||
* @param {string} projectRoot - Project directory path
|
||||
* @returns {string[]} - Array of installed profile names
|
||||
*/
|
||||
export function getInstalledProfiles(projectRoot) {
|
||||
const installedProfiles = [];
|
||||
|
||||
for (const profileName of RULE_PROFILES) {
|
||||
const profileConfig = getRulesProfile(profileName);
|
||||
if (!profileConfig) continue;
|
||||
try {
|
||||
const profile = getRulesProfile(profileName);
|
||||
const profileDir = path.join(projectRoot, profile.profileDir);
|
||||
|
||||
// Check if the profile directory exists
|
||||
const profileDir = path.join(projectRoot, profileConfig.profileDir);
|
||||
const rulesDir = path.join(projectRoot, profileConfig.rulesDir);
|
||||
|
||||
// A profile is considered installed if either the profile dir or rules dir exists
|
||||
if (fs.existsSync(profileDir) || fs.existsSync(rulesDir)) {
|
||||
// Check if profile directory exists (skip root directory check)
|
||||
if (profile.profileDir === '.' || fs.existsSync(profileDir)) {
|
||||
// Check if any files from the profile's fileMap exist
|
||||
const rulesDir = path.join(projectRoot, profile.rulesDir);
|
||||
if (fs.existsSync(rulesDir)) {
|
||||
const ruleFiles = Object.values(profile.fileMap);
|
||||
const hasRuleFiles = ruleFiles.some((ruleFile) =>
|
||||
fs.existsSync(path.join(rulesDir, ruleFile))
|
||||
);
|
||||
if (hasRuleFiles) {
|
||||
installedProfiles.push(profileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Skip profiles that can't be loaded
|
||||
}
|
||||
}
|
||||
|
||||
return installedProfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if removing the specified profiles would result in no profiles remaining
|
||||
* Check if removing specified profiles would leave no profiles installed
|
||||
* @param {string} projectRoot - Project root directory
|
||||
* @param {string[]} profilesToRemove - Array of profile names to remove
|
||||
* @returns {boolean} True if removal would result in no profiles remaining
|
||||
* @returns {boolean} - True if removal would leave no profiles
|
||||
*/
|
||||
export function wouldRemovalLeaveNoProfiles(projectRoot, profilesToRemove) {
|
||||
const installedProfiles = getInstalledProfiles(projectRoot);
|
||||
|
||||
// If no profiles are currently installed, removal cannot leave no profiles
|
||||
if (installedProfiles.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const remainingProfiles = installedProfiles.filter(
|
||||
(profile) => !profilesToRemove.includes(profile)
|
||||
);
|
||||
|
||||
return remainingProfiles.length === 0 && installedProfiles.length > 0;
|
||||
return remainingProfiles.length === 0;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// PROFILE SETUP
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Get the display name for a profile
|
||||
*/
|
||||
function getProfileDisplayName(name) {
|
||||
const profile = getRulesProfile(name);
|
||||
return profile?.displayName || name.charAt(0).toUpperCase() + name.slice(1);
|
||||
}
|
||||
|
||||
// Note: Profile choices are now generated dynamically within runInteractiveProfilesSetup()
|
||||
// to ensure proper alphabetical sorting and pagination configuration
|
||||
|
||||
@@ -86,27 +107,33 @@ export async function runInteractiveProfilesSetup() {
|
||||
const displayName = getProfileDisplayName(profileName);
|
||||
const profile = getRulesProfile(profileName);
|
||||
|
||||
// Determine description based on profile type
|
||||
// Determine description based on profile capabilities
|
||||
let description;
|
||||
if (Object.keys(profile.fileMap).length === 0) {
|
||||
// Simple profiles (Claude, Codex) - specify the target file
|
||||
const targetFileName =
|
||||
profileName === 'claude' ? 'CLAUDE.md' : 'AGENTS.md';
|
||||
description = `Integration guide (${targetFileName})`;
|
||||
} else {
|
||||
// Full profiles with rules - check if they have MCP config
|
||||
const hasRules = Object.keys(profile.fileMap).length > 0;
|
||||
const hasMcpConfig = profile.mcpConfig === true;
|
||||
if (hasMcpConfig) {
|
||||
// Special case for Roo to mention agent modes
|
||||
|
||||
if (!profile.includeDefaultRules) {
|
||||
// Integration guide profiles (claude, codex, gemini) - don't include standard coding rules
|
||||
if (profileName === 'claude') {
|
||||
description = 'Integration guide with Task Master slash commands';
|
||||
} else if (profileName === 'codex') {
|
||||
description = 'Comprehensive Task Master integration guide';
|
||||
} else if (profileName === 'gemini') {
|
||||
description = 'Integration guide and MCP config';
|
||||
} else {
|
||||
description = 'Integration guide';
|
||||
}
|
||||
} else if (hasRules && hasMcpConfig) {
|
||||
// Full rule profiles with MCP config
|
||||
if (profileName === 'roo') {
|
||||
description = 'Rule profile, MCP config, and agent modes';
|
||||
} else {
|
||||
description = 'Rule profile and MCP config';
|
||||
}
|
||||
} else {
|
||||
} else if (hasRules) {
|
||||
// Rule profiles without MCP config
|
||||
description = 'Rule profile';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
profileName,
|
||||
@@ -170,14 +197,13 @@ export async function runInteractiveProfilesSetup() {
|
||||
*/
|
||||
export function generateProfileSummary(profileName, addResult) {
|
||||
const profileConfig = getRulesProfile(profileName);
|
||||
const isSimpleProfile = Object.keys(profileConfig.fileMap).length === 0;
|
||||
|
||||
if (isSimpleProfile) {
|
||||
// Simple profiles like Claude and Codex only copy AGENTS.md
|
||||
const targetFileName = profileName === 'claude' ? 'CLAUDE.md' : 'AGENTS.md';
|
||||
return `Summary for ${profileName}: Integration guide copied to ${targetFileName}`;
|
||||
if (!profileConfig.includeDefaultRules) {
|
||||
// Integration guide profiles (claude, codex, gemini)
|
||||
return `Summary for ${profileName}: Integration guide installed.`;
|
||||
} else {
|
||||
return `Summary for ${profileName}: ${addResult.success} rules added, ${addResult.failed} failed.`;
|
||||
// Rule profiles with coding guidelines
|
||||
return `Summary for ${profileName}: ${addResult.success} files processed, ${addResult.failed} failed.`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +214,6 @@ export function generateProfileSummary(profileName, addResult) {
|
||||
* @returns {string} Formatted summary message
|
||||
*/
|
||||
export function generateProfileRemovalSummary(profileName, removeResult) {
|
||||
const profileConfig = getRulesProfile(profileName);
|
||||
const isSimpleProfile = Object.keys(profileConfig.fileMap).length === 0;
|
||||
|
||||
if (removeResult.skipped) {
|
||||
return `Summary for ${profileName}: Skipped (default or protected files)`;
|
||||
}
|
||||
@@ -199,13 +222,18 @@ export function generateProfileRemovalSummary(profileName, removeResult) {
|
||||
return `Summary for ${profileName}: Failed to remove - ${removeResult.error}`;
|
||||
}
|
||||
|
||||
if (isSimpleProfile) {
|
||||
// Simple profiles like Claude and Codex only have an integration guide
|
||||
const targetFileName = profileName === 'claude' ? 'CLAUDE.md' : 'AGENTS.md';
|
||||
return `Summary for ${profileName}: Integration guide (${targetFileName}) removed`;
|
||||
const profileConfig = getRulesProfile(profileName);
|
||||
|
||||
if (!profileConfig.includeDefaultRules) {
|
||||
// Integration guide profiles (claude, codex, gemini)
|
||||
const baseMessage = `Summary for ${profileName}: Integration guide removed`;
|
||||
if (removeResult.notice) {
|
||||
return `${baseMessage} (${removeResult.notice})`;
|
||||
}
|
||||
return baseMessage;
|
||||
} else {
|
||||
// Full profiles have rules directories and potentially MCP configs
|
||||
const baseMessage = `Summary for ${profileName}: Rules directory removed`;
|
||||
// Rule profiles with coding guidelines
|
||||
const baseMessage = `Summary for ${profileName}: Rule profile removed`;
|
||||
if (removeResult.notice) {
|
||||
return `${baseMessage} (${removeResult.notice})`;
|
||||
}
|
||||
@@ -220,7 +248,6 @@ export function generateProfileRemovalSummary(profileName, removeResult) {
|
||||
*/
|
||||
export function categorizeProfileResults(addResults) {
|
||||
const successfulProfiles = [];
|
||||
const simpleProfiles = [];
|
||||
let totalSuccess = 0;
|
||||
let totalFailed = 0;
|
||||
|
||||
@@ -228,22 +255,15 @@ export function categorizeProfileResults(addResults) {
|
||||
totalSuccess += r.success;
|
||||
totalFailed += r.failed;
|
||||
|
||||
const profileConfig = getRulesProfile(r.profileName);
|
||||
const isSimpleProfile = Object.keys(profileConfig.fileMap).length === 0;
|
||||
|
||||
if (isSimpleProfile) {
|
||||
// Simple profiles are successful if they completed without error
|
||||
simpleProfiles.push(r.profileName);
|
||||
} else if (r.success > 0) {
|
||||
// Full profiles are successful if they added rules
|
||||
// All profiles are considered successful if they completed without major errors
|
||||
if (r.success > 0 || r.failed === 0) {
|
||||
successfulProfiles.push(r.profileName);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
successfulProfiles,
|
||||
simpleProfiles,
|
||||
allSuccessfulProfiles: [...successfulProfiles, ...simpleProfiles],
|
||||
allSuccessfulProfiles: successfulProfiles,
|
||||
totalSuccess,
|
||||
totalFailed
|
||||
};
|
||||
|
||||
@@ -199,50 +199,53 @@ export function convertRuleToProfileRule(sourcePath, targetPath, profile) {
|
||||
* Convert all Cursor rules to profile rules for a specific profile
|
||||
*/
|
||||
export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
// Handle simple profiles (Claude, Codex) that just copy files to root
|
||||
const isSimpleProfile = Object.keys(profile.fileMap).length === 0;
|
||||
if (isSimpleProfile) {
|
||||
// For simple profiles, just call their post-processing hook and return
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const assetsDir = path.join(__dirname, '..', '..', 'assets');
|
||||
|
||||
if (typeof profile.onPostConvertRulesProfile === 'function') {
|
||||
profile.onPostConvertRulesProfile(projectRoot, assetsDir);
|
||||
}
|
||||
return { success: 1, failed: 0 };
|
||||
}
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const sourceDir = path.join(__dirname, '..', '..', 'assets', 'rules');
|
||||
const targetDir = path.join(projectRoot, profile.rulesDir);
|
||||
|
||||
// Ensure target directory exists
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Setup MCP configuration if enabled
|
||||
if (profile.mcpConfig !== false) {
|
||||
setupMCPConfiguration(projectRoot, profile.mcpConfigPath);
|
||||
}
|
||||
const assetsDir = path.join(__dirname, '..', '..', 'assets');
|
||||
|
||||
let success = 0;
|
||||
let failed = 0;
|
||||
|
||||
// Use fileMap to determine which files to copy
|
||||
// 1. Call onAddRulesProfile first (for pre-processing like copying assets)
|
||||
if (typeof profile.onAddRulesProfile === 'function') {
|
||||
try {
|
||||
profile.onAddRulesProfile(projectRoot, assetsDir);
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Called onAddRulesProfile for ${profile.profileName}`
|
||||
);
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] onAddRulesProfile failed for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Handle fileMap-based rule conversion (if any)
|
||||
const sourceFiles = Object.keys(profile.fileMap);
|
||||
if (sourceFiles.length > 0) {
|
||||
// Only create rules directory if we have files to copy
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
|
||||
for (const sourceFile of sourceFiles) {
|
||||
// Determine if this is an asset file (not a rule file)
|
||||
const isAssetFile = !sourceFile.startsWith('rules/');
|
||||
|
||||
try {
|
||||
const sourcePath = path.join(sourceDir, sourceFile);
|
||||
// Use explicit path from fileMap - assets/ is the base directory
|
||||
const sourcePath = path.join(assetsDir, sourceFile);
|
||||
|
||||
// Check if source file exists
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
log(
|
||||
'warn',
|
||||
`[Rule Transformer] Source file not found: ${sourceFile}, skipping`
|
||||
`[Rule Transformer] Source file not found: ${sourcePath}, skipping`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -259,12 +262,14 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
// Read source content
|
||||
let content = fs.readFileSync(sourcePath, 'utf8');
|
||||
|
||||
// Apply transformations
|
||||
// Apply transformations (only if this is a rule file, not an asset file)
|
||||
if (!isAssetFile) {
|
||||
content = transformRuleContent(
|
||||
content,
|
||||
profile.conversionConfig,
|
||||
profile.globalReplacements
|
||||
);
|
||||
}
|
||||
|
||||
// Write to target
|
||||
fs.writeFileSync(targetPath, content, 'utf8');
|
||||
@@ -272,24 +277,52 @@ export function convertAllRulesToProfileRules(projectRoot, profile) {
|
||||
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Converted ${sourceFile} -> ${targetFilename} for ${profile.profileName}`
|
||||
`[Rule Transformer] ${isAssetFile ? 'Copied' : 'Converted'} ${sourceFile} -> ${targetFilename} for ${profile.profileName}`
|
||||
);
|
||||
} catch (error) {
|
||||
failed++;
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] Failed to convert ${sourceFile} for ${profile.profileName}: ${error.message}`
|
||||
`[Rule Transformer] Failed to ${isAssetFile ? 'copy' : 'convert'} ${sourceFile} for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Setup MCP configuration (if enabled)
|
||||
if (profile.mcpConfig !== false) {
|
||||
try {
|
||||
setupMCPConfiguration(projectRoot, profile.mcpConfigPath);
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Setup MCP configuration for ${profile.profileName}`
|
||||
);
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] MCP setup failed for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Call post-processing hook if defined (e.g., for Roo's rules-*mode* folders)
|
||||
// 4. Call post-conversion hook (for finalization)
|
||||
if (typeof profile.onPostConvertRulesProfile === 'function') {
|
||||
const assetsDir = path.join(__dirname, '..', '..', 'assets');
|
||||
try {
|
||||
profile.onPostConvertRulesProfile(projectRoot, assetsDir);
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Called onPostConvertRulesProfile for ${profile.profileName}`
|
||||
);
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] onPostConvertRulesProfile failed for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { success, failed };
|
||||
// Ensure we return at least 1 success for profiles that only use lifecycle functions
|
||||
return { success: Math.max(success, 1), failed };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,22 +347,25 @@ export function removeProfileRules(projectRoot, profile) {
|
||||
};
|
||||
|
||||
try {
|
||||
// Handle simple profiles (Claude, Codex) that just copy files to root
|
||||
const isSimpleProfile = Object.keys(profile.fileMap).length === 0;
|
||||
|
||||
if (isSimpleProfile) {
|
||||
// For simple profiles, just call their removal hook and return
|
||||
// 1. Call onRemoveRulesProfile first (for custom cleanup like removing assets)
|
||||
if (typeof profile.onRemoveRulesProfile === 'function') {
|
||||
try {
|
||||
profile.onRemoveRulesProfile(projectRoot);
|
||||
}
|
||||
result.success = true;
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Successfully removed ${profile.profileName} files from ${projectRoot}`
|
||||
`[Rule Transformer] Called onRemoveRulesProfile for ${profile.profileName}`
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] onRemoveRulesProfile failed for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Remove fileMap-based files (if any)
|
||||
const sourceFiles = Object.keys(profile.fileMap);
|
||||
if (sourceFiles.length > 0) {
|
||||
// Check if profile directory exists at all (for full profiles)
|
||||
if (!fs.existsSync(profileDir)) {
|
||||
result.success = true;
|
||||
@@ -341,68 +377,51 @@ export function removeProfileRules(projectRoot, profile) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// 1. Remove only Task Master specific files from the rules directory
|
||||
let hasOtherRulesFiles = false;
|
||||
|
||||
if (fs.existsSync(targetDir)) {
|
||||
const taskmasterFiles = Object.values(profile.fileMap);
|
||||
const removedFiles = [];
|
||||
// Get list of files we're responsible for
|
||||
const taskMasterFiles = sourceFiles.map(
|
||||
(sourceFile) => profile.fileMap[sourceFile]
|
||||
);
|
||||
|
||||
// Helper function to recursively check and remove Task Master files
|
||||
function processDirectory(dirPath, relativePath = '') {
|
||||
const items = fs.readdirSync(dirPath);
|
||||
// Get all files in the rules directory
|
||||
const allFiles = fs.readdirSync(targetDir, { recursive: true });
|
||||
const allFilePaths = allFiles
|
||||
.filter((file) => {
|
||||
const fullPath = path.join(targetDir, file);
|
||||
return fs.statSync(fullPath).isFile();
|
||||
})
|
||||
.map((file) => file.toString()); // Ensure it's a string
|
||||
|
||||
for (const item of items) {
|
||||
const itemPath = path.join(dirPath, item);
|
||||
const relativeItemPath = relativePath
|
||||
? path.join(relativePath, item)
|
||||
: item;
|
||||
const stat = fs.statSync(itemPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// Recursively process subdirectory
|
||||
processDirectory(itemPath, relativeItemPath);
|
||||
|
||||
// Check if directory is empty after processing and remove if so
|
||||
// Remove only Task Master files
|
||||
for (const taskMasterFile of taskMasterFiles) {
|
||||
const filePath = path.join(targetDir, taskMasterFile);
|
||||
if (fs.existsSync(filePath)) {
|
||||
try {
|
||||
const remainingItems = fs.readdirSync(itemPath);
|
||||
if (remainingItems.length === 0) {
|
||||
fs.rmSync(itemPath, { recursive: true, force: true });
|
||||
fs.rmSync(filePath, { force: true });
|
||||
result.filesRemoved.push(taskMasterFile);
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Removed empty directory: ${relativeItemPath}`
|
||||
`[Rule Transformer] Removed Task Master file: ${taskMasterFile}`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// Directory might have been removed already, ignore
|
||||
}
|
||||
} else if (stat.isFile()) {
|
||||
if (taskmasterFiles.includes(relativeItemPath)) {
|
||||
// This is a Task Master file, remove it
|
||||
fs.rmSync(itemPath, { force: true });
|
||||
removedFiles.push(relativeItemPath);
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Removed Task Master file: ${relativeItemPath}`
|
||||
);
|
||||
} else {
|
||||
// This is not a Task Master file, leave it
|
||||
hasOtherRulesFiles = true;
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Preserved existing file: ${relativeItemPath}`
|
||||
'error',
|
||||
`[Rule Transformer] Failed to remove ${taskMasterFile}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process the rules directory recursively
|
||||
processDirectory(targetDir);
|
||||
// Check for other (non-Task Master) files
|
||||
const remainingFiles = allFilePaths.filter(
|
||||
(file) => !taskMasterFiles.includes(file)
|
||||
);
|
||||
|
||||
result.filesRemoved = removedFiles;
|
||||
hasOtherRulesFiles = remainingFiles.length > 0;
|
||||
|
||||
// Only remove the rules directory if it's empty after removing Task Master files
|
||||
const remainingFiles = fs.readdirSync(targetDir);
|
||||
// Remove empty directories or note preserved files
|
||||
if (remainingFiles.length === 0) {
|
||||
fs.rmSync(targetDir, { recursive: true, force: true });
|
||||
log(
|
||||
@@ -414,9 +433,11 @@ export function removeProfileRules(projectRoot, profile) {
|
||||
log('info', `[Rule Transformer] ${result.notice}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Handle MCP configuration - only remove Task Master, preserve other servers
|
||||
// 3. Handle MCP configuration - only remove Task Master, preserve other servers
|
||||
if (profile.mcpConfig !== false) {
|
||||
try {
|
||||
result.mcpResult = removeTaskMasterMCPConfiguration(
|
||||
projectRoot,
|
||||
profile.mcpConfigPath
|
||||
@@ -428,62 +449,45 @@ export function removeProfileRules(projectRoot, profile) {
|
||||
result.notice += '; preserved other MCP server configurations';
|
||||
}
|
||||
}
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Processed MCP configuration for ${profile.profileName}`
|
||||
);
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] MCP cleanup failed for ${profile.profileName}: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Call removal hook if defined (e.g., Roo's custom cleanup)
|
||||
if (typeof profile.onRemoveRulesProfile === 'function') {
|
||||
profile.onRemoveRulesProfile(projectRoot);
|
||||
}
|
||||
|
||||
// 4. Only remove profile directory if:
|
||||
// - It's completely empty after all operations, AND
|
||||
// - All rules removed were Task Master rules (no existing rules preserved), AND
|
||||
// - MCP config was completely deleted (not just Task Master removed), AND
|
||||
// - No other files or folders exist in the profile directory
|
||||
// 4. Check if we should remove the entire profile directory
|
||||
if (fs.existsSync(profileDir)) {
|
||||
const remaining = fs.readdirSync(profileDir);
|
||||
const allRulesWereTaskMaster = !hasOtherRulesFiles;
|
||||
const mcpConfigCompletelyDeleted = result.mcpResult?.deleted === true;
|
||||
|
||||
// Check if there are any other files or folders beyond what we expect
|
||||
const hasOtherFilesOrFolders = remaining.length > 0;
|
||||
|
||||
if (
|
||||
remaining.length === 0 &&
|
||||
allRulesWereTaskMaster &&
|
||||
(profile.mcpConfig === false || mcpConfigCompletelyDeleted) &&
|
||||
!hasOtherFilesOrFolders
|
||||
) {
|
||||
const remainingContents = fs.readdirSync(profileDir);
|
||||
if (remainingContents.length === 0 && profile.profileDir !== '.') {
|
||||
// Only remove profile directory if it's empty and not root directory
|
||||
try {
|
||||
fs.rmSync(profileDir, { recursive: true, force: true });
|
||||
result.profileDirRemoved = true;
|
||||
log(
|
||||
'debug',
|
||||
`[Rule Transformer] Removed profile directory: ${profileDir} (completely empty, all rules were Task Master rules, and MCP config was completely removed)`
|
||||
`[Rule Transformer] Removed empty profile directory: ${profileDir}`
|
||||
);
|
||||
} else {
|
||||
// Determine what was preserved and why
|
||||
const preservationReasons = [];
|
||||
if (hasOtherFilesOrFolders) {
|
||||
preservationReasons.push(
|
||||
`${remaining.length} existing files/folders`
|
||||
} catch (error) {
|
||||
log(
|
||||
'error',
|
||||
`[Rule Transformer] Failed to remove profile directory ${profileDir}: ${error.message}`
|
||||
);
|
||||
}
|
||||
if (hasOtherRulesFiles) {
|
||||
preservationReasons.push('existing rule files');
|
||||
}
|
||||
if (result.mcpResult?.hasOtherServers) {
|
||||
preservationReasons.push('other MCP server configurations');
|
||||
}
|
||||
|
||||
const preservationMessage = `Preserved ${preservationReasons.join(', ')} in ${profile.profileDir}`;
|
||||
|
||||
} else if (remainingContents.length > 0) {
|
||||
// Profile directory has remaining files/folders, add notice
|
||||
const preservedNotice = `Preserved ${remainingContents.length} existing files/folders in ${profile.profileDir}`;
|
||||
if (!result.notice) {
|
||||
result.notice = preservationMessage;
|
||||
} else if (!result.notice.includes('Preserved')) {
|
||||
result.notice += `; ${preservationMessage.toLowerCase()}`;
|
||||
result.notice = preservedNotice;
|
||||
} else {
|
||||
result.notice += `; ${preservedNotice.toLowerCase()}`;
|
||||
}
|
||||
|
||||
log('info', `[Rule Transformer] ${preservationMessage}`);
|
||||
log('info', `[Rule Transformer] ${preservedNotice}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { claudeProfile } from '../../../src/profiles/claude.js';
|
||||
|
||||
describe('Claude Profile Initialization Functionality', () => {
|
||||
let claudeProfileContent;
|
||||
@@ -14,23 +15,25 @@ describe('Claude Profile Initialization Functionality', () => {
|
||||
claudeProfileContent = fs.readFileSync(claudeJsPath, 'utf8');
|
||||
});
|
||||
|
||||
test('claude.js is a simple profile with correct configuration', () => {
|
||||
expect(claudeProfileContent).toContain("profileName: 'claude'");
|
||||
test('claude.js has correct asset-only profile configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(claudeProfileContent).toContain("name: 'claude'");
|
||||
expect(claudeProfileContent).toContain("displayName: 'Claude Code'");
|
||||
expect(claudeProfileContent).toContain("profileDir: '.'");
|
||||
expect(claudeProfileContent).toContain("rulesDir: '.'");
|
||||
});
|
||||
expect(claudeProfileContent).toContain("profileDir: '.'"); // non-default
|
||||
expect(claudeProfileContent).toContain("rulesDir: '.'"); // non-default
|
||||
expect(claudeProfileContent).toContain('mcpConfig: false'); // non-default
|
||||
expect(claudeProfileContent).toContain('includeDefaultRules: false'); // non-default
|
||||
expect(claudeProfileContent).toContain("'AGENTS.md': 'CLAUDE.md'");
|
||||
|
||||
test('claude.js has no MCP configuration', () => {
|
||||
expect(claudeProfileContent).toContain('mcpConfig: false');
|
||||
expect(claudeProfileContent).toContain('mcpConfigName: null');
|
||||
expect(claudeProfileContent).toContain('mcpConfigPath: null');
|
||||
});
|
||||
|
||||
test('claude.js has empty file map (simple profile)', () => {
|
||||
expect(claudeProfileContent).toContain('fileMap: {}');
|
||||
expect(claudeProfileContent).toContain('conversionConfig: {}');
|
||||
expect(claudeProfileContent).toContain('globalReplacements: []');
|
||||
// Check the final computed properties on the profile object
|
||||
expect(claudeProfile.profileName).toBe('claude');
|
||||
expect(claudeProfile.displayName).toBe('Claude Code');
|
||||
expect(claudeProfile.profileDir).toBe('.');
|
||||
expect(claudeProfile.rulesDir).toBe('.');
|
||||
expect(claudeProfile.mcpConfig).toBe(false);
|
||||
expect(claudeProfile.mcpConfigName).toBe(null); // computed
|
||||
expect(claudeProfile.includeDefaultRules).toBe(false);
|
||||
expect(claudeProfile.fileMap['AGENTS.md']).toBe('CLAUDE.md');
|
||||
});
|
||||
|
||||
test('claude.js has lifecycle functions for file management', () => {
|
||||
@@ -41,13 +44,12 @@ describe('Claude Profile Initialization Functionality', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('claude.js copies AGENTS.md to CLAUDE.md', () => {
|
||||
expect(claudeProfileContent).toContain("'AGENTS.md'");
|
||||
expect(claudeProfileContent).toContain("'CLAUDE.md'");
|
||||
expect(claudeProfileContent).toContain('copyFileSync');
|
||||
test('claude.js handles .claude directory in lifecycle functions', () => {
|
||||
expect(claudeProfileContent).toContain('.claude');
|
||||
expect(claudeProfileContent).toContain('copyRecursiveSync');
|
||||
});
|
||||
|
||||
test('claude.js has proper error handling', () => {
|
||||
test('claude.js has proper error handling in lifecycle functions', () => {
|
||||
expect(claudeProfileContent).toContain('try {');
|
||||
expect(claudeProfileContent).toContain('} catch (err) {');
|
||||
expect(claudeProfileContent).toContain("log('error'");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { clineProfile } from '../../../src/profiles/cline.js';
|
||||
|
||||
describe('Cline Profile Initialization Functionality', () => {
|
||||
let clineProfileContent;
|
||||
@@ -10,39 +11,48 @@ describe('Cline Profile Initialization Functionality', () => {
|
||||
});
|
||||
|
||||
test('cline.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(clineProfileContent).toContain("name: 'cline'");
|
||||
expect(clineProfileContent).toContain("displayName: 'Cline'");
|
||||
expect(clineProfileContent).toContain("rulesDir: '.clinerules'");
|
||||
expect(clineProfileContent).toContain("profileDir: '.clinerules'");
|
||||
expect(clineProfileContent).toContain("profileDir: '.clinerules'"); // non-default
|
||||
expect(clineProfileContent).toContain("rulesDir: '.clinerules'"); // non-default
|
||||
expect(clineProfileContent).toContain('mcpConfig: false'); // non-default
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(clineProfile.profileName).toBe('cline');
|
||||
expect(clineProfile.displayName).toBe('Cline');
|
||||
expect(clineProfile.profileDir).toBe('.clinerules');
|
||||
expect(clineProfile.rulesDir).toBe('.clinerules');
|
||||
expect(clineProfile.mcpConfig).toBe(false);
|
||||
expect(clineProfile.mcpConfigName).toBe(null);
|
||||
});
|
||||
|
||||
test('cline.js configures .mdc to .md extension mapping', () => {
|
||||
expect(clineProfileContent).toContain("fileExtension: '.mdc'");
|
||||
expect(clineProfileContent).toContain("targetExtension: '.md'");
|
||||
});
|
||||
|
||||
test('cline.js uses standard tool mappings', () => {
|
||||
expect(clineProfileContent).toContain('COMMON_TOOL_MAPPINGS.STANDARD');
|
||||
// Should contain comment about standard tool names
|
||||
expect(clineProfileContent).toContain('standard tool names');
|
||||
});
|
||||
|
||||
test('cline.js contains correct URL configuration', () => {
|
||||
expect(clineProfileContent).toContain("url: 'cline.bot'");
|
||||
expect(clineProfileContent).toContain("docsUrl: 'docs.cline.bot'");
|
||||
});
|
||||
|
||||
test('cline.js has MCP configuration disabled', () => {
|
||||
expect(clineProfileContent).toContain('mcpConfig: false');
|
||||
expect(clineProfileContent).toContain(
|
||||
"mcpConfigName: 'cline_mcp_settings.json'"
|
||||
// Check that the profile object has the correct file mapping behavior (cline converts to .md)
|
||||
expect(clineProfile.fileMap['rules/cursor_rules.mdc']).toBe(
|
||||
'cline_rules.md'
|
||||
);
|
||||
});
|
||||
|
||||
test('cline.js uses standard tool mappings', () => {
|
||||
// Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD)
|
||||
// This verifies the architectural pattern: no custom toolMappings = standard tool names
|
||||
expect(clineProfileContent).not.toContain('toolMappings:');
|
||||
expect(clineProfileContent).not.toContain('apply_diff');
|
||||
expect(clineProfileContent).not.toContain('search_files');
|
||||
|
||||
// Verify the result: default mappings means tools keep their original names
|
||||
expect(clineProfile.conversionConfig.toolNames.edit_file).toBe('edit_file');
|
||||
expect(clineProfile.conversionConfig.toolNames.search).toBe('search');
|
||||
});
|
||||
|
||||
test('cline.js has custom file mapping for cursor_rules.mdc', () => {
|
||||
expect(clineProfileContent).toContain('customFileMap:');
|
||||
expect(clineProfileContent).toContain(
|
||||
"'cursor_rules.mdc': 'cline_rules.md'"
|
||||
// Check actual behavior - cline gets default rule files
|
||||
expect(Object.keys(clineProfile.fileMap)).toContain(
|
||||
'rules/cursor_rules.mdc'
|
||||
);
|
||||
expect(clineProfile.fileMap['rules/cursor_rules.mdc']).toBe(
|
||||
'cline_rules.md'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { codexProfile } from '../../../src/profiles/codex.js';
|
||||
|
||||
describe('Codex Profile Initialization Functionality', () => {
|
||||
let codexProfileContent;
|
||||
@@ -9,46 +10,41 @@ describe('Codex Profile Initialization Functionality', () => {
|
||||
codexProfileContent = fs.readFileSync(codexJsPath, 'utf8');
|
||||
});
|
||||
|
||||
test('codex.js is a simple profile with correct configuration', () => {
|
||||
expect(codexProfileContent).toContain("profileName: 'codex'");
|
||||
test('codex.js has correct asset-only profile configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(codexProfileContent).toContain("name: 'codex'");
|
||||
expect(codexProfileContent).toContain("displayName: 'Codex'");
|
||||
expect(codexProfileContent).toContain("profileDir: '.'");
|
||||
expect(codexProfileContent).toContain("rulesDir: '.'");
|
||||
expect(codexProfileContent).toContain("profileDir: '.'"); // non-default
|
||||
expect(codexProfileContent).toContain("rulesDir: '.'"); // non-default
|
||||
expect(codexProfileContent).toContain('mcpConfig: false'); // non-default
|
||||
expect(codexProfileContent).toContain('includeDefaultRules: false'); // non-default
|
||||
expect(codexProfileContent).toContain("'AGENTS.md': 'AGENTS.md'");
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(codexProfile.profileName).toBe('codex');
|
||||
expect(codexProfile.displayName).toBe('Codex');
|
||||
expect(codexProfile.profileDir).toBe('.');
|
||||
expect(codexProfile.rulesDir).toBe('.');
|
||||
expect(codexProfile.mcpConfig).toBe(false);
|
||||
expect(codexProfile.mcpConfigName).toBe(null); // computed
|
||||
expect(codexProfile.includeDefaultRules).toBe(false);
|
||||
expect(codexProfile.fileMap['AGENTS.md']).toBe('AGENTS.md');
|
||||
});
|
||||
|
||||
test('codex.js has no MCP configuration', () => {
|
||||
expect(codexProfileContent).toContain('mcpConfig: false');
|
||||
expect(codexProfileContent).toContain('mcpConfigName: null');
|
||||
expect(codexProfileContent).toContain('mcpConfigPath: null');
|
||||
test('codex.js has no lifecycle functions', () => {
|
||||
// Codex has been simplified - no lifecycle functions
|
||||
expect(codexProfileContent).not.toContain('function onAddRulesProfile');
|
||||
expect(codexProfileContent).not.toContain('function onRemoveRulesProfile');
|
||||
expect(codexProfileContent).not.toContain(
|
||||
'function onPostConvertRulesProfile'
|
||||
);
|
||||
expect(codexProfileContent).not.toContain('log(');
|
||||
});
|
||||
|
||||
test('codex.js has empty file map (simple profile)', () => {
|
||||
expect(codexProfileContent).toContain('fileMap: {}');
|
||||
expect(codexProfileContent).toContain('conversionConfig: {}');
|
||||
expect(codexProfileContent).toContain('globalReplacements: []');
|
||||
});
|
||||
|
||||
test('codex.js has lifecycle functions for file management', () => {
|
||||
expect(codexProfileContent).toContain('function onAddRulesProfile');
|
||||
expect(codexProfileContent).toContain('function onRemoveRulesProfile');
|
||||
expect(codexProfileContent).toContain('function onPostConvertRulesProfile');
|
||||
});
|
||||
|
||||
test('codex.js copies AGENTS.md to AGENTS.md (same filename)', () => {
|
||||
expect(codexProfileContent).toContain("'AGENTS.md'");
|
||||
expect(codexProfileContent).toContain('copyFileSync');
|
||||
// Should copy to the same filename (AGENTS.md)
|
||||
expect(codexProfileContent).toMatch(/destFile.*AGENTS\.md/);
|
||||
});
|
||||
|
||||
test('codex.js has proper error handling', () => {
|
||||
expect(codexProfileContent).toContain('try {');
|
||||
expect(codexProfileContent).toContain('} catch (err) {');
|
||||
expect(codexProfileContent).toContain("log('error'");
|
||||
});
|
||||
|
||||
test('codex.js removes AGENTS.md on profile removal', () => {
|
||||
expect(codexProfileContent).toContain('rmSync');
|
||||
expect(codexProfileContent).toContain('force: true');
|
||||
test('codex.js has minimal implementation', () => {
|
||||
// Should just use createProfile factory
|
||||
expect(codexProfileContent).toContain('createProfile({');
|
||||
expect(codexProfileContent).toContain("name: 'codex'");
|
||||
expect(codexProfileContent).toContain("'AGENTS.md': 'AGENTS.md'");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { cursorProfile } from '../../../src/profiles/cursor.js';
|
||||
|
||||
describe('Cursor Profile Initialization Functionality', () => {
|
||||
let cursorProfileContent;
|
||||
@@ -15,30 +16,42 @@ describe('Cursor Profile Initialization Functionality', () => {
|
||||
});
|
||||
|
||||
test('cursor.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(cursorProfileContent).toContain("name: 'cursor'");
|
||||
expect(cursorProfileContent).toContain("displayName: 'Cursor'");
|
||||
expect(cursorProfileContent).toContain("rulesDir: '.cursor/rules'");
|
||||
expect(cursorProfileContent).toContain("profileDir: '.cursor'");
|
||||
expect(cursorProfileContent).toContain("url: 'cursor.so'");
|
||||
expect(cursorProfileContent).toContain("docsUrl: 'docs.cursor.com'");
|
||||
expect(cursorProfileContent).toContain("targetExtension: '.mdc'"); // non-default
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(cursorProfile.profileName).toBe('cursor');
|
||||
expect(cursorProfile.displayName).toBe('Cursor');
|
||||
expect(cursorProfile.profileDir).toBe('.cursor'); // default
|
||||
expect(cursorProfile.rulesDir).toBe('.cursor/rules'); // default
|
||||
expect(cursorProfile.mcpConfig).toBe(true); // default
|
||||
expect(cursorProfile.mcpConfigName).toBe('mcp.json'); // default
|
||||
});
|
||||
|
||||
test('cursor.js preserves .mdc extension in both input and output', () => {
|
||||
expect(cursorProfileContent).toContain("fileExtension: '.mdc'");
|
||||
expect(cursorProfileContent).toContain("targetExtension: '.mdc'");
|
||||
// Should preserve cursor_rules.mdc filename
|
||||
expect(cursorProfileContent).toContain(
|
||||
"'cursor_rules.mdc': 'cursor_rules.mdc'"
|
||||
// Check that the profile object has the correct file mapping behavior (cursor keeps .mdc)
|
||||
expect(cursorProfile.fileMap['rules/cursor_rules.mdc']).toBe(
|
||||
'cursor_rules.mdc'
|
||||
);
|
||||
// Also check that targetExtension is explicitly set in the file
|
||||
expect(cursorProfileContent).toContain("targetExtension: '.mdc'");
|
||||
});
|
||||
|
||||
test('cursor.js uses standard tool mappings (no tool renaming)', () => {
|
||||
expect(cursorProfileContent).toContain('COMMON_TOOL_MAPPINGS.STANDARD');
|
||||
// Should not contain custom tool mappings since cursor keeps original names
|
||||
expect(cursorProfileContent).not.toContain('edit_file');
|
||||
// Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD)
|
||||
// This verifies the architectural pattern: no custom toolMappings = standard tool names
|
||||
expect(cursorProfileContent).not.toContain('toolMappings:');
|
||||
expect(cursorProfileContent).not.toContain('apply_diff');
|
||||
});
|
||||
expect(cursorProfileContent).not.toContain('search_files');
|
||||
|
||||
test('cursor.js contains correct URL configuration', () => {
|
||||
expect(cursorProfileContent).toContain("url: 'cursor.so'");
|
||||
expect(cursorProfileContent).toContain("docsUrl: 'docs.cursor.com'");
|
||||
// Verify the result: default mappings means tools keep their original names
|
||||
expect(cursorProfile.conversionConfig.toolNames.edit_file).toBe(
|
||||
'edit_file'
|
||||
);
|
||||
expect(cursorProfile.conversionConfig.toolNames.search).toBe('search');
|
||||
});
|
||||
});
|
||||
|
||||
72
tests/integration/profiles/gemini-init-functionality.test.js
Normal file
72
tests/integration/profiles/gemini-init-functionality.test.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { geminiProfile } from '../../../src/profiles/gemini.js';
|
||||
|
||||
describe('Gemini Profile Initialization Functionality', () => {
|
||||
let geminiProfileContent;
|
||||
|
||||
beforeAll(() => {
|
||||
const geminiJsPath = path.join(
|
||||
process.cwd(),
|
||||
'src',
|
||||
'profiles',
|
||||
'gemini.js'
|
||||
);
|
||||
geminiProfileContent = fs.readFileSync(geminiJsPath, 'utf8');
|
||||
});
|
||||
|
||||
test('gemini.js has correct profile configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(geminiProfileContent).toContain("name: 'gemini'");
|
||||
expect(geminiProfileContent).toContain("displayName: 'Gemini'");
|
||||
expect(geminiProfileContent).toContain("url: 'codeassist.google'");
|
||||
expect(geminiProfileContent).toContain(
|
||||
"docsUrl: 'github.com/google-gemini/gemini-cli'"
|
||||
);
|
||||
expect(geminiProfileContent).toContain("profileDir: '.gemini'");
|
||||
expect(geminiProfileContent).toContain("rulesDir: '.'"); // non-default
|
||||
expect(geminiProfileContent).toContain("mcpConfigName: 'settings.json'"); // non-default
|
||||
expect(geminiProfileContent).toContain('includeDefaultRules: false'); // non-default
|
||||
expect(geminiProfileContent).toContain("'AGENTS.md': 'GEMINI.md'");
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(geminiProfile.profileName).toBe('gemini');
|
||||
expect(geminiProfile.displayName).toBe('Gemini');
|
||||
expect(geminiProfile.profileDir).toBe('.gemini');
|
||||
expect(geminiProfile.rulesDir).toBe('.');
|
||||
expect(geminiProfile.mcpConfig).toBe(true); // computed from mcpConfigName
|
||||
expect(geminiProfile.mcpConfigName).toBe('settings.json');
|
||||
expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json'); // computed
|
||||
expect(geminiProfile.includeDefaultRules).toBe(false);
|
||||
expect(geminiProfile.fileMap['AGENTS.md']).toBe('GEMINI.md');
|
||||
});
|
||||
|
||||
test('gemini.js has no lifecycle functions', () => {
|
||||
// Gemini profile should not have any lifecycle functions
|
||||
expect(geminiProfileContent).not.toContain('function onAddRulesProfile');
|
||||
expect(geminiProfileContent).not.toContain('function onRemoveRulesProfile');
|
||||
expect(geminiProfileContent).not.toContain(
|
||||
'function onPostConvertRulesProfile'
|
||||
);
|
||||
expect(geminiProfileContent).not.toContain('onAddRulesProfile:');
|
||||
expect(geminiProfileContent).not.toContain('onRemoveRulesProfile:');
|
||||
expect(geminiProfileContent).not.toContain('onPostConvertRulesProfile:');
|
||||
});
|
||||
|
||||
test('gemini.js uses custom MCP config name', () => {
|
||||
// Gemini uses settings.json instead of mcp.json
|
||||
expect(geminiProfileContent).toContain("mcpConfigName: 'settings.json'");
|
||||
// Should not contain mcp.json as a config value (comments are OK)
|
||||
expect(geminiProfileContent).not.toMatch(
|
||||
/mcpConfigName:\s*['"]mcp\.json['"]/
|
||||
);
|
||||
});
|
||||
|
||||
test('gemini.js has minimal implementation', () => {
|
||||
// Verify the profile is minimal (no extra functions or logic)
|
||||
const lines = geminiProfileContent.split('\n');
|
||||
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
||||
// Should be around 16 lines (import, export, and profile definition)
|
||||
expect(nonEmptyLines.length).toBeLessThan(20);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,8 @@
|
||||
import { jest } from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { rooProfile } from '../../../src/profiles/roo.js';
|
||||
import { COMMON_TOOL_MAPPINGS } from '../../../src/profiles/base-profile.js';
|
||||
|
||||
describe('Roo Profile Initialization Functionality', () => {
|
||||
let rooProfileContent;
|
||||
@@ -11,6 +13,33 @@ describe('Roo Profile Initialization Functionality', () => {
|
||||
rooProfileContent = fs.readFileSync(rooJsPath, 'utf8');
|
||||
});
|
||||
|
||||
test('roo.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(rooProfileContent).toContain("name: 'roo'");
|
||||
expect(rooProfileContent).toContain("displayName: 'Roo Code'");
|
||||
expect(rooProfileContent).toContain(
|
||||
'toolMappings: COMMON_TOOL_MAPPINGS.ROO_STYLE'
|
||||
);
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(rooProfile.profileName).toBe('roo');
|
||||
expect(rooProfile.displayName).toBe('Roo Code');
|
||||
expect(rooProfile.profileDir).toBe('.roo'); // default
|
||||
expect(rooProfile.rulesDir).toBe('.roo/rules'); // default
|
||||
expect(rooProfile.mcpConfig).toBe(true); // default
|
||||
});
|
||||
|
||||
test('roo.js uses custom ROO_STYLE tool mappings', () => {
|
||||
// Check that the profile uses the correct, non-standard tool mappings
|
||||
expect(rooProfileContent).toContain(
|
||||
'toolMappings: COMMON_TOOL_MAPPINGS.ROO_STYLE'
|
||||
);
|
||||
|
||||
// Verify the result: roo uses custom tool names
|
||||
expect(rooProfile.conversionConfig.toolNames.edit_file).toBe('apply_diff');
|
||||
expect(rooProfile.conversionConfig.toolNames.search).toBe('search_files');
|
||||
});
|
||||
|
||||
test('roo.js profile ensures Roo directory structure via onAddRulesProfile', () => {
|
||||
// Check if onAddRulesProfile function exists
|
||||
expect(rooProfileContent).toContain(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { traeProfile } from '../../../src/profiles/trae.js';
|
||||
|
||||
describe('Trae Profile Initialization Functionality', () => {
|
||||
let traeProfileContent;
|
||||
@@ -10,32 +11,36 @@ describe('Trae Profile Initialization Functionality', () => {
|
||||
});
|
||||
|
||||
test('trae.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(traeProfileContent).toContain("name: 'trae'");
|
||||
expect(traeProfileContent).toContain("displayName: 'Trae'");
|
||||
expect(traeProfileContent).toContain("rulesDir: '.trae/rules'");
|
||||
expect(traeProfileContent).toContain("profileDir: '.trae'");
|
||||
expect(traeProfileContent).toContain("url: 'trae.ai'");
|
||||
expect(traeProfileContent).toContain("docsUrl: 'docs.trae.ai'");
|
||||
expect(traeProfileContent).toContain('mcpConfig: false');
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(traeProfile.profileName).toBe('trae');
|
||||
expect(traeProfile.displayName).toBe('Trae');
|
||||
expect(traeProfile.profileDir).toBe('.trae'); // default
|
||||
expect(traeProfile.rulesDir).toBe('.trae/rules'); // default
|
||||
expect(traeProfile.mcpConfig).toBe(false); // non-default
|
||||
expect(traeProfile.mcpConfigName).toBe(null); // computed from mcpConfig
|
||||
});
|
||||
|
||||
test('trae.js configures .mdc to .md extension mapping', () => {
|
||||
expect(traeProfileContent).toContain("fileExtension: '.mdc'");
|
||||
expect(traeProfileContent).toContain("targetExtension: '.md'");
|
||||
// Check that the profile object has the correct file mapping behavior (trae converts to .md)
|
||||
expect(traeProfile.fileMap['rules/cursor_rules.mdc']).toBe('trae_rules.md');
|
||||
});
|
||||
|
||||
test('trae.js uses standard tool mappings', () => {
|
||||
expect(traeProfileContent).toContain('COMMON_TOOL_MAPPINGS.STANDARD');
|
||||
// Should contain comment about standard tool names
|
||||
expect(traeProfileContent).toContain('standard tool names');
|
||||
});
|
||||
// Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD)
|
||||
// This verifies the architectural pattern: no custom toolMappings = standard tool names
|
||||
expect(traeProfileContent).not.toContain('toolMappings:');
|
||||
expect(traeProfileContent).not.toContain('apply_diff');
|
||||
expect(traeProfileContent).not.toContain('search_files');
|
||||
|
||||
test('trae.js contains correct URL configuration', () => {
|
||||
expect(traeProfileContent).toContain("url: 'trae.ai'");
|
||||
expect(traeProfileContent).toContain("docsUrl: 'docs.trae.ai'");
|
||||
});
|
||||
|
||||
test('trae.js has MCP configuration disabled', () => {
|
||||
expect(traeProfileContent).toContain('mcpConfig: false');
|
||||
expect(traeProfileContent).toContain(
|
||||
"mcpConfigName: 'trae_mcp_settings.json'"
|
||||
);
|
||||
// Verify the result: default mappings means tools keep their original names
|
||||
expect(traeProfile.conversionConfig.toolNames.edit_file).toBe('edit_file');
|
||||
expect(traeProfile.conversionConfig.toolNames.search).toBe('search');
|
||||
});
|
||||
});
|
||||
|
||||
58
tests/integration/profiles/vscode-init-functionality.test.js
Normal file
58
tests/integration/profiles/vscode-init-functionality.test.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { vscodeProfile } from '../../../src/profiles/vscode.js';
|
||||
|
||||
describe('VSCode Profile Initialization Functionality', () => {
|
||||
let vscodeProfileContent;
|
||||
|
||||
beforeAll(() => {
|
||||
const vscodeJsPath = path.join(
|
||||
process.cwd(),
|
||||
'src',
|
||||
'profiles',
|
||||
'vscode.js'
|
||||
);
|
||||
vscodeProfileContent = fs.readFileSync(vscodeJsPath, 'utf8');
|
||||
});
|
||||
|
||||
test('vscode.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(vscodeProfileContent).toContain("name: 'vscode'");
|
||||
expect(vscodeProfileContent).toContain("displayName: 'VS Code'");
|
||||
expect(vscodeProfileContent).toContain("url: 'code.visualstudio.com'");
|
||||
expect(vscodeProfileContent).toContain(
|
||||
"docsUrl: 'code.visualstudio.com/docs'"
|
||||
);
|
||||
expect(vscodeProfileContent).toContain("rulesDir: '.github/instructions'"); // non-default
|
||||
expect(vscodeProfileContent).toContain('customReplacements'); // non-default
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(vscodeProfile.profileName).toBe('vscode');
|
||||
expect(vscodeProfile.displayName).toBe('VS Code');
|
||||
expect(vscodeProfile.profileDir).toBe('.vscode'); // default
|
||||
expect(vscodeProfile.rulesDir).toBe('.github/instructions'); // non-default
|
||||
expect(vscodeProfile.globalReplacements).toBeDefined(); // computed from customReplacements
|
||||
expect(Array.isArray(vscodeProfile.globalReplacements)).toBe(true);
|
||||
});
|
||||
|
||||
test('vscode.js configures .mdc to .md extension mapping', () => {
|
||||
// Check that the profile object has the correct file mapping behavior (vscode converts to .md)
|
||||
expect(vscodeProfile.fileMap['rules/cursor_rules.mdc']).toBe(
|
||||
'vscode_rules.md'
|
||||
);
|
||||
});
|
||||
|
||||
test('vscode.js uses standard tool mappings', () => {
|
||||
// Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD)
|
||||
// This verifies the architectural pattern: no custom toolMappings = standard tool names
|
||||
expect(vscodeProfileContent).not.toContain('toolMappings:');
|
||||
expect(vscodeProfileContent).not.toContain('apply_diff');
|
||||
expect(vscodeProfileContent).not.toContain('search_files');
|
||||
|
||||
// Verify the result: default mappings means tools keep their original names
|
||||
expect(vscodeProfile.conversionConfig.toolNames.edit_file).toBe(
|
||||
'edit_file'
|
||||
);
|
||||
expect(vscodeProfile.conversionConfig.toolNames.search).toBe('search');
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { windsurfProfile } from '../../../src/profiles/windsurf.js';
|
||||
|
||||
describe('Windsurf Profile Initialization Functionality', () => {
|
||||
let windsurfProfileContent;
|
||||
@@ -15,25 +16,39 @@ describe('Windsurf Profile Initialization Functionality', () => {
|
||||
});
|
||||
|
||||
test('windsurf.js uses factory pattern with correct configuration', () => {
|
||||
// Check for explicit, non-default values in the source file
|
||||
expect(windsurfProfileContent).toContain("name: 'windsurf'");
|
||||
expect(windsurfProfileContent).toContain("displayName: 'Windsurf'");
|
||||
expect(windsurfProfileContent).toContain("rulesDir: '.windsurf/rules'");
|
||||
expect(windsurfProfileContent).toContain("profileDir: '.windsurf'");
|
||||
expect(windsurfProfileContent).toContain("url: 'windsurf.com'");
|
||||
expect(windsurfProfileContent).toContain("docsUrl: 'docs.windsurf.com'");
|
||||
|
||||
// Check the final computed properties on the profile object
|
||||
expect(windsurfProfile.profileName).toBe('windsurf');
|
||||
expect(windsurfProfile.displayName).toBe('Windsurf');
|
||||
expect(windsurfProfile.profileDir).toBe('.windsurf'); // default
|
||||
expect(windsurfProfile.rulesDir).toBe('.windsurf/rules'); // default
|
||||
expect(windsurfProfile.mcpConfig).toBe(true); // default
|
||||
expect(windsurfProfile.mcpConfigName).toBe('mcp.json'); // default
|
||||
});
|
||||
|
||||
test('windsurf.js configures .mdc to .md extension mapping', () => {
|
||||
expect(windsurfProfileContent).toContain("fileExtension: '.mdc'");
|
||||
expect(windsurfProfileContent).toContain("targetExtension: '.md'");
|
||||
// Check that the profile object has the correct file mapping behavior (windsurf converts to .md)
|
||||
expect(windsurfProfile.fileMap['rules/cursor_rules.mdc']).toBe(
|
||||
'windsurf_rules.md'
|
||||
);
|
||||
});
|
||||
|
||||
test('windsurf.js uses standard tool mappings', () => {
|
||||
expect(windsurfProfileContent).toContain('COMMON_TOOL_MAPPINGS.STANDARD');
|
||||
// Should contain comment about standard tool names
|
||||
expect(windsurfProfileContent).toContain('standard tool names');
|
||||
});
|
||||
// Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD)
|
||||
// This verifies the architectural pattern: no custom toolMappings = standard tool names
|
||||
expect(windsurfProfileContent).not.toContain('toolMappings:');
|
||||
expect(windsurfProfileContent).not.toContain('apply_diff');
|
||||
expect(windsurfProfileContent).not.toContain('search_files');
|
||||
|
||||
test('windsurf.js contains correct URL configuration', () => {
|
||||
expect(windsurfProfileContent).toContain("url: 'windsurf.com'");
|
||||
expect(windsurfProfileContent).toContain("docsUrl: 'docs.windsurf.com'");
|
||||
// Verify the result: default mappings means tools keep their original names
|
||||
expect(windsurfProfile.conversionConfig.toolNames.edit_file).toBe(
|
||||
'edit_file'
|
||||
);
|
||||
expect(windsurfProfile.conversionConfig.toolNames.search).toBe('search');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -372,9 +372,7 @@ describe('rules command', () => {
|
||||
expect.stringMatching(/removing rules for profile: roo/i)
|
||||
);
|
||||
expect(mockConsoleLog).toHaveBeenCalledWith(
|
||||
expect.stringMatching(
|
||||
/Summary for roo: (Rules directory removed|Skipped \(default or protected files\))/i
|
||||
)
|
||||
expect.stringMatching(/Summary for roo: Rule profile removed/i)
|
||||
);
|
||||
// Should not exit with error
|
||||
expect(mockExit).not.toHaveBeenCalledWith(1);
|
||||
|
||||
156
tests/unit/profiles/gemini-integration.test.js
Normal file
156
tests/unit/profiles/gemini-integration.test.js
Normal file
@@ -0,0 +1,156 @@
|
||||
import { jest } from '@jest/globals';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
|
||||
// Mock external modules
|
||||
jest.mock('child_process', () => ({
|
||||
execSync: jest.fn()
|
||||
}));
|
||||
|
||||
// Mock console methods
|
||||
jest.mock('console', () => ({
|
||||
log: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
clear: jest.fn()
|
||||
}));
|
||||
|
||||
describe('Gemini Profile Integration', () => {
|
||||
let tempDir;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
// Create a temporary directory for testing
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-'));
|
||||
|
||||
// Spy on fs methods
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
|
||||
jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => {
|
||||
if (filePath.toString().includes('AGENTS.md')) {
|
||||
return 'Sample AGENTS.md content for Gemini integration';
|
||||
}
|
||||
return '{}';
|
||||
});
|
||||
jest.spyOn(fs, 'existsSync').mockImplementation(() => false);
|
||||
jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up the temporary directory
|
||||
try {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch (err) {
|
||||
console.error(`Error cleaning up: ${err.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Test function that simulates the Gemini profile file copying behavior
|
||||
function mockCreateGeminiStructure() {
|
||||
// Gemini profile copies AGENTS.md to GEMINI.md in project root
|
||||
const sourceContent = 'Sample AGENTS.md content for Gemini integration';
|
||||
fs.writeFileSync(path.join(tempDir, 'GEMINI.md'), sourceContent);
|
||||
|
||||
// Gemini profile creates .gemini directory
|
||||
fs.mkdirSync(path.join(tempDir, '.gemini'), { recursive: true });
|
||||
|
||||
// Gemini profile creates settings.json in .gemini directory
|
||||
const settingsContent = JSON.stringify(
|
||||
{
|
||||
mcpServers: {
|
||||
'task-master-ai': {
|
||||
command: 'npx',
|
||||
args: ['-y', 'task-master-ai'],
|
||||
env: {
|
||||
YOUR_ANTHROPIC_API_KEY: 'your-api-key-here',
|
||||
YOUR_PERPLEXITY_API_KEY: 'your-api-key-here',
|
||||
YOUR_OPENAI_API_KEY: 'your-api-key-here',
|
||||
YOUR_GOOGLE_API_KEY: 'your-api-key-here',
|
||||
YOUR_MISTRAL_API_KEY: 'your-api-key-here',
|
||||
YOUR_AZURE_OPENAI_API_KEY: 'your-api-key-here',
|
||||
YOUR_AZURE_OPENAI_ENDPOINT: 'your-endpoint-here',
|
||||
YOUR_OPENROUTER_API_KEY: 'your-api-key-here',
|
||||
YOUR_XAI_API_KEY: 'your-api-key-here',
|
||||
YOUR_OLLAMA_API_KEY: 'your-api-key-here',
|
||||
YOUR_OLLAMA_BASE_URL: 'http://localhost:11434/api',
|
||||
YOUR_AWS_ACCESS_KEY_ID: 'your-access-key-id',
|
||||
YOUR_AWS_SECRET_ACCESS_KEY: 'your-secret-access-key',
|
||||
YOUR_AWS_REGION: 'us-east-1'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(tempDir, '.gemini', 'settings.json'),
|
||||
settingsContent
|
||||
);
|
||||
}
|
||||
|
||||
test('creates GEMINI.md file in project root', () => {
|
||||
// Act
|
||||
mockCreateGeminiStructure();
|
||||
|
||||
// Assert
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(
|
||||
path.join(tempDir, 'GEMINI.md'),
|
||||
'Sample AGENTS.md content for Gemini integration'
|
||||
);
|
||||
});
|
||||
|
||||
test('creates .gemini profile directory', () => {
|
||||
// Act
|
||||
mockCreateGeminiStructure();
|
||||
|
||||
// Assert
|
||||
expect(fs.mkdirSync).toHaveBeenCalledWith(path.join(tempDir, '.gemini'), {
|
||||
recursive: true
|
||||
});
|
||||
});
|
||||
|
||||
test('creates MCP configuration as settings.json', () => {
|
||||
// Act
|
||||
mockCreateGeminiStructure();
|
||||
|
||||
// Assert - Gemini profile should create settings.json instead of mcp.json
|
||||
const writeFileCalls = fs.writeFileSync.mock.calls;
|
||||
const settingsJsonCall = writeFileCalls.find((call) =>
|
||||
call[0].toString().includes('.gemini/settings.json')
|
||||
);
|
||||
expect(settingsJsonCall).toBeDefined();
|
||||
});
|
||||
|
||||
test('uses settings.json instead of mcp.json', () => {
|
||||
// Act
|
||||
mockCreateGeminiStructure();
|
||||
|
||||
// Assert - Should use settings.json, not mcp.json
|
||||
const writeFileCalls = fs.writeFileSync.mock.calls;
|
||||
const mcpJsonCalls = writeFileCalls.filter((call) =>
|
||||
call[0].toString().includes('mcp.json')
|
||||
);
|
||||
expect(mcpJsonCalls).toHaveLength(0);
|
||||
|
||||
const settingsJsonCalls = writeFileCalls.filter((call) =>
|
||||
call[0].toString().includes('settings.json')
|
||||
);
|
||||
expect(settingsJsonCalls).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('renames AGENTS.md to GEMINI.md', () => {
|
||||
// Act
|
||||
mockCreateGeminiStructure();
|
||||
|
||||
// Assert - Gemini should rename AGENTS.md to GEMINI.md
|
||||
const writeFileCalls = fs.writeFileSync.mock.calls;
|
||||
const geminiMdCall = writeFileCalls.find((call) =>
|
||||
call[0].toString().includes('GEMINI.md')
|
||||
);
|
||||
expect(geminiMdCall).toBeDefined();
|
||||
expect(geminiMdCall[0]).toBe(path.join(tempDir, 'GEMINI.md'));
|
||||
});
|
||||
});
|
||||
@@ -8,8 +8,8 @@ describe('MCP Configuration Validation', () => {
|
||||
cline: {
|
||||
shouldHaveMcp: false,
|
||||
expectedDir: '.clinerules',
|
||||
expectedConfigName: 'cline_mcp_settings.json',
|
||||
expectedPath: '.clinerules/cline_mcp_settings.json'
|
||||
expectedConfigName: null,
|
||||
expectedPath: null
|
||||
},
|
||||
cursor: {
|
||||
shouldHaveMcp: true,
|
||||
@@ -17,6 +17,12 @@ describe('MCP Configuration Validation', () => {
|
||||
expectedConfigName: 'mcp.json',
|
||||
expectedPath: '.cursor/mcp.json'
|
||||
},
|
||||
gemini: {
|
||||
shouldHaveMcp: true,
|
||||
expectedDir: '.gemini',
|
||||
expectedConfigName: 'settings.json',
|
||||
expectedPath: '.gemini/settings.json'
|
||||
},
|
||||
roo: {
|
||||
shouldHaveMcp: true,
|
||||
expectedDir: '.roo',
|
||||
@@ -26,8 +32,8 @@ describe('MCP Configuration Validation', () => {
|
||||
trae: {
|
||||
shouldHaveMcp: false,
|
||||
expectedDir: '.trae',
|
||||
expectedConfigName: 'trae_mcp_settings.json',
|
||||
expectedPath: '.trae/trae_mcp_settings.json'
|
||||
expectedConfigName: null,
|
||||
expectedPath: null
|
||||
},
|
||||
vscode: {
|
||||
shouldHaveMcp: true,
|
||||
@@ -111,51 +117,68 @@ describe('MCP Configuration Validation', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('should use profile-specific config name for non-MCP profiles', () => {
|
||||
test('should use custom settings.json for Gemini profile', () => {
|
||||
const profile = getRulesProfile('gemini');
|
||||
expect(profile.mcpConfigName).toBe('settings.json');
|
||||
});
|
||||
|
||||
test('should have null config name for non-MCP profiles', () => {
|
||||
const clineProfile = getRulesProfile('cline');
|
||||
expect(clineProfile.mcpConfigName).toBe('cline_mcp_settings.json');
|
||||
expect(clineProfile.mcpConfigName).toBe(null);
|
||||
|
||||
const traeProfile = getRulesProfile('trae');
|
||||
expect(traeProfile.mcpConfigName).toBe('trae_mcp_settings.json');
|
||||
expect(traeProfile.mcpConfigName).toBe(null);
|
||||
|
||||
const claudeProfile = getRulesProfile('claude');
|
||||
expect(claudeProfile.mcpConfigName).toBe(null);
|
||||
|
||||
const codexProfile = getRulesProfile('codex');
|
||||
expect(codexProfile.mcpConfigName).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Profile Directory Structure', () => {
|
||||
test('should ensure each profile has a unique directory', () => {
|
||||
const profileDirs = new Set();
|
||||
// Simple profiles that use root directory (can share the same directory)
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
// Profiles that use root directory (can share the same directory)
|
||||
const rootProfiles = ['claude', 'codex', 'gemini'];
|
||||
|
||||
RULE_PROFILES.forEach((profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
|
||||
// Simple profiles can share the root directory
|
||||
if (simpleProfiles.includes(profileName)) {
|
||||
expect(profile.profileDir).toBe('.');
|
||||
return;
|
||||
// Root profiles can share the root directory for rules
|
||||
if (rootProfiles.includes(profileName) && profile.rulesDir === '.') {
|
||||
expect(profile.rulesDir).toBe('.');
|
||||
}
|
||||
|
||||
// Full profiles should have unique directories
|
||||
// Profile directories should be unique (except for root profiles)
|
||||
if (!rootProfiles.includes(profileName) || profile.profileDir !== '.') {
|
||||
expect(profileDirs.has(profile.profileDir)).toBe(false);
|
||||
profileDirs.add(profile.profileDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('should ensure profile directories follow expected naming convention', () => {
|
||||
// Simple profiles that use root directory
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
// Profiles that use root directory for rules
|
||||
const rootRulesProfiles = ['claude', 'codex', 'gemini'];
|
||||
|
||||
RULE_PROFILES.forEach((profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
|
||||
// Simple profiles use root directory
|
||||
if (simpleProfiles.includes(profileName)) {
|
||||
expect(profile.profileDir).toBe('.');
|
||||
return;
|
||||
// Some profiles use root directory for rules
|
||||
if (
|
||||
rootRulesProfiles.includes(profileName) &&
|
||||
profile.rulesDir === '.'
|
||||
) {
|
||||
expect(profile.rulesDir).toBe('.');
|
||||
}
|
||||
|
||||
// Full profiles should follow the .name pattern
|
||||
// Profile directories (not rules directories) should follow the .name pattern
|
||||
// unless they are root profiles with profileDir = '.'
|
||||
if (profile.profileDir !== '.') {
|
||||
expect(profile.profileDir).toMatch(/^\.[\w-]+$/);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -168,6 +191,7 @@ describe('MCP Configuration Validation', () => {
|
||||
});
|
||||
|
||||
expect(mcpEnabledProfiles).toContain('cursor');
|
||||
expect(mcpEnabledProfiles).toContain('gemini');
|
||||
expect(mcpEnabledProfiles).toContain('roo');
|
||||
expect(mcpEnabledProfiles).toContain('vscode');
|
||||
expect(mcpEnabledProfiles).toContain('windsurf');
|
||||
@@ -244,4 +268,84 @@ describe('MCP Configuration Validation', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('MCP configuration validation', () => {
|
||||
const mcpProfiles = ['cursor', 'gemini', 'roo', 'windsurf', 'vscode'];
|
||||
const nonMcpProfiles = ['claude', 'codex', 'cline', 'trae'];
|
||||
|
||||
test.each(mcpProfiles)(
|
||||
'should have valid MCP config for %s profile',
|
||||
(profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
expect(profile).toBeDefined();
|
||||
expect(profile.mcpConfig).toBe(true);
|
||||
expect(profile.mcpConfigPath).toBeDefined();
|
||||
expect(typeof profile.mcpConfigPath).toBe('string');
|
||||
}
|
||||
);
|
||||
|
||||
test.each(nonMcpProfiles)(
|
||||
'should not require MCP config for %s profile',
|
||||
(profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
expect(profile).toBeDefined();
|
||||
expect(profile.mcpConfig).toBe(false);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Profile structure validation', () => {
|
||||
const mcpProfiles = [
|
||||
'cursor',
|
||||
'gemini',
|
||||
'roo',
|
||||
'windsurf',
|
||||
'cline',
|
||||
'trae',
|
||||
'vscode'
|
||||
];
|
||||
const profilesWithLifecycle = ['claude'];
|
||||
const profilesWithoutLifecycle = ['codex'];
|
||||
|
||||
test.each(mcpProfiles)(
|
||||
'should have file mappings for %s profile',
|
||||
(profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
expect(profile).toBeDefined();
|
||||
expect(profile.fileMap).toBeDefined();
|
||||
expect(typeof profile.fileMap).toBe('object');
|
||||
expect(Object.keys(profile.fileMap).length).toBeGreaterThan(0);
|
||||
}
|
||||
);
|
||||
|
||||
test.each(profilesWithLifecycle)(
|
||||
'should have file mappings and lifecycle functions for %s profile',
|
||||
(profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
expect(profile).toBeDefined();
|
||||
// Claude profile has both fileMap and lifecycle functions
|
||||
expect(profile.fileMap).toBeDefined();
|
||||
expect(typeof profile.fileMap).toBe('object');
|
||||
expect(Object.keys(profile.fileMap).length).toBeGreaterThan(0);
|
||||
expect(typeof profile.onAddRulesProfile).toBe('function');
|
||||
expect(typeof profile.onRemoveRulesProfile).toBe('function');
|
||||
expect(typeof profile.onPostConvertRulesProfile).toBe('function');
|
||||
}
|
||||
);
|
||||
|
||||
test.each(profilesWithoutLifecycle)(
|
||||
'should have file mappings without lifecycle functions for %s profile',
|
||||
(profileName) => {
|
||||
const profile = getRulesProfile(profileName);
|
||||
expect(profile).toBeDefined();
|
||||
// Codex profile has fileMap but no lifecycle functions (simplified)
|
||||
expect(profile.fileMap).toBeDefined();
|
||||
expect(typeof profile.fileMap).toBe('object');
|
||||
expect(Object.keys(profile.fileMap).length).toBeGreaterThan(0);
|
||||
expect(profile.onAddRulesProfile).toBeUndefined();
|
||||
expect(profile.onRemoveRulesProfile).toBeUndefined();
|
||||
expect(profile.onPostConvertRulesProfile).toBeUndefined();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
70
tests/unit/profiles/rule-transformer-gemini.test.js
Normal file
70
tests/unit/profiles/rule-transformer-gemini.test.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import { jest } from '@jest/globals';
|
||||
import { getRulesProfile } from '../../../src/utils/rule-transformer.js';
|
||||
import { geminiProfile } from '../../../src/profiles/gemini.js';
|
||||
|
||||
describe('Rule Transformer - Gemini Profile', () => {
|
||||
test('should have correct profile configuration', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
|
||||
expect(geminiProfile).toBeDefined();
|
||||
expect(geminiProfile.profileName).toBe('gemini');
|
||||
expect(geminiProfile.displayName).toBe('Gemini');
|
||||
expect(geminiProfile.profileDir).toBe('.gemini');
|
||||
expect(geminiProfile.rulesDir).toBe('.');
|
||||
expect(geminiProfile.mcpConfig).toBe(true);
|
||||
expect(geminiProfile.mcpConfigName).toBe('settings.json');
|
||||
expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
|
||||
expect(geminiProfile.includeDefaultRules).toBe(false);
|
||||
expect(geminiProfile.fileMap).toEqual({
|
||||
'AGENTS.md': 'GEMINI.md'
|
||||
});
|
||||
});
|
||||
|
||||
test('should have minimal profile implementation', () => {
|
||||
// Verify that gemini.js is minimal (no lifecycle functions)
|
||||
expect(geminiProfile.onAddRulesProfile).toBeUndefined();
|
||||
expect(geminiProfile.onRemoveRulesProfile).toBeUndefined();
|
||||
expect(geminiProfile.onPostConvertRulesProfile).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should use settings.json instead of mcp.json', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
expect(geminiProfile.mcpConfigName).toBe('settings.json');
|
||||
expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
|
||||
});
|
||||
|
||||
test('should not include default rules', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
expect(geminiProfile.includeDefaultRules).toBe(false);
|
||||
});
|
||||
|
||||
test('should have correct file mapping', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
expect(geminiProfile.fileMap).toEqual({
|
||||
'AGENTS.md': 'GEMINI.md'
|
||||
});
|
||||
});
|
||||
|
||||
test('should place GEMINI.md in root directory', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
// rulesDir determines where fileMap files go
|
||||
expect(geminiProfile.rulesDir).toBe('.');
|
||||
// This means AGENTS.md -> GEMINI.md will be placed in the root
|
||||
});
|
||||
|
||||
test('should place settings.json in .gemini directory', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
// profileDir + mcpConfigName determines MCP config location
|
||||
expect(geminiProfile.profileDir).toBe('.gemini');
|
||||
expect(geminiProfile.mcpConfigName).toBe('settings.json');
|
||||
expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
|
||||
});
|
||||
|
||||
test('should have proper conversion config', () => {
|
||||
const geminiProfile = getRulesProfile('gemini');
|
||||
// Gemini should have the standard conversion config
|
||||
expect(geminiProfile.conversionConfig).toBeDefined();
|
||||
expect(geminiProfile.globalReplacements).toBeDefined();
|
||||
expect(Array.isArray(geminiProfile.globalReplacements)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -17,6 +17,7 @@ describe('Rule Transformer - General', () => {
|
||||
'cline',
|
||||
'codex',
|
||||
'cursor',
|
||||
'gemini',
|
||||
'roo',
|
||||
'trae',
|
||||
'vscode',
|
||||
@@ -55,9 +56,6 @@ describe('Rule Transformer - General', () => {
|
||||
|
||||
describe('Profile Structure', () => {
|
||||
it('should have all required properties for each profile', () => {
|
||||
// Simple profiles that only copy files (no rule transformation)
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
|
||||
RULE_PROFILES.forEach((profile) => {
|
||||
const profileConfig = getRulesProfile(profile);
|
||||
|
||||
@@ -68,50 +66,50 @@ describe('Rule Transformer - General', () => {
|
||||
expect(profileConfig).toHaveProperty('rulesDir');
|
||||
expect(profileConfig).toHaveProperty('profileDir');
|
||||
|
||||
// Simple profiles have minimal structure
|
||||
if (simpleProfiles.includes(profile)) {
|
||||
// For simple profiles, conversionConfig and fileMap can be empty
|
||||
// All profiles should have conversionConfig and fileMap objects
|
||||
expect(typeof profileConfig.conversionConfig).toBe('object');
|
||||
expect(typeof profileConfig.fileMap).toBe('object');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that conversionConfig has required structure for full profiles
|
||||
// Check that conversionConfig has required structure for profiles with rules
|
||||
const hasRules = Object.keys(profileConfig.fileMap).length > 0;
|
||||
if (hasRules) {
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('profileTerms');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('toolNames');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('toolContexts');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('toolGroups');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('docUrls');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty('fileReferences');
|
||||
expect(profileConfig.conversionConfig).toHaveProperty(
|
||||
'fileReferences'
|
||||
);
|
||||
|
||||
// Verify arrays are actually arrays
|
||||
expect(Array.isArray(profileConfig.conversionConfig.profileTerms)).toBe(
|
||||
true
|
||||
);
|
||||
expect(typeof profileConfig.conversionConfig.toolNames).toBe('object');
|
||||
expect(Array.isArray(profileConfig.conversionConfig.toolContexts)).toBe(
|
||||
true
|
||||
expect(
|
||||
Array.isArray(profileConfig.conversionConfig.profileTerms)
|
||||
).toBe(true);
|
||||
expect(typeof profileConfig.conversionConfig.toolNames).toBe(
|
||||
'object'
|
||||
);
|
||||
expect(
|
||||
Array.isArray(profileConfig.conversionConfig.toolContexts)
|
||||
).toBe(true);
|
||||
expect(Array.isArray(profileConfig.conversionConfig.toolGroups)).toBe(
|
||||
true
|
||||
);
|
||||
expect(Array.isArray(profileConfig.conversionConfig.docUrls)).toBe(
|
||||
true
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should have valid fileMap with required files for each profile', () => {
|
||||
const expectedFiles = [
|
||||
const expectedRuleFiles = [
|
||||
'cursor_rules.mdc',
|
||||
'dev_workflow.mdc',
|
||||
'self_improve.mdc',
|
||||
'taskmaster.mdc'
|
||||
];
|
||||
|
||||
// Simple profiles that only copy files (no rule transformation)
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
|
||||
RULE_PROFILES.forEach((profile) => {
|
||||
const profileConfig = getRulesProfile(profile);
|
||||
|
||||
@@ -120,33 +118,43 @@ describe('Rule Transformer - General', () => {
|
||||
expect(typeof profileConfig.fileMap).toBe('object');
|
||||
expect(profileConfig.fileMap).not.toBeNull();
|
||||
|
||||
// Simple profiles can have empty fileMap since they don't transform rules
|
||||
if (simpleProfiles.includes(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that fileMap is not empty for full profiles
|
||||
const fileMapKeys = Object.keys(profileConfig.fileMap);
|
||||
|
||||
// All profiles should have some fileMap entries now
|
||||
expect(fileMapKeys.length).toBeGreaterThan(0);
|
||||
|
||||
// Check that all expected source files are defined in fileMap
|
||||
expectedFiles.forEach((expectedFile) => {
|
||||
// Check if this profile has rule files or asset files
|
||||
const hasRuleFiles = expectedRuleFiles.some((file) =>
|
||||
fileMapKeys.includes(file)
|
||||
);
|
||||
const hasAssetFiles = fileMapKeys.some(
|
||||
(file) => !expectedRuleFiles.includes(file)
|
||||
);
|
||||
|
||||
if (hasRuleFiles) {
|
||||
// Profiles with rule files should have all expected rule files
|
||||
expectedRuleFiles.forEach((expectedFile) => {
|
||||
expect(fileMapKeys).toContain(expectedFile);
|
||||
expect(typeof profileConfig.fileMap[expectedFile]).toBe('string');
|
||||
expect(profileConfig.fileMap[expectedFile].length).toBeGreaterThan(0);
|
||||
expect(profileConfig.fileMap[expectedFile].length).toBeGreaterThan(
|
||||
0
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Verify fileMap has exactly the expected files
|
||||
expect(fileMapKeys.sort()).toEqual(expectedFiles.sort());
|
||||
if (hasAssetFiles) {
|
||||
// Profiles with asset files (like Claude/Codex) should have valid asset mappings
|
||||
fileMapKeys.forEach((key) => {
|
||||
expect(typeof profileConfig.fileMap[key]).toBe('string');
|
||||
expect(profileConfig.fileMap[key].length).toBeGreaterThan(0);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('MCP Configuration Properties', () => {
|
||||
it('should have all required MCP properties for each profile', () => {
|
||||
// Simple profiles that only copy files (no MCP configuration)
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
|
||||
RULE_PROFILES.forEach((profile) => {
|
||||
const profileConfig = getRulesProfile(profile);
|
||||
|
||||
@@ -155,16 +163,15 @@ describe('Rule Transformer - General', () => {
|
||||
expect(profileConfig).toHaveProperty('mcpConfigName');
|
||||
expect(profileConfig).toHaveProperty('mcpConfigPath');
|
||||
|
||||
// Simple profiles have no MCP configuration
|
||||
if (simpleProfiles.includes(profile)) {
|
||||
expect(profileConfig.mcpConfig).toBe(false);
|
||||
// Check types based on MCP configuration
|
||||
expect(typeof profileConfig.mcpConfig).toBe('boolean');
|
||||
|
||||
if (profileConfig.mcpConfig === false) {
|
||||
// Profiles without MCP configuration
|
||||
expect(profileConfig.mcpConfigName).toBe(null);
|
||||
expect(profileConfig.mcpConfigPath).toBe(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check types for full profiles
|
||||
expect(typeof profileConfig.mcpConfig).toBe('boolean');
|
||||
} else {
|
||||
// Profiles with MCP configuration
|
||||
expect(typeof profileConfig.mcpConfigName).toBe('string');
|
||||
expect(typeof profileConfig.mcpConfigPath).toBe('string');
|
||||
|
||||
@@ -172,6 +179,7 @@ describe('Rule Transformer - General', () => {
|
||||
expect(profileConfig.mcpConfigPath).toBe(
|
||||
`${profileConfig.profileDir}/${profileConfig.mcpConfigName}`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -184,8 +192,8 @@ describe('Rule Transformer - General', () => {
|
||||
},
|
||||
cline: {
|
||||
mcpConfig: false,
|
||||
mcpConfigName: 'cline_mcp_settings.json',
|
||||
expectedPath: '.clinerules/cline_mcp_settings.json'
|
||||
mcpConfigName: null,
|
||||
expectedPath: null
|
||||
},
|
||||
codex: {
|
||||
mcpConfig: false,
|
||||
@@ -197,6 +205,11 @@ describe('Rule Transformer - General', () => {
|
||||
mcpConfigName: 'mcp.json',
|
||||
expectedPath: '.cursor/mcp.json'
|
||||
},
|
||||
gemini: {
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'settings.json',
|
||||
expectedPath: '.gemini/settings.json'
|
||||
},
|
||||
roo: {
|
||||
mcpConfig: true,
|
||||
mcpConfigName: 'mcp.json',
|
||||
@@ -204,8 +217,8 @@ describe('Rule Transformer - General', () => {
|
||||
},
|
||||
trae: {
|
||||
mcpConfig: false,
|
||||
mcpConfigName: 'trae_mcp_settings.json',
|
||||
expectedPath: '.trae/trae_mcp_settings.json'
|
||||
mcpConfigName: null,
|
||||
expectedPath: null
|
||||
},
|
||||
vscode: {
|
||||
mcpConfig: true,
|
||||
@@ -230,18 +243,14 @@ describe('Rule Transformer - General', () => {
|
||||
});
|
||||
|
||||
it('should have consistent profileDir and mcpConfigPath relationship', () => {
|
||||
// Simple profiles that only copy files (no MCP configuration)
|
||||
const simpleProfiles = ['claude', 'codex'];
|
||||
|
||||
RULE_PROFILES.forEach((profile) => {
|
||||
const profileConfig = getRulesProfile(profile);
|
||||
|
||||
// Simple profiles have null mcpConfigPath
|
||||
if (simpleProfiles.includes(profile)) {
|
||||
if (profileConfig.mcpConfig === false) {
|
||||
// Profiles without MCP configuration have null mcpConfigPath
|
||||
expect(profileConfig.mcpConfigPath).toBe(null);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Profiles with MCP configuration should have valid paths
|
||||
// The mcpConfigPath should start with the profileDir
|
||||
expect(profileConfig.mcpConfigPath).toMatch(
|
||||
new RegExp(
|
||||
@@ -255,6 +264,7 @@ describe('Rule Transformer - General', () => {
|
||||
`${profileConfig.mcpConfigName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -136,8 +136,8 @@ describe('Selective Rules Removal', () => {
|
||||
expect(result.filesRemoved).toEqual([
|
||||
'cursor_rules.mdc',
|
||||
'taskmaster/dev_workflow.mdc',
|
||||
'taskmaster/taskmaster.mdc',
|
||||
'self_improve.mdc'
|
||||
'self_improve.mdc',
|
||||
'taskmaster/taskmaster.mdc'
|
||||
]);
|
||||
expect(result.notice).toContain('Preserved 2 existing rule files');
|
||||
|
||||
@@ -226,8 +226,8 @@ describe('Selective Rules Removal', () => {
|
||||
expect(result.filesRemoved).toEqual([
|
||||
'cursor_rules.mdc',
|
||||
'taskmaster/dev_workflow.mdc',
|
||||
'taskmaster/taskmaster.mdc',
|
||||
'self_improve.mdc'
|
||||
'self_improve.mdc',
|
||||
'taskmaster/taskmaster.mdc'
|
||||
]);
|
||||
|
||||
// The function may fail due to directory reading issues in the test environment,
|
||||
@@ -354,8 +354,8 @@ describe('Selective Rules Removal', () => {
|
||||
// Mock sequence: only Task Master rules, rules dir removed, but profile dir not empty due to MCP
|
||||
mockReaddirSync
|
||||
.mockReturnValueOnce(['cursor_rules.mdc']) // Only Task Master files
|
||||
.mockReturnValueOnce([]) // rules dir empty after removal
|
||||
.mockReturnValueOnce(['mcp.json']); // Profile dir has MCP config remaining
|
||||
.mockReturnValueOnce(['my_custom_rule.mdc']) // rules dir has other files remaining
|
||||
.mockReturnValueOnce(['rules', 'mcp.json']); // Profile dir has rules and MCP config remaining
|
||||
|
||||
// Mock MCP config with multiple servers (Task Master will be removed, others preserved)
|
||||
const mockMcpConfig = {
|
||||
@@ -400,8 +400,9 @@ describe('Selective Rules Removal', () => {
|
||||
|
||||
// Mock sequence: only Task Master rules, rules dir removed, but profile dir has other files/folders
|
||||
mockReaddirSync
|
||||
.mockReturnValueOnce(['cursor_rules.mdc']) // Only Task Master files
|
||||
.mockReturnValueOnce([]) // rules dir empty after removal
|
||||
.mockReturnValueOnce(['cursor_rules.mdc']) // Only Task Master files (initial check)
|
||||
.mockReturnValueOnce(['cursor_rules.mdc']) // Task Master files list for filtering
|
||||
.mockReturnValueOnce([]) // Rules dir empty after removal (not used since no remaining files)
|
||||
.mockReturnValueOnce(['workflows', 'custom-config.json']); // Profile dir has other files/folders
|
||||
|
||||
// Mock MCP config with only Task Master (will be completely deleted)
|
||||
@@ -420,7 +421,7 @@ describe('Selective Rules Removal', () => {
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.profileDirRemoved).toBe(false);
|
||||
expect(result.mcpResult.deleted).toBe(true);
|
||||
expect(result.notice).toContain('Preserved 2 existing files/folders');
|
||||
expect(result.notice).toContain('existing files/folders in .cursor');
|
||||
|
||||
// Verify profile directory was NOT removed (other files/folders exist)
|
||||
expect(mockRmSync).not.toHaveBeenCalledWith(
|
||||
@@ -587,8 +588,30 @@ describe('Selective Rules Removal', () => {
|
||||
|
||||
// Mock mixed scenario: some Task Master files, some existing files, other MCP servers
|
||||
mockExistsSync.mockImplementation((filePath) => {
|
||||
if (filePath.includes('.cursor')) return true;
|
||||
if (filePath.includes('mcp.json')) return true;
|
||||
// Only .cursor directories exist
|
||||
if (filePath === path.join(projectRoot, '.cursor')) return true;
|
||||
if (filePath === path.join(projectRoot, '.cursor/rules')) return true;
|
||||
if (filePath === path.join(projectRoot, '.cursor/mcp.json'))
|
||||
return true;
|
||||
// Only cursor_rules.mdc exists, not the other taskmaster files
|
||||
if (
|
||||
filePath === path.join(projectRoot, '.cursor/rules/cursor_rules.mdc')
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
filePath ===
|
||||
path.join(projectRoot, '.cursor/rules/taskmaster/dev_workflow.mdc')
|
||||
)
|
||||
return false;
|
||||
if (
|
||||
filePath === path.join(projectRoot, '.cursor/rules/self_improve.mdc')
|
||||
)
|
||||
return false;
|
||||
if (
|
||||
filePath ===
|
||||
path.join(projectRoot, '.cursor/rules/taskmaster/taskmaster.mdc')
|
||||
)
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ describe('Rules Subdirectory Support Feature', () => {
|
||||
expect(cursorProfile.supportsRulesSubdirectories).toBe(true);
|
||||
|
||||
// Verify that Cursor uses taskmaster subdirectories in its file mapping
|
||||
expect(cursorProfile.fileMap['dev_workflow.mdc']).toBe(
|
||||
expect(cursorProfile.fileMap['rules/dev_workflow.mdc']).toBe(
|
||||
'taskmaster/dev_workflow.mdc'
|
||||
);
|
||||
expect(cursorProfile.fileMap['taskmaster.mdc']).toBe(
|
||||
expect(cursorProfile.fileMap['rules/taskmaster.mdc']).toBe(
|
||||
'taskmaster/taskmaster.mdc'
|
||||
);
|
||||
});
|
||||
@@ -26,10 +26,10 @@ describe('Rules Subdirectory Support Feature', () => {
|
||||
|
||||
// Verify that these profiles do NOT use taskmaster subdirectories in their file mapping
|
||||
const expectedExt = profile.targetExtension || '.md';
|
||||
expect(profile.fileMap['dev_workflow.mdc']).toBe(
|
||||
expect(profile.fileMap['rules/dev_workflow.mdc']).toBe(
|
||||
`dev_workflow${expectedExt}`
|
||||
);
|
||||
expect(profile.fileMap['taskmaster.mdc']).toBe(
|
||||
expect(profile.fileMap['rules/taskmaster.mdc']).toBe(
|
||||
`taskmaster${expectedExt}`
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user