This is page 5 of 52. Use http://codebase.md/eyaltoledano/claude-task-master?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .changeset │ ├── config.json │ └── README.md ├── .claude │ ├── agents │ │ ├── task-checker.md │ │ ├── task-executor.md │ │ └── task-orchestrator.md │ ├── commands │ │ ├── dedupe.md │ │ └── tm │ │ ├── add-dependency │ │ │ └── add-dependency.md │ │ ├── add-subtask │ │ │ ├── add-subtask.md │ │ │ └── convert-task-to-subtask.md │ │ ├── add-task │ │ │ └── add-task.md │ │ ├── analyze-complexity │ │ │ └── analyze-complexity.md │ │ ├── complexity-report │ │ │ └── complexity-report.md │ │ ├── expand │ │ │ ├── expand-all-tasks.md │ │ │ └── expand-task.md │ │ ├── fix-dependencies │ │ │ └── fix-dependencies.md │ │ ├── generate │ │ │ └── generate-tasks.md │ │ ├── help.md │ │ ├── init │ │ │ ├── init-project-quick.md │ │ │ └── init-project.md │ │ ├── learn.md │ │ ├── list │ │ │ ├── list-tasks-by-status.md │ │ │ ├── list-tasks-with-subtasks.md │ │ │ └── list-tasks.md │ │ ├── models │ │ │ ├── setup-models.md │ │ │ └── view-models.md │ │ ├── next │ │ │ └── next-task.md │ │ ├── parse-prd │ │ │ ├── parse-prd-with-research.md │ │ │ └── parse-prd.md │ │ ├── remove-dependency │ │ │ └── remove-dependency.md │ │ ├── remove-subtask │ │ │ └── remove-subtask.md │ │ ├── remove-subtasks │ │ │ ├── remove-all-subtasks.md │ │ │ └── remove-subtasks.md │ │ ├── remove-task │ │ │ └── remove-task.md │ │ ├── set-status │ │ │ ├── to-cancelled.md │ │ │ ├── to-deferred.md │ │ │ ├── to-done.md │ │ │ ├── to-in-progress.md │ │ │ ├── to-pending.md │ │ │ └── to-review.md │ │ ├── setup │ │ │ ├── install-taskmaster.md │ │ │ └── quick-install-taskmaster.md │ │ ├── show │ │ │ └── show-task.md │ │ ├── status │ │ │ └── project-status.md │ │ ├── sync-readme │ │ │ └── sync-readme.md │ │ ├── tm-main.md │ │ ├── update │ │ │ ├── update-single-task.md │ │ │ ├── update-task.md │ │ │ └── update-tasks-from-id.md │ │ ├── utils │ │ │ └── analyze-project.md │ │ ├── validate-dependencies │ │ │ └── validate-dependencies.md │ │ └── workflows │ │ ├── auto-implement-tasks.md │ │ ├── command-pipeline.md │ │ └── smart-workflow.md │ └── TM_COMMANDS_GUIDE.md ├── .coderabbit.yaml ├── .cursor │ ├── mcp.json │ └── rules │ ├── ai_providers.mdc │ ├── ai_services.mdc │ ├── architecture.mdc │ ├── changeset.mdc │ ├── commands.mdc │ ├── context_gathering.mdc │ ├── cursor_rules.mdc │ ├── dependencies.mdc │ ├── dev_workflow.mdc │ ├── git_workflow.mdc │ ├── glossary.mdc │ ├── mcp.mdc │ ├── new_features.mdc │ ├── self_improve.mdc │ ├── tags.mdc │ ├── taskmaster.mdc │ ├── tasks.mdc │ ├── telemetry.mdc │ ├── test_workflow.mdc │ ├── tests.mdc │ ├── ui.mdc │ └── utilities.mdc ├── .cursorignore ├── .env.example ├── .github │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.md │ │ ├── enhancements---feature-requests.md │ │ └── feedback.md │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bugfix.md │ │ ├── config.yml │ │ ├── feature.md │ │ └── integration.md │ ├── PULL_REQUEST_TEMPLATE.md │ ├── scripts │ │ ├── auto-close-duplicates.mjs │ │ ├── backfill-duplicate-comments.mjs │ │ ├── check-pre-release-mode.mjs │ │ ├── parse-metrics.mjs │ │ ├── release.mjs │ │ ├── tag-extension.mjs │ │ └── utils.mjs │ └── workflows │ ├── auto-close-duplicates.yml │ ├── backfill-duplicate-comments.yml │ ├── ci.yml │ ├── claude-dedupe-issues.yml │ ├── claude-docs-trigger.yml │ ├── claude-docs-updater.yml │ ├── claude-issue-triage.yml │ ├── claude.yml │ ├── extension-ci.yml │ ├── extension-release.yml │ ├── log-issue-events.yml │ ├── pre-release.yml │ ├── release-check.yml │ ├── release.yml │ ├── update-models-md.yml │ └── weekly-metrics-discord.yml ├── .gitignore ├── .kiro │ ├── hooks │ │ ├── tm-code-change-task-tracker.kiro.hook │ │ ├── tm-complexity-analyzer.kiro.hook │ │ ├── tm-daily-standup-assistant.kiro.hook │ │ ├── tm-git-commit-task-linker.kiro.hook │ │ ├── tm-pr-readiness-checker.kiro.hook │ │ ├── tm-task-dependency-auto-progression.kiro.hook │ │ └── tm-test-success-task-completer.kiro.hook │ ├── settings │ │ └── mcp.json │ └── steering │ ├── dev_workflow.md │ ├── kiro_rules.md │ ├── self_improve.md │ ├── taskmaster_hooks_workflow.md │ └── taskmaster.md ├── .manypkg.json ├── .mcp.json ├── .npmignore ├── .nvmrc ├── .taskmaster │ ├── CLAUDE.md │ ├── config.json │ ├── docs │ │ ├── MIGRATION-ROADMAP.md │ │ ├── prd-tm-start.txt │ │ ├── prd.txt │ │ ├── README.md │ │ ├── research │ │ │ ├── 2025-06-14_how-can-i-improve-the-scope-up-and-scope-down-comm.md │ │ │ ├── 2025-06-14_should-i-be-using-any-specific-libraries-for-this.md │ │ │ ├── 2025-06-14_test-save-functionality.md │ │ │ ├── 2025-06-14_test-the-fix-for-duplicate-saves-final-test.md │ │ │ └── 2025-08-01_do-we-need-to-add-new-commands-or-can-we-just-weap.md │ │ ├── task-template-importing-prd.txt │ │ ├── test-prd.txt │ │ └── tm-core-phase-1.txt │ ├── reports │ │ ├── task-complexity-report_cc-kiro-hooks.json │ │ ├── task-complexity-report_test-prd-tag.json │ │ ├── task-complexity-report_tm-core-phase-1.json │ │ ├── task-complexity-report.json │ │ └── tm-core-complexity.json │ ├── state.json │ ├── tasks │ │ ├── task_001_tm-start.txt │ │ ├── task_002_tm-start.txt │ │ ├── task_003_tm-start.txt │ │ ├── task_004_tm-start.txt │ │ ├── task_007_tm-start.txt │ │ └── tasks.json │ └── templates │ └── example_prd.txt ├── .vscode │ ├── extensions.json │ └── settings.json ├── apps │ ├── cli │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ ├── commands │ │ │ │ ├── auth.command.ts │ │ │ │ ├── context.command.ts │ │ │ │ ├── list.command.ts │ │ │ │ ├── set-status.command.ts │ │ │ │ ├── show.command.ts │ │ │ │ └── start.command.ts │ │ │ ├── index.ts │ │ │ ├── ui │ │ │ │ ├── components │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── next-task.component.ts │ │ │ │ │ ├── suggested-steps.component.ts │ │ │ │ │ └── task-detail.component.ts │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ ├── auto-update.ts │ │ │ └── ui.ts │ │ └── tsconfig.json │ ├── docs │ │ ├── archive │ │ │ ├── ai-client-utils-example.mdx │ │ │ ├── ai-development-workflow.mdx │ │ │ ├── command-reference.mdx │ │ │ ├── configuration.mdx │ │ │ ├── cursor-setup.mdx │ │ │ ├── examples.mdx │ │ │ └── Installation.mdx │ │ ├── best-practices │ │ │ ├── advanced-tasks.mdx │ │ │ ├── configuration-advanced.mdx │ │ │ └── index.mdx │ │ ├── capabilities │ │ │ ├── cli-root-commands.mdx │ │ │ ├── index.mdx │ │ │ ├── mcp.mdx │ │ │ └── task-structure.mdx │ │ ├── CHANGELOG.md │ │ ├── docs.json │ │ ├── favicon.svg │ │ ├── getting-started │ │ │ ├── contribute.mdx │ │ │ ├── faq.mdx │ │ │ └── quick-start │ │ │ ├── configuration-quick.mdx │ │ │ ├── execute-quick.mdx │ │ │ ├── installation.mdx │ │ │ ├── moving-forward.mdx │ │ │ ├── prd-quick.mdx │ │ │ ├── quick-start.mdx │ │ │ ├── requirements.mdx │ │ │ ├── rules-quick.mdx │ │ │ └── tasks-quick.mdx │ │ ├── introduction.mdx │ │ ├── licensing.md │ │ ├── logo │ │ │ ├── dark.svg │ │ │ ├── light.svg │ │ │ └── task-master-logo.png │ │ ├── package.json │ │ ├── README.md │ │ ├── style.css │ │ ├── vercel.json │ │ └── whats-new.mdx │ └── extension │ ├── .vscodeignore │ ├── assets │ │ ├── banner.png │ │ ├── icon-dark.svg │ │ ├── icon-light.svg │ │ ├── icon.png │ │ ├── screenshots │ │ │ ├── kanban-board.png │ │ │ └── task-details.png │ │ └── sidebar-icon.svg │ ├── CHANGELOG.md │ ├── components.json │ ├── docs │ │ ├── extension-CI-setup.md │ │ └── extension-development-guide.md │ ├── esbuild.js │ ├── LICENSE │ ├── package.json │ ├── package.mjs │ ├── package.publish.json │ ├── README.md │ ├── src │ │ ├── components │ │ │ ├── ConfigView.tsx │ │ │ ├── constants.ts │ │ │ ├── TaskDetails │ │ │ │ ├── AIActionsSection.tsx │ │ │ │ ├── DetailsSection.tsx │ │ │ │ ├── PriorityBadge.tsx │ │ │ │ ├── SubtasksSection.tsx │ │ │ │ ├── TaskMetadataSidebar.tsx │ │ │ │ └── useTaskDetails.ts │ │ │ ├── TaskDetailsView.tsx │ │ │ ├── TaskMasterLogo.tsx │ │ │ └── ui │ │ │ ├── badge.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── CollapsibleSection.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── label.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── separator.tsx │ │ │ ├── shadcn-io │ │ │ │ └── kanban │ │ │ │ └── index.tsx │ │ │ └── textarea.tsx │ │ ├── extension.ts │ │ ├── index.ts │ │ ├── lib │ │ │ └── utils.ts │ │ ├── services │ │ │ ├── config-service.ts │ │ │ ├── error-handler.ts │ │ │ ├── notification-preferences.ts │ │ │ ├── polling-service.ts │ │ │ ├── polling-strategies.ts │ │ │ ├── sidebar-webview-manager.ts │ │ │ ├── task-repository.ts │ │ │ ├── terminal-manager.ts │ │ │ └── webview-manager.ts │ │ ├── test │ │ │ └── extension.test.ts │ │ ├── utils │ │ │ ├── configManager.ts │ │ │ ├── connectionManager.ts │ │ │ ├── errorHandler.ts │ │ │ ├── event-emitter.ts │ │ │ ├── logger.ts │ │ │ ├── mcpClient.ts │ │ │ ├── notificationPreferences.ts │ │ │ └── task-master-api │ │ │ ├── cache │ │ │ │ └── cache-manager.ts │ │ │ ├── index.ts │ │ │ ├── mcp-client.ts │ │ │ ├── transformers │ │ │ │ └── task-transformer.ts │ │ │ └── types │ │ │ └── index.ts │ │ └── webview │ │ ├── App.tsx │ │ ├── components │ │ │ ├── AppContent.tsx │ │ │ ├── EmptyState.tsx │ │ │ ├── ErrorBoundary.tsx │ │ │ ├── PollingStatus.tsx │ │ │ ├── PriorityBadge.tsx │ │ │ ├── SidebarView.tsx │ │ │ ├── TagDropdown.tsx │ │ │ ├── TaskCard.tsx │ │ │ ├── TaskEditModal.tsx │ │ │ ├── TaskMasterKanban.tsx │ │ │ ├── ToastContainer.tsx │ │ │ └── ToastNotification.tsx │ │ ├── constants │ │ │ └── index.ts │ │ ├── contexts │ │ │ └── VSCodeContext.tsx │ │ ├── hooks │ │ │ ├── useTaskQueries.ts │ │ │ ├── useVSCodeMessages.ts │ │ │ └── useWebviewHeight.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── providers │ │ │ └── QueryProvider.tsx │ │ ├── reducers │ │ │ └── appReducer.ts │ │ ├── sidebar.tsx │ │ ├── types │ │ │ └── index.ts │ │ └── utils │ │ ├── logger.ts │ │ └── toast.ts │ └── tsconfig.json ├── assets │ ├── .windsurfrules │ ├── AGENTS.md │ ├── claude │ │ ├── agents │ │ │ ├── task-checker.md │ │ │ ├── task-executor.md │ │ │ └── task-orchestrator.md │ │ ├── commands │ │ │ └── tm │ │ │ ├── add-dependency │ │ │ │ └── add-dependency.md │ │ │ ├── add-subtask │ │ │ │ ├── add-subtask.md │ │ │ │ └── convert-task-to-subtask.md │ │ │ ├── add-task │ │ │ │ └── add-task.md │ │ │ ├── analyze-complexity │ │ │ │ └── analyze-complexity.md │ │ │ ├── clear-subtasks │ │ │ │ ├── clear-all-subtasks.md │ │ │ │ └── clear-subtasks.md │ │ │ ├── complexity-report │ │ │ │ └── complexity-report.md │ │ │ ├── expand │ │ │ │ ├── expand-all-tasks.md │ │ │ │ └── expand-task.md │ │ │ ├── fix-dependencies │ │ │ │ └── fix-dependencies.md │ │ │ ├── generate │ │ │ │ └── generate-tasks.md │ │ │ ├── help.md │ │ │ ├── init │ │ │ │ ├── init-project-quick.md │ │ │ │ └── init-project.md │ │ │ ├── learn.md │ │ │ ├── list │ │ │ │ ├── list-tasks-by-status.md │ │ │ │ ├── list-tasks-with-subtasks.md │ │ │ │ └── list-tasks.md │ │ │ ├── models │ │ │ │ ├── setup-models.md │ │ │ │ └── view-models.md │ │ │ ├── next │ │ │ │ └── next-task.md │ │ │ ├── parse-prd │ │ │ │ ├── parse-prd-with-research.md │ │ │ │ └── parse-prd.md │ │ │ ├── remove-dependency │ │ │ │ └── remove-dependency.md │ │ │ ├── remove-subtask │ │ │ │ └── remove-subtask.md │ │ │ ├── remove-subtasks │ │ │ │ ├── remove-all-subtasks.md │ │ │ │ └── remove-subtasks.md │ │ │ ├── remove-task │ │ │ │ └── remove-task.md │ │ │ ├── set-status │ │ │ │ ├── to-cancelled.md │ │ │ │ ├── to-deferred.md │ │ │ │ ├── to-done.md │ │ │ │ ├── to-in-progress.md │ │ │ │ ├── to-pending.md │ │ │ │ └── to-review.md │ │ │ ├── setup │ │ │ │ ├── install-taskmaster.md │ │ │ │ └── quick-install-taskmaster.md │ │ │ ├── show │ │ │ │ └── show-task.md │ │ │ ├── status │ │ │ │ └── project-status.md │ │ │ ├── sync-readme │ │ │ │ └── sync-readme.md │ │ │ ├── tm-main.md │ │ │ ├── update │ │ │ │ ├── update-single-task.md │ │ │ │ ├── update-task.md │ │ │ │ └── update-tasks-from-id.md │ │ │ ├── utils │ │ │ │ └── analyze-project.md │ │ │ ├── validate-dependencies │ │ │ │ └── validate-dependencies.md │ │ │ └── workflows │ │ │ ├── auto-implement-tasks.md │ │ │ ├── command-pipeline.md │ │ │ └── smart-workflow.md │ │ └── TM_COMMANDS_GUIDE.md │ ├── config.json │ ├── env.example │ ├── example_prd.txt │ ├── gitignore │ ├── kiro-hooks │ │ ├── tm-code-change-task-tracker.kiro.hook │ │ ├── tm-complexity-analyzer.kiro.hook │ │ ├── tm-daily-standup-assistant.kiro.hook │ │ ├── tm-git-commit-task-linker.kiro.hook │ │ ├── tm-pr-readiness-checker.kiro.hook │ │ ├── tm-task-dependency-auto-progression.kiro.hook │ │ └── tm-test-success-task-completer.kiro.hook │ ├── roocode │ │ ├── .roo │ │ │ ├── rules-architect │ │ │ │ └── architect-rules │ │ │ ├── rules-ask │ │ │ │ └── ask-rules │ │ │ ├── rules-code │ │ │ │ └── code-rules │ │ │ ├── rules-debug │ │ │ │ └── debug-rules │ │ │ ├── rules-orchestrator │ │ │ │ └── orchestrator-rules │ │ │ └── rules-test │ │ │ └── test-rules │ │ └── .roomodes │ ├── rules │ │ ├── cursor_rules.mdc │ │ ├── dev_workflow.mdc │ │ ├── self_improve.mdc │ │ ├── taskmaster_hooks_workflow.mdc │ │ └── taskmaster.mdc │ └── scripts_README.md ├── bin │ └── task-master.js ├── biome.json ├── CHANGELOG.md ├── CLAUDE.md ├── context │ ├── chats │ │ ├── add-task-dependencies-1.md │ │ └── max-min-tokens.txt.md │ ├── fastmcp-core.txt │ ├── fastmcp-docs.txt │ ├── MCP_INTEGRATION.md │ ├── mcp-js-sdk-docs.txt │ ├── mcp-protocol-repo.txt │ ├── mcp-protocol-schema-03262025.json │ └── mcp-protocol-spec.txt ├── CONTRIBUTING.md ├── docs │ ├── CLI-COMMANDER-PATTERN.md │ ├── command-reference.md │ ├── configuration.md │ ├── contributor-docs │ │ └── testing-roo-integration.md │ ├── cross-tag-task-movement.md │ ├── examples │ │ └── claude-code-usage.md │ ├── examples.md │ ├── licensing.md │ ├── mcp-provider-guide.md │ ├── mcp-provider.md │ ├── migration-guide.md │ ├── models.md │ ├── providers │ │ └── gemini-cli.md │ ├── README.md │ ├── scripts │ │ └── models-json-to-markdown.js │ ├── task-structure.md │ └── tutorial.md ├── images │ └── logo.png ├── index.js ├── jest.config.js ├── jest.resolver.cjs ├── LICENSE ├── llms-install.md ├── mcp-server │ ├── server.js │ └── src │ ├── core │ │ ├── __tests__ │ │ │ └── context-manager.test.js │ │ ├── context-manager.js │ │ ├── direct-functions │ │ │ ├── add-dependency.js │ │ │ ├── add-subtask.js │ │ │ ├── add-tag.js │ │ │ ├── add-task.js │ │ │ ├── analyze-task-complexity.js │ │ │ ├── cache-stats.js │ │ │ ├── clear-subtasks.js │ │ │ ├── complexity-report.js │ │ │ ├── copy-tag.js │ │ │ ├── create-tag-from-branch.js │ │ │ ├── delete-tag.js │ │ │ ├── expand-all-tasks.js │ │ │ ├── expand-task.js │ │ │ ├── fix-dependencies.js │ │ │ ├── generate-task-files.js │ │ │ ├── initialize-project.js │ │ │ ├── list-tags.js │ │ │ ├── list-tasks.js │ │ │ ├── models.js │ │ │ ├── move-task-cross-tag.js │ │ │ ├── move-task.js │ │ │ ├── next-task.js │ │ │ ├── parse-prd.js │ │ │ ├── remove-dependency.js │ │ │ ├── remove-subtask.js │ │ │ ├── remove-task.js │ │ │ ├── rename-tag.js │ │ │ ├── research.js │ │ │ ├── response-language.js │ │ │ ├── rules.js │ │ │ ├── scope-down.js │ │ │ ├── scope-up.js │ │ │ ├── set-task-status.js │ │ │ ├── show-task.js │ │ │ ├── update-subtask-by-id.js │ │ │ ├── update-task-by-id.js │ │ │ ├── update-tasks.js │ │ │ ├── use-tag.js │ │ │ └── validate-dependencies.js │ │ ├── task-master-core.js │ │ └── utils │ │ ├── env-utils.js │ │ └── path-utils.js │ ├── custom-sdk │ │ ├── errors.js │ │ ├── index.js │ │ ├── json-extractor.js │ │ ├── language-model.js │ │ ├── message-converter.js │ │ └── schema-converter.js │ ├── index.js │ ├── logger.js │ ├── providers │ │ └── mcp-provider.js │ └── tools │ ├── add-dependency.js │ ├── add-subtask.js │ ├── add-tag.js │ ├── add-task.js │ ├── analyze.js │ ├── clear-subtasks.js │ ├── complexity-report.js │ ├── copy-tag.js │ ├── delete-tag.js │ ├── expand-all.js │ ├── expand-task.js │ ├── fix-dependencies.js │ ├── generate.js │ ├── get-operation-status.js │ ├── get-task.js │ ├── get-tasks.js │ ├── index.js │ ├── initialize-project.js │ ├── list-tags.js │ ├── models.js │ ├── move-task.js │ ├── next-task.js │ ├── parse-prd.js │ ├── remove-dependency.js │ ├── remove-subtask.js │ ├── remove-task.js │ ├── rename-tag.js │ ├── research.js │ ├── response-language.js │ ├── rules.js │ ├── scope-down.js │ ├── scope-up.js │ ├── set-task-status.js │ ├── update-subtask.js │ ├── update-task.js │ ├── update.js │ ├── use-tag.js │ ├── utils.js │ └── validate-dependencies.js ├── mcp-test.js ├── output.json ├── package-lock.json ├── package.json ├── packages │ ├── build-config │ │ ├── CHANGELOG.md │ │ ├── package.json │ │ ├── src │ │ │ └── tsdown.base.ts │ │ └── tsconfig.json │ └── tm-core │ ├── .gitignore │ ├── CHANGELOG.md │ ├── docs │ │ └── listTasks-architecture.md │ ├── package.json │ ├── POC-STATUS.md │ ├── README.md │ ├── src │ │ ├── auth │ │ │ ├── auth-manager.test.ts │ │ │ ├── auth-manager.ts │ │ │ ├── config.ts │ │ │ ├── credential-store.test.ts │ │ │ ├── credential-store.ts │ │ │ ├── index.ts │ │ │ ├── oauth-service.ts │ │ │ ├── supabase-session-storage.ts │ │ │ └── types.ts │ │ ├── clients │ │ │ ├── index.ts │ │ │ └── supabase-client.ts │ │ ├── config │ │ │ ├── config-manager.spec.ts │ │ │ ├── config-manager.ts │ │ │ ├── index.ts │ │ │ └── services │ │ │ ├── config-loader.service.spec.ts │ │ │ ├── config-loader.service.ts │ │ │ ├── config-merger.service.spec.ts │ │ │ ├── config-merger.service.ts │ │ │ ├── config-persistence.service.spec.ts │ │ │ ├── config-persistence.service.ts │ │ │ ├── environment-config-provider.service.spec.ts │ │ │ ├── environment-config-provider.service.ts │ │ │ ├── index.ts │ │ │ ├── runtime-state-manager.service.spec.ts │ │ │ └── runtime-state-manager.service.ts │ │ ├── constants │ │ │ └── index.ts │ │ ├── entities │ │ │ └── task.entity.ts │ │ ├── errors │ │ │ ├── index.ts │ │ │ └── task-master-error.ts │ │ ├── executors │ │ │ ├── base-executor.ts │ │ │ ├── claude-executor.ts │ │ │ ├── executor-factory.ts │ │ │ ├── executor-service.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── interfaces │ │ │ ├── ai-provider.interface.ts │ │ │ ├── configuration.interface.ts │ │ │ ├── index.ts │ │ │ └── storage.interface.ts │ │ ├── logger │ │ │ ├── factory.ts │ │ │ ├── index.ts │ │ │ └── logger.ts │ │ ├── mappers │ │ │ └── TaskMapper.ts │ │ ├── parser │ │ │ └── index.ts │ │ ├── providers │ │ │ ├── ai │ │ │ │ ├── base-provider.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── repositories │ │ │ ├── supabase-task-repository.ts │ │ │ └── task-repository.interface.ts │ │ ├── services │ │ │ ├── index.ts │ │ │ ├── organization.service.ts │ │ │ ├── task-execution-service.ts │ │ │ └── task-service.ts │ │ ├── storage │ │ │ ├── api-storage.ts │ │ │ ├── file-storage │ │ │ │ ├── file-operations.ts │ │ │ │ ├── file-storage.ts │ │ │ │ ├── format-handler.ts │ │ │ │ ├── index.ts │ │ │ │ └── path-resolver.ts │ │ │ ├── index.ts │ │ │ └── storage-factory.ts │ │ ├── subpath-exports.test.ts │ │ ├── task-master-core.ts │ │ ├── types │ │ │ ├── database.types.ts │ │ │ ├── index.ts │ │ │ └── legacy.ts │ │ └── utils │ │ ├── id-generator.ts │ │ └── index.ts │ ├── tests │ │ ├── integration │ │ │ └── list-tasks.test.ts │ │ ├── mocks │ │ │ └── mock-provider.ts │ │ ├── setup.ts │ │ └── unit │ │ ├── base-provider.test.ts │ │ ├── executor.test.ts │ │ └── smoke.test.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── README-task-master.md ├── README.md ├── scripts │ ├── dev.js │ ├── init.js │ ├── modules │ │ ├── ai-services-unified.js │ │ ├── commands.js │ │ ├── config-manager.js │ │ ├── dependency-manager.js │ │ ├── index.js │ │ ├── prompt-manager.js │ │ ├── supported-models.json │ │ ├── sync-readme.js │ │ ├── task-manager │ │ │ ├── add-subtask.js │ │ │ ├── add-task.js │ │ │ ├── analyze-task-complexity.js │ │ │ ├── clear-subtasks.js │ │ │ ├── expand-all-tasks.js │ │ │ ├── expand-task.js │ │ │ ├── find-next-task.js │ │ │ ├── generate-task-files.js │ │ │ ├── is-task-dependent.js │ │ │ ├── list-tasks.js │ │ │ ├── migrate.js │ │ │ ├── models.js │ │ │ ├── move-task.js │ │ │ ├── parse-prd │ │ │ │ ├── index.js │ │ │ │ ├── parse-prd-config.js │ │ │ │ ├── parse-prd-helpers.js │ │ │ │ ├── parse-prd-non-streaming.js │ │ │ │ ├── parse-prd-streaming.js │ │ │ │ └── parse-prd.js │ │ │ ├── remove-subtask.js │ │ │ ├── remove-task.js │ │ │ ├── research.js │ │ │ ├── response-language.js │ │ │ ├── scope-adjustment.js │ │ │ ├── set-task-status.js │ │ │ ├── tag-management.js │ │ │ ├── task-exists.js │ │ │ ├── update-single-task-status.js │ │ │ ├── update-subtask-by-id.js │ │ │ ├── update-task-by-id.js │ │ │ └── update-tasks.js │ │ ├── task-manager.js │ │ ├── ui.js │ │ ├── update-config-tokens.js │ │ ├── utils │ │ │ ├── contextGatherer.js │ │ │ ├── fuzzyTaskSearch.js │ │ │ └── git-utils.js │ │ └── utils.js │ ├── task-complexity-report.json │ ├── test-claude-errors.js │ └── test-claude.js ├── src │ ├── ai-providers │ │ ├── anthropic.js │ │ ├── azure.js │ │ ├── base-provider.js │ │ ├── bedrock.js │ │ ├── claude-code.js │ │ ├── custom-sdk │ │ │ ├── claude-code │ │ │ │ ├── errors.js │ │ │ │ ├── index.js │ │ │ │ ├── json-extractor.js │ │ │ │ ├── language-model.js │ │ │ │ ├── message-converter.js │ │ │ │ └── types.js │ │ │ └── grok-cli │ │ │ ├── errors.js │ │ │ ├── index.js │ │ │ ├── json-extractor.js │ │ │ ├── language-model.js │ │ │ ├── message-converter.js │ │ │ └── types.js │ │ ├── gemini-cli.js │ │ ├── google-vertex.js │ │ ├── google.js │ │ ├── grok-cli.js │ │ ├── groq.js │ │ ├── index.js │ │ ├── ollama.js │ │ ├── openai.js │ │ ├── openrouter.js │ │ ├── perplexity.js │ │ └── xai.js │ ├── constants │ │ ├── commands.js │ │ ├── paths.js │ │ ├── profiles.js │ │ ├── providers.js │ │ ├── rules-actions.js │ │ ├── task-priority.js │ │ └── task-status.js │ ├── profiles │ │ ├── amp.js │ │ ├── base-profile.js │ │ ├── claude.js │ │ ├── cline.js │ │ ├── codex.js │ │ ├── cursor.js │ │ ├── gemini.js │ │ ├── index.js │ │ ├── kilo.js │ │ ├── kiro.js │ │ ├── opencode.js │ │ ├── roo.js │ │ ├── trae.js │ │ ├── vscode.js │ │ ├── windsurf.js │ │ └── zed.js │ ├── progress │ │ ├── base-progress-tracker.js │ │ ├── cli-progress-factory.js │ │ ├── parse-prd-tracker.js │ │ ├── progress-tracker-builder.js │ │ └── tracker-ui.js │ ├── prompts │ │ ├── add-task.json │ │ ├── analyze-complexity.json │ │ ├── expand-task.json │ │ ├── parse-prd.json │ │ ├── README.md │ │ ├── research.json │ │ ├── schemas │ │ │ ├── parameter.schema.json │ │ │ ├── prompt-template.schema.json │ │ │ ├── README.md │ │ │ └── variant.schema.json │ │ ├── update-subtask.json │ │ ├── update-task.json │ │ └── update-tasks.json │ ├── provider-registry │ │ └── index.js │ ├── task-master.js │ ├── ui │ │ ├── confirm.js │ │ ├── indicators.js │ │ └── parse-prd.js │ └── utils │ ├── asset-resolver.js │ ├── create-mcp-config.js │ ├── format.js │ ├── getVersion.js │ ├── logger-utils.js │ ├── manage-gitignore.js │ ├── path-utils.js │ ├── profiles.js │ ├── rule-transformer.js │ ├── stream-parser.js │ └── timeout-manager.js ├── test-clean-tags.js ├── test-config-manager.js ├── test-prd.txt ├── test-tag-functions.js ├── test-version-check-full.js ├── test-version-check.js ├── tests │ ├── e2e │ │ ├── e2e_helpers.sh │ │ ├── parse_llm_output.cjs │ │ ├── run_e2e.sh │ │ ├── run_fallback_verification.sh │ │ └── test_llm_analysis.sh │ ├── fixture │ │ └── test-tasks.json │ ├── fixtures │ │ ├── .taskmasterconfig │ │ ├── sample-claude-response.js │ │ ├── sample-prd.txt │ │ └── sample-tasks.js │ ├── integration │ │ ├── claude-code-optional.test.js │ │ ├── cli │ │ │ ├── commands.test.js │ │ │ ├── complex-cross-tag-scenarios.test.js │ │ │ └── move-cross-tag.test.js │ │ ├── manage-gitignore.test.js │ │ ├── mcp-server │ │ │ └── direct-functions.test.js │ │ ├── move-task-cross-tag.integration.test.js │ │ ├── move-task-simple.integration.test.js │ │ └── profiles │ │ ├── amp-init-functionality.test.js │ │ ├── claude-init-functionality.test.js │ │ ├── cline-init-functionality.test.js │ │ ├── codex-init-functionality.test.js │ │ ├── cursor-init-functionality.test.js │ │ ├── gemini-init-functionality.test.js │ │ ├── opencode-init-functionality.test.js │ │ ├── roo-files-inclusion.test.js │ │ ├── roo-init-functionality.test.js │ │ ├── rules-files-inclusion.test.js │ │ ├── trae-init-functionality.test.js │ │ ├── vscode-init-functionality.test.js │ │ └── windsurf-init-functionality.test.js │ ├── manual │ │ ├── progress │ │ │ ├── parse-prd-analysis.js │ │ │ ├── test-parse-prd.js │ │ │ └── TESTING_GUIDE.md │ │ └── prompts │ │ ├── prompt-test.js │ │ └── README.md │ ├── README.md │ ├── setup.js │ └── unit │ ├── ai-providers │ │ ├── claude-code.test.js │ │ ├── custom-sdk │ │ │ └── claude-code │ │ │ └── language-model.test.js │ │ ├── gemini-cli.test.js │ │ ├── mcp-components.test.js │ │ └── openai.test.js │ ├── ai-services-unified.test.js │ ├── commands.test.js │ ├── config-manager.test.js │ ├── config-manager.test.mjs │ ├── dependency-manager.test.js │ ├── init.test.js │ ├── initialize-project.test.js │ ├── kebab-case-validation.test.js │ ├── manage-gitignore.test.js │ ├── mcp │ │ └── tools │ │ ├── __mocks__ │ │ │ └── move-task.js │ │ ├── add-task.test.js │ │ ├── analyze-complexity.test.js │ │ ├── expand-all.test.js │ │ ├── get-tasks.test.js │ │ ├── initialize-project.test.js │ │ ├── move-task-cross-tag-options.test.js │ │ ├── move-task-cross-tag.test.js │ │ └── remove-task.test.js │ ├── mcp-providers │ │ ├── mcp-components.test.js │ │ └── mcp-provider.test.js │ ├── parse-prd.test.js │ ├── profiles │ │ ├── amp-integration.test.js │ │ ├── claude-integration.test.js │ │ ├── cline-integration.test.js │ │ ├── codex-integration.test.js │ │ ├── cursor-integration.test.js │ │ ├── gemini-integration.test.js │ │ ├── kilo-integration.test.js │ │ ├── kiro-integration.test.js │ │ ├── mcp-config-validation.test.js │ │ ├── opencode-integration.test.js │ │ ├── profile-safety-check.test.js │ │ ├── roo-integration.test.js │ │ ├── rule-transformer-cline.test.js │ │ ├── rule-transformer-cursor.test.js │ │ ├── rule-transformer-gemini.test.js │ │ ├── rule-transformer-kilo.test.js │ │ ├── rule-transformer-kiro.test.js │ │ ├── rule-transformer-opencode.test.js │ │ ├── rule-transformer-roo.test.js │ │ ├── rule-transformer-trae.test.js │ │ ├── rule-transformer-vscode.test.js │ │ ├── rule-transformer-windsurf.test.js │ │ ├── rule-transformer-zed.test.js │ │ ├── rule-transformer.test.js │ │ ├── selective-profile-removal.test.js │ │ ├── subdirectory-support.test.js │ │ ├── trae-integration.test.js │ │ ├── vscode-integration.test.js │ │ ├── windsurf-integration.test.js │ │ └── zed-integration.test.js │ ├── progress │ │ └── base-progress-tracker.test.js │ ├── prompt-manager.test.js │ ├── prompts │ │ └── expand-task-prompt.test.js │ ├── providers │ │ └── provider-registry.test.js │ ├── scripts │ │ └── modules │ │ ├── commands │ │ │ ├── move-cross-tag.test.js │ │ │ └── README.md │ │ ├── dependency-manager │ │ │ ├── circular-dependencies.test.js │ │ │ ├── cross-tag-dependencies.test.js │ │ │ └── fix-dependencies-command.test.js │ │ ├── task-manager │ │ │ ├── add-subtask.test.js │ │ │ ├── add-task.test.js │ │ │ ├── analyze-task-complexity.test.js │ │ │ ├── clear-subtasks.test.js │ │ │ ├── complexity-report-tag-isolation.test.js │ │ │ ├── expand-all-tasks.test.js │ │ │ ├── expand-task.test.js │ │ │ ├── find-next-task.test.js │ │ │ ├── generate-task-files.test.js │ │ │ ├── list-tasks.test.js │ │ │ ├── move-task-cross-tag.test.js │ │ │ ├── move-task.test.js │ │ │ ├── parse-prd.test.js │ │ │ ├── remove-subtask.test.js │ │ │ ├── remove-task.test.js │ │ │ ├── research.test.js │ │ │ ├── scope-adjustment.test.js │ │ │ ├── set-task-status.test.js │ │ │ ├── setup.js │ │ │ ├── update-single-task-status.test.js │ │ │ ├── update-subtask-by-id.test.js │ │ │ ├── update-task-by-id.test.js │ │ │ └── update-tasks.test.js │ │ ├── ui │ │ │ └── cross-tag-error-display.test.js │ │ └── utils-tag-aware-paths.test.js │ ├── task-finder.test.js │ ├── task-manager │ │ ├── clear-subtasks.test.js │ │ ├── move-task.test.js │ │ ├── tag-boundary.test.js │ │ └── tag-management.test.js │ ├── task-master.test.js │ ├── ui │ │ └── indicators.test.js │ ├── ui.test.js │ ├── utils-strip-ansi.test.js │ └── utils.test.js ├── tsconfig.json ├── tsdown.config.ts └── turbo.json ``` # Files -------------------------------------------------------------------------------- /mcp-server/src/tools/use-tag.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/use-tag.js 3 | * Tool to switch to a different tag context 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | createErrorResponse, 9 | handleApiResult, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { useTagDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | 15 | /** 16 | * Register the useTag tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerUseTagTool(server) { 20 | server.addTool({ 21 | name: 'use_tag', 22 | description: 'Switch to a different tag context for task operations', 23 | parameters: z.object({ 24 | name: z.string().describe('Name of the tag to switch to'), 25 | file: z 26 | .string() 27 | .optional() 28 | .describe('Path to the tasks file (default: tasks/tasks.json)'), 29 | projectRoot: z 30 | .string() 31 | .describe('The directory of the project. Must be an absolute path.') 32 | }), 33 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 34 | try { 35 | log.info(`Starting use-tag with args: ${JSON.stringify(args)}`); 36 | 37 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 38 | let tasksJsonPath; 39 | try { 40 | tasksJsonPath = findTasksPath( 41 | { projectRoot: args.projectRoot, file: args.file }, 42 | log 43 | ); 44 | } catch (error) { 45 | log.error(`Error finding tasks.json: ${error.message}`); 46 | return createErrorResponse( 47 | `Failed to find tasks.json: ${error.message}` 48 | ); 49 | } 50 | 51 | // Call the direct function 52 | const result = await useTagDirect( 53 | { 54 | tasksJsonPath: tasksJsonPath, 55 | name: args.name, 56 | projectRoot: args.projectRoot 57 | }, 58 | log, 59 | { session } 60 | ); 61 | 62 | return handleApiResult( 63 | result, 64 | log, 65 | 'Error switching tag', 66 | undefined, 67 | args.projectRoot 68 | ); 69 | } catch (error) { 70 | log.error(`Error in use-tag tool: ${error.message}`); 71 | return createErrorResponse(error.message); 72 | } 73 | }) 74 | }); 75 | } 76 | ``` -------------------------------------------------------------------------------- /tests/unit/utils-strip-ansi.test.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * Tests for the stripAnsiCodes utility function 3 | */ 4 | import { jest } from '@jest/globals'; 5 | 6 | // Import the module under test 7 | const { stripAnsiCodes } = await import('../../scripts/modules/utils.js'); 8 | 9 | describe('stripAnsiCodes', () => { 10 | test('should remove ANSI color codes from text', () => { 11 | const textWithColors = '\x1b[31mRed text\x1b[0m \x1b[32mGreen text\x1b[0m'; 12 | const result = stripAnsiCodes(textWithColors); 13 | expect(result).toBe('Red text Green text'); 14 | }); 15 | 16 | test('should handle text without ANSI codes', () => { 17 | const plainText = 'This is plain text'; 18 | const result = stripAnsiCodes(plainText); 19 | expect(result).toBe('This is plain text'); 20 | }); 21 | 22 | test('should handle empty string', () => { 23 | const result = stripAnsiCodes(''); 24 | expect(result).toBe(''); 25 | }); 26 | 27 | test('should handle complex ANSI sequences', () => { 28 | // Test with various ANSI escape sequences 29 | const complexText = 30 | '\x1b[1;31mBold red\x1b[0m \x1b[4;32mUnderlined green\x1b[0m \x1b[33;46mYellow on cyan\x1b[0m'; 31 | const result = stripAnsiCodes(complexText); 32 | expect(result).toBe('Bold red Underlined green Yellow on cyan'); 33 | }); 34 | 35 | test('should handle non-string input gracefully', () => { 36 | expect(stripAnsiCodes(null)).toBe(null); 37 | expect(stripAnsiCodes(undefined)).toBe(undefined); 38 | expect(stripAnsiCodes(123)).toBe(123); 39 | expect(stripAnsiCodes({})).toEqual({}); 40 | }); 41 | 42 | test('should handle real chalk output patterns', () => { 43 | // Test patterns similar to what chalk produces 44 | const chalkLikeText = 45 | '1 \x1b[32m✓ done\x1b[39m Setup Project \x1b[31m(high)\x1b[39m'; 46 | const result = stripAnsiCodes(chalkLikeText); 47 | expect(result).toBe('1 ✓ done Setup Project (high)'); 48 | }); 49 | 50 | test('should handle multiline text with ANSI codes', () => { 51 | const multilineText = 52 | '\x1b[31mLine 1\x1b[0m\n\x1b[32mLine 2\x1b[0m\n\x1b[33mLine 3\x1b[0m'; 53 | const result = stripAnsiCodes(multilineText); 54 | expect(result).toBe('Line 1\nLine 2\nLine 3'); 55 | }); 56 | }); 57 | ``` -------------------------------------------------------------------------------- /mcp-test.js: -------------------------------------------------------------------------------- ```javascript 1 | #!/usr/bin/env node 2 | 3 | import { Config } from 'fastmcp'; 4 | import path from 'path'; 5 | import fs from 'fs'; 6 | 7 | // Log the current directory 8 | console.error(`Current working directory: ${process.cwd()}`); 9 | 10 | try { 11 | console.error('Attempting to load FastMCP Config...'); 12 | 13 | // Check if .cursor/mcp.json exists 14 | const mcpPath = path.join(process.cwd(), '.cursor', 'mcp.json'); 15 | console.error(`Checking if mcp.json exists at: ${mcpPath}`); 16 | 17 | if (fs.existsSync(mcpPath)) { 18 | console.error('mcp.json file found'); 19 | console.error( 20 | `File content: ${JSON.stringify(JSON.parse(fs.readFileSync(mcpPath, 'utf8')), null, 2)}` 21 | ); 22 | } else { 23 | console.error('mcp.json file not found'); 24 | } 25 | 26 | // Try to create Config 27 | const config = new Config(); 28 | console.error('Config created successfully'); 29 | 30 | // Check if env property exists 31 | if (config.env) { 32 | console.error( 33 | `Config.env exists with keys: ${Object.keys(config.env).join(', ')}` 34 | ); 35 | 36 | // Print each env var value (careful with sensitive values) 37 | for (const [key, value] of Object.entries(config.env)) { 38 | if (key.includes('KEY')) { 39 | console.error(`${key}: [value hidden]`); 40 | } else { 41 | console.error(`${key}: ${value}`); 42 | } 43 | } 44 | } else { 45 | console.error('Config.env does not exist'); 46 | } 47 | } catch (error) { 48 | console.error(`Error loading Config: ${error.message}`); 49 | console.error(`Stack trace: ${error.stack}`); 50 | } 51 | 52 | // Log process.env to see if values from mcp.json were loaded automatically 53 | console.error('\nChecking if process.env already has values from mcp.json:'); 54 | const envVars = [ 55 | 'ANTHROPIC_API_KEY', 56 | 'PERPLEXITY_API_KEY', 57 | 'MODEL', 58 | 'PERPLEXITY_MODEL', 59 | 'MAX_TOKENS', 60 | 'TEMPERATURE', 61 | 'DEFAULT_SUBTASKS', 62 | 'DEFAULT_PRIORITY' 63 | ]; 64 | 65 | for (const varName of envVars) { 66 | if (process.env[varName]) { 67 | if (varName.includes('KEY')) { 68 | console.error(`${varName}: [value hidden]`); 69 | } else { 70 | console.error(`${varName}: ${process.env[varName]}`); 71 | } 72 | } else { 73 | console.error(`${varName}: not set`); 74 | } 75 | } 76 | ``` -------------------------------------------------------------------------------- /tests/unit/profiles/cursor-integration.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import { jest } from '@jest/globals'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | import os from 'os'; 5 | 6 | // Mock external modules 7 | jest.mock('child_process', () => ({ 8 | execSync: jest.fn() 9 | })); 10 | 11 | // Mock console methods 12 | jest.mock('console', () => ({ 13 | log: jest.fn(), 14 | info: jest.fn(), 15 | warn: jest.fn(), 16 | error: jest.fn(), 17 | clear: jest.fn() 18 | })); 19 | 20 | describe('Cursor Integration', () => { 21 | let tempDir; 22 | 23 | beforeEach(() => { 24 | jest.clearAllMocks(); 25 | 26 | // Create a temporary directory for testing 27 | tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-')); 28 | 29 | // Spy on fs methods 30 | jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); 31 | jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => { 32 | if (filePath.toString().includes('mcp.json')) { 33 | return JSON.stringify({ mcpServers: {} }, null, 2); 34 | } 35 | return '{}'; 36 | }); 37 | jest.spyOn(fs, 'existsSync').mockImplementation(() => false); 38 | jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {}); 39 | }); 40 | 41 | afterEach(() => { 42 | // Clean up the temporary directory 43 | try { 44 | fs.rmSync(tempDir, { recursive: true, force: true }); 45 | } catch (err) { 46 | console.error(`Error cleaning up: ${err.message}`); 47 | } 48 | }); 49 | 50 | // Test function that simulates the createProjectStructure behavior for Cursor files 51 | function mockCreateCursorStructure() { 52 | // Create main .cursor directory 53 | fs.mkdirSync(path.join(tempDir, '.cursor'), { recursive: true }); 54 | 55 | // Create rules directory 56 | fs.mkdirSync(path.join(tempDir, '.cursor', 'rules'), { recursive: true }); 57 | 58 | // Create MCP config file 59 | fs.writeFileSync( 60 | path.join(tempDir, '.cursor', 'mcp.json'), 61 | JSON.stringify({ mcpServers: {} }, null, 2) 62 | ); 63 | } 64 | 65 | test('creates all required .cursor directories', () => { 66 | // Act 67 | mockCreateCursorStructure(); 68 | 69 | // Assert 70 | expect(fs.mkdirSync).toHaveBeenCalledWith(path.join(tempDir, '.cursor'), { 71 | recursive: true 72 | }); 73 | expect(fs.mkdirSync).toHaveBeenCalledWith( 74 | path.join(tempDir, '.cursor', 'rules'), 75 | { recursive: true } 76 | ); 77 | }); 78 | }); 79 | ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/rename-tag.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/rename-tag.js 3 | * Tool to rename an existing tag 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | createErrorResponse, 9 | handleApiResult, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { renameTagDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | 15 | /** 16 | * Register the renameTag tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerRenameTagTool(server) { 20 | server.addTool({ 21 | name: 'rename_tag', 22 | description: 'Rename an existing tag', 23 | parameters: z.object({ 24 | oldName: z.string().describe('Current name of the tag to rename'), 25 | newName: z.string().describe('New name for the tag'), 26 | file: z 27 | .string() 28 | .optional() 29 | .describe('Path to the tasks file (default: tasks/tasks.json)'), 30 | projectRoot: z 31 | .string() 32 | .describe('The directory of the project. Must be an absolute path.') 33 | }), 34 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 35 | try { 36 | log.info(`Starting rename-tag with args: ${JSON.stringify(args)}`); 37 | 38 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 39 | let tasksJsonPath; 40 | try { 41 | tasksJsonPath = findTasksPath( 42 | { projectRoot: args.projectRoot, file: args.file }, 43 | log 44 | ); 45 | } catch (error) { 46 | log.error(`Error finding tasks.json: ${error.message}`); 47 | return createErrorResponse( 48 | `Failed to find tasks.json: ${error.message}` 49 | ); 50 | } 51 | 52 | // Call the direct function 53 | const result = await renameTagDirect( 54 | { 55 | tasksJsonPath: tasksJsonPath, 56 | oldName: args.oldName, 57 | newName: args.newName, 58 | projectRoot: args.projectRoot 59 | }, 60 | log, 61 | { session } 62 | ); 63 | 64 | return handleApiResult( 65 | result, 66 | log, 67 | 'Error renaming tag', 68 | undefined, 69 | args.projectRoot 70 | ); 71 | } catch (error) { 72 | log.error(`Error in rename-tag tool: ${error.message}`); 73 | return createErrorResponse(error.message); 74 | } 75 | }) 76 | }); 77 | } 78 | ``` -------------------------------------------------------------------------------- /apps/docs/getting-started/quick-start/tasks-quick.mdx: -------------------------------------------------------------------------------- ```markdown 1 | --- 2 | title: Tasks Setup 3 | sidebarTitle: "Tasks Setup" 4 | --- 5 | Now that your tasks are generated you can review the plan and prepare for execution. 6 | 7 | <Tip> 8 | Not all of the setup steps are required but they are recommended in order to ensure your coding agents work on accurate tasks. 9 | </Tip> 10 | 11 | ## Expand Tasks 12 | Used to add detail to tasks and create subtasks. We recommend expanding all tasks using the MCP request below: 13 | ``` 14 | Expand all tasks into subtasks. 15 | ``` 16 | The agent will execute 17 | ```bash 18 | task-master expand --all 19 | ``` 20 | ## List/Show Tasks 21 | 22 | Used to view task details. It is important to review the plan and ensure it makes sense in your project. Check for correct folder structures, dependencies, out of scope subtasks, etc. 23 | 24 | To see a list of tasks and descriptions use the following command: 25 | 26 | ``` 27 | List all pending tasks so I can review. 28 | ``` 29 | To see all tasks in the CLI you can use: 30 | ```bash 31 | task-master list 32 | ``` 33 | 34 | To see all implementation details of an individual task, including subtasks and testing strategy, you can use Show Task: 35 | 36 | ``` 37 | Show task 2 so I can review. 38 | ``` 39 | 40 | ```bash 41 | task-master show --id=<##> 42 | ``` 43 | 44 | ## Update Tasks 45 | 46 | If the task details need to be edited you can update the task using this request: 47 | 48 | ``` 49 | Update Task 2 to use Postgres instead of MongoDB and remove the sharding subtask 50 | ``` 51 | Or this CLI command: 52 | 53 | ```bash 54 | task-master update-task --id=2 --prompt="use Postgres instead of MongoDB and remove the sharding subtask" 55 | ``` 56 | ## Analyze complexity 57 | 58 | Task Master can provide a complexity report which can be helpful to read before you begin. If you didn't already expand all your tasks, it could help identify which could be broken down further with subtasks. 59 | 60 | ``` 61 | Can you analyze the complexity of our tasks to help me understand which ones need to be broken down further? 62 | ``` 63 | 64 | You can view the report in a friendly table using: 65 | ``` 66 | Can you show me the complexity report in a more readable format? 67 | ``` 68 | 69 | <Check>Now you are ready to begin [executing tasks](/docs/getting-started/quick-start/execute-quick)</Check> ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/button.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { Slot } from '@radix-ui/react-slot'; 2 | import { type VariantProps, cva } from 'class-variance-authority'; 3 | import type * as React from 'react'; 4 | 5 | import { cn } from '../../lib/utils'; 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90', 14 | destructive: 15 | 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', 16 | outline: 17 | 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', 18 | secondary: 19 | 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80', 20 | ghost: 21 | 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', 22 | link: 'text-primary underline-offset-4 hover:underline' 23 | }, 24 | size: { 25 | default: 'h-9 px-4 py-2 has-[>svg]:px-3', 26 | sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', 27 | lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', 28 | icon: 'size-9' 29 | } 30 | }, 31 | defaultVariants: { 32 | variant: 'default', 33 | size: 'default' 34 | } 35 | } 36 | ); 37 | 38 | function Button({ 39 | className, 40 | variant, 41 | size, 42 | asChild = false, 43 | ...props 44 | }: React.ComponentProps<'button'> & 45 | VariantProps<typeof buttonVariants> & { 46 | asChild?: boolean; 47 | }) { 48 | const Comp = asChild ? Slot : 'button'; 49 | 50 | return ( 51 | <Comp 52 | data-slot="button" 53 | className={cn(buttonVariants({ variant, size, className }))} 54 | {...props} 55 | /> 56 | ); 57 | } 58 | 59 | export { Button, buttonVariants }; 60 | ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/list-tags.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/list-tags.js 3 | * Tool to list all available tags 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | createErrorResponse, 9 | handleApiResult, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { listTagsDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | 15 | /** 16 | * Register the listTags tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerListTagsTool(server) { 20 | server.addTool({ 21 | name: 'list_tags', 22 | description: 'List all available tags with task counts and metadata', 23 | parameters: z.object({ 24 | showMetadata: z 25 | .boolean() 26 | .optional() 27 | .describe('Whether to include metadata in the output (default: false)'), 28 | file: z 29 | .string() 30 | .optional() 31 | .describe('Path to the tasks file (default: tasks/tasks.json)'), 32 | projectRoot: z 33 | .string() 34 | .describe('The directory of the project. Must be an absolute path.') 35 | }), 36 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 37 | try { 38 | log.info(`Starting list-tags with args: ${JSON.stringify(args)}`); 39 | 40 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 41 | let tasksJsonPath; 42 | try { 43 | tasksJsonPath = findTasksPath( 44 | { projectRoot: args.projectRoot, file: args.file }, 45 | log 46 | ); 47 | } catch (error) { 48 | log.error(`Error finding tasks.json: ${error.message}`); 49 | return createErrorResponse( 50 | `Failed to find tasks.json: ${error.message}` 51 | ); 52 | } 53 | 54 | // Call the direct function 55 | const result = await listTagsDirect( 56 | { 57 | tasksJsonPath: tasksJsonPath, 58 | showMetadata: args.showMetadata, 59 | projectRoot: args.projectRoot 60 | }, 61 | log, 62 | { session } 63 | ); 64 | 65 | return handleApiResult( 66 | result, 67 | log, 68 | 'Error listing tags', 69 | undefined, 70 | args.projectRoot 71 | ); 72 | } catch (error) { 73 | log.error(`Error in list-tags tool: ${error.message}`); 74 | return createErrorResponse(error.message); 75 | } 76 | }) 77 | }); 78 | } 79 | ``` -------------------------------------------------------------------------------- /tests/e2e/test_llm_analysis.sh: -------------------------------------------------------------------------------- ```bash 1 | #!/bin/bash 2 | 3 | # Script to test the LLM analysis function independently 4 | 5 | # Exit on error 6 | set -u 7 | set -o pipefail 8 | 9 | # Source the helper functions 10 | HELPER_SCRIPT="tests/e2e/e2e_helpers.sh" 11 | if [ -f "$HELPER_SCRIPT" ]; then 12 | source "$HELPER_SCRIPT" 13 | echo "[INFO] Sourced helper script: $HELPER_SCRIPT" 14 | else 15 | echo "[ERROR] Helper script not found at $HELPER_SCRIPT. Exiting." >&2 16 | exit 1 17 | fi 18 | 19 | # --- Configuration --- 20 | # Get the absolute path to the project root (assuming this script is run from the root) 21 | PROJECT_ROOT="$(pwd)" 22 | 23 | # --- Argument Parsing --- 24 | if [ "$#" -ne 2 ]; then 25 | echo "Usage: $0 <path_to_log_file> <path_to_test_run_directory>" >&2 26 | echo "Example: $0 tests/e2e/log/e2e_run_YYYYMMDD_HHMMSS.log tests/e2e/_runs/run_YYYYMMDD_HHMMSS" >&2 27 | exit 1 28 | fi 29 | 30 | LOG_FILE_REL="$1" # Relative path from project root 31 | TEST_RUN_DIR_REL="$2" # Relative path from project root 32 | 33 | # Construct absolute paths 34 | LOG_FILE_ABS="$PROJECT_ROOT/$LOG_FILE_REL" 35 | TEST_RUN_DIR_ABS="$PROJECT_ROOT/$TEST_RUN_DIR_REL" 36 | 37 | # --- Validation --- 38 | if [ ! -f "$LOG_FILE_ABS" ]; then 39 | echo "[ERROR] Log file not found: $LOG_FILE_ABS" >&2 40 | exit 1 41 | fi 42 | 43 | if [ ! -d "$TEST_RUN_DIR_ABS" ]; then 44 | echo "[ERROR] Test run directory not found: $TEST_RUN_DIR_ABS" >&2 45 | exit 1 46 | fi 47 | 48 | if [ ! -f "$TEST_RUN_DIR_ABS/.env" ]; then 49 | echo "[ERROR] .env file not found in test run directory: $TEST_RUN_DIR_ABS/.env" >&2 50 | exit 1 51 | fi 52 | 53 | 54 | # --- Execution --- 55 | echo "[INFO] Changing directory to test run directory: $TEST_RUN_DIR_ABS" 56 | cd "$TEST_RUN_DIR_ABS" || { echo "[ERROR] Failed to cd into $TEST_RUN_DIR_ABS"; exit 1; } 57 | 58 | echo "[INFO] Current directory: $(pwd)" 59 | echo "[INFO] Calling analyze_log_with_llm function with log file: $LOG_FILE_ABS" 60 | 61 | # Call the function (sourced earlier) 62 | analyze_log_with_llm "$LOG_FILE_ABS" 63 | ANALYSIS_EXIT_CODE=$? 64 | 65 | echo "[INFO] analyze_log_with_llm finished with exit code: $ANALYSIS_EXIT_CODE" 66 | 67 | # Optional: cd back to original directory 68 | # echo "[INFO] Changing back to project root: $PROJECT_ROOT" 69 | # cd "$PROJECT_ROOT" 70 | 71 | exit $ANALYSIS_EXIT_CODE ``` -------------------------------------------------------------------------------- /apps/extension/src/services/polling-service.ts: -------------------------------------------------------------------------------- ```typescript 1 | /** 2 | * Polling Service - Simplified version 3 | * Uses strategy pattern for different polling behaviors 4 | */ 5 | 6 | import type { ExtensionLogger } from '../utils/logger'; 7 | import type { TaskRepository } from './task-repository'; 8 | 9 | export interface PollingStrategy { 10 | calculateNextInterval( 11 | consecutiveNoChanges: number, 12 | lastChangeTime?: number 13 | ): number; 14 | getName(): string; 15 | } 16 | 17 | export class PollingService { 18 | private timer?: NodeJS.Timeout; 19 | private consecutiveNoChanges = 0; 20 | private lastChangeTime?: number; 21 | private lastTasksJson?: string; 22 | 23 | constructor( 24 | private repository: TaskRepository, 25 | private strategy: PollingStrategy, 26 | private logger: ExtensionLogger 27 | ) {} 28 | 29 | start(): void { 30 | if (this.timer) { 31 | return; 32 | } 33 | 34 | this.logger.log( 35 | `Starting polling with ${this.strategy.getName()} strategy` 36 | ); 37 | this.scheduleNextPoll(); 38 | } 39 | 40 | stop(): void { 41 | if (this.timer) { 42 | clearTimeout(this.timer); 43 | this.timer = undefined; 44 | this.logger.log('Polling stopped'); 45 | } 46 | } 47 | 48 | setStrategy(strategy: PollingStrategy): void { 49 | this.strategy = strategy; 50 | this.logger.log(`Changed to ${strategy.getName()} polling strategy`); 51 | 52 | // Restart with new strategy if running 53 | if (this.timer) { 54 | this.stop(); 55 | this.start(); 56 | } 57 | } 58 | 59 | private async poll(): Promise<void> { 60 | try { 61 | const tasks = await this.repository.getAll(); 62 | const tasksJson = JSON.stringify(tasks); 63 | 64 | // Check for changes 65 | if (tasksJson !== this.lastTasksJson) { 66 | this.consecutiveNoChanges = 0; 67 | this.lastChangeTime = Date.now(); 68 | this.logger.debug('Tasks changed'); 69 | } else { 70 | this.consecutiveNoChanges++; 71 | } 72 | 73 | this.lastTasksJson = tasksJson; 74 | } catch (error) { 75 | this.logger.error('Polling error', error); 76 | } 77 | } 78 | 79 | private scheduleNextPoll(): void { 80 | const interval = this.strategy.calculateNextInterval( 81 | this.consecutiveNoChanges, 82 | this.lastChangeTime 83 | ); 84 | 85 | this.timer = setTimeout(async () => { 86 | await this.poll(); 87 | this.scheduleNextPoll(); 88 | }, interval); 89 | 90 | this.logger.debug(`Next poll in ${interval}ms`); 91 | } 92 | } 93 | ``` -------------------------------------------------------------------------------- /.github/workflows/claude-docs-trigger.yml: -------------------------------------------------------------------------------- ```yaml 1 | name: Trigger Claude Documentation Update 2 | 3 | on: 4 | push: 5 | branches: 6 | - next 7 | paths-ignore: 8 | - "apps/docs/**" 9 | - "*.md" 10 | - ".github/workflows/**" 11 | 12 | jobs: 13 | trigger-docs-update: 14 | # Only run if changes were merged (not direct pushes from bots) 15 | if: github.actor != 'github-actions[bot]' && github.actor != 'dependabot[bot]' 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: read 19 | actions: write 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 2 # Need previous commit for comparison 25 | 26 | - name: Get changed files 27 | id: changed-files 28 | run: | 29 | echo "Changed files in this push:" 30 | git diff --name-only HEAD^ HEAD | tee changed_files.txt 31 | 32 | # Store changed files for Claude to analyze (escaped for JSON) 33 | CHANGED_FILES=$(git diff --name-only HEAD^ HEAD | jq -Rs .) 34 | echo "changed_files=$CHANGED_FILES" >> $GITHUB_OUTPUT 35 | 36 | # Get the commit message (escaped for JSON) 37 | COMMIT_MSG=$(git log -1 --pretty=%B | jq -Rs .) 38 | echo "commit_message=$COMMIT_MSG" >> $GITHUB_OUTPUT 39 | 40 | # Get diff for documentation context (escaped for JSON) 41 | COMMIT_DIFF=$(git diff HEAD^ HEAD --stat | jq -Rs .) 42 | echo "commit_diff=$COMMIT_DIFF" >> $GITHUB_OUTPUT 43 | 44 | # Get commit SHA 45 | echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT 46 | 47 | - name: Trigger Claude workflow 48 | env: 49 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | run: | 51 | # Trigger the Claude docs updater workflow with the change information 52 | gh workflow run claude-docs-updater.yml \ 53 | --ref next \ 54 | -f commit_sha="${{ steps.changed-files.outputs.commit_sha }}" \ 55 | -f commit_message=${{ steps.changed-files.outputs.commit_message }} \ 56 | -f changed_files=${{ steps.changed-files.outputs.changed_files }} \ 57 | -f commit_diff=${{ steps.changed-files.outputs.commit_diff }} ``` -------------------------------------------------------------------------------- /src/constants/paths.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * Path constants for Task Master application 3 | */ 4 | 5 | // .taskmaster directory structure paths 6 | export const TASKMASTER_DIR = '.taskmaster'; 7 | export const TASKMASTER_TASKS_DIR = '.taskmaster/tasks'; 8 | export const TASKMASTER_DOCS_DIR = '.taskmaster/docs'; 9 | export const TASKMASTER_REPORTS_DIR = '.taskmaster/reports'; 10 | export const TASKMASTER_TEMPLATES_DIR = '.taskmaster/templates'; 11 | 12 | // Task Master configuration files 13 | export const TASKMASTER_CONFIG_FILE = '.taskmaster/config.json'; 14 | export const TASKMASTER_STATE_FILE = '.taskmaster/state.json'; 15 | export const LEGACY_CONFIG_FILE = '.taskmasterconfig'; 16 | 17 | // Task Master report files 18 | export const COMPLEXITY_REPORT_FILE = 19 | '.taskmaster/reports/task-complexity-report.json'; 20 | export const LEGACY_COMPLEXITY_REPORT_FILE = 21 | 'scripts/task-complexity-report.json'; 22 | 23 | // Task Master PRD file paths 24 | export const PRD_FILE = '.taskmaster/docs/prd.txt'; 25 | export const LEGACY_PRD_FILE = 'scripts/prd.txt'; 26 | 27 | // Task Master template files 28 | export const EXAMPLE_PRD_FILE = '.taskmaster/templates/example_prd.txt'; 29 | export const LEGACY_EXAMPLE_PRD_FILE = 'scripts/example_prd.txt'; 30 | 31 | // Task Master task file paths 32 | export const TASKMASTER_TASKS_FILE = '.taskmaster/tasks/tasks.json'; 33 | export const LEGACY_TASKS_FILE = 'tasks/tasks.json'; 34 | 35 | // General project files (not Task Master specific but commonly used) 36 | export const ENV_EXAMPLE_FILE = '.env.example'; 37 | export const GITIGNORE_FILE = '.gitignore'; 38 | 39 | // Task file naming pattern 40 | export const TASK_FILE_PREFIX = 'task_'; 41 | export const TASK_FILE_EXTENSION = '.txt'; 42 | 43 | /** 44 | * Project markers used to identify a task-master project root 45 | * These files/directories indicate that a directory is a Task Master project 46 | */ 47 | export const PROJECT_MARKERS = [ 48 | '.taskmaster', // New taskmaster directory 49 | LEGACY_CONFIG_FILE, // .taskmasterconfig 50 | 'tasks.json', // Generic tasks file 51 | LEGACY_TASKS_FILE, // tasks/tasks.json (legacy location) 52 | TASKMASTER_TASKS_FILE, // .taskmaster/tasks/tasks.json (new location) 53 | '.git', // Git repository 54 | '.svn' // SVN repository 55 | ]; 56 | ``` -------------------------------------------------------------------------------- /tests/unit/profiles/windsurf-integration.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import { jest } from '@jest/globals'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | import os from 'os'; 5 | 6 | // Mock external modules 7 | jest.mock('child_process', () => ({ 8 | execSync: jest.fn() 9 | })); 10 | 11 | // Mock console methods 12 | jest.mock('console', () => ({ 13 | log: jest.fn(), 14 | info: jest.fn(), 15 | warn: jest.fn(), 16 | error: jest.fn(), 17 | clear: jest.fn() 18 | })); 19 | 20 | describe('Windsurf Integration', () => { 21 | let tempDir; 22 | 23 | beforeEach(() => { 24 | jest.clearAllMocks(); 25 | 26 | // Create a temporary directory for testing 27 | tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-')); 28 | 29 | // Spy on fs methods 30 | jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); 31 | jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => { 32 | if (filePath.toString().includes('mcp.json')) { 33 | return JSON.stringify({ mcpServers: {} }, null, 2); 34 | } 35 | return '{}'; 36 | }); 37 | jest.spyOn(fs, 'existsSync').mockImplementation(() => false); 38 | jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {}); 39 | }); 40 | 41 | afterEach(() => { 42 | // Clean up the temporary directory 43 | try { 44 | fs.rmSync(tempDir, { recursive: true, force: true }); 45 | } catch (err) { 46 | console.error(`Error cleaning up: ${err.message}`); 47 | } 48 | }); 49 | 50 | // Test function that simulates the createProjectStructure behavior for Windsurf files 51 | function mockCreateWindsurfStructure() { 52 | // Create main .windsurf directory 53 | fs.mkdirSync(path.join(tempDir, '.windsurf'), { recursive: true }); 54 | 55 | // Create rules directory 56 | fs.mkdirSync(path.join(tempDir, '.windsurf', 'rules'), { recursive: true }); 57 | 58 | // Create MCP config file 59 | fs.writeFileSync( 60 | path.join(tempDir, '.windsurf', 'mcp.json'), 61 | JSON.stringify({ mcpServers: {} }, null, 2) 62 | ); 63 | } 64 | 65 | test('creates all required .windsurf directories', () => { 66 | // Act 67 | mockCreateWindsurfStructure(); 68 | 69 | // Assert 70 | expect(fs.mkdirSync).toHaveBeenCalledWith(path.join(tempDir, '.windsurf'), { 71 | recursive: true 72 | }); 73 | expect(fs.mkdirSync).toHaveBeenCalledWith( 74 | path.join(tempDir, '.windsurf', 'rules'), 75 | { recursive: true } 76 | ); 77 | }); 78 | }); 79 | ``` -------------------------------------------------------------------------------- /packages/tm-core/src/executors/base-executor.ts: -------------------------------------------------------------------------------- ```typescript 1 | /** 2 | * Base executor class providing common functionality for all executors 3 | */ 4 | 5 | import type { Task } from '../types/index.js'; 6 | import type { ITaskExecutor, ExecutorType, ExecutionResult } from './types.js'; 7 | import { getLogger } from '../logger/index.js'; 8 | 9 | export abstract class BaseExecutor implements ITaskExecutor { 10 | protected readonly logger = getLogger('BaseExecutor'); 11 | protected readonly projectRoot: string; 12 | protected readonly config: Record<string, any>; 13 | 14 | constructor(projectRoot: string, config: Record<string, any> = {}) { 15 | this.projectRoot = projectRoot; 16 | this.config = config; 17 | } 18 | 19 | abstract execute(task: Task): Promise<ExecutionResult>; 20 | abstract getType(): ExecutorType; 21 | abstract isAvailable(): Promise<boolean>; 22 | 23 | /** 24 | * Format task details into a readable prompt 25 | */ 26 | protected formatTaskPrompt(task: Task): string { 27 | const sections: string[] = []; 28 | 29 | sections.push(`Task ID: ${task.id}`); 30 | sections.push(`Title: ${task.title}`); 31 | 32 | if (task.description) { 33 | sections.push(`\nDescription:\n${task.description}`); 34 | } 35 | 36 | if (task.details) { 37 | sections.push(`\nImplementation Details:\n${task.details}`); 38 | } 39 | 40 | if (task.testStrategy) { 41 | sections.push(`\nTest Strategy:\n${task.testStrategy}`); 42 | } 43 | 44 | if (task.dependencies && task.dependencies.length > 0) { 45 | sections.push(`\nDependencies: ${task.dependencies.join(', ')}`); 46 | } 47 | 48 | if (task.subtasks && task.subtasks.length > 0) { 49 | const subtaskList = task.subtasks 50 | .map((st) => ` - [${st.status}] ${st.id}: ${st.title}`) 51 | .join('\n'); 52 | sections.push(`\nSubtasks:\n${subtaskList}`); 53 | } 54 | 55 | sections.push(`\nStatus: ${task.status}`); 56 | sections.push(`Priority: ${task.priority}`); 57 | 58 | return sections.join('\n'); 59 | } 60 | 61 | /** 62 | * Create base execution result 63 | */ 64 | protected createResult( 65 | taskId: string, 66 | success: boolean, 67 | output?: string, 68 | error?: string 69 | ): ExecutionResult { 70 | return { 71 | success, 72 | taskId, 73 | executorType: this.getType(), 74 | output, 75 | error, 76 | startTime: new Date().toISOString(), 77 | endTime: new Date().toISOString() 78 | }; 79 | } 80 | } 81 | ``` -------------------------------------------------------------------------------- /scripts/modules/task-manager/response-language.js: -------------------------------------------------------------------------------- ```javascript 1 | import { 2 | getConfig, 3 | isConfigFilePresent, 4 | writeConfig 5 | } from '../config-manager.js'; 6 | import { findConfigPath } from '../../../src/utils/path-utils.js'; 7 | import { log } from '../utils.js'; 8 | 9 | function setResponseLanguage(lang, options = {}) { 10 | const { mcpLog, projectRoot } = options; 11 | 12 | const report = (level, ...args) => { 13 | if (mcpLog && typeof mcpLog[level] === 'function') { 14 | mcpLog[level](...args); 15 | } 16 | }; 17 | 18 | // Use centralized config path finding instead of hardcoded path 19 | const configPath = findConfigPath(null, { projectRoot }); 20 | const configExists = isConfigFilePresent(projectRoot); 21 | 22 | log( 23 | 'debug', 24 | `Checking for config file using findConfigPath, found: ${configPath}` 25 | ); 26 | log( 27 | 'debug', 28 | `Checking config file using isConfigFilePresent(), exists: ${configExists}` 29 | ); 30 | 31 | if (!configExists) { 32 | return { 33 | success: false, 34 | error: { 35 | code: 'CONFIG_MISSING', 36 | message: 37 | 'The configuration file is missing. Run "task-master init" to create it.' 38 | } 39 | }; 40 | } 41 | 42 | // Validate response language 43 | if (typeof lang !== 'string' || lang.trim() === '') { 44 | return { 45 | success: false, 46 | error: { 47 | code: 'INVALID_RESPONSE_LANGUAGE', 48 | message: `Invalid response language: ${lang}. Must be a non-empty string.` 49 | } 50 | }; 51 | } 52 | 53 | try { 54 | const currentConfig = getConfig(projectRoot); 55 | currentConfig.global.responseLanguage = lang; 56 | const writeResult = writeConfig(currentConfig, projectRoot); 57 | 58 | if (!writeResult) { 59 | return { 60 | success: false, 61 | error: { 62 | code: 'WRITE_ERROR', 63 | message: 'Error writing updated configuration to configuration file' 64 | } 65 | }; 66 | } 67 | 68 | const successMessage = `Successfully set response language to: ${lang}`; 69 | report('info', successMessage); 70 | return { 71 | success: true, 72 | data: { 73 | responseLanguage: lang, 74 | message: successMessage 75 | } 76 | }; 77 | } catch (error) { 78 | report('error', `Error setting response language: ${error.message}`); 79 | return { 80 | success: false, 81 | error: { 82 | code: 'SET_RESPONSE_LANGUAGE_ERROR', 83 | message: error.message 84 | } 85 | }; 86 | } 87 | } 88 | 89 | export default setResponseLanguage; 90 | ``` -------------------------------------------------------------------------------- /.claude/commands/tm/show/show-task.md: -------------------------------------------------------------------------------- ```markdown 1 | Show detailed task information with rich context and insights. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Enhanced Task Display 6 | 7 | Parse arguments to determine what to show and how. 8 | 9 | ### 1. **Smart Task Selection** 10 | 11 | Based on $ARGUMENTS: 12 | - Number → Show specific task with full context 13 | - "current" → Show active in-progress task(s) 14 | - "next" → Show recommended next task 15 | - "blocked" → Show all blocked tasks with reasons 16 | - "critical" → Show critical path tasks 17 | - Multiple IDs → Comparative view 18 | 19 | ### 2. **Contextual Information** 20 | 21 | For each task, intelligently include: 22 | 23 | **Core Details** 24 | - Full task information (id, title, description, details) 25 | - Current status with history 26 | - Test strategy and acceptance criteria 27 | - Priority and complexity analysis 28 | 29 | **Relationships** 30 | - Dependencies (what it needs) 31 | - Dependents (what needs it) 32 | - Parent/subtask hierarchy 33 | - Related tasks (similar work) 34 | 35 | **Time Intelligence** 36 | - Created/updated timestamps 37 | - Time in current status 38 | - Estimated vs actual time 39 | - Historical completion patterns 40 | 41 | ### 3. **Visual Enhancements** 42 | 43 | ``` 44 | 📋 Task #45: Implement User Authentication 45 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 46 | Status: 🟡 in-progress (2 hours) 47 | Priority: 🔴 High | Complexity: 73/100 48 | 49 | Dependencies: ✅ #41, ✅ #42, ⏳ #43 (blocked) 50 | Blocks: #46, #47, #52 51 | 52 | Progress: ████████░░ 80% complete 53 | 54 | Recent Activity: 55 | - 2h ago: Status changed to in-progress 56 | - 4h ago: Dependency #42 completed 57 | - Yesterday: Task expanded with 3 subtasks 58 | ``` 59 | 60 | ### 4. **Intelligent Insights** 61 | 62 | Based on task analysis: 63 | - **Risk Assessment**: Complexity vs time remaining 64 | - **Bottleneck Analysis**: Is this blocking critical work? 65 | - **Recommendation**: Suggested approach or concerns 66 | - **Similar Tasks**: How others completed similar work 67 | 68 | ### 5. **Action Suggestions** 69 | 70 | Context-aware next steps: 71 | - If blocked → Show how to unblock 72 | - If complex → Suggest expansion 73 | - If in-progress → Show completion checklist 74 | - If done → Show dependent tasks ready to start 75 | 76 | ### 6. **Multi-Task View** 77 | 78 | When showing multiple tasks: 79 | - Common dependencies 80 | - Optimal completion order 81 | - Parallel work opportunities 82 | - Combined complexity analysis ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/show/show-task.md: -------------------------------------------------------------------------------- ```markdown 1 | Show detailed task information with rich context and insights. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Enhanced Task Display 6 | 7 | Parse arguments to determine what to show and how. 8 | 9 | ### 1. **Smart Task Selection** 10 | 11 | Based on $ARGUMENTS: 12 | - Number → Show specific task with full context 13 | - "current" → Show active in-progress task(s) 14 | - "next" → Show recommended next task 15 | - "blocked" → Show all blocked tasks with reasons 16 | - "critical" → Show critical path tasks 17 | - Multiple IDs → Comparative view 18 | 19 | ### 2. **Contextual Information** 20 | 21 | For each task, intelligently include: 22 | 23 | **Core Details** 24 | - Full task information (id, title, description, details) 25 | - Current status with history 26 | - Test strategy and acceptance criteria 27 | - Priority and complexity analysis 28 | 29 | **Relationships** 30 | - Dependencies (what it needs) 31 | - Dependents (what needs it) 32 | - Parent/subtask hierarchy 33 | - Related tasks (similar work) 34 | 35 | **Time Intelligence** 36 | - Created/updated timestamps 37 | - Time in current status 38 | - Estimated vs actual time 39 | - Historical completion patterns 40 | 41 | ### 3. **Visual Enhancements** 42 | 43 | ``` 44 | 📋 Task #45: Implement User Authentication 45 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 46 | Status: 🟡 in-progress (2 hours) 47 | Priority: 🔴 High | Complexity: 73/100 48 | 49 | Dependencies: ✅ #41, ✅ #42, ⏳ #43 (blocked) 50 | Blocks: #46, #47, #52 51 | 52 | Progress: ████████░░ 80% complete 53 | 54 | Recent Activity: 55 | - 2h ago: Status changed to in-progress 56 | - 4h ago: Dependency #42 completed 57 | - Yesterday: Task expanded with 3 subtasks 58 | ``` 59 | 60 | ### 4. **Intelligent Insights** 61 | 62 | Based on task analysis: 63 | - **Risk Assessment**: Complexity vs time remaining 64 | - **Bottleneck Analysis**: Is this blocking critical work? 65 | - **Recommendation**: Suggested approach or concerns 66 | - **Similar Tasks**: How others completed similar work 67 | 68 | ### 5. **Action Suggestions** 69 | 70 | Context-aware next steps: 71 | - If blocked → Show how to unblock 72 | - If complex → Suggest expansion 73 | - If in-progress → Show completion checklist 74 | - If done → Show dependent tasks ready to start 75 | 76 | ### 6. **Multi-Task View** 77 | 78 | When showing multiple tasks: 79 | - Common dependencies 80 | - Optimal completion order 81 | - Parallel work opportunities 82 | - Combined complexity analysis ``` -------------------------------------------------------------------------------- /.claude/commands/tm/sync-readme/sync-readme.md: -------------------------------------------------------------------------------- ```markdown 1 | Export tasks to README.md with professional formatting. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | Generate a well-formatted README with current task information. 6 | 7 | ## README Synchronization 8 | 9 | Creates or updates README.md with beautifully formatted task information. 10 | 11 | ## Argument Parsing 12 | 13 | Optional filters: 14 | - "pending" → Only pending tasks 15 | - "with-subtasks" → Include subtask details 16 | - "by-priority" → Group by priority 17 | - "sprint" → Current sprint only 18 | 19 | ## Execution 20 | 21 | ```bash 22 | task-master sync-readme [--with-subtasks] [--status=<status>] 23 | ``` 24 | 25 | ## README Generation 26 | 27 | ### 1. **Project Header** 28 | ```markdown 29 | # Project Name 30 | 31 | ## 📋 Task Progress 32 | 33 | Last Updated: 2024-01-15 10:30 AM 34 | 35 | ### Summary 36 | - Total Tasks: 45 37 | - Completed: 15 (33%) 38 | - In Progress: 5 (11%) 39 | - Pending: 25 (56%) 40 | ``` 41 | 42 | ### 2. **Task Sections** 43 | Organized by status or priority: 44 | - Progress indicators 45 | - Task descriptions 46 | - Dependencies noted 47 | - Time estimates 48 | 49 | ### 3. **Visual Elements** 50 | - Progress bars 51 | - Status badges 52 | - Priority indicators 53 | - Completion checkmarks 54 | 55 | ## Smart Features 56 | 57 | 1. **Intelligent Grouping** 58 | - By feature area 59 | - By sprint/milestone 60 | - By assigned developer 61 | - By priority 62 | 63 | 2. **Progress Tracking** 64 | - Overall completion 65 | - Sprint velocity 66 | - Burndown indication 67 | - Time tracking 68 | 69 | 3. **Formatting Options** 70 | - GitHub-flavored markdown 71 | - Task checkboxes 72 | - Collapsible sections 73 | - Table format available 74 | 75 | ## Example Output 76 | 77 | ```markdown 78 | ## 🚀 Current Sprint 79 | 80 | ### In Progress 81 | - [ ] 🔄 #5 **Implement user authentication** (60% complete) 82 | - Dependencies: API design (#3 ✅) 83 | - Subtasks: 4 (2 completed) 84 | - Est: 8h / Spent: 5h 85 | 86 | ### Pending (High Priority) 87 | - [ ] ⚡ #8 **Create dashboard UI** 88 | - Blocked by: #5 89 | - Complexity: High 90 | - Est: 12h 91 | ``` 92 | 93 | ## Customization 94 | 95 | Based on arguments: 96 | - Include/exclude sections 97 | - Detail level control 98 | - Custom grouping 99 | - Filter by criteria 100 | 101 | ## Post-Sync 102 | 103 | After generation: 104 | 1. Show diff preview 105 | 2. Backup existing README 106 | 3. Write new content 107 | 4. Commit reminder 108 | 5. Update timestamp 109 | 110 | ## Integration 111 | 112 | Works well with: 113 | - Git workflows 114 | - CI/CD pipelines 115 | - Project documentation 116 | - Team updates 117 | - Client reports ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/sync-readme/sync-readme.md: -------------------------------------------------------------------------------- ```markdown 1 | Export tasks to README.md with professional formatting. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | Generate a well-formatted README with current task information. 6 | 7 | ## README Synchronization 8 | 9 | Creates or updates README.md with beautifully formatted task information. 10 | 11 | ## Argument Parsing 12 | 13 | Optional filters: 14 | - "pending" → Only pending tasks 15 | - "with-subtasks" → Include subtask details 16 | - "by-priority" → Group by priority 17 | - "sprint" → Current sprint only 18 | 19 | ## Execution 20 | 21 | ```bash 22 | task-master sync-readme [--with-subtasks] [--status=<status>] 23 | ``` 24 | 25 | ## README Generation 26 | 27 | ### 1. **Project Header** 28 | ```markdown 29 | # Project Name 30 | 31 | ## 📋 Task Progress 32 | 33 | Last Updated: 2024-01-15 10:30 AM 34 | 35 | ### Summary 36 | - Total Tasks: 45 37 | - Completed: 15 (33%) 38 | - In Progress: 5 (11%) 39 | - Pending: 25 (56%) 40 | ``` 41 | 42 | ### 2. **Task Sections** 43 | Organized by status or priority: 44 | - Progress indicators 45 | - Task descriptions 46 | - Dependencies noted 47 | - Time estimates 48 | 49 | ### 3. **Visual Elements** 50 | - Progress bars 51 | - Status badges 52 | - Priority indicators 53 | - Completion checkmarks 54 | 55 | ## Smart Features 56 | 57 | 1. **Intelligent Grouping** 58 | - By feature area 59 | - By sprint/milestone 60 | - By assigned developer 61 | - By priority 62 | 63 | 2. **Progress Tracking** 64 | - Overall completion 65 | - Sprint velocity 66 | - Burndown indication 67 | - Time tracking 68 | 69 | 3. **Formatting Options** 70 | - GitHub-flavored markdown 71 | - Task checkboxes 72 | - Collapsible sections 73 | - Table format available 74 | 75 | ## Example Output 76 | 77 | ```markdown 78 | ## 🚀 Current Sprint 79 | 80 | ### In Progress 81 | - [ ] 🔄 #5 **Implement user authentication** (60% complete) 82 | - Dependencies: API design (#3 ✅) 83 | - Subtasks: 4 (2 completed) 84 | - Est: 8h / Spent: 5h 85 | 86 | ### Pending (High Priority) 87 | - [ ] ⚡ #8 **Create dashboard UI** 88 | - Blocked by: #5 89 | - Complexity: High 90 | - Est: 12h 91 | ``` 92 | 93 | ## Customization 94 | 95 | Based on arguments: 96 | - Include/exclude sections 97 | - Detail level control 98 | - Custom grouping 99 | - Filter by criteria 100 | 101 | ## Post-Sync 102 | 103 | After generation: 104 | 1. Show diff preview 105 | 2. Backup existing README 106 | 3. Write new content 107 | 4. Commit reminder 108 | 5. Update timestamp 109 | 110 | ## Integration 111 | 112 | Works well with: 113 | - Git workflows 114 | - CI/CD pipelines 115 | - Project documentation 116 | - Team updates 117 | - Client reports ``` -------------------------------------------------------------------------------- /mcp-server/src/providers/mcp-provider.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * mcp-server/src/providers/mcp-provider.js 3 | * 4 | * Implementation for MCP custom AI SDK provider that integrates with 5 | * the existing MCP server infrastructure and provider registry. 6 | * Follows the Claude Code provider pattern for session-based providers. 7 | */ 8 | 9 | import { createMCP } from '../custom-sdk/index.js'; 10 | import { BaseAIProvider } from '../../../src/ai-providers/base-provider.js'; 11 | 12 | export class MCPProvider extends BaseAIProvider { 13 | constructor() { 14 | super(); 15 | this.name = 'mcp'; 16 | this.session = null; // MCP server session object 17 | } 18 | 19 | getRequiredApiKeyName() { 20 | return 'MCP_API_KEY'; 21 | } 22 | 23 | isRequiredApiKey() { 24 | return false; 25 | } 26 | 27 | /** 28 | * Override validateAuth to validate MCP session instead of API key 29 | * @param {object} params - Parameters to validate 30 | */ 31 | validateAuth(params) { 32 | // Validate MCP session instead of API key 33 | if (!this.session) { 34 | throw new Error('MCP Provider requires active MCP session'); 35 | } 36 | 37 | if (!this.session.clientCapabilities?.sampling) { 38 | throw new Error('MCP session must have client sampling capabilities'); 39 | } 40 | } 41 | 42 | /** 43 | * Creates and returns an MCP AI SDK client instance. 44 | * @param {object} params - Parameters for client initialization 45 | * @returns {Function} MCP AI SDK client function 46 | * @throws {Error} If initialization fails 47 | */ 48 | getClient(params) { 49 | try { 50 | // Pass MCP session to AI SDK implementation 51 | return createMCP({ 52 | session: this.session, 53 | defaultSettings: { 54 | temperature: params.temperature, 55 | maxTokens: params.maxTokens 56 | } 57 | }); 58 | } catch (error) { 59 | this.handleError('client initialization', error); 60 | } 61 | } 62 | 63 | /** 64 | * Method called by MCP server on connect events 65 | * @param {object} session - MCP session object 66 | */ 67 | setSession(session) { 68 | this.session = session; 69 | 70 | if (!session) { 71 | this.logger?.warn('Set null session on MCP Provider'); 72 | } else { 73 | this.logger?.debug('Updated MCP Provider session'); 74 | } 75 | } 76 | 77 | /** 78 | * Get current session status 79 | * @returns {boolean} True if session is available and valid 80 | */ 81 | hasValidSession() { 82 | return !!(this.session && this.session.clientCapabilities?.sampling); 83 | } 84 | } 85 | ``` -------------------------------------------------------------------------------- /.claude/commands/tm/workflows/auto-implement-tasks.md: -------------------------------------------------------------------------------- ```markdown 1 | Enhanced auto-implementation with intelligent code generation and testing. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Intelligent Auto-Implementation 6 | 7 | Advanced implementation with context awareness and quality checks. 8 | 9 | ### 1. **Pre-Implementation Analysis** 10 | 11 | Before starting: 12 | - Analyze task complexity and requirements 13 | - Check codebase patterns and conventions 14 | - Identify similar completed tasks 15 | - Assess test coverage needs 16 | - Detect potential risks 17 | 18 | ### 2. **Smart Implementation Strategy** 19 | 20 | Based on task type and context: 21 | 22 | **Feature Tasks** 23 | 1. Research existing patterns 24 | 2. Design component architecture 25 | 3. Implement with tests 26 | 4. Integrate with system 27 | 5. Update documentation 28 | 29 | **Bug Fix Tasks** 30 | 1. Reproduce issue 31 | 2. Identify root cause 32 | 3. Implement minimal fix 33 | 4. Add regression tests 34 | 5. Verify side effects 35 | 36 | **Refactoring Tasks** 37 | 1. Analyze current structure 38 | 2. Plan incremental changes 39 | 3. Maintain test coverage 40 | 4. Refactor step-by-step 41 | 5. Verify behavior unchanged 42 | 43 | ### 3. **Code Intelligence** 44 | 45 | **Pattern Recognition** 46 | - Learn from existing code 47 | - Follow team conventions 48 | - Use preferred libraries 49 | - Match style guidelines 50 | 51 | **Test-Driven Approach** 52 | - Write tests first when possible 53 | - Ensure comprehensive coverage 54 | - Include edge cases 55 | - Performance considerations 56 | 57 | ### 4. **Progressive Implementation** 58 | 59 | Step-by-step with validation: 60 | ``` 61 | Step 1/5: Setting up component structure ✓ 62 | Step 2/5: Implementing core logic ✓ 63 | Step 3/5: Adding error handling ⚡ (in progress) 64 | Step 4/5: Writing tests ⏳ 65 | Step 5/5: Integration testing ⏳ 66 | 67 | Current: Adding try-catch blocks and validation... 68 | ``` 69 | 70 | ### 5. **Quality Assurance** 71 | 72 | Automated checks: 73 | - Linting and formatting 74 | - Test execution 75 | - Type checking 76 | - Dependency validation 77 | - Performance analysis 78 | 79 | ### 6. **Smart Recovery** 80 | 81 | If issues arise: 82 | - Diagnostic analysis 83 | - Suggestion generation 84 | - Fallback strategies 85 | - Manual intervention points 86 | - Learning from failures 87 | 88 | ### 7. **Post-Implementation** 89 | 90 | After completion: 91 | - Generate PR description 92 | - Update documentation 93 | - Log lessons learned 94 | - Suggest follow-up tasks 95 | - Update task relationships 96 | 97 | Result: High-quality, production-ready implementations. ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/workflows/auto-implement-tasks.md: -------------------------------------------------------------------------------- ```markdown 1 | Enhanced auto-implementation with intelligent code generation and testing. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Intelligent Auto-Implementation 6 | 7 | Advanced implementation with context awareness and quality checks. 8 | 9 | ### 1. **Pre-Implementation Analysis** 10 | 11 | Before starting: 12 | - Analyze task complexity and requirements 13 | - Check codebase patterns and conventions 14 | - Identify similar completed tasks 15 | - Assess test coverage needs 16 | - Detect potential risks 17 | 18 | ### 2. **Smart Implementation Strategy** 19 | 20 | Based on task type and context: 21 | 22 | **Feature Tasks** 23 | 1. Research existing patterns 24 | 2. Design component architecture 25 | 3. Implement with tests 26 | 4. Integrate with system 27 | 5. Update documentation 28 | 29 | **Bug Fix Tasks** 30 | 1. Reproduce issue 31 | 2. Identify root cause 32 | 3. Implement minimal fix 33 | 4. Add regression tests 34 | 5. Verify side effects 35 | 36 | **Refactoring Tasks** 37 | 1. Analyze current structure 38 | 2. Plan incremental changes 39 | 3. Maintain test coverage 40 | 4. Refactor step-by-step 41 | 5. Verify behavior unchanged 42 | 43 | ### 3. **Code Intelligence** 44 | 45 | **Pattern Recognition** 46 | - Learn from existing code 47 | - Follow team conventions 48 | - Use preferred libraries 49 | - Match style guidelines 50 | 51 | **Test-Driven Approach** 52 | - Write tests first when possible 53 | - Ensure comprehensive coverage 54 | - Include edge cases 55 | - Performance considerations 56 | 57 | ### 4. **Progressive Implementation** 58 | 59 | Step-by-step with validation: 60 | ``` 61 | Step 1/5: Setting up component structure ✓ 62 | Step 2/5: Implementing core logic ✓ 63 | Step 3/5: Adding error handling ⚡ (in progress) 64 | Step 4/5: Writing tests ⏳ 65 | Step 5/5: Integration testing ⏳ 66 | 67 | Current: Adding try-catch blocks and validation... 68 | ``` 69 | 70 | ### 5. **Quality Assurance** 71 | 72 | Automated checks: 73 | - Linting and formatting 74 | - Test execution 75 | - Type checking 76 | - Dependency validation 77 | - Performance analysis 78 | 79 | ### 6. **Smart Recovery** 80 | 81 | If issues arise: 82 | - Diagnostic analysis 83 | - Suggestion generation 84 | - Fallback strategies 85 | - Manual intervention points 86 | - Learning from failures 87 | 88 | ### 7. **Post-Implementation** 89 | 90 | After completion: 91 | - Generate PR description 92 | - Update documentation 93 | - Log lessons learned 94 | - Suggest follow-up tasks 95 | - Update task relationships 96 | 97 | Result: High-quality, production-ready implementations. ``` -------------------------------------------------------------------------------- /tests/integration/profiles/trae-init-functionality.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { traeProfile } from '../../../src/profiles/trae.js'; 4 | 5 | describe('Trae Profile Initialization Functionality', () => { 6 | let traeProfileContent; 7 | 8 | beforeAll(() => { 9 | const traeJsPath = path.join(process.cwd(), 'src', 'profiles', 'trae.js'); 10 | traeProfileContent = fs.readFileSync(traeJsPath, 'utf8'); 11 | }); 12 | 13 | test('trae.js uses factory pattern with correct configuration', () => { 14 | // Check for explicit, non-default values in the source file 15 | expect(traeProfileContent).toContain("name: 'trae'"); 16 | expect(traeProfileContent).toContain("displayName: 'Trae'"); 17 | expect(traeProfileContent).toContain("url: 'trae.ai'"); 18 | expect(traeProfileContent).toContain("docsUrl: 'docs.trae.ai'"); 19 | expect(traeProfileContent).toContain('mcpConfig: false'); 20 | 21 | // Check the final computed properties on the profile object 22 | expect(traeProfile.profileName).toBe('trae'); 23 | expect(traeProfile.displayName).toBe('Trae'); 24 | expect(traeProfile.profileDir).toBe('.trae'); // default 25 | expect(traeProfile.rulesDir).toBe('.trae/rules'); // default 26 | expect(traeProfile.mcpConfig).toBe(false); // non-default 27 | expect(traeProfile.mcpConfigName).toBe(null); // computed from mcpConfig 28 | }); 29 | 30 | test('trae.js configures .mdc to .md extension mapping', () => { 31 | // Check that the profile object has the correct file mapping behavior (trae converts to .md) 32 | expect(traeProfile.fileMap['rules/cursor_rules.mdc']).toBe('trae_rules.md'); 33 | }); 34 | 35 | test('trae.js uses standard tool mappings', () => { 36 | // Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD) 37 | // This verifies the architectural pattern: no custom toolMappings = standard tool names 38 | expect(traeProfileContent).not.toContain('toolMappings:'); 39 | expect(traeProfileContent).not.toContain('apply_diff'); 40 | expect(traeProfileContent).not.toContain('search_files'); 41 | 42 | // Verify the result: default mappings means tools keep their original names 43 | expect(traeProfile.conversionConfig.toolNames.edit_file).toBe('edit_file'); 44 | expect(traeProfile.conversionConfig.toolNames.search).toBe('search'); 45 | }); 46 | }); 47 | ``` -------------------------------------------------------------------------------- /.kiro/steering/taskmaster_hooks_workflow.md: -------------------------------------------------------------------------------- ```markdown 1 | --- 2 | inclusion: always 3 | --- 4 | 5 | # Taskmaster Hook-Driven Workflow 6 | 7 | ## Core Principle: Hooks Automate Task Management 8 | 9 | When working with Taskmaster in Kiro, **avoid manually marking tasks as done**. The hook system automatically handles task completion based on: 10 | 11 | - **Test Success**: `[TM] Test Success Task Completer` detects passing tests and prompts for task completion 12 | - **Code Changes**: `[TM] Code Change Task Tracker` monitors implementation progress 13 | - **Dependency Chains**: `[TM] Task Dependency Auto-Progression` auto-starts dependent tasks 14 | 15 | ## AI Assistant Workflow 16 | 17 | Follow this pattern when implementing features: 18 | 19 | 1. **Implement First**: Write code, create tests, make changes 20 | 2. **Save Frequently**: Hooks trigger on file saves to track progress automatically 21 | 3. **Let Hooks Decide**: Allow hooks to detect completion rather than manually setting status 22 | 4. **Respond to Prompts**: Confirm when hooks suggest task completion 23 | 24 | ## Key Rules for AI Assistants 25 | 26 | - **Never use `tm set-status --status=done`** unless hooks fail to detect completion 27 | - **Always write tests** - they provide the most reliable completion signal 28 | - **Save files after implementation** - this triggers progress tracking 29 | - **Trust hook suggestions** - if no completion prompt appears, more work may be needed 30 | 31 | ## Automatic Behaviors 32 | 33 | The hook system provides: 34 | 35 | - **Progress Logging**: Implementation details automatically added to task notes 36 | - **Evidence-Based Completion**: Tasks marked done only when criteria are met 37 | - **Dependency Management**: Next tasks auto-started when dependencies complete 38 | - **Natural Flow**: Focus on coding, not task management overhead 39 | 40 | ## Manual Override Cases 41 | 42 | Only manually set task status for: 43 | 44 | - Documentation-only tasks 45 | - Tasks without testable outcomes 46 | - Emergency fixes without proper test coverage 47 | 48 | Use `tm set-status` sparingly - prefer hook-driven completion. 49 | 50 | ## Implementation Pattern 51 | 52 | ``` 53 | 1. Implement feature → Save file 54 | 2. Write tests → Save test file 55 | 3. Tests pass → Hook prompts completion 56 | 4. Confirm completion → Next task auto-starts 57 | ``` 58 | 59 | This workflow ensures proper task tracking while maintaining development flow. ``` -------------------------------------------------------------------------------- /.claude/commands/tm/utils/analyze-project.md: -------------------------------------------------------------------------------- ```markdown 1 | Advanced project analysis with actionable insights and recommendations. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Comprehensive Project Analysis 6 | 7 | Multi-dimensional analysis based on requested focus area. 8 | 9 | ### 1. **Analysis Modes** 10 | 11 | Based on $ARGUMENTS: 12 | - "velocity" → Sprint velocity and trends 13 | - "quality" → Code quality metrics 14 | - "risk" → Risk assessment and mitigation 15 | - "dependencies" → Dependency graph analysis 16 | - "team" → Workload and skill distribution 17 | - "architecture" → System design coherence 18 | - Default → Full spectrum analysis 19 | 20 | ### 2. **Velocity Analytics** 21 | 22 | ``` 23 | 📊 Velocity Analysis 24 | ━━━━━━━━━━━━━━━━━━━ 25 | Current Sprint: 24 points/week ↗️ +20% 26 | Rolling Average: 20 points/week 27 | Efficiency: 85% (17/20 tasks on time) 28 | 29 | Bottlenecks Detected: 30 | - Code review delays (avg 4h wait) 31 | - Test environment availability 32 | - Dependency on external team 33 | 34 | Recommendations: 35 | 1. Implement parallel review process 36 | 2. Add staging environment 37 | 3. Mock external dependencies 38 | ``` 39 | 40 | ### 3. **Risk Assessment** 41 | 42 | **Technical Risks** 43 | - High complexity tasks without backup assignee 44 | - Single points of failure in architecture 45 | - Insufficient test coverage in critical paths 46 | - Technical debt accumulation rate 47 | 48 | **Project Risks** 49 | - Critical path dependencies 50 | - Resource availability gaps 51 | - Deadline feasibility analysis 52 | - Scope creep indicators 53 | 54 | ### 4. **Dependency Intelligence** 55 | 56 | Visual dependency analysis: 57 | ``` 58 | Critical Path: 59 | #12 → #15 → #23 → #45 → #50 (20 days) 60 | ↘ #24 → #46 ↗ 61 | 62 | Optimization: Parallelize #15 and #24 63 | Time Saved: 3 days 64 | ``` 65 | 66 | ### 5. **Quality Metrics** 67 | 68 | **Code Quality** 69 | - Test coverage trends 70 | - Complexity scores 71 | - Technical debt ratio 72 | - Review feedback patterns 73 | 74 | **Process Quality** 75 | - Rework frequency 76 | - Bug introduction rate 77 | - Time to resolution 78 | - Knowledge distribution 79 | 80 | ### 6. **Predictive Insights** 81 | 82 | Based on patterns: 83 | - Completion probability by deadline 84 | - Resource needs projection 85 | - Risk materialization likelihood 86 | - Suggested interventions 87 | 88 | ### 7. **Executive Dashboard** 89 | 90 | High-level summary with: 91 | - Health score (0-100) 92 | - Top 3 risks 93 | - Top 3 opportunities 94 | - Recommended actions 95 | - Success probability 96 | 97 | Result: Data-driven decisions with clear action paths. ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/utils/analyze-project.md: -------------------------------------------------------------------------------- ```markdown 1 | Advanced project analysis with actionable insights and recommendations. 2 | 3 | Arguments: $ARGUMENTS 4 | 5 | ## Comprehensive Project Analysis 6 | 7 | Multi-dimensional analysis based on requested focus area. 8 | 9 | ### 1. **Analysis Modes** 10 | 11 | Based on $ARGUMENTS: 12 | - "velocity" → Sprint velocity and trends 13 | - "quality" → Code quality metrics 14 | - "risk" → Risk assessment and mitigation 15 | - "dependencies" → Dependency graph analysis 16 | - "team" → Workload and skill distribution 17 | - "architecture" → System design coherence 18 | - Default → Full spectrum analysis 19 | 20 | ### 2. **Velocity Analytics** 21 | 22 | ``` 23 | 📊 Velocity Analysis 24 | ━━━━━━━━━━━━━━━━━━━ 25 | Current Sprint: 24 points/week ↗️ +20% 26 | Rolling Average: 20 points/week 27 | Efficiency: 85% (17/20 tasks on time) 28 | 29 | Bottlenecks Detected: 30 | - Code review delays (avg 4h wait) 31 | - Test environment availability 32 | - Dependency on external team 33 | 34 | Recommendations: 35 | 1. Implement parallel review process 36 | 2. Add staging environment 37 | 3. Mock external dependencies 38 | ``` 39 | 40 | ### 3. **Risk Assessment** 41 | 42 | **Technical Risks** 43 | - High complexity tasks without backup assignee 44 | - Single points of failure in architecture 45 | - Insufficient test coverage in critical paths 46 | - Technical debt accumulation rate 47 | 48 | **Project Risks** 49 | - Critical path dependencies 50 | - Resource availability gaps 51 | - Deadline feasibility analysis 52 | - Scope creep indicators 53 | 54 | ### 4. **Dependency Intelligence** 55 | 56 | Visual dependency analysis: 57 | ``` 58 | Critical Path: 59 | #12 → #15 → #23 → #45 → #50 (20 days) 60 | ↘ #24 → #46 ↗ 61 | 62 | Optimization: Parallelize #15 and #24 63 | Time Saved: 3 days 64 | ``` 65 | 66 | ### 5. **Quality Metrics** 67 | 68 | **Code Quality** 69 | - Test coverage trends 70 | - Complexity scores 71 | - Technical debt ratio 72 | - Review feedback patterns 73 | 74 | **Process Quality** 75 | - Rework frequency 76 | - Bug introduction rate 77 | - Time to resolution 78 | - Knowledge distribution 79 | 80 | ### 6. **Predictive Insights** 81 | 82 | Based on patterns: 83 | - Completion probability by deadline 84 | - Resource needs projection 85 | - Risk materialization likelihood 86 | - Suggested interventions 87 | 88 | ### 7. **Executive Dashboard** 89 | 90 | High-level summary with: 91 | - Health score (0-100) 92 | - Top 3 risks 93 | - Top 3 opportunities 94 | - Recommended actions 95 | - Success probability 96 | 97 | Result: Data-driven decisions with clear action paths. ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/delete-tag.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/delete-tag.js 3 | * Tool to delete an existing tag 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | createErrorResponse, 9 | handleApiResult, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { deleteTagDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | 15 | /** 16 | * Register the deleteTag tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerDeleteTagTool(server) { 20 | server.addTool({ 21 | name: 'delete_tag', 22 | description: 'Delete an existing tag and all its tasks', 23 | parameters: z.object({ 24 | name: z.string().describe('Name of the tag to delete'), 25 | yes: z 26 | .boolean() 27 | .optional() 28 | .describe('Skip confirmation prompts (default: true for MCP)'), 29 | file: z 30 | .string() 31 | .optional() 32 | .describe('Path to the tasks file (default: tasks/tasks.json)'), 33 | projectRoot: z 34 | .string() 35 | .describe('The directory of the project. Must be an absolute path.') 36 | }), 37 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 38 | try { 39 | log.info(`Starting delete-tag with args: ${JSON.stringify(args)}`); 40 | 41 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 42 | let tasksJsonPath; 43 | try { 44 | tasksJsonPath = findTasksPath( 45 | { projectRoot: args.projectRoot, file: args.file }, 46 | log 47 | ); 48 | } catch (error) { 49 | log.error(`Error finding tasks.json: ${error.message}`); 50 | return createErrorResponse( 51 | `Failed to find tasks.json: ${error.message}` 52 | ); 53 | } 54 | 55 | // Call the direct function (always skip confirmation for MCP) 56 | const result = await deleteTagDirect( 57 | { 58 | tasksJsonPath: tasksJsonPath, 59 | name: args.name, 60 | yes: args.yes !== undefined ? args.yes : true, // Default to true for MCP 61 | projectRoot: args.projectRoot 62 | }, 63 | log, 64 | { session } 65 | ); 66 | 67 | return handleApiResult( 68 | result, 69 | log, 70 | 'Error deleting tag', 71 | undefined, 72 | args.projectRoot 73 | ); 74 | } catch (error) { 75 | log.error(`Error in delete-tag tool: ${error.message}`); 76 | return createErrorResponse(error.message); 77 | } 78 | }) 79 | }); 80 | } 81 | ``` -------------------------------------------------------------------------------- /mcp-server/src/core/direct-functions/validate-dependencies.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * Direct function wrapper for validateDependenciesCommand 3 | */ 4 | 5 | import { validateDependenciesCommand } from '../../../../scripts/modules/dependency-manager.js'; 6 | import { 7 | enableSilentMode, 8 | disableSilentMode 9 | } from '../../../../scripts/modules/utils.js'; 10 | import fs from 'fs'; 11 | 12 | /** 13 | * Validate dependencies in tasks.json 14 | * @param {Object} args - Function arguments 15 | * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file. 16 | * @param {string} args.projectRoot - Project root path (for MCP/env fallback) 17 | * @param {string} args.tag - Tag for the task (optional) 18 | * @param {Object} log - Logger object 19 | * @returns {Promise<{success: boolean, data?: Object, error?: {code: string, message: string}}>} 20 | */ 21 | export async function validateDependenciesDirect(args, log) { 22 | // Destructure the explicit tasksJsonPath 23 | const { tasksJsonPath, projectRoot, tag } = args; 24 | 25 | if (!tasksJsonPath) { 26 | log.error('validateDependenciesDirect called without tasksJsonPath'); 27 | return { 28 | success: false, 29 | error: { 30 | code: 'MISSING_ARGUMENT', 31 | message: 'tasksJsonPath is required' 32 | } 33 | }; 34 | } 35 | 36 | try { 37 | log.info(`Validating dependencies in tasks: ${tasksJsonPath}`); 38 | 39 | // Use the provided tasksJsonPath 40 | const tasksPath = tasksJsonPath; 41 | 42 | // Verify the file exists 43 | if (!fs.existsSync(tasksPath)) { 44 | return { 45 | success: false, 46 | error: { 47 | code: 'FILE_NOT_FOUND', 48 | message: `Tasks file not found at ${tasksPath}` 49 | } 50 | }; 51 | } 52 | 53 | // Enable silent mode to prevent console logs from interfering with JSON response 54 | enableSilentMode(); 55 | 56 | const options = { projectRoot, tag }; 57 | // Call the original command function using the provided tasksPath 58 | await validateDependenciesCommand(tasksPath, options); 59 | 60 | // Restore normal logging 61 | disableSilentMode(); 62 | 63 | return { 64 | success: true, 65 | data: { 66 | message: 'Dependencies validated successfully', 67 | tasksPath 68 | } 69 | }; 70 | } catch (error) { 71 | // Make sure to restore normal logging even if there's an error 72 | disableSilentMode(); 73 | 74 | log.error(`Error validating dependencies: ${error.message}`); 75 | return { 76 | success: false, 77 | error: { 78 | code: 'VALIDATION_ERROR', 79 | message: error.message 80 | } 81 | }; 82 | } 83 | } 84 | ``` -------------------------------------------------------------------------------- /tests/integration/profiles/codex-init-functionality.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { codexProfile } from '../../../src/profiles/codex.js'; 4 | 5 | describe('Codex Profile Initialization Functionality', () => { 6 | let codexProfileContent; 7 | 8 | beforeAll(() => { 9 | const codexJsPath = path.join(process.cwd(), 'src', 'profiles', 'codex.js'); 10 | codexProfileContent = fs.readFileSync(codexJsPath, 'utf8'); 11 | }); 12 | 13 | test('codex.js has correct asset-only profile configuration', () => { 14 | // Check for explicit, non-default values in the source file 15 | expect(codexProfileContent).toContain("name: 'codex'"); 16 | expect(codexProfileContent).toContain("displayName: 'Codex'"); 17 | expect(codexProfileContent).toContain("profileDir: '.'"); // non-default 18 | expect(codexProfileContent).toContain("rulesDir: '.'"); // non-default 19 | expect(codexProfileContent).toContain('mcpConfig: false'); // non-default 20 | expect(codexProfileContent).toContain('includeDefaultRules: false'); // non-default 21 | expect(codexProfileContent).toContain("'AGENTS.md': 'AGENTS.md'"); 22 | 23 | // Check the final computed properties on the profile object 24 | expect(codexProfile.profileName).toBe('codex'); 25 | expect(codexProfile.displayName).toBe('Codex'); 26 | expect(codexProfile.profileDir).toBe('.'); 27 | expect(codexProfile.rulesDir).toBe('.'); 28 | expect(codexProfile.mcpConfig).toBe(false); 29 | expect(codexProfile.mcpConfigName).toBe(null); // computed 30 | expect(codexProfile.includeDefaultRules).toBe(false); 31 | expect(codexProfile.fileMap['AGENTS.md']).toBe('AGENTS.md'); 32 | }); 33 | 34 | test('codex.js has no lifecycle functions', () => { 35 | // Codex has been simplified - no lifecycle functions 36 | expect(codexProfileContent).not.toContain('function onAddRulesProfile'); 37 | expect(codexProfileContent).not.toContain('function onRemoveRulesProfile'); 38 | expect(codexProfileContent).not.toContain( 39 | 'function onPostConvertRulesProfile' 40 | ); 41 | expect(codexProfileContent).not.toContain('log('); 42 | }); 43 | 44 | test('codex.js has minimal implementation', () => { 45 | // Should just use createProfile factory 46 | expect(codexProfileContent).toContain('createProfile({'); 47 | expect(codexProfileContent).toContain("name: 'codex'"); 48 | expect(codexProfileContent).toContain("'AGENTS.md': 'AGENTS.md'"); 49 | }); 50 | }); 51 | ``` -------------------------------------------------------------------------------- /src/ai-providers/custom-sdk/grok-cli/index.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * @fileoverview Grok CLI provider factory and exports 3 | */ 4 | 5 | import { NoSuchModelError } from '@ai-sdk/provider'; 6 | import { GrokCliLanguageModel } from './language-model.js'; 7 | 8 | /** 9 | * @typedef {import('./types.js').GrokCliSettings} GrokCliSettings 10 | * @typedef {import('./types.js').GrokCliModelId} GrokCliModelId 11 | * @typedef {import('./types.js').GrokCliProvider} GrokCliProvider 12 | * @typedef {import('./types.js').GrokCliProviderSettings} GrokCliProviderSettings 13 | */ 14 | 15 | /** 16 | * Create a Grok CLI provider 17 | * @param {GrokCliProviderSettings} [options={}] - Provider configuration options 18 | * @returns {GrokCliProvider} Grok CLI provider instance 19 | */ 20 | export function createGrokCli(options = {}) { 21 | /** 22 | * Create a language model instance 23 | * @param {GrokCliModelId} modelId - Model ID 24 | * @param {GrokCliSettings} [settings={}] - Model settings 25 | * @returns {GrokCliLanguageModel} 26 | */ 27 | const createModel = (modelId, settings = {}) => { 28 | return new GrokCliLanguageModel({ 29 | id: modelId, 30 | settings: { 31 | ...options.defaultSettings, 32 | ...settings 33 | } 34 | }); 35 | }; 36 | 37 | /** 38 | * Provider function 39 | * @param {GrokCliModelId} modelId - Model ID 40 | * @param {GrokCliSettings} [settings] - Model settings 41 | * @returns {GrokCliLanguageModel} 42 | */ 43 | const provider = function (modelId, settings) { 44 | if (new.target) { 45 | throw new Error( 46 | 'The Grok CLI model function cannot be called with the new keyword.' 47 | ); 48 | } 49 | 50 | return createModel(modelId, settings); 51 | }; 52 | 53 | provider.languageModel = createModel; 54 | provider.chat = createModel; // Alias for languageModel 55 | 56 | // Add textEmbeddingModel method that throws NoSuchModelError 57 | provider.textEmbeddingModel = (modelId) => { 58 | throw new NoSuchModelError({ 59 | modelId, 60 | modelType: 'textEmbeddingModel' 61 | }); 62 | }; 63 | 64 | return /** @type {GrokCliProvider} */ (provider); 65 | } 66 | 67 | /** 68 | * Default Grok CLI provider instance 69 | */ 70 | export const grokCli = createGrokCli(); 71 | 72 | // Provider exports 73 | export { GrokCliLanguageModel } from './language-model.js'; 74 | 75 | // Error handling exports 76 | export { 77 | isAuthenticationError, 78 | isTimeoutError, 79 | isInstallationError, 80 | getErrorMetadata, 81 | createAPICallError, 82 | createAuthenticationError, 83 | createTimeoutError, 84 | createInstallationError 85 | } from './errors.js'; 86 | ``` -------------------------------------------------------------------------------- /tests/unit/profiles/subdirectory-support.test.js: -------------------------------------------------------------------------------- ```javascript 1 | // Test for supportsRulesSubdirectories feature 2 | import { getRulesProfile } from '../../../src/utils/rule-transformer.js'; 3 | 4 | describe('Rules Subdirectory Support Feature', () => { 5 | it('should support taskmaster subdirectories only for Cursor profile', () => { 6 | // Test Cursor profile - should use subdirectories 7 | const cursorProfile = getRulesProfile('cursor'); 8 | expect(cursorProfile.supportsRulesSubdirectories).toBe(true); 9 | 10 | // Verify that Cursor uses taskmaster subdirectories in its file mapping 11 | expect(cursorProfile.fileMap['rules/dev_workflow.mdc']).toBe( 12 | 'taskmaster/dev_workflow.mdc' 13 | ); 14 | expect(cursorProfile.fileMap['rules/taskmaster.mdc']).toBe( 15 | 'taskmaster/taskmaster.mdc' 16 | ); 17 | }); 18 | 19 | it('should not use taskmaster subdirectories for other profiles', () => { 20 | // Test profiles that should NOT use subdirectories (new default) 21 | const profiles = ['roo', 'vscode', 'cline', 'windsurf', 'trae']; 22 | 23 | profiles.forEach((profileName) => { 24 | const profile = getRulesProfile(profileName); 25 | expect(profile.supportsRulesSubdirectories).toBe(false); 26 | 27 | // Verify that these profiles do NOT use taskmaster subdirectories in their file mapping 28 | const expectedExt = profile.targetExtension || '.md'; 29 | expect(profile.fileMap['rules/dev_workflow.mdc']).toBe( 30 | `dev_workflow${expectedExt}` 31 | ); 32 | expect(profile.fileMap['rules/taskmaster.mdc']).toBe( 33 | `taskmaster${expectedExt}` 34 | ); 35 | }); 36 | }); 37 | 38 | it('should have supportsRulesSubdirectories property accessible on all profiles', () => { 39 | const allProfiles = [ 40 | 'cursor', 41 | 'roo', 42 | 'vscode', 43 | 'cline', 44 | 'windsurf', 45 | 'trae' 46 | ]; 47 | 48 | allProfiles.forEach((profileName) => { 49 | const profile = getRulesProfile(profileName); 50 | expect(profile).toBeDefined(); 51 | expect(typeof profile.supportsRulesSubdirectories).toBe('boolean'); 52 | }); 53 | }); 54 | 55 | it('should default to false for supportsRulesSubdirectories when not specified', () => { 56 | // Most profiles should now default to NOT supporting subdirectories 57 | const profiles = ['roo', 'windsurf', 'trae', 'vscode', 'cline']; 58 | 59 | profiles.forEach((profileName) => { 60 | const profile = getRulesProfile(profileName); 61 | expect(profile.supportsRulesSubdirectories).toBe(false); 62 | }); 63 | }); 64 | }); 65 | ``` -------------------------------------------------------------------------------- /mcp-server/src/core/direct-functions/fix-dependencies.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * Direct function wrapper for fixDependenciesCommand 3 | */ 4 | 5 | import { fixDependenciesCommand } from '../../../../scripts/modules/dependency-manager.js'; 6 | import { 7 | enableSilentMode, 8 | disableSilentMode 9 | } from '../../../../scripts/modules/utils.js'; 10 | import fs from 'fs'; 11 | 12 | /** 13 | * Fix invalid dependencies in tasks.json automatically 14 | * @param {Object} args - Function arguments 15 | * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file. 16 | * @param {string} args.projectRoot - Project root directory 17 | * @param {string} args.tag - Tag for the project 18 | * @param {Object} log - Logger object 19 | * @returns {Promise<{success: boolean, data?: Object, error?: {code: string, message: string}}>} 20 | */ 21 | export async function fixDependenciesDirect(args, log) { 22 | // Destructure expected args 23 | const { tasksJsonPath, projectRoot, tag } = args; 24 | try { 25 | log.info(`Fixing invalid dependencies in tasks: ${tasksJsonPath}`); 26 | 27 | // Check if tasksJsonPath was provided 28 | if (!tasksJsonPath) { 29 | log.error('fixDependenciesDirect called without tasksJsonPath'); 30 | return { 31 | success: false, 32 | error: { 33 | code: 'MISSING_ARGUMENT', 34 | message: 'tasksJsonPath is required' 35 | } 36 | }; 37 | } 38 | 39 | // Use provided path 40 | const tasksPath = tasksJsonPath; 41 | 42 | // Verify the file exists 43 | if (!fs.existsSync(tasksPath)) { 44 | return { 45 | success: false, 46 | error: { 47 | code: 'FILE_NOT_FOUND', 48 | message: `Tasks file not found at ${tasksPath}` 49 | } 50 | }; 51 | } 52 | 53 | // Enable silent mode to prevent console logs from interfering with JSON response 54 | enableSilentMode(); 55 | 56 | const options = { projectRoot, tag }; 57 | // Call the original command function using the provided path and proper context 58 | await fixDependenciesCommand(tasksPath, options); 59 | 60 | // Restore normal logging 61 | disableSilentMode(); 62 | 63 | return { 64 | success: true, 65 | data: { 66 | message: 'Dependencies fixed successfully', 67 | tasksPath, 68 | tag: tag || 'master' 69 | } 70 | }; 71 | } catch (error) { 72 | // Make sure to restore normal logging even if there's an error 73 | disableSilentMode(); 74 | 75 | log.error(`Error fixing dependencies: ${error.message}`); 76 | return { 77 | success: false, 78 | error: { 79 | code: 'FIX_DEPENDENCIES_ERROR', 80 | message: error.message 81 | } 82 | }; 83 | } 84 | } 85 | ``` -------------------------------------------------------------------------------- /apps/extension/src/components/ui/breadcrumb.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { Slot } from '@radix-ui/react-slot'; 2 | import { ChevronRight, MoreHorizontal } from 'lucide-react'; 3 | import type * as React from 'react'; 4 | 5 | import { cn } from '@/lib/utils'; 6 | 7 | function Breadcrumb({ ...props }: React.ComponentProps<'nav'>) { 8 | return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />; 9 | } 10 | 11 | function BreadcrumbList({ className, ...props }: React.ComponentProps<'ol'>) { 12 | return ( 13 | <ol 14 | data-slot="breadcrumb-list" 15 | className={cn( 16 | 'text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5', 17 | className 18 | )} 19 | {...props} 20 | /> 21 | ); 22 | } 23 | 24 | function BreadcrumbItem({ className, ...props }: React.ComponentProps<'li'>) { 25 | return ( 26 | <li 27 | data-slot="breadcrumb-item" 28 | className={cn('inline-flex items-center gap-1.5', className)} 29 | {...props} 30 | /> 31 | ); 32 | } 33 | 34 | function BreadcrumbLink({ 35 | asChild, 36 | className, 37 | ...props 38 | }: React.ComponentProps<'a'> & { 39 | asChild?: boolean; 40 | }) { 41 | const Comp = asChild ? Slot : 'a'; 42 | 43 | return ( 44 | <Comp 45 | data-slot="breadcrumb-link" 46 | className={cn('hover:text-foreground transition-colors', className)} 47 | {...props} 48 | /> 49 | ); 50 | } 51 | 52 | function BreadcrumbPage({ className, ...props }: React.ComponentProps<'span'>) { 53 | return ( 54 | <span 55 | data-slot="breadcrumb-page" 56 | role="link" 57 | aria-disabled="true" 58 | aria-current="page" 59 | className={cn('text-foreground font-normal', className)} 60 | {...props} 61 | /> 62 | ); 63 | } 64 | 65 | function BreadcrumbSeparator({ 66 | children, 67 | className, 68 | ...props 69 | }: React.ComponentProps<'li'>) { 70 | return ( 71 | <li 72 | data-slot="breadcrumb-separator" 73 | role="presentation" 74 | aria-hidden="true" 75 | className={cn('[&>svg]:size-3.5', className)} 76 | {...props} 77 | > 78 | {children ?? <ChevronRight />} 79 | </li> 80 | ); 81 | } 82 | 83 | function BreadcrumbEllipsis({ 84 | className, 85 | ...props 86 | }: React.ComponentProps<'span'>) { 87 | return ( 88 | <span 89 | data-slot="breadcrumb-ellipsis" 90 | role="presentation" 91 | aria-hidden="true" 92 | className={cn('flex size-9 items-center justify-center', className)} 93 | {...props} 94 | > 95 | <MoreHorizontal className="size-4" /> 96 | <span className="sr-only">More</span> 97 | </span> 98 | ); 99 | } 100 | 101 | export { 102 | Breadcrumb, 103 | BreadcrumbList, 104 | BreadcrumbItem, 105 | BreadcrumbLink, 106 | BreadcrumbPage, 107 | BreadcrumbSeparator, 108 | BreadcrumbEllipsis 109 | }; 110 | ``` -------------------------------------------------------------------------------- /scripts/modules/task-manager.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * task-manager.js 3 | * Task management functions for the Task Master CLI 4 | */ 5 | 6 | import { findTaskById } from './utils.js'; 7 | import parsePRD from './task-manager/parse-prd/index.js'; 8 | import updateTasks from './task-manager/update-tasks.js'; 9 | import updateTaskById from './task-manager/update-task-by-id.js'; 10 | import generateTaskFiles from './task-manager/generate-task-files.js'; 11 | import setTaskStatus from './task-manager/set-task-status.js'; 12 | import updateSingleTaskStatus from './task-manager/update-single-task-status.js'; 13 | import listTasks from './task-manager/list-tasks.js'; 14 | import expandTask from './task-manager/expand-task.js'; 15 | import expandAllTasks from './task-manager/expand-all-tasks.js'; 16 | import clearSubtasks from './task-manager/clear-subtasks.js'; 17 | import addTask from './task-manager/add-task.js'; 18 | import analyzeTaskComplexity from './task-manager/analyze-task-complexity.js'; 19 | import findNextTask from './task-manager/find-next-task.js'; 20 | import addSubtask from './task-manager/add-subtask.js'; 21 | import removeSubtask from './task-manager/remove-subtask.js'; 22 | import updateSubtaskById from './task-manager/update-subtask-by-id.js'; 23 | import removeTask from './task-manager/remove-task.js'; 24 | import taskExists from './task-manager/task-exists.js'; 25 | import isTaskDependentOn from './task-manager/is-task-dependent.js'; 26 | import setResponseLanguage from './task-manager/response-language.js'; 27 | import moveTask from './task-manager/move-task.js'; 28 | import { migrateProject } from './task-manager/migrate.js'; 29 | import { performResearch } from './task-manager/research.js'; 30 | import { readComplexityReport } from './utils.js'; 31 | import { 32 | scopeUpTask, 33 | scopeDownTask, 34 | validateStrength 35 | } from './task-manager/scope-adjustment.js'; 36 | 37 | // Export task manager functions 38 | export { 39 | parsePRD, 40 | updateTasks, 41 | updateTaskById, 42 | updateSubtaskById, 43 | generateTaskFiles, 44 | setTaskStatus, 45 | updateSingleTaskStatus, 46 | listTasks, 47 | expandTask, 48 | expandAllTasks, 49 | clearSubtasks, 50 | addTask, 51 | addSubtask, 52 | removeSubtask, 53 | findNextTask, 54 | analyzeTaskComplexity, 55 | removeTask, 56 | findTaskById, 57 | taskExists, 58 | isTaskDependentOn, 59 | setResponseLanguage, 60 | moveTask, 61 | readComplexityReport, 62 | migrateProject, 63 | performResearch, 64 | scopeUpTask, 65 | scopeDownTask, 66 | validateStrength 67 | }; 68 | ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/copy-tag.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/copy-tag.js 3 | * Tool to copy an existing tag to a new tag 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | createErrorResponse, 9 | handleApiResult, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { copyTagDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | 15 | /** 16 | * Register the copyTag tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerCopyTagTool(server) { 20 | server.addTool({ 21 | name: 'copy_tag', 22 | description: 23 | 'Copy an existing tag to create a new tag with all tasks and metadata', 24 | parameters: z.object({ 25 | sourceName: z.string().describe('Name of the source tag to copy from'), 26 | targetName: z.string().describe('Name of the new tag to create'), 27 | description: z 28 | .string() 29 | .optional() 30 | .describe('Optional description for the new tag'), 31 | file: z 32 | .string() 33 | .optional() 34 | .describe('Path to the tasks file (default: tasks/tasks.json)'), 35 | projectRoot: z 36 | .string() 37 | .describe('The directory of the project. Must be an absolute path.') 38 | }), 39 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 40 | try { 41 | log.info(`Starting copy-tag with args: ${JSON.stringify(args)}`); 42 | 43 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 44 | let tasksJsonPath; 45 | try { 46 | tasksJsonPath = findTasksPath( 47 | { projectRoot: args.projectRoot, file: args.file }, 48 | log 49 | ); 50 | } catch (error) { 51 | log.error(`Error finding tasks.json: ${error.message}`); 52 | return createErrorResponse( 53 | `Failed to find tasks.json: ${error.message}` 54 | ); 55 | } 56 | 57 | // Call the direct function 58 | const result = await copyTagDirect( 59 | { 60 | tasksJsonPath: tasksJsonPath, 61 | sourceName: args.sourceName, 62 | targetName: args.targetName, 63 | description: args.description, 64 | projectRoot: args.projectRoot 65 | }, 66 | log, 67 | { session } 68 | ); 69 | 70 | return handleApiResult( 71 | result, 72 | log, 73 | 'Error copying tag', 74 | undefined, 75 | args.projectRoot 76 | ); 77 | } catch (error) { 78 | log.error(`Error in copy-tag tool: ${error.message}`); 79 | return createErrorResponse(error.message); 80 | } 81 | }) 82 | }); 83 | } 84 | ``` -------------------------------------------------------------------------------- /.claude/commands/tm/remove-task/remove-task.md: -------------------------------------------------------------------------------- ```markdown 1 | Remove a task permanently from the project. 2 | 3 | Arguments: $ARGUMENTS (task ID) 4 | 5 | Delete a task and handle all its relationships properly. 6 | 7 | ## Task Removal 8 | 9 | Permanently removes a task while maintaining project integrity. 10 | 11 | ## Argument Parsing 12 | 13 | - "remove task 5" 14 | - "delete 5" 15 | - "5" → remove task 5 16 | - Can include "-y" for auto-confirm 17 | 18 | ## Execution 19 | 20 | ```bash 21 | task-master remove-task --id=<id> [-y] 22 | ``` 23 | 24 | ## Pre-Removal Analysis 25 | 26 | 1. **Task Details** 27 | - Current status 28 | - Work completed 29 | - Time invested 30 | - Associated data 31 | 32 | 2. **Relationship Check** 33 | - Tasks that depend on this 34 | - Dependencies this task has 35 | - Subtasks that will be removed 36 | - Blocking implications 37 | 38 | 3. **Impact Assessment** 39 | ``` 40 | Task Removal Impact 41 | ━━━━━━━━━━━━━━━━━━ 42 | Task: #5 "Implement authentication" (in-progress) 43 | Status: 60% complete (~8 hours work) 44 | 45 | Will affect: 46 | - 3 tasks depend on this (will be blocked) 47 | - Has 4 subtasks (will be deleted) 48 | - Part of critical path 49 | 50 | ⚠️ This action cannot be undone 51 | ``` 52 | 53 | ## Smart Warnings 54 | 55 | - Warn if task is in-progress 56 | - Show dependent tasks that will be blocked 57 | - Highlight if part of critical path 58 | - Note any completed work being lost 59 | 60 | ## Removal Process 61 | 62 | 1. Show comprehensive impact 63 | 2. Require confirmation (unless -y) 64 | 3. Update dependent task references 65 | 4. Remove task and subtasks 66 | 5. Clean up orphaned dependencies 67 | 6. Log removal with timestamp 68 | 69 | ## Alternative Actions 70 | 71 | Suggest before deletion: 72 | - Mark as cancelled instead 73 | - Convert to documentation 74 | - Archive task data 75 | - Transfer work to another task 76 | 77 | ## Post-Removal 78 | 79 | - List affected tasks 80 | - Show broken dependencies 81 | - Update project statistics 82 | - Suggest dependency fixes 83 | - Recalculate timeline 84 | 85 | ## Example Flows 86 | 87 | ``` 88 | /project:tm/remove-task 5 89 | → Task #5 is in-progress with 8 hours logged 90 | → 3 other tasks depend on this 91 | → Suggestion: Mark as cancelled instead? 92 | Remove anyway? (y/n) 93 | 94 | /project:tm/remove-task 5 -y 95 | → Removed: Task #5 and 4 subtasks 96 | → Updated: 3 task dependencies 97 | → Warning: Tasks #7, #8, #9 now have missing dependency 98 | → Run /project:tm/fix-dependencies to resolve 99 | ``` 100 | 101 | ## Safety Features 102 | 103 | - Confirmation required 104 | - Impact preview 105 | - Removal logging 106 | - Suggest alternatives 107 | - No cascade delete of dependents ``` -------------------------------------------------------------------------------- /assets/claude/commands/tm/remove-task/remove-task.md: -------------------------------------------------------------------------------- ```markdown 1 | Remove a task permanently from the project. 2 | 3 | Arguments: $ARGUMENTS (task ID) 4 | 5 | Delete a task and handle all its relationships properly. 6 | 7 | ## Task Removal 8 | 9 | Permanently removes a task while maintaining project integrity. 10 | 11 | ## Argument Parsing 12 | 13 | - "remove task 5" 14 | - "delete 5" 15 | - "5" → remove task 5 16 | - Can include "-y" for auto-confirm 17 | 18 | ## Execution 19 | 20 | ```bash 21 | task-master remove-task --id=<id> [-y] 22 | ``` 23 | 24 | ## Pre-Removal Analysis 25 | 26 | 1. **Task Details** 27 | - Current status 28 | - Work completed 29 | - Time invested 30 | - Associated data 31 | 32 | 2. **Relationship Check** 33 | - Tasks that depend on this 34 | - Dependencies this task has 35 | - Subtasks that will be removed 36 | - Blocking implications 37 | 38 | 3. **Impact Assessment** 39 | ``` 40 | Task Removal Impact 41 | ━━━━━━━━━━━━━━━━━━ 42 | Task: #5 "Implement authentication" (in-progress) 43 | Status: 60% complete (~8 hours work) 44 | 45 | Will affect: 46 | - 3 tasks depend on this (will be blocked) 47 | - Has 4 subtasks (will be deleted) 48 | - Part of critical path 49 | 50 | ⚠️ This action cannot be undone 51 | ``` 52 | 53 | ## Smart Warnings 54 | 55 | - Warn if task is in-progress 56 | - Show dependent tasks that will be blocked 57 | - Highlight if part of critical path 58 | - Note any completed work being lost 59 | 60 | ## Removal Process 61 | 62 | 1. Show comprehensive impact 63 | 2. Require confirmation (unless -y) 64 | 3. Update dependent task references 65 | 4. Remove task and subtasks 66 | 5. Clean up orphaned dependencies 67 | 6. Log removal with timestamp 68 | 69 | ## Alternative Actions 70 | 71 | Suggest before deletion: 72 | - Mark as cancelled instead 73 | - Convert to documentation 74 | - Archive task data 75 | - Transfer work to another task 76 | 77 | ## Post-Removal 78 | 79 | - List affected tasks 80 | - Show broken dependencies 81 | - Update project statistics 82 | - Suggest dependency fixes 83 | - Recalculate timeline 84 | 85 | ## Example Flows 86 | 87 | ``` 88 | /project:tm/remove-task 5 89 | → Task #5 is in-progress with 8 hours logged 90 | → 3 other tasks depend on this 91 | → Suggestion: Mark as cancelled instead? 92 | Remove anyway? (y/n) 93 | 94 | /project:tm/remove-task 5 -y 95 | → Removed: Task #5 and 4 subtasks 96 | → Updated: 3 task dependencies 97 | → Warning: Tasks #7, #8, #9 now have missing dependency 98 | → Run /project:tm/fix-dependencies to resolve 99 | ``` 100 | 101 | ## Safety Features 102 | 103 | - Confirmation required 104 | - Impact preview 105 | - Removal logging 106 | - Suggest alternatives 107 | - No cascade delete of dependents ``` -------------------------------------------------------------------------------- /tests/integration/profiles/windsurf-init-functionality.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { windsurfProfile } from '../../../src/profiles/windsurf.js'; 4 | 5 | describe('Windsurf Profile Initialization Functionality', () => { 6 | let windsurfProfileContent; 7 | 8 | beforeAll(() => { 9 | const windsurfJsPath = path.join( 10 | process.cwd(), 11 | 'src', 12 | 'profiles', 13 | 'windsurf.js' 14 | ); 15 | windsurfProfileContent = fs.readFileSync(windsurfJsPath, 'utf8'); 16 | }); 17 | 18 | test('windsurf.js uses factory pattern with correct configuration', () => { 19 | // Check for explicit, non-default values in the source file 20 | expect(windsurfProfileContent).toContain("name: 'windsurf'"); 21 | expect(windsurfProfileContent).toContain("displayName: 'Windsurf'"); 22 | expect(windsurfProfileContent).toContain("url: 'windsurf.com'"); 23 | expect(windsurfProfileContent).toContain("docsUrl: 'docs.windsurf.com'"); 24 | 25 | // Check the final computed properties on the profile object 26 | expect(windsurfProfile.profileName).toBe('windsurf'); 27 | expect(windsurfProfile.displayName).toBe('Windsurf'); 28 | expect(windsurfProfile.profileDir).toBe('.windsurf'); // default 29 | expect(windsurfProfile.rulesDir).toBe('.windsurf/rules'); // default 30 | expect(windsurfProfile.mcpConfig).toBe(true); // default 31 | expect(windsurfProfile.mcpConfigName).toBe('mcp.json'); // default 32 | }); 33 | 34 | test('windsurf.js configures .mdc to .md extension mapping', () => { 35 | // Check that the profile object has the correct file mapping behavior (windsurf converts to .md) 36 | expect(windsurfProfile.fileMap['rules/cursor_rules.mdc']).toBe( 37 | 'windsurf_rules.md' 38 | ); 39 | }); 40 | 41 | test('windsurf.js uses standard tool mappings', () => { 42 | // Check that the profile uses default tool mappings (equivalent to COMMON_TOOL_MAPPINGS.STANDARD) 43 | // This verifies the architectural pattern: no custom toolMappings = standard tool names 44 | expect(windsurfProfileContent).not.toContain('toolMappings:'); 45 | expect(windsurfProfileContent).not.toContain('apply_diff'); 46 | expect(windsurfProfileContent).not.toContain('search_files'); 47 | 48 | // Verify the result: default mappings means tools keep their original names 49 | expect(windsurfProfile.conversionConfig.toolNames.edit_file).toBe( 50 | 'edit_file' 51 | ); 52 | expect(windsurfProfile.conversionConfig.toolNames.search).toBe('search'); 53 | }); 54 | }); 55 | ``` -------------------------------------------------------------------------------- /packages/tm-core/tests/unit/executor.test.ts: -------------------------------------------------------------------------------- ```typescript 1 | /** 2 | * Tests for executor functionality 3 | */ 4 | 5 | import { describe, it, expect, beforeEach, vi } from 'vitest'; 6 | import { 7 | ExecutorFactory, 8 | ClaudeExecutor, 9 | type ExecutorOptions 10 | } from '../../src/executors/index.js'; 11 | 12 | describe('ExecutorFactory', () => { 13 | const mockProjectRoot = '/test/project'; 14 | 15 | it('should create a Claude executor', () => { 16 | const options: ExecutorOptions = { 17 | type: 'claude', 18 | projectRoot: mockProjectRoot 19 | }; 20 | 21 | const executor = ExecutorFactory.create(options); 22 | expect(executor).toBeInstanceOf(ClaudeExecutor); 23 | }); 24 | 25 | it('should throw error for unimplemented executor types', () => { 26 | const options: ExecutorOptions = { 27 | type: 'shell', 28 | projectRoot: mockProjectRoot 29 | }; 30 | 31 | expect(() => ExecutorFactory.create(options)).toThrow( 32 | 'Shell executor not yet implemented' 33 | ); 34 | }); 35 | 36 | it('should get available executor types', () => { 37 | const types = ExecutorFactory.getAvailableTypes(); 38 | expect(types).toContain('claude'); 39 | expect(types).toContain('shell'); 40 | expect(types).toContain('custom'); 41 | }); 42 | }); 43 | 44 | describe('ClaudeExecutor', () => { 45 | const mockProjectRoot = '/test/project'; 46 | let executor: ClaudeExecutor; 47 | 48 | beforeEach(() => { 49 | executor = new ClaudeExecutor(mockProjectRoot); 50 | }); 51 | 52 | it('should return claude as executor type', () => { 53 | expect(executor.getType()).toBe('claude'); 54 | }); 55 | 56 | it('should format task prompt correctly', () => { 57 | const mockTask = { 58 | id: '1', 59 | title: 'Test Task', 60 | description: 'Test description', 61 | status: 'pending' as const, 62 | priority: 'high' as const, 63 | dependencies: [], 64 | details: 'Implementation details', 65 | testStrategy: 'Unit tests', 66 | subtasks: [] 67 | }; 68 | 69 | // Access protected method through any type assertion for testing 70 | const formattedPrompt = (executor as any).formatTaskPrompt(mockTask); 71 | 72 | expect(formattedPrompt).toContain('Task ID: 1'); 73 | expect(formattedPrompt).toContain('Title: Test Task'); 74 | expect(formattedPrompt).toContain('Description:\nTest description'); 75 | expect(formattedPrompt).toContain( 76 | 'Implementation Details:\nImplementation details' 77 | ); 78 | expect(formattedPrompt).toContain('Test Strategy:\nUnit tests'); 79 | expect(formattedPrompt).toContain('Status: pending'); 80 | expect(formattedPrompt).toContain('Priority: high'); 81 | }); 82 | }); 83 | ``` -------------------------------------------------------------------------------- /packages/tm-core/src/auth/types.ts: -------------------------------------------------------------------------------- ```typescript 1 | /** 2 | * Authentication types and interfaces 3 | */ 4 | 5 | export interface AuthCredentials { 6 | token: string; 7 | refreshToken?: string; 8 | userId: string; 9 | email?: string; 10 | expiresAt?: string | number; 11 | tokenType?: 'standard'; 12 | savedAt: string; 13 | selectedContext?: UserContext; 14 | } 15 | 16 | export interface UserContext { 17 | orgId?: string; 18 | orgName?: string; 19 | briefId?: string; 20 | briefName?: string; 21 | updatedAt: string; 22 | } 23 | 24 | export interface OAuthFlowOptions { 25 | /** Callback to open the browser with the auth URL. If not provided, browser won't be opened */ 26 | openBrowser?: (url: string) => Promise<void>; 27 | /** Timeout for the OAuth flow in milliseconds. Default: 300000 (5 minutes) */ 28 | timeout?: number; 29 | /** Callback to be invoked with the authorization URL */ 30 | onAuthUrl?: (url: string) => void; 31 | /** Callback to be invoked when waiting for authentication */ 32 | onWaitingForAuth?: () => void; 33 | /** Callback to be invoked on successful authentication */ 34 | onSuccess?: (credentials: AuthCredentials) => void; 35 | /** Callback to be invoked on authentication error */ 36 | onError?: (error: AuthenticationError) => void; 37 | } 38 | 39 | export interface AuthConfig { 40 | baseUrl: string; 41 | configDir: string; 42 | configFile: string; 43 | } 44 | 45 | export interface CliData { 46 | callback: string; 47 | state: string; 48 | name: string; 49 | version: string; 50 | device?: string; 51 | user?: string; 52 | platform?: string; 53 | timestamp?: number; 54 | } 55 | 56 | /** 57 | * Authentication error codes 58 | */ 59 | export type AuthErrorCode = 60 | | 'AUTH_TIMEOUT' 61 | | 'AUTH_EXPIRED' 62 | | 'OAUTH_FAILED' 63 | | 'OAUTH_ERROR' 64 | | 'OAUTH_CANCELED' 65 | | 'URL_GENERATION_FAILED' 66 | | 'INVALID_STATE' 67 | | 'NO_TOKEN' 68 | | 'TOKEN_EXCHANGE_FAILED' 69 | | 'INVALID_CREDENTIALS' 70 | | 'NO_REFRESH_TOKEN' 71 | | 'NOT_AUTHENTICATED' 72 | | 'NETWORK_ERROR' 73 | | 'CONFIG_MISSING' 74 | | 'SAVE_FAILED' 75 | | 'CLEAR_FAILED' 76 | | 'STORAGE_ERROR' 77 | | 'NOT_SUPPORTED' 78 | | 'REFRESH_FAILED' 79 | | 'INVALID_RESPONSE' 80 | | 'PKCE_INIT_FAILED' 81 | | 'PKCE_FAILED' 82 | | 'CODE_EXCHANGE_FAILED' 83 | | 'SESSION_SET_FAILED'; 84 | 85 | /** 86 | * Authentication error class 87 | */ 88 | export class AuthenticationError extends Error { 89 | constructor( 90 | message: string, 91 | public code: AuthErrorCode, 92 | public cause?: unknown 93 | ) { 94 | super(message); 95 | this.name = 'AuthenticationError'; 96 | if (cause && cause instanceof Error) { 97 | this.stack = `${this.stack}\nCaused by: ${cause.stack}`; 98 | } 99 | } 100 | } 101 | ``` -------------------------------------------------------------------------------- /src/ai-providers/custom-sdk/claude-code/index.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * @fileoverview Claude Code provider factory and exports 3 | */ 4 | 5 | import { NoSuchModelError } from '@ai-sdk/provider'; 6 | import { ClaudeCodeLanguageModel } from './language-model.js'; 7 | 8 | /** 9 | * @typedef {import('./types.js').ClaudeCodeSettings} ClaudeCodeSettings 10 | * @typedef {import('./types.js').ClaudeCodeModelId} ClaudeCodeModelId 11 | * @typedef {import('./types.js').ClaudeCodeProvider} ClaudeCodeProvider 12 | * @typedef {import('./types.js').ClaudeCodeProviderSettings} ClaudeCodeProviderSettings 13 | */ 14 | 15 | /** 16 | * Create a Claude Code provider using the official SDK 17 | * @param {ClaudeCodeProviderSettings} [options={}] - Provider configuration options 18 | * @returns {ClaudeCodeProvider} Claude Code provider instance 19 | */ 20 | export function createClaudeCode(options = {}) { 21 | /** 22 | * Create a language model instance 23 | * @param {ClaudeCodeModelId} modelId - Model ID 24 | * @param {ClaudeCodeSettings} [settings={}] - Model settings 25 | * @returns {ClaudeCodeLanguageModel} 26 | */ 27 | const createModel = (modelId, settings = {}) => { 28 | return new ClaudeCodeLanguageModel({ 29 | id: modelId, 30 | settings: { 31 | ...options.defaultSettings, 32 | ...settings 33 | } 34 | }); 35 | }; 36 | 37 | /** 38 | * Provider function 39 | * @param {ClaudeCodeModelId} modelId - Model ID 40 | * @param {ClaudeCodeSettings} [settings] - Model settings 41 | * @returns {ClaudeCodeLanguageModel} 42 | */ 43 | const provider = function (modelId, settings) { 44 | if (new.target) { 45 | throw new Error( 46 | 'The Claude Code model function cannot be called with the new keyword.' 47 | ); 48 | } 49 | 50 | return createModel(modelId, settings); 51 | }; 52 | 53 | provider.languageModel = createModel; 54 | provider.chat = createModel; // Alias for languageModel 55 | 56 | // Add textEmbeddingModel method that throws NoSuchModelError 57 | provider.textEmbeddingModel = (modelId) => { 58 | throw new NoSuchModelError({ 59 | modelId, 60 | modelType: 'textEmbeddingModel' 61 | }); 62 | }; 63 | 64 | return /** @type {ClaudeCodeProvider} */ (provider); 65 | } 66 | 67 | /** 68 | * Default Claude Code provider instance 69 | */ 70 | export const claudeCode = createClaudeCode(); 71 | 72 | // Provider exports 73 | export { ClaudeCodeLanguageModel } from './language-model.js'; 74 | 75 | // Error handling exports 76 | export { 77 | isAuthenticationError, 78 | isTimeoutError, 79 | getErrorMetadata, 80 | createAPICallError, 81 | createAuthenticationError, 82 | createTimeoutError 83 | } from './errors.js'; 84 | ``` -------------------------------------------------------------------------------- /tests/fixtures/sample-tasks.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * Sample task data for testing 3 | */ 4 | 5 | export const sampleTasks = { 6 | meta: { 7 | projectName: 'Test Project', 8 | projectVersion: '1.0.0', 9 | createdAt: '2023-01-01T00:00:00.000Z', 10 | updatedAt: '2023-01-01T00:00:00.000Z' 11 | }, 12 | tasks: [ 13 | { 14 | id: 1, 15 | title: 'Initialize Project', 16 | description: 'Set up the project structure and dependencies', 17 | status: 'done', 18 | dependencies: [], 19 | priority: 'high', 20 | details: 21 | 'Create directory structure, initialize package.json, and install dependencies', 22 | testStrategy: 'Verify all directories and files are created correctly' 23 | }, 24 | { 25 | id: 2, 26 | title: 'Create Core Functionality', 27 | description: 'Implement the main features of the application', 28 | status: 'in-progress', 29 | dependencies: [1], 30 | priority: 'high', 31 | details: 32 | 'Implement user authentication, data processing, and API endpoints', 33 | testStrategy: 'Write unit tests for all core functions', 34 | subtasks: [ 35 | { 36 | id: 1, 37 | title: 'Implement Authentication', 38 | description: 'Create user authentication system', 39 | status: 'done', 40 | dependencies: [] 41 | }, 42 | { 43 | id: 2, 44 | title: 'Set Up Database', 45 | description: 'Configure database connection and models', 46 | status: 'pending', 47 | dependencies: [1] 48 | } 49 | ] 50 | }, 51 | { 52 | id: 3, 53 | title: 'Implement UI Components', 54 | description: 'Create the user interface components', 55 | status: 'pending', 56 | dependencies: [2], 57 | priority: 'medium', 58 | details: 'Design and implement React components for the user interface', 59 | testStrategy: 'Test components with React Testing Library', 60 | subtasks: [ 61 | { 62 | id: 1, 63 | title: 'Create Header Component', 64 | description: 'Implement the header component', 65 | status: 'pending', 66 | dependencies: [], 67 | details: 'Create a responsive header with navigation links' 68 | }, 69 | { 70 | id: 2, 71 | title: 'Create Footer Component', 72 | description: 'Implement the footer component', 73 | status: 'pending', 74 | dependencies: [], 75 | details: 'Create a footer with copyright information and links' 76 | } 77 | ] 78 | } 79 | ] 80 | }; 81 | 82 | export const emptySampleTasks = { 83 | meta: { 84 | projectName: 'Empty Project', 85 | projectVersion: '1.0.0', 86 | createdAt: '2023-01-01T00:00:00.000Z', 87 | updatedAt: '2023-01-01T00:00:00.000Z' 88 | }, 89 | tasks: [] 90 | }; 91 | ``` -------------------------------------------------------------------------------- /docs/contributor-docs/testing-roo-integration.md: -------------------------------------------------------------------------------- ```markdown 1 | # Testing Roo Integration 2 | 3 | This document provides instructions for testing the Roo integration in the Task Master package. 4 | 5 | ## Running Tests 6 | 7 | To run the tests for the Roo integration: 8 | 9 | ```bash 10 | # Run all tests 11 | npm test 12 | 13 | # Run only Roo integration tests 14 | npm test -- -t "Roo" 15 | 16 | # Run specific test file 17 | npm test -- tests/integration/roo-files-inclusion.test.js 18 | ``` 19 | 20 | ## Manual Testing 21 | 22 | To manually verify that the Roo files are properly included in the package: 23 | 24 | 1. Create a test directory: 25 | 26 | ```bash 27 | mkdir test-tm 28 | cd test-tm 29 | ``` 30 | 31 | 2. Create a package.json file: 32 | 33 | ```bash 34 | npm init -y 35 | ``` 36 | 37 | 3. Install the task-master-ai package locally: 38 | 39 | ```bash 40 | # From the root of the claude-task-master repository 41 | cd .. 42 | npm pack 43 | # This will create a file like task-master-ai-0.12.0.tgz 44 | 45 | # Move back to the test directory 46 | cd test-tm 47 | npm install ../task-master-ai-0.12.0.tgz 48 | ``` 49 | 50 | 4. Initialize a new Task Master project: 51 | 52 | ```bash 53 | npx task-master init --yes 54 | ``` 55 | 56 | 5. Verify that all Roo files and directories are created: 57 | 58 | ```bash 59 | # Check that .roomodes file exists 60 | ls -la | grep .roomodes 61 | 62 | # Check that .roo directory exists and contains all mode directories 63 | ls -la .roo 64 | ls -la .roo/rules 65 | ls -la .roo/rules-architect 66 | ls -la .roo/rules-ask 67 | ls -la .roo/rules-orchestrator 68 | ls -la .roo/rules-code 69 | ls -la .roo/rules-debug 70 | ls -la .roo/rules-test 71 | ``` 72 | 73 | ## What to Look For 74 | 75 | When running the tests or performing manual verification, ensure that: 76 | 77 | 1. The package includes `.roo/**` and `.roomodes` in the `files` array in package.json 78 | 2. The `prepare-package.js` script verifies the existence of all required Roo files 79 | 3. The `init.js` script creates all necessary .roo directories and copies .roomodes file 80 | 4. All source files for Roo integration exist in `assets/roocode/.roo` and `assets/roocode/.roomodes` 81 | 82 | ## Compatibility 83 | 84 | Ensure that the Roo integration works alongside existing Cursor functionality: 85 | 86 | 1. Initialize a new project that uses both Cursor and Roo: 87 | 88 | ```bash 89 | npx task-master init --yes 90 | ``` 91 | 92 | 2. Verify that both `.cursor` and `.roo` directories are created 93 | 3. Verify that both `.windsurfrules` and `.roomodes` files are created 94 | 4. Confirm that existing functionality continues to work as expected 95 | ``` -------------------------------------------------------------------------------- /.kiro/steering/self_improve.md: -------------------------------------------------------------------------------- ```markdown 1 | --- 2 | inclusion: always 3 | --- 4 | 5 | - **Rule Improvement Triggers:** 6 | - New code patterns not covered by existing rules 7 | - Repeated similar implementations across files 8 | - Common error patterns that could be prevented 9 | - New libraries or tools being used consistently 10 | - Emerging best practices in the codebase 11 | 12 | - **Analysis Process:** 13 | - Compare new code with existing rules 14 | - Identify patterns that should be standardized 15 | - Look for references to external documentation 16 | - Check for consistent error handling patterns 17 | - Monitor test patterns and coverage 18 | 19 | - **Rule Updates:** 20 | - **Add New Rules When:** 21 | - A new technology/pattern is used in 3+ files 22 | - Common bugs could be prevented by a rule 23 | - Code reviews repeatedly mention the same feedback 24 | - New security or performance patterns emerge 25 | 26 | - **Modify Existing Rules When:** 27 | - Better examples exist in the codebase 28 | - Additional edge cases are discovered 29 | - Related rules have been updated 30 | - Implementation details have changed 31 | 32 | - **Example Pattern Recognition:** 33 | ```typescript 34 | // If you see repeated patterns like: 35 | const data = await prisma.user.findMany({ 36 | select: { id: true, email: true }, 37 | where: { status: 'ACTIVE' } 38 | }); 39 | 40 | // Consider adding to [prisma.md](.kiro/steering/prisma.md): 41 | // - Standard select fields 42 | // - Common where conditions 43 | // - Performance optimization patterns 44 | ``` 45 | 46 | - **Rule Quality Checks:** 47 | - Rules should be actionable and specific 48 | - Examples should come from actual code 49 | - References should be up to date 50 | - Patterns should be consistently enforced 51 | 52 | - **Continuous Improvement:** 53 | - Monitor code review comments 54 | - Track common development questions 55 | - Update rules after major refactors 56 | - Add links to relevant documentation 57 | - Cross-reference related rules 58 | 59 | - **Rule Deprecation:** 60 | - Mark outdated patterns as deprecated 61 | - Remove rules that no longer apply 62 | - Update references to deprecated rules 63 | - Document migration paths for old patterns 64 | 65 | - **Documentation Updates:** 66 | - Keep examples synchronized with code 67 | - Update references to external docs 68 | - Maintain links between related rules 69 | - Document breaking changes 70 | Follow [kiro_rules.md](.kiro/steering/kiro_rules.md) for proper rule formatting and structure. 71 | ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/fix-dependencies.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/fix-dependencies.js 3 | * Tool for automatically fixing invalid task dependencies 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | handleApiResult, 9 | createErrorResponse, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { fixDependenciesDirect } from '../core/task-master-core.js'; 13 | import { findTasksPath } from '../core/utils/path-utils.js'; 14 | import { resolveTag } from '../../../scripts/modules/utils.js'; 15 | /** 16 | * Register the fixDependencies tool with the MCP server 17 | * @param {Object} server - FastMCP server instance 18 | */ 19 | export function registerFixDependenciesTool(server) { 20 | server.addTool({ 21 | name: 'fix_dependencies', 22 | description: 'Fix invalid dependencies in tasks automatically', 23 | parameters: z.object({ 24 | file: z.string().optional().describe('Absolute path to the tasks file'), 25 | projectRoot: z 26 | .string() 27 | .describe('The directory of the project. Must be an absolute path.'), 28 | tag: z.string().optional().describe('Tag context to operate on') 29 | }), 30 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 31 | try { 32 | log.info(`Fixing dependencies with args: ${JSON.stringify(args)}`); 33 | 34 | const resolvedTag = resolveTag({ 35 | projectRoot: args.projectRoot, 36 | tag: args.tag 37 | }); 38 | 39 | // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) 40 | let tasksJsonPath; 41 | try { 42 | tasksJsonPath = findTasksPath( 43 | { projectRoot: args.projectRoot, file: args.file }, 44 | log 45 | ); 46 | } catch (error) { 47 | log.error(`Error finding tasks.json: ${error.message}`); 48 | return createErrorResponse( 49 | `Failed to find tasks.json: ${error.message}` 50 | ); 51 | } 52 | 53 | const result = await fixDependenciesDirect( 54 | { 55 | tasksJsonPath: tasksJsonPath, 56 | projectRoot: args.projectRoot, 57 | tag: resolvedTag 58 | }, 59 | log 60 | ); 61 | 62 | if (result.success) { 63 | log.info(`Successfully fixed dependencies: ${result.data.message}`); 64 | } else { 65 | log.error(`Failed to fix dependencies: ${result.error.message}`); 66 | } 67 | 68 | return handleApiResult( 69 | result, 70 | log, 71 | 'Error fixing dependencies', 72 | undefined, 73 | args.projectRoot 74 | ); 75 | } catch (error) { 76 | log.error(`Error in fixDependencies tool: ${error.message}`); 77 | return createErrorResponse(error.message); 78 | } 79 | }) 80 | }); 81 | } 82 | ``` -------------------------------------------------------------------------------- /tests/unit/profiles/rule-transformer-opencode.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import { jest } from '@jest/globals'; 2 | import { getRulesProfile } from '../../../src/utils/rule-transformer.js'; 3 | import { opencodeProfile } from '../../../src/profiles/opencode.js'; 4 | 5 | describe('Rule Transformer - OpenCode Profile', () => { 6 | test('should have correct profile configuration', () => { 7 | const opencodeProfile = getRulesProfile('opencode'); 8 | 9 | expect(opencodeProfile).toBeDefined(); 10 | expect(opencodeProfile.profileName).toBe('opencode'); 11 | expect(opencodeProfile.displayName).toBe('OpenCode'); 12 | expect(opencodeProfile.profileDir).toBe('.'); 13 | expect(opencodeProfile.rulesDir).toBe('.'); 14 | expect(opencodeProfile.mcpConfig).toBe(true); 15 | expect(opencodeProfile.mcpConfigName).toBe('opencode.json'); 16 | expect(opencodeProfile.mcpConfigPath).toBe('opencode.json'); 17 | expect(opencodeProfile.includeDefaultRules).toBe(false); 18 | expect(opencodeProfile.fileMap).toEqual({ 19 | 'AGENTS.md': 'AGENTS.md' 20 | }); 21 | }); 22 | 23 | test('should have lifecycle functions for MCP config transformation', () => { 24 | // Verify that opencode.js has lifecycle functions 25 | expect(opencodeProfile.onPostConvertRulesProfile).toBeDefined(); 26 | expect(typeof opencodeProfile.onPostConvertRulesProfile).toBe('function'); 27 | expect(opencodeProfile.onRemoveRulesProfile).toBeDefined(); 28 | expect(typeof opencodeProfile.onRemoveRulesProfile).toBe('function'); 29 | }); 30 | 31 | test('should use opencode.json instead of mcp.json', () => { 32 | const opencodeProfile = getRulesProfile('opencode'); 33 | expect(opencodeProfile.mcpConfigName).toBe('opencode.json'); 34 | expect(opencodeProfile.mcpConfigPath).toBe('opencode.json'); 35 | }); 36 | 37 | test('should not include default rules', () => { 38 | const opencodeProfile = getRulesProfile('opencode'); 39 | expect(opencodeProfile.includeDefaultRules).toBe(false); 40 | }); 41 | 42 | test('should have correct file mapping', () => { 43 | const opencodeProfile = getRulesProfile('opencode'); 44 | expect(opencodeProfile.fileMap).toEqual({ 45 | 'AGENTS.md': 'AGENTS.md' 46 | }); 47 | }); 48 | 49 | test('should use root directory for both profile and rules', () => { 50 | const opencodeProfile = getRulesProfile('opencode'); 51 | expect(opencodeProfile.profileDir).toBe('.'); 52 | expect(opencodeProfile.rulesDir).toBe('.'); 53 | }); 54 | 55 | test('should have MCP configuration enabled', () => { 56 | const opencodeProfile = getRulesProfile('opencode'); 57 | expect(opencodeProfile.mcpConfig).toBe(true); 58 | }); 59 | }); 60 | ``` -------------------------------------------------------------------------------- /tests/unit/task-manager/tag-management.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { 4 | createTag, 5 | deleteTag, 6 | renameTag, 7 | copyTag, 8 | tags as listTags 9 | } from '../../../scripts/modules/task-manager/tag-management.js'; 10 | 11 | const TEMP_DIR = path.join(process.cwd(), '.tmp_tag_management_tests'); 12 | const TASKS_PATH = path.join(TEMP_DIR, 'tasks.json'); 13 | 14 | /** 15 | * Helper to write an initial tagged tasks.json structure 16 | */ 17 | function writeInitialFile() { 18 | const initialData = { 19 | master: { 20 | tasks: [{ id: 1, title: 'Initial Task', status: 'pending' }], 21 | metadata: { 22 | created: new Date().toISOString(), 23 | description: 'Master tag' 24 | } 25 | } 26 | }; 27 | fs.mkdirSync(TEMP_DIR, { recursive: true }); 28 | fs.writeFileSync(TASKS_PATH, JSON.stringify(initialData, null, 2)); 29 | } 30 | 31 | describe('Tag Management – writeJSON context preservation', () => { 32 | beforeEach(() => { 33 | writeInitialFile(); 34 | }); 35 | 36 | afterEach(() => { 37 | fs.rmSync(TEMP_DIR, { recursive: true, force: true }); 38 | }); 39 | 40 | it('createTag should not corrupt other tags', async () => { 41 | await createTag( 42 | TASKS_PATH, 43 | 'feature', 44 | { copyFromCurrent: true }, 45 | { projectRoot: TEMP_DIR }, 46 | 'json' 47 | ); 48 | 49 | const data = JSON.parse(fs.readFileSync(TASKS_PATH, 'utf8')); 50 | expect(data.master).toBeDefined(); 51 | expect(data.feature).toBeDefined(); 52 | }); 53 | 54 | it('renameTag should keep overall structure intact', async () => { 55 | await createTag( 56 | TASKS_PATH, 57 | 'oldtag', 58 | {}, 59 | { projectRoot: TEMP_DIR }, 60 | 'json' 61 | ); 62 | 63 | await renameTag( 64 | TASKS_PATH, 65 | 'oldtag', 66 | 'newtag', 67 | {}, 68 | { projectRoot: TEMP_DIR }, 69 | 'json' 70 | ); 71 | 72 | const data = JSON.parse(fs.readFileSync(TASKS_PATH, 'utf8')); 73 | expect(data.newtag).toBeDefined(); 74 | expect(data.oldtag).toBeUndefined(); 75 | }); 76 | 77 | it('copyTag then deleteTag preserves other tags', async () => { 78 | await createTag( 79 | TASKS_PATH, 80 | 'source', 81 | {}, 82 | { projectRoot: TEMP_DIR }, 83 | 'json' 84 | ); 85 | 86 | await copyTag( 87 | TASKS_PATH, 88 | 'source', 89 | 'copy', 90 | {}, 91 | { projectRoot: TEMP_DIR }, 92 | 'json' 93 | ); 94 | 95 | await deleteTag( 96 | TASKS_PATH, 97 | 'copy', 98 | { yes: true }, 99 | { projectRoot: TEMP_DIR }, 100 | 'json' 101 | ); 102 | 103 | const tagsList = await listTags( 104 | TASKS_PATH, 105 | {}, 106 | { projectRoot: TEMP_DIR }, 107 | 'json' 108 | ); 109 | 110 | const tagNames = tagsList.tags.map((t) => t.name); 111 | expect(tagNames).toContain('master'); 112 | expect(tagNames).toContain('source'); 113 | expect(tagNames).not.toContain('copy'); 114 | }); 115 | }); 116 | ``` -------------------------------------------------------------------------------- /mcp-server/src/tools/complexity-report.js: -------------------------------------------------------------------------------- ```javascript 1 | /** 2 | * tools/complexity-report.js 3 | * Tool for displaying the complexity analysis report 4 | */ 5 | 6 | import { z } from 'zod'; 7 | import { 8 | handleApiResult, 9 | createErrorResponse, 10 | withNormalizedProjectRoot 11 | } from './utils.js'; 12 | import { complexityReportDirect } from '../core/task-master-core.js'; 13 | import { COMPLEXITY_REPORT_FILE } from '../../../src/constants/paths.js'; 14 | import { findComplexityReportPath } from '../core/utils/path-utils.js'; 15 | import { getCurrentTag } from '../../../scripts/modules/utils.js'; 16 | 17 | /** 18 | * Register the complexityReport tool with the MCP server 19 | * @param {Object} server - FastMCP server instance 20 | */ 21 | export function registerComplexityReportTool(server) { 22 | server.addTool({ 23 | name: 'complexity_report', 24 | description: 'Display the complexity analysis report in a readable format', 25 | parameters: z.object({ 26 | file: z 27 | .string() 28 | .optional() 29 | .describe( 30 | `Path to the report file (default: ${COMPLEXITY_REPORT_FILE})` 31 | ), 32 | projectRoot: z 33 | .string() 34 | .describe('The directory of the project. Must be an absolute path.') 35 | }), 36 | execute: withNormalizedProjectRoot(async (args, { log, session }) => { 37 | try { 38 | log.info( 39 | `Getting complexity report with args: ${JSON.stringify(args)}` 40 | ); 41 | 42 | const resolvedTag = getCurrentTag(args.projectRoot); 43 | 44 | const pathArgs = { 45 | projectRoot: args.projectRoot, 46 | complexityReport: args.file, 47 | tag: resolvedTag 48 | }; 49 | 50 | const reportPath = findComplexityReportPath(pathArgs, log); 51 | log.info('Reading complexity report from path: ', reportPath); 52 | 53 | if (!reportPath) { 54 | return createErrorResponse( 55 | 'No complexity report found. Run task-master analyze-complexity first.' 56 | ); 57 | } 58 | 59 | const result = await complexityReportDirect( 60 | { 61 | reportPath: reportPath 62 | }, 63 | log 64 | ); 65 | 66 | if (result.success) { 67 | log.info('Successfully retrieved complexity report'); 68 | } else { 69 | log.error( 70 | `Failed to retrieve complexity report: ${result.error.message}` 71 | ); 72 | } 73 | 74 | return handleApiResult( 75 | result, 76 | log, 77 | 'Error retrieving complexity report', 78 | undefined, 79 | args.projectRoot 80 | ); 81 | } catch (error) { 82 | log.error(`Error in complexity-report tool: ${error.message}`); 83 | return createErrorResponse( 84 | `Failed to retrieve complexity report: ${error.message}` 85 | ); 86 | } 87 | }) 88 | }); 89 | } 90 | ``` -------------------------------------------------------------------------------- /apps/docs/archive/configuration.mdx: -------------------------------------------------------------------------------- ```markdown 1 | --- 2 | title: "Configuration" 3 | description: "Configure Task Master through environment variables in a .env file" 4 | --- 5 | 6 | ## Required Configuration 7 | 8 | <Note> 9 | Task Master requires an Anthropic API key to function. Add this to your `.env` file: 10 | 11 | ```bash 12 | ANTHROPIC_API_KEY=sk-ant-api03-your-api-key 13 | ``` 14 | 15 | You can obtain an API key from the [Anthropic Console](https://console.anthropic.com/). 16 | </Note> 17 | 18 | ## Optional Configuration 19 | 20 | | Variable | Default Value | Description | Example | 21 | | --- | --- | --- | --- | 22 | | `MODEL` | `"claude-3-7-sonnet-20250219"` | Claude model to use | `MODEL=claude-3-opus-20240229` | 23 | | `MAX_TOKENS` | `"4000"` | Maximum tokens for responses | `MAX_TOKENS=8000` | 24 | | `TEMPERATURE` | `"0.7"` | Temperature for model responses | `TEMPERATURE=0.5` | 25 | | `DEBUG` | `"false"` | Enable debug logging | `DEBUG=true` | 26 | | `LOG_LEVEL` | `"info"` | Console output level | `LOG_LEVEL=debug` | 27 | | `DEFAULT_SUBTASKS` | `"3"` | Default subtask count | `DEFAULT_SUBTASKS=5` | 28 | | `DEFAULT_PRIORITY` | `"medium"` | Default priority | `DEFAULT_PRIORITY=high` | 29 | | `PROJECT_NAME` | `"MCP SaaS MVP"` | Project name in metadata | `PROJECT_NAME=My Awesome Project` | 30 | | `PROJECT_VERSION` | `"1.0.0"` | Version in metadata | `PROJECT_VERSION=2.1.0` | 31 | | `PERPLEXITY_API_KEY` | - | For research-backed features | `PERPLEXITY_API_KEY=pplx-...` | 32 | | `PERPLEXITY_MODEL` | `"sonar-medium-online"` | Perplexity model | `PERPLEXITY_MODEL=sonar-large-online` | 33 | 34 | ## Example .env File 35 | 36 | ``` 37 | # Required 38 | ANTHROPIC_API_KEY=sk-ant-api03-your-api-key 39 | 40 | # Optional - Claude Configuration 41 | MODEL=claude-3-7-sonnet-20250219 42 | MAX_TOKENS=4000 43 | TEMPERATURE=0.7 44 | 45 | # Optional - Perplexity API for Research 46 | PERPLEXITY_API_KEY=pplx-your-api-key 47 | PERPLEXITY_MODEL=sonar-medium-online 48 | 49 | # Optional - Project Info 50 | PROJECT_NAME=My Project 51 | PROJECT_VERSION=1.0.0 52 | 53 | # Optional - Application Configuration 54 | DEFAULT_SUBTASKS=3 55 | DEFAULT_PRIORITY=medium 56 | DEBUG=false 57 | LOG_LEVEL=info 58 | ``` 59 | 60 | ## Troubleshooting 61 | 62 | ### If `task-master init` doesn't respond: 63 | 64 | Try running it with Node directly: 65 | 66 | ```bash 67 | node node_modules/claude-task-master/scripts/init.js 68 | ``` 69 | 70 | Or clone the repository and run: 71 | 72 | ```bash 73 | git clone https://github.com/eyaltoledano/claude-task-master.git 74 | cd claude-task-master 75 | node scripts/init.js 76 | ``` 77 | 78 | <Note> 79 | For advanced configuration options and detailed customization, see our [Advanced Configuration Guide] page. 80 | </Note> ```