#
tokens: 49956/50000 49/975 files (page 6/50)
lines: off (toggle) GitHub
raw markdown copy
This is page 6 of 50. Use http://codebase.md/eyaltoledano/claude-task-master?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── README.md
├── .claude
│   ├── commands
│   │   └── dedupe.md
│   └── TM_COMMANDS_GUIDE.md
├── .claude-plugin
│   └── marketplace.json
├── .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
│   │   └── validate-changesets.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
│   │   ├── autonomous-tdd-git-workflow.md
│   │   ├── 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
│   │   ├── tdd-workflow-phase-0-spike.md
│   │   ├── tdd-workflow-phase-1-core-rails.md
│   │   ├── tdd-workflow-phase-1-orchestrator.md
│   │   ├── tdd-workflow-phase-2-pr-resumability.md
│   │   ├── tdd-workflow-phase-3-extensibility-guardrails.md
│   │   ├── test-prd.txt
│   │   └── tm-core-phase-1.txt
│   ├── reports
│   │   ├── task-complexity-report_autonomous-tdd-git-workflow.json
│   │   ├── task-complexity-report_cc-kiro-hooks.json
│   │   ├── task-complexity-report_tdd-phase-1-core-rails.json
│   │   ├── task-complexity-report_tdd-workflow-phase-0.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_rpg.md
│       └── example_prd.md
├── .vscode
│   ├── extensions.json
│   └── settings.json
├── apps
│   ├── cli
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── command-registry.ts
│   │   │   ├── commands
│   │   │   │   ├── auth.command.ts
│   │   │   │   ├── autopilot
│   │   │   │   │   ├── abort.command.ts
│   │   │   │   │   ├── commit.command.ts
│   │   │   │   │   ├── complete.command.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── next.command.ts
│   │   │   │   │   ├── resume.command.ts
│   │   │   │   │   ├── shared.ts
│   │   │   │   │   ├── start.command.ts
│   │   │   │   │   └── status.command.ts
│   │   │   │   ├── briefs.command.ts
│   │   │   │   ├── context.command.ts
│   │   │   │   ├── export.command.ts
│   │   │   │   ├── list.command.ts
│   │   │   │   ├── models
│   │   │   │   │   ├── custom-providers.ts
│   │   │   │   │   ├── fetchers.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── prompts.ts
│   │   │   │   │   ├── setup.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── next.command.ts
│   │   │   │   ├── set-status.command.ts
│   │   │   │   ├── show.command.ts
│   │   │   │   ├── start.command.ts
│   │   │   │   └── tags.command.ts
│   │   │   ├── index.ts
│   │   │   ├── lib
│   │   │   │   └── model-management.ts
│   │   │   ├── types
│   │   │   │   └── tag-management.d.ts
│   │   │   ├── ui
│   │   │   │   ├── components
│   │   │   │   │   ├── cardBox.component.ts
│   │   │   │   │   ├── dashboard.component.ts
│   │   │   │   │   ├── header.component.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── next-task.component.ts
│   │   │   │   │   ├── suggested-steps.component.ts
│   │   │   │   │   └── task-detail.component.ts
│   │   │   │   ├── display
│   │   │   │   │   ├── messages.ts
│   │   │   │   │   └── tables.ts
│   │   │   │   ├── formatters
│   │   │   │   │   ├── complexity-formatters.ts
│   │   │   │   │   ├── dependency-formatters.ts
│   │   │   │   │   ├── priority-formatters.ts
│   │   │   │   │   ├── status-formatters.spec.ts
│   │   │   │   │   └── status-formatters.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── layout
│   │   │   │       ├── helpers.spec.ts
│   │   │   │       └── helpers.ts
│   │   │   └── utils
│   │   │       ├── auth-helpers.ts
│   │   │       ├── auto-update.ts
│   │   │       ├── brief-selection.ts
│   │   │       ├── display-helpers.ts
│   │   │       ├── error-handler.ts
│   │   │       ├── index.ts
│   │   │       ├── project-root.ts
│   │   │       ├── task-status.ts
│   │   │       ├── ui.spec.ts
│   │   │       └── ui.ts
│   │   ├── tests
│   │   │   ├── integration
│   │   │   │   └── commands
│   │   │   │       └── autopilot
│   │   │   │           └── workflow.test.ts
│   │   │   └── unit
│   │   │       ├── commands
│   │   │       │   ├── autopilot
│   │   │       │   │   └── shared.test.ts
│   │   │       │   ├── list.command.spec.ts
│   │   │       │   └── show.command.spec.ts
│   │   │       └── ui
│   │   │           └── dashboard.component.spec.ts
│   │   ├── tsconfig.json
│   │   └── vitest.config.ts
│   ├── 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
│   │   │   ├── rpg-method.mdx
│   │   │   └── task-structure.mdx
│   │   ├── CHANGELOG.md
│   │   ├── command-reference.mdx
│   │   ├── configuration.mdx
│   │   ├── docs.json
│   │   ├── favicon.svg
│   │   ├── getting-started
│   │   │   ├── api-keys.mdx
│   │   │   ├── 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
│   │   ├── tdd-workflow
│   │   │   ├── ai-agent-integration.mdx
│   │   │   └── quickstart.mdx
│   │   ├── 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
│   └── mcp
│       ├── CHANGELOG.md
│       ├── package.json
│       ├── src
│       │   ├── index.ts
│       │   ├── shared
│       │   │   ├── types.ts
│       │   │   └── utils.ts
│       │   └── tools
│       │       ├── autopilot
│       │       │   ├── abort.tool.ts
│       │       │   ├── commit.tool.ts
│       │       │   ├── complete.tool.ts
│       │       │   ├── finalize.tool.ts
│       │       │   ├── index.ts
│       │       │   ├── next.tool.ts
│       │       │   ├── resume.tool.ts
│       │       │   ├── start.tool.ts
│       │       │   └── status.tool.ts
│       │       ├── README-ZOD-V3.md
│       │       └── tasks
│       │           ├── get-task.tool.ts
│       │           ├── get-tasks.tool.ts
│       │           └── index.ts
│       ├── tsconfig.json
│       └── vitest.config.ts
├── assets
│   ├── .windsurfrules
│   ├── AGENTS.md
│   ├── claude
│   │   └── TM_COMMANDS_GUIDE.md
│   ├── config.json
│   ├── env.example
│   ├── example_prd_rpg.txt
│   ├── example_prd.txt
│   ├── GEMINI.md
│   ├── 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_CODE_PLUGIN.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
│   ├── claude-code-integration.md
│   ├── CLI-COMMANDER-PATTERN.md
│   ├── command-reference.md
│   ├── configuration.md
│   ├── contributor-docs
│   │   ├── testing-roo-integration.md
│   │   └── worktree-setup.md
│   ├── cross-tag-task-movement.md
│   ├── examples
│   │   ├── claude-code-usage.md
│   │   └── codex-cli-usage.md
│   ├── examples.md
│   ├── licensing.md
│   ├── mcp-provider-guide.md
│   ├── mcp-provider.md
│   ├── migration-guide.md
│   ├── models.md
│   ├── providers
│   │   ├── codex-cli.md
│   │   └── gemini-cli.md
│   ├── README.md
│   ├── scripts
│   │   └── models-json-to-markdown.js
│   ├── task-structure.md
│   └── tutorial.md
├── images
│   ├── hamster-hiring.png
│   └── 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
│       │   │   ├── 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
│       │   │   ├── 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
│           ├── index.js
│           ├── initialize-project.js
│           ├── list-tags.js
│           ├── models.js
│           ├── move-task.js
│           ├── next-task.js
│           ├── parse-prd.js
│           ├── README-ZOD-V3.md
│           ├── 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
│           ├── tool-registry.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
│   ├── ai-sdk-provider-grok-cli
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── errors.test.ts
│   │   │   ├── errors.ts
│   │   │   ├── grok-cli-language-model.ts
│   │   │   ├── grok-cli-provider.test.ts
│   │   │   ├── grok-cli-provider.ts
│   │   │   ├── index.ts
│   │   │   ├── json-extractor.test.ts
│   │   │   ├── json-extractor.ts
│   │   │   ├── message-converter.test.ts
│   │   │   ├── message-converter.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── build-config
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src
│   │   │   └── tsdown.base.ts
│   │   └── tsconfig.json
│   ├── claude-code-plugin
│   │   ├── .claude-plugin
│   │   │   └── plugin.json
│   │   ├── .gitignore
│   │   ├── agents
│   │   │   ├── task-checker.md
│   │   │   ├── task-executor.md
│   │   │   └── task-orchestrator.md
│   │   ├── CHANGELOG.md
│   │   ├── commands
│   │   │   ├── add-dependency.md
│   │   │   ├── add-subtask.md
│   │   │   ├── add-task.md
│   │   │   ├── analyze-complexity.md
│   │   │   ├── analyze-project.md
│   │   │   ├── auto-implement-tasks.md
│   │   │   ├── command-pipeline.md
│   │   │   ├── complexity-report.md
│   │   │   ├── convert-task-to-subtask.md
│   │   │   ├── expand-all-tasks.md
│   │   │   ├── expand-task.md
│   │   │   ├── fix-dependencies.md
│   │   │   ├── generate-tasks.md
│   │   │   ├── help.md
│   │   │   ├── init-project-quick.md
│   │   │   ├── init-project.md
│   │   │   ├── install-taskmaster.md
│   │   │   ├── learn.md
│   │   │   ├── list-tasks-by-status.md
│   │   │   ├── list-tasks-with-subtasks.md
│   │   │   ├── list-tasks.md
│   │   │   ├── next-task.md
│   │   │   ├── parse-prd-with-research.md
│   │   │   ├── parse-prd.md
│   │   │   ├── project-status.md
│   │   │   ├── quick-install-taskmaster.md
│   │   │   ├── remove-all-subtasks.md
│   │   │   ├── remove-dependency.md
│   │   │   ├── remove-subtask.md
│   │   │   ├── remove-subtasks.md
│   │   │   ├── remove-task.md
│   │   │   ├── setup-models.md
│   │   │   ├── show-task.md
│   │   │   ├── smart-workflow.md
│   │   │   ├── sync-readme.md
│   │   │   ├── tm-main.md
│   │   │   ├── to-cancelled.md
│   │   │   ├── to-deferred.md
│   │   │   ├── to-done.md
│   │   │   ├── to-in-progress.md
│   │   │   ├── to-pending.md
│   │   │   ├── to-review.md
│   │   │   ├── update-single-task.md
│   │   │   ├── update-task.md
│   │   │   ├── update-tasks-from-id.md
│   │   │   ├── validate-dependencies.md
│   │   │   └── view-models.md
│   │   ├── mcp.json
│   │   └── package.json
│   ├── tm-bridge
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── add-tag-bridge.ts
│   │   │   ├── bridge-types.ts
│   │   │   ├── bridge-utils.ts
│   │   │   ├── expand-bridge.ts
│   │   │   ├── index.ts
│   │   │   ├── tags-bridge.ts
│   │   │   ├── update-bridge.ts
│   │   │   └── use-tag-bridge.ts
│   │   └── tsconfig.json
│   └── tm-core
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── docs
│       │   └── listTasks-architecture.md
│       ├── package.json
│       ├── POC-STATUS.md
│       ├── README.md
│       ├── src
│       │   ├── common
│       │   │   ├── constants
│       │   │   │   ├── index.ts
│       │   │   │   ├── paths.ts
│       │   │   │   └── providers.ts
│       │   │   ├── errors
│       │   │   │   ├── index.ts
│       │   │   │   └── task-master-error.ts
│       │   │   ├── interfaces
│       │   │   │   ├── configuration.interface.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── storage.interface.ts
│       │   │   ├── logger
│       │   │   │   ├── factory.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── logger.spec.ts
│       │   │   │   └── logger.ts
│       │   │   ├── mappers
│       │   │   │   ├── TaskMapper.test.ts
│       │   │   │   └── TaskMapper.ts
│       │   │   ├── types
│       │   │   │   ├── database.types.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── legacy.ts
│       │   │   │   └── repository-types.ts
│       │   │   └── utils
│       │   │       ├── git-utils.ts
│       │   │       ├── id-generator.ts
│       │   │       ├── index.ts
│       │   │       ├── path-helpers.ts
│       │   │       ├── path-normalizer.spec.ts
│       │   │       ├── path-normalizer.ts
│       │   │       ├── project-root-finder.spec.ts
│       │   │       ├── project-root-finder.ts
│       │   │       ├── run-id-generator.spec.ts
│       │   │       └── run-id-generator.ts
│       │   ├── index.ts
│       │   ├── modules
│       │   │   ├── ai
│       │   │   │   ├── index.ts
│       │   │   │   ├── interfaces
│       │   │   │   │   └── ai-provider.interface.ts
│       │   │   │   └── providers
│       │   │   │       ├── base-provider.ts
│       │   │   │       └── index.ts
│       │   │   ├── auth
│       │   │   │   ├── auth-domain.spec.ts
│       │   │   │   ├── auth-domain.ts
│       │   │   │   ├── config.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── managers
│       │   │   │   │   ├── auth-manager.spec.ts
│       │   │   │   │   └── auth-manager.ts
│       │   │   │   ├── services
│       │   │   │   │   ├── context-store.ts
│       │   │   │   │   ├── oauth-service.ts
│       │   │   │   │   ├── organization.service.ts
│       │   │   │   │   ├── supabase-session-storage.spec.ts
│       │   │   │   │   └── supabase-session-storage.ts
│       │   │   │   └── types.ts
│       │   │   ├── briefs
│       │   │   │   ├── briefs-domain.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── services
│       │   │   │   │   └── brief-service.ts
│       │   │   │   ├── types.ts
│       │   │   │   └── utils
│       │   │   │       └── url-parser.ts
│       │   │   ├── commands
│       │   │   │   └── index.ts
│       │   │   ├── config
│       │   │   │   ├── config-domain.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── managers
│       │   │   │   │   ├── config-manager.spec.ts
│       │   │   │   │   └── config-manager.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
│       │   │   ├── dependencies
│       │   │   │   └── index.ts
│       │   │   ├── execution
│       │   │   │   ├── executors
│       │   │   │   │   ├── base-executor.ts
│       │   │   │   │   ├── claude-executor.ts
│       │   │   │   │   └── executor-factory.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── services
│       │   │   │   │   └── executor-service.ts
│       │   │   │   └── types.ts
│       │   │   ├── git
│       │   │   │   ├── adapters
│       │   │   │   │   ├── git-adapter.test.ts
│       │   │   │   │   └── git-adapter.ts
│       │   │   │   ├── git-domain.ts
│       │   │   │   ├── index.ts
│       │   │   │   └── services
│       │   │   │       ├── branch-name-generator.spec.ts
│       │   │   │       ├── branch-name-generator.ts
│       │   │   │       ├── commit-message-generator.test.ts
│       │   │   │       ├── commit-message-generator.ts
│       │   │   │       ├── scope-detector.test.ts
│       │   │   │       ├── scope-detector.ts
│       │   │   │       ├── template-engine.test.ts
│       │   │   │       └── template-engine.ts
│       │   │   ├── integration
│       │   │   │   ├── clients
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── supabase-client.ts
│       │   │   │   ├── integration-domain.ts
│       │   │   │   └── services
│       │   │   │       ├── export.service.ts
│       │   │   │       ├── task-expansion.service.ts
│       │   │   │       └── task-retrieval.service.ts
│       │   │   ├── reports
│       │   │   │   ├── index.ts
│       │   │   │   ├── managers
│       │   │   │   │   └── complexity-report-manager.ts
│       │   │   │   └── types.ts
│       │   │   ├── storage
│       │   │   │   ├── adapters
│       │   │   │   │   ├── activity-logger.ts
│       │   │   │   │   ├── api-storage.ts
│       │   │   │   │   └── file-storage
│       │   │   │   │       ├── file-operations.ts
│       │   │   │   │       ├── file-storage.ts
│       │   │   │   │       ├── format-handler.ts
│       │   │   │   │       ├── index.ts
│       │   │   │   │       └── path-resolver.ts
│       │   │   │   ├── index.ts
│       │   │   │   ├── services
│       │   │   │   │   └── storage-factory.ts
│       │   │   │   └── utils
│       │   │   │       └── api-client.ts
│       │   │   ├── tasks
│       │   │   │   ├── entities
│       │   │   │   │   └── task.entity.ts
│       │   │   │   ├── parser
│       │   │   │   │   └── index.ts
│       │   │   │   ├── repositories
│       │   │   │   │   ├── supabase
│       │   │   │   │   │   ├── dependency-fetcher.ts
│       │   │   │   │   │   ├── index.ts
│       │   │   │   │   │   └── supabase-repository.ts
│       │   │   │   │   └── task-repository.interface.ts
│       │   │   │   ├── services
│       │   │   │   │   ├── preflight-checker.service.ts
│       │   │   │   │   ├── tag.service.ts
│       │   │   │   │   ├── task-execution-service.ts
│       │   │   │   │   ├── task-loader.service.ts
│       │   │   │   │   └── task-service.ts
│       │   │   │   └── tasks-domain.ts
│       │   │   ├── ui
│       │   │   │   └── index.ts
│       │   │   └── workflow
│       │   │       ├── managers
│       │   │       │   ├── workflow-state-manager.spec.ts
│       │   │       │   └── workflow-state-manager.ts
│       │   │       ├── orchestrators
│       │   │       │   ├── workflow-orchestrator.test.ts
│       │   │       │   └── workflow-orchestrator.ts
│       │   │       ├── services
│       │   │       │   ├── test-result-validator.test.ts
│       │   │       │   ├── test-result-validator.ts
│       │   │       │   ├── test-result-validator.types.ts
│       │   │       │   ├── workflow-activity-logger.ts
│       │   │       │   └── workflow.service.ts
│       │   │       ├── types.ts
│       │   │       └── workflow-domain.ts
│       │   ├── subpath-exports.test.ts
│       │   ├── tm-core.ts
│       │   └── utils
│       │       └── time.utils.ts
│       ├── tests
│       │   ├── auth
│       │   │   └── auth-refresh.test.ts
│       │   ├── integration
│       │   │   ├── auth-token-refresh.test.ts
│       │   │   ├── list-tasks.test.ts
│       │   │   └── storage
│       │   │       └── activity-logger.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
│   ├── create-worktree.sh
│   ├── dev.js
│   ├── init.js
│   ├── list-worktrees.sh
│   ├── modules
│   │   ├── ai-services-unified.js
│   │   ├── bridge-utils.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
├── sonar-project.properties
├── src
│   ├── ai-providers
│   │   ├── anthropic.js
│   │   ├── azure.js
│   │   ├── base-provider.js
│   │   ├── bedrock.js
│   │   ├── claude-code.js
│   │   ├── codex-cli.js
│   │   ├── gemini-cli.js
│   │   ├── google-vertex.js
│   │   ├── google.js
│   │   ├── grok-cli.js
│   │   ├── groq.js
│   │   ├── index.js
│   │   ├── lmstudio.js
│   │   ├── ollama.js
│   │   ├── openai-compatible.js
│   │   ├── openai.js
│   │   ├── openrouter.js
│   │   ├── perplexity.js
│   │   ├── xai.js
│   │   ├── zai-coding.js
│   │   └── zai.js
│   ├── constants
│   │   ├── commands.js
│   │   ├── paths.js
│   │   ├── profiles.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
│   ├── schemas
│   │   ├── add-task.js
│   │   ├── analyze-complexity.js
│   │   ├── base-schemas.js
│   │   ├── expand-task.js
│   │   ├── parse-prd.js
│   │   ├── registry.js
│   │   ├── update-subtask.js
│   │   ├── update-task.js
│   │   └── update-tasks.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
│   ├── fixtures
│   │   ├── .taskmasterconfig
│   │   ├── sample-claude-response.js
│   │   ├── sample-prd.txt
│   │   └── sample-tasks.js
│   ├── helpers
│   │   └── tool-counts.js
│   ├── integration
│   │   ├── claude-code-error-handling.test.js
│   │   ├── 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
│   │   └── providers
│   │       └── temperature-support.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
│       │   ├── base-provider.test.js
│       │   ├── claude-code.test.js
│       │   ├── codex-cli.test.js
│       │   ├── gemini-cli.test.js
│       │   ├── lmstudio.test.js
│       │   ├── mcp-components.test.js
│       │   ├── openai-compatible.test.js
│       │   ├── openai.test.js
│       │   ├── provider-registry.test.js
│       │   ├── zai-coding.test.js
│       │   ├── zai-provider.test.js
│       │   ├── zai-schema-introspection.test.js
│       │   └── zai.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
│       │       └── tool-registration.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
│       │   └── prompt-migration.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
│       │       │   ├── models-baseurl.test.js
│       │       │   ├── move-task-cross-tag.test.js
│       │       │   ├── move-task.test.js
│       │       │   ├── parse-prd-schema.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
└── update-task-migration-plan.md
```

# Files

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/use-tag.js:
--------------------------------------------------------------------------------

```javascript
/**
 * use-tag.js
 * Direct function implementation for switching to a tag
 */

import { useTag } from '../../../../scripts/modules/task-manager/tag-management.js';
import {
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';
import { createLogWrapper } from '../../tools/utils.js';

/**
 * Direct function wrapper for switching to a tag with error handling.
 *
 * @param {Object} args - Command arguments
 * @param {string} args.name - Name of the tag to switch to
 * @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
 * @param {string} [args.projectRoot] - Project root path
 * @param {Object} log - Logger object
 * @param {Object} context - Additional context (session)
 * @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
 */
export async function useTagDirect(args, log, context = {}) {
	// Destructure expected args
	const { tasksJsonPath, name, projectRoot } = args;
	const { session } = context;

	// Enable silent mode to prevent console logs from interfering with JSON response
	enableSilentMode();

	// Create logger wrapper using the utility
	const mcpLog = createLogWrapper(log);

	try {
		// Check if tasksJsonPath was provided
		if (!tasksJsonPath) {
			log.error('useTagDirect called without tasksJsonPath');
			disableSilentMode();
			return {
				success: false,
				error: {
					code: 'MISSING_ARGUMENT',
					message: 'tasksJsonPath is required'
				}
			};
		}

		// Check required parameters
		if (!name || typeof name !== 'string') {
			log.error('Missing required parameter: name');
			disableSilentMode();
			return {
				success: false,
				error: {
					code: 'MISSING_PARAMETER',
					message: 'Tag name is required and must be a string'
				}
			};
		}

		log.info(`Switching to tag: ${name}`);

		// Call the useTag function
		const result = await useTag(
			tasksJsonPath,
			name,
			{}, // options (empty for now)
			{
				session,
				mcpLog,
				projectRoot
			},
			'json' // outputFormat - use 'json' to suppress CLI UI
		);

		// Restore normal logging
		disableSilentMode();

		return {
			success: true,
			data: {
				tagName: result.currentTag,
				switched: result.switched,
				previousTag: result.previousTag,
				taskCount: result.taskCount,
				message: `Successfully switched to tag "${result.currentTag}"`
			}
		};
	} catch (error) {
		// Make sure to restore normal logging even if there's an error
		disableSilentMode();

		log.error(`Error in useTagDirect: ${error.message}`);
		return {
			success: false,
			error: {
				code: error.code || 'USE_TAG_ERROR',
				message: error.message
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/add-dependency.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/add-dependency.js
 * Tool for adding a dependency to a task
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { addDependencyDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the addDependency tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerAddDependencyTool(server) {
	server.addTool({
		name: 'add_dependency',
		description: 'Add a dependency relationship between two tasks',
		parameters: z.object({
			id: z.string().describe('ID of task that will depend on another task'),
			dependsOn: z
				.string()
				.describe('ID of task that will become a dependency'),
			file: z
				.string()
				.optional()
				.describe(
					'Absolute path to the tasks file (default: tasks/tasks.json)'
				),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				log.info(
					`Adding dependency for task ${args.id} to depend on ${args.dependsOn}`
				);
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});
				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				// Call the direct function with the resolved path
				const result = await addDependencyDirect(
					{
						// Pass the explicitly resolved path
						tasksJsonPath: tasksJsonPath,
						// Pass other relevant args
						id: args.id,
						dependsOn: args.dependsOn,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log
					// Remove context object
				);

				// Log result
				if (result.success) {
					log.info(`Successfully added dependency: ${result.data.message}`);
				} else {
					log.error(`Failed to add dependency: ${result.error.message}`);
				}

				// Use handleApiResult to format the response
				return handleApiResult(
					result,
					log,
					'Error adding dependency',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in addDependency tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/clear-subtasks.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/clear-subtasks.js
 * Tool for clearing subtasks from parent tasks
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { clearSubtasksDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the clearSubtasks tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerClearSubtasksTool(server) {
	server.addTool({
		name: 'clear_subtasks',
		description: 'Clear subtasks from specified tasks',
		parameters: z
			.object({
				id: z
					.string()
					.optional()
					.describe('Task IDs (comma-separated) to clear subtasks from'),
				all: z.boolean().optional().describe('Clear subtasks from all tasks'),
				file: z
					.string()
					.optional()
					.describe(
						'Absolute path to the tasks file (default: tasks/tasks.json)'
					),
				projectRoot: z
					.string()
					.describe('The directory of the project. Must be an absolute path.'),
				tag: z.string().optional().describe('Tag context to operate on')
			})
			.refine((data) => data.id || data.all, {
				message: "Either 'id' or 'all' parameter must be provided",
				path: ['id', 'all']
			}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				log.info(`Clearing subtasks with args: ${JSON.stringify(args)}`);

				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});

				// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				const result = await clearSubtasksDirect(
					{
						tasksJsonPath: tasksJsonPath,
						id: args.id,
						all: args.all,

						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				if (result.success) {
					log.info(`Subtasks cleared successfully: ${result.data.message}`);
				} else {
					log.error(`Failed to clear subtasks: ${result.error.message}`);
				}

				return handleApiResult(
					result,
					log,
					'Error clearing subtasks',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in clearSubtasks tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/tests/unit/scripts/modules/utils-tag-aware-paths.test.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Test for getTagAwareFilePath utility function
 * Tests the fix for Issue #850
 */

import { getTagAwareFilePath } from '../../../../scripts/modules/utils.js';
import path from 'path';

describe('getTagAwareFilePath utility function', () => {
	const projectRoot = '/test/project';
	const basePath = '.taskmaster/reports/task-complexity-report.json';

	it('should return base path for master tag', () => {
		const result = getTagAwareFilePath(basePath, 'master', projectRoot);
		const expected = path.join(projectRoot, basePath);
		expect(result).toBe(expected);
	});

	it('should return base path for null tag', () => {
		const result = getTagAwareFilePath(basePath, null, projectRoot);
		const expected = path.join(projectRoot, basePath);
		expect(result).toBe(expected);
	});

	it('should return base path for undefined tag', () => {
		const result = getTagAwareFilePath(basePath, undefined, projectRoot);
		const expected = path.join(projectRoot, basePath);
		expect(result).toBe(expected);
	});

	it('should return tag-specific path for non-master tag', () => {
		const tag = 'feature-branch';
		const result = getTagAwareFilePath(basePath, tag, projectRoot);
		const expected = path.join(
			projectRoot,
			'.taskmaster/reports/task-complexity-report_feature-branch.json'
		);
		expect(result).toBe(expected);
	});

	it('should handle different file extensions', () => {
		const csvBasePath = '.taskmaster/reports/export.csv';
		const tag = 'dev-branch';
		const result = getTagAwareFilePath(csvBasePath, tag, projectRoot);
		const expected = path.join(
			projectRoot,
			'.taskmaster/reports/export_dev-branch.csv'
		);
		expect(result).toBe(expected);
	});

	it('should handle paths without extensions', () => {
		const noExtPath = '.taskmaster/reports/summary';
		const tag = 'test-tag';
		const result = getTagAwareFilePath(noExtPath, tag, projectRoot);
		// Since there's no extension, it should append the tag
		const expected = path.join(
			projectRoot,
			'.taskmaster/reports/summary_test-tag'
		);
		expect(result).toBe(expected);
	});

	it('should use default project root when not provided', () => {
		const tag = 'feature-tag';
		const result = getTagAwareFilePath(basePath, tag);
		const expected = path.join(
			'.',
			'.taskmaster/reports/task-complexity-report_feature-tag.json'
		);
		expect(result).toBe(expected);
	});

	it('should handle complex tag names with special characters', () => {
		const tag = 'feature-user-auth-v2';
		const result = getTagAwareFilePath(basePath, tag, projectRoot);
		const expected = path.join(
			projectRoot,
			'.taskmaster/reports/task-complexity-report_feature-user-auth-v2.json'
		);
		expect(result).toBe(expected);
	});
});

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/scope-down.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/scope-down.js
 * Tool to scope down task complexity
 */

import { z } from 'zod';
import {
	createErrorResponse,
	handleApiResult,
	withNormalizedProjectRoot
} from './utils.js';
import { scopeDownDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the scopeDown tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerScopeDownTool(server) {
	server.addTool({
		name: 'scope_down_task',
		description: 'Decrease the complexity of one or more tasks using AI',
		parameters: z.object({
			id: z
				.string()
				.describe(
					'Comma-separated list of task IDs to scope down (e.g., "1,3,5")'
				),
			strength: z
				.string()
				.optional()
				.describe(
					'Strength level: light, regular, or heavy (default: regular)'
				),
			prompt: z
				.string()
				.optional()
				.describe('Custom prompt for specific scoping adjustments'),
			file: z
				.string()
				.optional()
				.describe('Path to the tasks file (default: tasks/tasks.json)'),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on'),
			research: z
				.boolean()
				.optional()
				.describe('Whether to use research capabilities for scoping')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				log.info(`Starting scope-down with args: ${JSON.stringify(args)}`);

				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});

				// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				// Call the direct function
				const result = await scopeDownDirect(
					{
						tasksJsonPath: tasksJsonPath,
						id: args.id,
						strength: args.strength,
						prompt: args.prompt,
						research: args.research,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				return handleApiResult(
					result,
					log,
					'Error scoping down task',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in scope-down tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/execution/services/executor-service.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Service for managing task execution
 */

import { getLogger } from '../../../common/logger/index.js';
import type { Task } from '../../../common/types/index.js';
import { ExecutorFactory } from '../executors/executor-factory.js';
import type {
	ExecutionResult,
	ExecutorOptions,
	ExecutorType,
	ITaskExecutor
} from '../types.js';

export interface ExecutorServiceOptions {
	projectRoot: string;
	defaultExecutor?: ExecutorType;
	executorConfig?: Record<string, any>;
}

export class ExecutorService {
	private logger = getLogger('ExecutorService');
	private projectRoot: string;
	private defaultExecutor?: ExecutorType;
	private executorConfig: Record<string, any>;
	private currentExecutor?: ITaskExecutor;

	constructor(options: ExecutorServiceOptions) {
		this.projectRoot = options.projectRoot;
		this.defaultExecutor = options.defaultExecutor;
		this.executorConfig = options.executorConfig || {};
	}

	/**
	 * Execute a task
	 */
	async executeTask(
		task: Task,
		executorType?: ExecutorType
	): Promise<ExecutionResult> {
		try {
			// Determine executor type
			const type =
				executorType ||
				this.defaultExecutor ||
				(await ExecutorFactory.getDefaultExecutor(this.projectRoot));
			if (!type) {
				return {
					success: false,
					taskId: task.id,
					executorType: 'claude',
					error:
						'No executor available. Please install Claude CLI or specify an executor type.',
					startTime: new Date().toISOString()
				};
			}

			// Create executor
			const executorOptions: ExecutorOptions = {
				type,
				projectRoot: this.projectRoot,
				config: this.executorConfig
			};

			this.currentExecutor = ExecutorFactory.create(executorOptions);

			// Check if executor is available
			const isAvailable = await this.currentExecutor.isAvailable();
			if (!isAvailable) {
				return {
					success: false,
					taskId: task.id,
					executorType: type,
					error: `Executor ${type} is not available or not configured properly`,
					startTime: new Date().toISOString()
				};
			}

			// Execute the task
			this.logger.info(`Starting task ${task.id} with ${type} executor`);
			const result = await this.currentExecutor.execute(task);

			return result;
		} catch (error: any) {
			this.logger.error(`Failed to execute task ${task.id}:`, error);
			return {
				success: false,
				taskId: task.id,
				executorType: executorType || 'claude',
				error: error.message || 'Unknown error occurred',
				startTime: new Date().toISOString()
			};
		}
	}

	/**
	 * Stop the current task execution
	 */
	async stopCurrentTask(): Promise<void> {
		if (this.currentExecutor && this.currentExecutor.stop) {
			await this.currentExecutor.stop();
			this.currentExecutor = undefined;
		}
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/next-task.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/next-task.js
 * Tool to find the next task to work on based on dependencies and status
 */

import { z } from 'zod';
import {
	createErrorResponse,
	handleApiResult,
	withNormalizedProjectRoot
} from './utils.js';
import { nextTaskDirect } from '../core/task-master-core.js';
import {
	resolveTasksPath,
	resolveComplexityReportPath
} from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the nextTask tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerNextTaskTool(server) {
	server.addTool({
		name: 'next_task',
		description:
			'Find the next task to work on based on dependencies and status',
		parameters: z.object({
			file: z.string().optional().describe('Absolute path to the tasks file'),
			complexityReport: z
				.string()
				.optional()
				.describe(
					'Path to the complexity report file (relative to project root or absolute)'
				),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				log.info(`Finding next task with args: ${JSON.stringify(args)}`);
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});

				// Resolve the path to tasks.json using new path utilities
				let tasksJsonPath;
				try {
					tasksJsonPath = resolveTasksPath(args, session);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				// Resolve the path to complexity report (optional)
				let complexityReportPath;
				try {
					complexityReportPath = resolveComplexityReportPath(
						{ ...args, tag: resolvedTag },
						session
					);
				} catch (error) {
					log.error(`Error finding complexity report: ${error.message}`);
					// This is optional, so we don't fail the operation
					complexityReportPath = null;
				}

				const result = await nextTaskDirect(
					{
						tasksJsonPath: tasksJsonPath,
						reportPath: complexityReportPath,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				log.info(`Next task result: ${result.success ? 'found' : 'none'}`);
				return handleApiResult(
					result,
					log,
					'Error finding next task',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error finding next task: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/src/utils/asset-resolver.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Asset Resolver Module
 * Handles resolving paths to asset files in the package
 *
 * The public/assets folder is copied to dist/assets during build via tsup's publicDir,
 * so we can reliably find it relative to the bundled files.
 */
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

/**
 * Get the assets directory path
 * When bundled, assets are in dist/assets
 * When in development, assets are in public/assets
 * @returns {string} Path to the assets directory
 */
export function getAssetsDir() {
	// Check multiple possible locations
	const possiblePaths = [
		// When running from dist (bundled) - assets are in dist/assets
		path.join(__dirname, 'assets'),
		path.join(__dirname, '..', 'assets'),
		// When running from source in development - now in public/assets
		path.join(__dirname, '..', '..', 'public', 'assets'),
		// When installed as npm package - assets at package root
		path.join(process.cwd(), 'assets'),
		// For npx usage - check node_modules
		path.join(
			process.cwd(),
			'node_modules',
			'task-master-ai',
			'dist',
			'assets'
		),
		path.join(process.cwd(), 'node_modules', 'task-master-ai', 'assets')
	];

	// Find the first existing assets directory
	for (const assetPath of possiblePaths) {
		if (fs.existsSync(assetPath)) {
			// Verify it's actually the assets directory by checking for known files
			const testFile = path.join(assetPath, 'rules', 'taskmaster.mdc');
			if (fs.existsSync(testFile)) {
				return assetPath;
			}
		}
	}

	// If no assets directory found, throw an error
	throw new Error(
		'Assets directory not found. This is likely a packaging issue.'
	);
}

/**
 * Get path to a specific asset file
 * @param {string} relativePath - Path relative to assets directory
 * @returns {string} Full path to the asset file
 */
export function getAssetPath(relativePath) {
	const assetsDir = getAssetsDir();
	return path.join(assetsDir, relativePath);
}

/**
 * Check if an asset file exists
 * @param {string} relativePath - Path relative to assets directory
 * @returns {boolean} True if the asset exists
 */
export function assetExists(relativePath) {
	try {
		const assetPath = getAssetPath(relativePath);
		return fs.existsSync(assetPath);
	} catch (error) {
		return false;
	}
}

/**
 * Read an asset file
 * @param {string} relativePath - Path relative to assets directory
 * @param {string} encoding - File encoding (default: 'utf8')
 * @returns {string|Buffer} File contents
 */
export function readAsset(relativePath, encoding = 'utf8') {
	const assetPath = getAssetPath(relativePath);
	return fs.readFileSync(assetPath, encoding);
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/move-task.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Direct function wrapper for moveTask
 */

import { moveTask } from '../../../../scripts/modules/task-manager.js';
import { findTasksPath } from '../utils/path-utils.js';
import {
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';

/**
 * Move a task or subtask to a new position
 * @param {Object} args - Function arguments
 * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file
 * @param {string} args.sourceId - ID of the task/subtask to move (e.g., '5' or '5.2' or '5,6,7')
 * @param {string} args.destinationId - ID of the destination (e.g., '7' or '7.3' or '7,8,9')
 * @param {string} args.file - Alternative path to the tasks.json file
 * @param {string} args.projectRoot - Project root directory
 * @param {string} args.tag - Tag for the task (optional)
 * @param {boolean} args.generateFiles - Whether to regenerate task files after moving (default: true)
 * @param {Object} log - Logger object
 * @returns {Promise<{success: boolean, data?: Object, error?: Object}>}
 */
export async function moveTaskDirect(args, log, context = {}) {
	const { session } = context;
	const { projectRoot, tag } = args;

	// Validate required parameters
	if (!args.sourceId) {
		return {
			success: false,
			error: {
				message: 'Source ID is required',
				code: 'MISSING_SOURCE_ID'
			}
		};
	}

	if (!args.destinationId) {
		return {
			success: false,
			error: {
				message: 'Destination ID is required',
				code: 'MISSING_DESTINATION_ID'
			}
		};
	}

	try {
		// Find tasks.json path if not provided
		let tasksPath = args.tasksJsonPath || args.file;
		if (!tasksPath) {
			if (!args.projectRoot) {
				return {
					success: false,
					error: {
						message:
							'Project root is required if tasksJsonPath is not provided',
						code: 'MISSING_PROJECT_ROOT'
					}
				};
			}
			tasksPath = findTasksPath(args, log);
		}

		// Enable silent mode to prevent console output during MCP operation
		enableSilentMode();

		// Call the core moveTask function with file generation control
		const generateFiles = args.generateFiles !== false; // Default to true
		const result = await moveTask(
			tasksPath,
			args.sourceId,
			args.destinationId,
			generateFiles,
			{
				projectRoot,
				tag
			}
		);

		// Restore console output
		disableSilentMode();

		return {
			success: true,
			data: {
				...result,
				message: `Successfully moved task/subtask ${args.sourceId} to ${args.destinationId}`
			}
		};
	} catch (error) {
		// Restore console output in case of error
		disableSilentMode();

		log.error(`Failed to move task: ${error.message}`);

		return {
			success: false,
			error: {
				message: error.message,
				code: 'MOVE_TASK_ERROR'
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/.github/workflows/claude-dedupe-issues.yml:
--------------------------------------------------------------------------------

```yaml
name: Claude Issue Dedupe
# description: Automatically dedupe GitHub issues using Claude Code

on:
  issues:
    types: [opened]
  workflow_dispatch:
    inputs:
      issue_number:
        description: "Issue number to process for duplicate detection"
        required: true
        type: string

jobs:
  claude-dedupe-issues:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read
      issues: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Run Claude Code slash command
        uses: anthropics/claude-code-base-action@beta
        with:
          prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          claude_env: |
            GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Log duplicate comment event to Statsig
        if: always()
        env:
          STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
        run: |
          ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}
          REPO=${{ github.repository }}

          if [ -z "$STATSIG_API_KEY" ]; then
            echo "STATSIG_API_KEY not found, skipping Statsig logging"
            exit 0
          fi

          # Prepare the event payload
          EVENT_PAYLOAD=$(jq -n \
            --arg issue_number "$ISSUE_NUMBER" \
            --arg repo "$REPO" \
            --arg triggered_by "${{ github.event_name }}" \
            '{
              events: [{
                eventName: "github_duplicate_comment_added",
                value: 1,
                metadata: {
                  repository: $repo,
                  issue_number: ($issue_number | tonumber),
                  triggered_by: $triggered_by,
                  workflow_run_id: "${{ github.run_id }}"
                },
                time: (now | floor | tostring)
              }]
            }')

          # Send to Statsig API
          echo "Logging duplicate comment event to Statsig for issue #${ISSUE_NUMBER}"

          RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
            -H "Content-Type: application/json" \
            -H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
            -d "$EVENT_PAYLOAD")

          HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
          BODY=$(echo "$RESPONSE" | head -n-1)

          if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
            echo "Successfully logged duplicate comment event for issue #${ISSUE_NUMBER}"
          else
            echo "Failed to log duplicate comment event for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
          fi

```

--------------------------------------------------------------------------------
/tests/unit/ai-providers/mcp-components.test.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tests/unit/ai-providers/mcp-components.test.js
 * Unit tests for MCP AI SDK custom components
 */

import { jest } from '@jest/globals';

describe('MCP Custom SDK Components', () => {
	describe('Message Converter', () => {
		let messageConverter;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/message-converter.js'
			);
			messageConverter = module;
		});

		describe('convertToMCPFormat', () => {
			it('should convert AI SDK messages to MCP format', () => {
				const input = [
					{ role: 'system', content: 'You are a helpful assistant.' },
					{ role: 'user', content: 'Hello!' }
				];

				const result = messageConverter.convertToMCPFormat(input);

				expect(result).toBeDefined();
				expect(result.messages).toBeDefined();
				expect(Array.isArray(result.messages)).toBe(true);
				expect(result.systemPrompt).toBe('You are a helpful assistant.');
				expect(result.messages).toHaveLength(1);
				expect(result.messages[0].role).toBe('user');
				expect(result.messages[0].content.text).toBe('Hello!');
			});
		});

		describe('convertFromMCPFormat', () => {
			it('should convert MCP response to AI SDK format', () => {
				const input = {
					content: 'Hello! How can I help you?',
					usage: { inputTokens: 10, outputTokens: 8 }
				};

				const result = messageConverter.convertFromMCPFormat(input);

				expect(result).toBeDefined();
				expect(result.text).toBe('Hello! How can I help you?');
				expect(result.usage).toEqual({ inputTokens: 10, outputTokens: 8 });
				expect(result.finishReason).toBe('stop');
				expect(result.warnings).toBeDefined();
			});
		});
	});

	describe('Language Model', () => {
		let languageModel;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/language-model.js'
			);
			languageModel = module;
		});

		it('should export MCPLanguageModel class', () => {
			expect(languageModel.MCPLanguageModel).toBeDefined();
			expect(typeof languageModel.MCPLanguageModel).toBe('function');
		});
	});

	describe('Error Handling', () => {
		let errors;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/errors.js'
			);
			errors = module;
		});

		it('should export error classes', () => {
			expect(errors.MCPError).toBeDefined();
			expect(typeof errors.MCPError).toBe('function');
		});
	});

	describe('Index Module', () => {
		let index;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/index.js'
			);
			index = module;
		});

		it('should export createMCP function', () => {
			expect(index.createMCP).toBeDefined();
			expect(typeof index.createMCP).toBe('function');
		});
	});
});

```

--------------------------------------------------------------------------------
/tests/unit/mcp-providers/mcp-components.test.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tests/unit/mcp-providers/mcp-components.test.js
 * Unit tests for MCP AI SDK custom components
 */

import { jest } from '@jest/globals';

describe('MCP Custom SDK Components', () => {
	describe('Message Converter', () => {
		let messageConverter;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/message-converter.js'
			);
			messageConverter = module;
		});

		describe('convertToMCPFormat', () => {
			it('should convert AI SDK messages to MCP format', () => {
				const input = [
					{ role: 'system', content: 'You are a helpful assistant.' },
					{ role: 'user', content: 'Hello!' }
				];

				const result = messageConverter.convertToMCPFormat(input);

				expect(result).toBeDefined();
				expect(result.messages).toBeDefined();
				expect(Array.isArray(result.messages)).toBe(true);
				expect(result.systemPrompt).toBe('You are a helpful assistant.');
				expect(result.messages).toHaveLength(1);
				expect(result.messages[0].role).toBe('user');
				expect(result.messages[0].content.text).toBe('Hello!');
			});
		});

		describe('convertFromMCPFormat', () => {
			it('should convert MCP response to AI SDK format', () => {
				const input = {
					content: 'Hello! How can I help you?',
					usage: { inputTokens: 10, outputTokens: 8 }
				};

				const result = messageConverter.convertFromMCPFormat(input);

				expect(result).toBeDefined();
				expect(result.text).toBe('Hello! How can I help you?');
				expect(result.usage).toEqual({ inputTokens: 10, outputTokens: 8 });
				expect(result.finishReason).toBe('stop');
				expect(result.warnings).toBeDefined();
			});
		});
	});

	describe('Language Model', () => {
		let languageModel;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/language-model.js'
			);
			languageModel = module;
		});

		it('should export MCPLanguageModel class', () => {
			expect(languageModel.MCPLanguageModel).toBeDefined();
			expect(typeof languageModel.MCPLanguageModel).toBe('function');
		});
	});

	describe('Error Handling', () => {
		let errors;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/errors.js'
			);
			errors = module;
		});

		it('should export error classes', () => {
			expect(errors.MCPError).toBeDefined();
			expect(typeof errors.MCPError).toBe('function');
		});
	});

	describe('Index Module', () => {
		let index;

		beforeAll(async () => {
			const module = await import(
				'../../../mcp-server/src/custom-sdk/index.js'
			);
			index = module;
		});

		it('should export createMCP function', () => {
			expect(index.createMCP).toBeDefined();
			expect(typeof index.createMCP).toBe('function');
		});
	});
});

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/remove-subtask.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/remove-subtask.js
 * Tool for removing subtasks from parent tasks
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { removeSubtaskDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the removeSubtask tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerRemoveSubtaskTool(server) {
	server.addTool({
		name: 'remove_subtask',
		description: 'Remove a subtask from its parent task',
		parameters: z.object({
			id: z
				.string()
				.describe(
					"Subtask ID to remove in format 'parentId.subtaskId' (required)"
				),
			convert: z
				.boolean()
				.optional()
				.describe(
					'Convert the subtask to a standalone task instead of deleting it'
				),
			file: z
				.string()
				.optional()
				.describe(
					'Absolute path to the tasks file (default: tasks/tasks.json)'
				),
			skipGenerate: z
				.boolean()
				.optional()
				.describe('Skip regenerating task files'),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});
				log.info(`Removing subtask with args: ${JSON.stringify(args)}`);

				// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				const result = await removeSubtaskDirect(
					{
						tasksJsonPath: tasksJsonPath,
						id: args.id,
						convert: args.convert,
						skipGenerate: args.skipGenerate,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				if (result.success) {
					log.info(`Subtask removed successfully: ${result.data.message}`);
				} else {
					log.error(`Failed to remove subtask: ${result.error.message}`);
				}

				return handleApiResult(
					result,
					log,
					'Error removing subtask',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in removeSubtask tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/packages/ai-sdk-provider-grok-cli/src/json-extractor.test.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Tests for JSON extraction utilities
 */

import { describe, expect, it } from 'vitest';
import { extractJson } from './json-extractor.js';

describe('extractJson', () => {
	it('should extract JSON from markdown code blocks', () => {
		const text = '```json\n{"name": "test", "value": 42}\n```';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should extract JSON from generic code blocks', () => {
		const text = '```\n{"name": "test", "value": 42}\n```';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should remove JavaScript variable declarations', () => {
		const text = 'const result = {"name": "test", "value": 42};';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should handle let variable declarations', () => {
		const text = 'let data = {"name": "test", "value": 42};';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should handle var variable declarations', () => {
		const text = 'var config = {"name": "test", "value": 42};';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should extract JSON arrays', () => {
		const text = '[{"name": "test1"}, {"name": "test2"}]';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual([{ name: 'test1' }, { name: 'test2' }]);
	});

	it('should convert JavaScript object literals to JSON', () => {
		const text = "{name: 'test', value: 42}";
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should return valid JSON (canonical formatting)', () => {
		const text = '{"name": "test", "value": 42}';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 42 });
	});

	it('should return original text when JSON parsing fails completely', () => {
		const text = 'This is not JSON at all';
		const result = extractJson(text);
		expect(result).toBe('This is not JSON at all');
	});

	it('should handle complex nested objects', () => {
		const text =
			'```json\n{\n  "user": {\n    "name": "John",\n    "age": 30\n  },\n  "items": [1, 2, 3]\n}\n```';
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({
			user: {
				name: 'John',
				age: 30
			},
			items: [1, 2, 3]
		});
	});

	it('should handle mixed quotes in object literals', () => {
		const text = `{name: "test", value: 'mixed quotes'}`;
		const result = extractJson(text);
		expect(JSON.parse(result)).toEqual({ name: 'test', value: 'mixed quotes' });
	});
});

```

--------------------------------------------------------------------------------
/packages/claude-code-plugin/commands/analyze-complexity.md:
--------------------------------------------------------------------------------

```markdown
Analyze task complexity and generate expansion recommendations.

Arguments: $ARGUMENTS

Perform deep analysis of task complexity across the project.

## Complexity Analysis

Uses AI to analyze tasks and recommend which ones need breakdown.

## Execution Options

```bash
task-master analyze-complexity [--research] [--threshold=5]
```

## Analysis Parameters

- `--research` → Use research AI for deeper analysis
- `--threshold=5` → Only flag tasks above complexity 5
- Default: Analyze all pending tasks

## Analysis Process

### 1. **Task Evaluation**
For each task, AI evaluates:
- Technical complexity
- Time requirements
- Dependency complexity
- Risk factors
- Knowledge requirements

### 2. **Complexity Scoring**
Assigns score 1-10 based on:
- Implementation difficulty
- Integration challenges
- Testing requirements
- Unknown factors
- Technical debt risk

### 3. **Recommendations**
For complex tasks:
- Suggest expansion approach
- Recommend subtask breakdown
- Identify risk areas
- Propose mitigation strategies

## Smart Analysis Features

1. **Pattern Recognition**
   - Similar task comparisons
   - Historical complexity accuracy
   - Team velocity consideration
   - Technology stack factors

2. **Contextual Factors**
   - Team expertise
   - Available resources
   - Timeline constraints
   - Business criticality

3. **Risk Assessment**
   - Technical risks
   - Timeline risks
   - Dependency risks
   - Knowledge gaps

## Output Format

```
Task Complexity Analysis Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

High Complexity Tasks (>7):
📍 #5 "Implement real-time sync" - Score: 9/10
   Factors: WebSocket complexity, state management, conflict resolution
   Recommendation: Expand into 5-7 subtasks
   Risks: Performance, data consistency

📍 #12 "Migrate database schema" - Score: 8/10
   Factors: Data migration, zero downtime, rollback strategy
   Recommendation: Expand into 4-5 subtasks
   Risks: Data loss, downtime

Medium Complexity Tasks (5-7):
📍 #23 "Add export functionality" - Score: 6/10
   Consider expansion if timeline tight

Low Complexity Tasks (<5):
✅ 15 tasks - No expansion needed

Summary:
- Expand immediately: 2 tasks
- Consider expanding: 5 tasks
- Keep as-is: 15 tasks
```

## Actionable Output

For each high-complexity task:
1. Complexity score with reasoning
2. Specific expansion suggestions
3. Risk mitigation approaches
4. Recommended subtask structure

## Integration

Results are:
- Saved to `.taskmaster/reports/complexity-analysis.md`
- Used by expand command
- Inform sprint planning
- Guide resource allocation

## Next Steps

After analysis:
```
/taskmaster:expand 5    # Expand specific task
/taskmaster:expand-all  # Expand all recommended
/taskmaster:complexity-report  # View detailed report
```
```

--------------------------------------------------------------------------------
/apps/docs/configuration.mdx:
--------------------------------------------------------------------------------

```markdown
---
title: "Configuration"
description: "Configure Task Master through environment variables in a .env file"
---

## Required Configuration

<Note>
  Task Master requires an Anthropic API key to function. Add this to your `.env` file:

  ```bash
  ANTHROPIC_API_KEY=sk-ant-api03-your-api-key
  ```

  You can obtain an API key from the [Anthropic Console](https://console.anthropic.com/).
</Note>

## Optional Configuration

| Variable | Default Value | Description | Example |
| --- | --- | --- | --- |
| `MODEL` | `"claude-3-7-sonnet-20250219"` | Claude model to use | `MODEL=claude-3-opus-20240229` |
| `MAX_TOKENS` | `"4000"` | Maximum tokens for responses | `MAX_TOKENS=8000` |
| `TEMPERATURE` | `"0.7"` | Temperature for model responses | `TEMPERATURE=0.5` |
| `DEBUG` | `"false"` | Enable debug logging | `DEBUG=true` |
| `LOG_LEVEL` | `"info"` | Console output level | `LOG_LEVEL=debug` |
| `DEFAULT_SUBTASKS` | `"3"` | Default subtask count | `DEFAULT_SUBTASKS=5` |
| `DEFAULT_PRIORITY` | `"medium"` | Default priority | `DEFAULT_PRIORITY=high` |
| `PROJECT_NAME` | `"MCP SaaS MVP"` | Project name in metadata | `PROJECT_NAME=My Awesome Project` |
| `PROJECT_VERSION` | `"1.0.0"` | Version in metadata | `PROJECT_VERSION=2.1.0` |
| `PERPLEXITY_API_KEY` | - | For research-backed features | `PERPLEXITY_API_KEY=pplx-...` |
| `PERPLEXITY_MODEL` | `"sonar-medium-online"` | Perplexity model | `PERPLEXITY_MODEL=sonar-large-online` |

## TDD Workflow Configuration

Additional options for autonomous TDD workflow:

| Variable | Default | Description |
| --- | --- | --- |
| `TM_MAX_ATTEMPTS` | `3` | Max attempts per subtask before marking blocked |
| `TM_AUTO_COMMIT` | `true` | Auto-commit after GREEN phase |
| `TM_PROJECT_ROOT` | Current dir | Default project root |

## Example .env File

```
# Required
ANTHROPIC_API_KEY=sk-ant-api03-your-api-key

# Optional - Claude Configuration
MODEL=claude-3-7-sonnet-20250219
MAX_TOKENS=4000
TEMPERATURE=0.7

# Optional - Perplexity API for Research
PERPLEXITY_API_KEY=pplx-your-api-key
PERPLEXITY_MODEL=sonar-medium-online

# Optional - Project Info
PROJECT_NAME=My Project
PROJECT_VERSION=1.0.0

# Optional - Application Configuration
DEFAULT_SUBTASKS=3
DEFAULT_PRIORITY=medium
DEBUG=false
LOG_LEVEL=info

# TDD Workflow
TM_MAX_ATTEMPTS=3
TM_AUTO_COMMIT=true
```

## Troubleshooting

### If `task-master init` doesn't respond:

Try running it with Node directly:

```bash
node node_modules/claude-task-master/scripts/init.js
```

Or clone the repository and run:

```bash
git clone https://github.com/eyaltoledano/claude-task-master.git
cd claude-task-master
node scripts/init.js
```

<Note>
For advanced configuration options and detailed customization, see our [Advanced Configuration Guide] page.
</Note>

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/config/services/config-merger.service.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Configuration Merger Service
 * Responsible for merging configurations from multiple sources with precedence
 */

import type { PartialConfiguration } from '../../../common/interfaces/configuration.interface.js';

/**
 * Configuration source with precedence
 */
export interface ConfigSource {
	/** Source name for debugging */
	name: string;
	/** Configuration data from this source */
	config: PartialConfiguration;
	/** Precedence level (higher = more important) */
	precedence: number;
}

/**
 * Configuration precedence levels (higher number = higher priority)
 */
export const CONFIG_PRECEDENCE = {
	DEFAULTS: 0,
	GLOBAL: 1, // Reserved for future implementation
	LOCAL: 2,
	ENVIRONMENT: 3
} as const;

/**
 * ConfigMerger handles merging configurations with precedence rules
 * Single responsibility: Configuration merging logic
 */
export class ConfigMerger {
	private configSources: ConfigSource[] = [];

	/**
	 * Add a configuration source
	 */
	addSource(source: ConfigSource): void {
		this.configSources.push(source);
	}

	/**
	 * Clear all configuration sources
	 */
	clearSources(): void {
		this.configSources = [];
	}

	/**
	 * Merge all configuration sources based on precedence
	 */
	merge(): PartialConfiguration {
		// Sort sources by precedence (lowest first)
		const sortedSources = [...this.configSources].sort(
			(a, b) => a.precedence - b.precedence
		);

		// Merge from lowest to highest precedence
		let merged: PartialConfiguration = {};
		for (const source of sortedSources) {
			merged = this.deepMerge(merged, source.config);
		}

		return merged;
	}

	/**
	 * Deep merge two configuration objects
	 * Higher precedence values override lower ones
	 */
	private deepMerge(target: any, source: any): any {
		if (!source) return target;
		if (!target) return source;

		const result = { ...target };

		for (const key in source) {
			if (source[key] === null || source[key] === undefined) {
				continue;
			}

			if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
				result[key] = this.deepMerge(result[key] || {}, source[key]);
			} else {
				result[key] = source[key];
			}
		}

		return result;
	}

	/**
	 * Get configuration sources for debugging
	 */
	getSources(): ConfigSource[] {
		return [...this.configSources].sort((a, b) => b.precedence - a.precedence);
	}

	/**
	 * Check if a source exists
	 */
	hasSource(name: string): boolean {
		return this.configSources.some((source) => source.name === name);
	}

	/**
	 * Remove a source by name
	 */
	removeSource(name: string): boolean {
		const initialLength = this.configSources.length;
		this.configSources = this.configSources.filter(
			(source) => source.name !== name
		);
		return this.configSources.length < initialLength;
	}
}

```

--------------------------------------------------------------------------------
/tests/unit/profiles/cline-integration.test.js:
--------------------------------------------------------------------------------

```javascript
import { jest } from '@jest/globals';
import fs from 'fs';
import path from 'path';
import os from 'os';

// Mock external modules
jest.mock('child_process', () => ({
	execSync: jest.fn()
}));

// Mock console methods
jest.mock('console', () => ({
	log: jest.fn(),
	info: jest.fn(),
	warn: jest.fn(),
	error: jest.fn(),
	clear: jest.fn()
}));

describe('Cline Integration', () => {
	let tempDir;

	beforeEach(() => {
		jest.clearAllMocks();

		// Create a temporary directory for testing
		tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-'));

		// Spy on fs methods
		jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
		jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => {
			if (filePath.toString().includes('.clinerules')) {
				return 'Existing cline rules content';
			}
			return '{}';
		});
		jest.spyOn(fs, 'existsSync').mockImplementation(() => false);
		jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {});
	});

	afterEach(() => {
		// Clean up the temporary directory
		try {
			fs.rmSync(tempDir, { recursive: true, force: true });
		} catch (err) {
			console.error(`Error cleaning up: ${err.message}`);
		}
	});

	// Test function that simulates the createProjectStructure behavior for Cline files
	function mockCreateClineStructure() {
		// Create main .clinerules directory
		fs.mkdirSync(path.join(tempDir, '.clinerules'), { recursive: true });

		// Create rule files
		const ruleFiles = [
			'dev_workflow.md',
			'taskmaster.md',
			'architecture.md',
			'commands.md',
			'dependencies.md'
		];

		for (const ruleFile of ruleFiles) {
			fs.writeFileSync(
				path.join(tempDir, '.clinerules', ruleFile),
				`Content for ${ruleFile}`
			);
		}
	}

	test('creates all required .clinerules directories', () => {
		// Act
		mockCreateClineStructure();

		// Assert
		expect(fs.mkdirSync).toHaveBeenCalledWith(
			path.join(tempDir, '.clinerules'),
			{ recursive: true }
		);
	});

	test('creates rule files for Cline', () => {
		// Act
		mockCreateClineStructure();

		// Assert - check rule files are created
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.clinerules', 'dev_workflow.md'),
			expect.any(String)
		);
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.clinerules', 'taskmaster.md'),
			expect.any(String)
		);
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.clinerules', 'architecture.md'),
			expect.any(String)
		);
	});

	test('does not create MCP configuration files', () => {
		// Act
		mockCreateClineStructure();

		// Assert - Cline doesn't use MCP configuration
		expect(fs.writeFileSync).not.toHaveBeenCalledWith(
			path.join(tempDir, '.clinerules', 'mcp.json'),
			expect.any(String)
		);
	});
});

```

--------------------------------------------------------------------------------
/apps/cli/src/commands/models/types.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Type definitions for model setup functionality
 */

/**
 * Represents a model role in the system
 */
export type ModelRole = 'main' | 'research' | 'fallback';

/**
 * Custom provider option identifiers
 */
export const CUSTOM_PROVIDER_IDS = {
	OPENROUTER: '__CUSTOM_OPENROUTER__',
	OLLAMA: '__CUSTOM_OLLAMA__',
	BEDROCK: '__CUSTOM_BEDROCK__',
	AZURE: '__CUSTOM_AZURE__',
	VERTEX: '__CUSTOM_VERTEX__',
	LMSTUDIO: '__CUSTOM_LMSTUDIO__',
	OPENAI_COMPATIBLE: '__CUSTOM_OPENAI_COMPATIBLE__'
} as const;

export type CustomProviderId =
	(typeof CUSTOM_PROVIDER_IDS)[keyof typeof CUSTOM_PROVIDER_IDS];

/**
 * Special control values for model selection
 */
export const CONTROL_VALUES = {
	CANCEL: '__CANCEL__',
	NO_CHANGE: '__NO_CHANGE__'
} as const;

/**
 * Model information for display
 */
export interface ModelInfo {
	id: string;
	name?: string;
	provider: string;
	cost_per_1m_tokens?: {
		input: number;
		output: number;
	};
	allowed_roles: ModelRole[];
}

/**
 * Currently configured model for a role
 */
export interface CurrentModel {
	modelId?: string;
	provider?: string;
	baseURL?: string;
}

/**
 * Current models configuration
 */
export interface CurrentModels {
	main: CurrentModel | null;
	research: CurrentModel | null;
	fallback: CurrentModel | null;
}

/**
 * Model selection choice for inquirer prompts
 */
export interface ModelChoice {
	name: string;
	value: { id: string; provider: string } | CustomProviderId | string | null;
	short?: string;
	type?: 'separator';
}

/**
 * Prompt data for a specific role
 */
export interface PromptData {
	choices: (ModelChoice | any)[]; // any to accommodate Separator instances
	default: number;
}

/**
 * Result from model fetcher functions
 */
export interface FetchResult<T> {
	success: boolean;
	data?: T;
	error?: string;
}

/**
 * OpenRouter model response
 */
export interface OpenRouterModel {
	id: string;
	name?: string;
	description?: string;
}

/**
 * Ollama model response
 */
export interface OllamaModel {
	model: string;
	name: string;
	modified_at?: string;
}

/**
 * Custom provider handler configuration
 */
export interface CustomProviderConfig {
	id: CustomProviderId;
	name: string;
	provider: string;
	promptMessage: (role: ModelRole) => string;
	validate?: (modelId: string, baseURL?: string) => Promise<boolean>;
	checkEnvVars?: () => boolean;
	fetchModels?: () => Promise<FetchResult<unknown[]>>;
	requiresBaseURL?: boolean;
	defaultBaseURL?: string;
}

/**
 * Model setup options
 */
export interface ModelSetupOptions {
	projectRoot: string;
	providerHint?: string;
}

/**
 * Model set result
 */
export interface ModelSetResult {
	success: boolean;
	data?: {
		message: string;
		provider: string;
		modelId: string;
		warning?: string;
	};
	error?: {
		message: string;
	};
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/__tests__/context-manager.test.js:
--------------------------------------------------------------------------------

```javascript
import { jest } from '@jest/globals';
import { ContextManager } from '../context-manager.js';

describe('ContextManager', () => {
	let contextManager;

	beforeEach(() => {
		contextManager = new ContextManager({
			maxCacheSize: 10,
			ttl: 1000, // 1 second for testing
			maxContextSize: 1000
		});
	});

	describe('getContext', () => {
		it('should create a new context when not in cache', async () => {
			const context = await contextManager.getContext('test-id', {
				test: true
			});
			expect(context.id).toBe('test-id');
			expect(context.metadata.test).toBe(true);
			expect(contextManager.stats.misses).toBe(1);
			expect(contextManager.stats.hits).toBe(0);
		});

		it('should return cached context when available', async () => {
			// First call creates the context
			await contextManager.getContext('test-id', { test: true });

			// Second call should hit cache
			const context = await contextManager.getContext('test-id', {
				test: true
			});
			expect(context.id).toBe('test-id');
			expect(context.metadata.test).toBe(true);
			expect(contextManager.stats.hits).toBe(1);
			expect(contextManager.stats.misses).toBe(1);
		});

		it('should respect TTL settings', async () => {
			// Create context
			await contextManager.getContext('test-id', { test: true });

			// Wait for TTL to expire
			await new Promise((resolve) => setTimeout(resolve, 1100));

			// Should create new context
			await contextManager.getContext('test-id', { test: true });
			expect(contextManager.stats.misses).toBe(2);
			expect(contextManager.stats.hits).toBe(0);
		});
	});

	describe('updateContext', () => {
		it('should update existing context metadata', async () => {
			await contextManager.getContext('test-id', { initial: true });
			const updated = await contextManager.updateContext('test-id', {
				updated: true
			});

			expect(updated.metadata.initial).toBe(true);
			expect(updated.metadata.updated).toBe(true);
		});
	});

	describe('invalidateContext', () => {
		it('should remove context from cache', async () => {
			await contextManager.getContext('test-id', { test: true });
			contextManager.invalidateContext('test-id', { test: true });

			// Should be a cache miss
			await contextManager.getContext('test-id', { test: true });
			expect(contextManager.stats.invalidations).toBe(1);
			expect(contextManager.stats.misses).toBe(2);
		});
	});

	describe('getStats', () => {
		it('should return current cache statistics', async () => {
			await contextManager.getContext('test-id', { test: true });
			const stats = contextManager.getStats();

			expect(stats.hits).toBe(0);
			expect(stats.misses).toBe(1);
			expect(stats.invalidations).toBe(0);
			expect(stats.size).toBe(1);
			expect(stats.maxSize).toBe(10);
			expect(stats.ttl).toBe(1000);
		});
	});
});

```

--------------------------------------------------------------------------------
/packages/ai-sdk-provider-grok-cli/src/grok-cli-provider.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Grok CLI provider implementation for AI SDK v5
 */

import type { LanguageModelV2, ProviderV2 } from '@ai-sdk/provider';
import { NoSuchModelError } from '@ai-sdk/provider';
import { GrokCliLanguageModel } from './grok-cli-language-model.js';
import type { GrokCliModelId, GrokCliSettings } from './types.js';

/**
 * Grok CLI provider interface that extends the AI SDK's ProviderV2
 */
export interface GrokCliProvider extends ProviderV2 {
	/**
	 * Creates a language model instance for the specified model ID.
	 * This is a shorthand for calling `languageModel()`.
	 */
	(modelId: GrokCliModelId, settings?: GrokCliSettings): LanguageModelV2;

	/**
	 * Creates a language model instance for text generation.
	 */
	languageModel(
		modelId: GrokCliModelId,
		settings?: GrokCliSettings
	): LanguageModelV2;

	/**
	 * Alias for `languageModel()` to maintain compatibility with AI SDK patterns.
	 */
	chat(modelId: GrokCliModelId, settings?: GrokCliSettings): LanguageModelV2;

	textEmbeddingModel(modelId: string): never;
	imageModel(modelId: string): never;
}

/**
 * Configuration options for creating a Grok CLI provider instance
 */
export interface GrokCliProviderSettings {
	/**
	 * Default settings to use for all models created by this provider.
	 * Individual model settings will override these defaults.
	 */
	defaultSettings?: GrokCliSettings;
}

/**
 * Creates a Grok CLI provider instance with the specified configuration.
 * The provider can be used to create language models for interacting with Grok models.
 */
export function createGrokCli(
	options: GrokCliProviderSettings = {}
): GrokCliProvider {
	const createModel = (
		modelId: GrokCliModelId,
		settings: GrokCliSettings = {}
	): LanguageModelV2 => {
		const mergedSettings = {
			...options.defaultSettings,
			...settings
		};

		return new GrokCliLanguageModel({
			id: modelId,
			settings: mergedSettings
		});
	};

	const provider = function (
		modelId: GrokCliModelId,
		settings?: GrokCliSettings
	) {
		if (new.target) {
			throw new Error(
				'The Grok CLI model function cannot be called with the new keyword.'
			);
		}

		return createModel(modelId, settings);
	};

	provider.languageModel = createModel;
	provider.chat = createModel; // Alias for languageModel

	// Add textEmbeddingModel method that throws NoSuchModelError
	provider.textEmbeddingModel = (modelId: string) => {
		throw new NoSuchModelError({
			modelId,
			modelType: 'textEmbeddingModel'
		});
	};

	provider.imageModel = (modelId: string) => {
		throw new NoSuchModelError({
			modelId,
			modelType: 'imageModel'
		});
	};

	return provider as GrokCliProvider;
}

/**
 * Default Grok CLI provider instance.
 * Pre-configured provider for quick usage without custom settings.
 */
export const grokCli = createGrokCli();

```

--------------------------------------------------------------------------------
/packages/tm-core/src/common/utils/path-normalizer.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Path normalization utilities for global storage system.
 * Converts project paths to storage-safe directory names using base64url encoding.
 *
 * This provides a bijective (one-to-one) mapping that preserves all characters
 * and supports perfect round-trip conversion between paths and storage names.
 *
 * @module path-normalizer
 */

/**
 * Normalizes a project path to a storage-safe directory name using base64url encoding.
 * This encoding is filesystem-safe (no slashes, backslashes, or special characters)
 * and fully reversible, preserving hyphens and all other characters in paths.
 *
 * @param {string} projectPath - The project path to normalize
 * @returns {string} The base64url-encoded path safe for use as a directory name
 *
 * @example
 * normalizeProjectPath('/Users/test/project') // returns base64url encoded string
 * normalizeProjectPath('C:\\Users\\test') // returns base64url encoded string
 * normalizeProjectPath('/projects/my-app') // returns base64url encoded string (hyphens preserved)
 */
export function normalizeProjectPath(projectPath: string): string {
	if (!projectPath) {
		return '';
	}

	// Use base64url encoding: filesystem-safe and fully reversible
	return Buffer.from(projectPath, 'utf-8').toString('base64url');
}

/**
 * Denormalizes a storage directory name back to the original path.
 * Decodes base64url-encoded paths with perfect fidelity.
 *
 * @param {string} normalizedPath - The base64url-encoded path to decode
 * @returns {string} The original path with all characters preserved
 *
 * @example
 * denormalizeProjectPath(normalizeProjectPath('/Users/test/project')) // returns '/Users/test/project'
 * denormalizeProjectPath(normalizeProjectPath('/projects/my-app')) // returns '/projects/my-app'
 */
export function denormalizeProjectPath(normalizedPath: string): string {
	if (!normalizedPath) {
		return '';
	}

	// Validate that input is valid base64url before attempting to decode
	if (!isValidNormalizedPath(normalizedPath)) {
		// Return original string for backward compatibility with non-base64url inputs
		return normalizedPath;
	}

	return Buffer.from(normalizedPath, 'base64url').toString('utf-8');
}

/**
 * Validates whether a path is in normalized (base64url) format.
 * Valid base64url strings contain only: A-Z, a-z, 0-9, -, _
 *
 * @param {string} path - The path to validate
 * @returns {boolean} True if the path is in normalized base64url format
 *
 * @example
 * isValidNormalizedPath('VXNlcnMvdGVzdC9wcm9qZWN0') // returns true (valid base64url)
 * isValidNormalizedPath('Users/test/project') // returns false (contains slashes)
 */
export function isValidNormalizedPath(path: string): boolean {
	if (path === '') {
		return true;
	}

	// Check if path is valid base64url: only A-Z, a-z, 0-9, -, _
	return /^[A-Za-z0-9_-]*$/.test(path);
}

```

--------------------------------------------------------------------------------
/CLAUDE_CODE_PLUGIN.md:
--------------------------------------------------------------------------------

```markdown
# Taskmaster AI - Claude Code Marketplace

This repository includes a Claude Code plugin marketplace in `.claude-plugin/marketplace.json`.

## Installation

### From GitHub (Public Repository)

Once this repository is pushed to GitHub, users can install with:

```bash
# Add the marketplace
/plugin marketplace add eyaltoledano/claude-task-master

# Install the plugin
/plugin install taskmaster@taskmaster
```

### Local Development/Testing

```bash
# From the project root directory
cd /path/to/claude-task-master

# Build the plugin first
cd packages/claude-code-plugin
npm run build
cd ../..

# In Claude Code
/plugin marketplace add .
/plugin install taskmaster@taskmaster
```

## Marketplace Structure

```
claude-task-master/
├── .claude-plugin/
│   └── marketplace.json        # Marketplace manifest (at repo root)
│
├── packages/claude-code-plugin/
│   ├── src/build.ts           # Build tooling
│   └── [generated plugin files]
│
└── assets/claude/              # Plugin source files
    ├── commands/
    └── agents/
```

## Available Plugins

### taskmaster

AI-powered task management system for ambitious development workflows.

**Features:**

- 49 slash commands for comprehensive task management
- 3 specialized AI agents (orchestrator, executor, checker)
- MCP server integration
- Complexity analysis and auto-expansion
- Dependency management and validation
- Automated workflow capabilities

**Quick Start:**

```bash
/tm:init
/tm:parse-prd
/tm:next
```

## For Contributors

### Adding New Plugins

To add more plugins to this marketplace:

1. **Update marketplace.json**:

   ```json
   {
     "plugins": [
       {
         "name": "new-plugin",
         "source": "./path/to/plugin",
         "description": "Plugin description",
         "version": "1.0.0"
       }
     ]
   }
   ```

2. **Commit and push** the changes

3. **Users update** with: `/plugin marketplace update taskmaster`

### Marketplace Versioning

The marketplace version is tracked in `.claude-plugin/marketplace.json`:

```json
{
  "metadata": {
    "version": "1.0.0"
  }
}
```

Increment the version when adding or updating plugins.

## Team Configuration

Organizations can auto-install this marketplace for all team members by adding to `.claude/settings.json`:

```json
{
  "extraKnownMarketplaces": {
    "task-master": {
      "source": {
        "source": "github",
        "repo": "eyaltoledano/claude-task-master"
      }
    }
  },
  "enabledPlugins": {
    "taskmaster": {
      "marketplace": "taskmaster"
    }
  }
}
```

Team members who trust the repository folder will automatically get the marketplace and plugins installed.

## Documentation

- [Claude Code Plugin Docs](https://docs.claude.com/en/docs/claude-code/plugins)
- [Marketplace Documentation](https://docs.claude.com/en/docs/claude-code/plugin-marketplaces)

```

--------------------------------------------------------------------------------
/apps/extension/src/utils/logger.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';

/**
 * Logger interface for dependency injection
 */
export interface ILogger {
	log(message: string, ...args: any[]): void;
	error(message: string, ...args: any[]): void;
	warn(message: string, ...args: any[]): void;
	debug(message: string, ...args: any[]): void;
	show(): void;
	dispose(): void;
}

/**
 * Logger that outputs to VS Code's output channel instead of console
 * This prevents interference with MCP stdio communication
 */
export class ExtensionLogger implements ILogger {
	private static instance: ExtensionLogger;
	private outputChannel: vscode.OutputChannel;
	private debugMode: boolean;

	private constructor() {
		this.outputChannel = vscode.window.createOutputChannel('TaskMaster');
		const config = vscode.workspace.getConfiguration('taskmaster');
		this.debugMode = config.get<boolean>('debug.enableLogging', true);
	}

	static getInstance(): ExtensionLogger {
		if (!ExtensionLogger.instance) {
			ExtensionLogger.instance = new ExtensionLogger();
		}
		return ExtensionLogger.instance;
	}

	log(message: string, ...args: any[]): void {
		if (!this.debugMode) {
			return;
		}
		const timestamp = new Date().toISOString();
		const formattedMessage = this.formatMessage(message, args);
		this.outputChannel.appendLine(`[${timestamp}] ${formattedMessage}`);
	}

	error(message: string, ...args: any[]): void {
		const timestamp = new Date().toISOString();
		const formattedMessage = this.formatMessage(message, args);
		this.outputChannel.appendLine(`[${timestamp}] ERROR: ${formattedMessage}`);
	}

	warn(message: string, ...args: any[]): void {
		if (!this.debugMode) {
			return;
		}
		const timestamp = new Date().toISOString();
		const formattedMessage = this.formatMessage(message, args);
		this.outputChannel.appendLine(`[${timestamp}] WARN: ${formattedMessage}`);
	}

	debug(message: string, ...args: any[]): void {
		if (!this.debugMode) {
			return;
		}
		const timestamp = new Date().toISOString();
		const formattedMessage = this.formatMessage(message, args);
		this.outputChannel.appendLine(`[${timestamp}] DEBUG: ${formattedMessage}`);
	}

	private formatMessage(message: string, args: any[]): string {
		if (args.length === 0) {
			return message;
		}

		// Convert objects to JSON for better readability
		const formattedArgs = args.map((arg) => {
			if (typeof arg === 'object' && arg !== null) {
				try {
					return JSON.stringify(arg, null, 2);
				} catch {
					return String(arg);
				}
			}
			return String(arg);
		});

		return `${message} ${formattedArgs.join(' ')}`;
	}

	show(): void {
		this.outputChannel.show();
	}

	dispose(): void {
		this.outputChannel.dispose();
	}

	setDebugMode(enabled: boolean): void {
		this.debugMode = enabled;
	}
}

// Export a singleton instance for convenience
export const logger = ExtensionLogger.getInstance();

```

--------------------------------------------------------------------------------
/src/progress/progress-tracker-builder.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Configuration for progress tracker features
 */
class TrackerConfig {
	constructor() {
		this.features = new Set();
		this.spinnerFrames = null;
		this.unitName = 'unit';
		this.totalUnits = 100;
	}

	addFeature(feature) {
		this.features.add(feature);
	}

	hasFeature(feature) {
		return this.features.has(feature);
	}

	getOptions() {
		return {
			numUnits: this.totalUnits,
			unitName: this.unitName,
			spinnerFrames: this.spinnerFrames,
			features: Array.from(this.features)
		};
	}
}

/**
 * Builder for creating configured progress trackers
 */
export class ProgressTrackerBuilder {
	constructor() {
		this.config = new TrackerConfig();
	}

	withPercent() {
		this.config.addFeature('percent');
		return this;
	}

	withTokens() {
		this.config.addFeature('tokens');
		return this;
	}

	withTasks() {
		this.config.addFeature('tasks');
		return this;
	}

	withSpinner(messages) {
		if (!messages || !Array.isArray(messages)) {
			throw new Error('Spinner messages must be an array');
		}
		this.config.spinnerFrames = messages;
		return this;
	}

	withUnits(total, unitName = 'unit') {
		this.config.totalUnits = total;
		this.config.unitName = unitName;
		return this;
	}

	build() {
		return new ProgressTracker(this.config);
	}
}

/**
 * Base progress tracker with configurable features
 */
class ProgressTracker {
	constructor(config) {
		this.config = config;
		this.isActive = false;
		this.current = 0;
		this.spinnerIndex = 0;
		this.startTime = null;
	}

	start() {
		this.isActive = true;
		this.startTime = Date.now();
		this.current = 0;

		if (this.config.spinnerFrames) {
			this._startSpinner();
		}
	}

	update(data = {}) {
		if (!this.isActive) return;

		if (data.current !== undefined) {
			this.current = data.current;
		}

		const progress = this._buildProgressData(data);
		return progress;
	}

	finish() {
		this.isActive = false;

		if (this.spinnerInterval) {
			clearInterval(this.spinnerInterval);
			this.spinnerInterval = null;
		}

		return this._buildSummary();
	}

	_startSpinner() {
		this.spinnerInterval = setInterval(() => {
			this.spinnerIndex =
				(this.spinnerIndex + 1) % this.config.spinnerFrames.length;
		}, 100);
	}

	_buildProgressData(data) {
		const progress = { ...data };

		if (this.config.hasFeature('percent')) {
			progress.percentage = Math.round(
				(this.current / this.config.totalUnits) * 100
			);
		}

		if (this.config.hasFeature('tasks')) {
			progress.tasks = `${this.current}/${this.config.totalUnits}`;
		}

		if (this.config.spinnerFrames) {
			progress.spinner = this.config.spinnerFrames[this.spinnerIndex];
		}

		return progress;
	}

	_buildSummary() {
		const elapsed = Date.now() - this.startTime;
		return {
			total: this.config.totalUnits,
			completed: this.current,
			elapsedMs: elapsed,
			features: Array.from(this.config.features)
		};
	}
}

```

--------------------------------------------------------------------------------
/src/profiles/kiro.js:
--------------------------------------------------------------------------------

```javascript
// Kiro profile for rule-transformer
import { createProfile } from './base-profile.js';
import fs from 'fs';
import path from 'path';
import { log } from '../../scripts/modules/utils.js';

// Create and export kiro profile using the base factory
export const kiroProfile = createProfile({
	name: 'kiro',
	displayName: 'Kiro',
	url: 'kiro.dev',
	docsUrl: 'kiro.dev/docs',
	profileDir: '.kiro',
	rulesDir: '.kiro/steering', // Kiro rules location (full path)
	mcpConfig: true,
	mcpConfigName: 'settings/mcp.json', // Create directly in settings subdirectory
	includeDefaultRules: true, // Include default rules to get all the standard files
	targetExtension: '.md',
	fileMap: {
		// Override specific mappings - the base profile will create:
		// 'rules/cursor_rules.mdc': 'kiro_rules.md'
		// 'rules/dev_workflow.mdc': 'dev_workflow.md'
		// 'rules/self_improve.mdc': 'self_improve.md'
		// 'rules/taskmaster.mdc': 'taskmaster.md'
		// We can add additional custom mappings here if needed
		'rules/taskmaster_hooks_workflow.mdc': 'taskmaster_hooks_workflow.md'
	},
	customReplacements: [
		// Core Kiro directory structure changes
		{ from: /\.cursor\/rules/g, to: '.kiro/steering' },
		{ from: /\.cursor\/mcp\.json/g, to: '.kiro/settings/mcp.json' },

		// Fix any remaining kiro/rules references that might be created during transformation
		{ from: /\.kiro\/rules/g, to: '.kiro/steering' },

		// Essential markdown link transformations for Kiro structure
		{
			from: /\[(.+?)\]\(mdc:\.cursor\/rules\/(.+?)\.mdc\)/g,
			to: '[$1](.kiro/steering/$2.md)'
		},

		// Kiro specific terminology
		{ from: /rules directory/g, to: 'steering directory' },
		{ from: /cursor rules/gi, to: 'Kiro steering files' },

		// Transform frontmatter to Kiro format
		// This regex matches the entire frontmatter block and replaces it
		{
			from: /^---\n(?:description:\s*[^\n]*\n)?(?:globs:\s*[^\n]*\n)?(?:alwaysApply:\s*true\n)?---/m,
			to: '---\ninclusion: always\n---'
		}
	],

	// Add lifecycle hook to copy Kiro hooks
	onPostConvert: (projectRoot, assetsDir) => {
		const hooksSourceDir = path.join(assetsDir, 'kiro-hooks');
		const hooksTargetDir = path.join(projectRoot, '.kiro', 'hooks');

		// Create hooks directory if it doesn't exist
		if (!fs.existsSync(hooksTargetDir)) {
			fs.mkdirSync(hooksTargetDir, { recursive: true });
		}

		// Copy all .kiro.hook files
		if (fs.existsSync(hooksSourceDir)) {
			const hookFiles = fs
				.readdirSync(hooksSourceDir)
				.filter((f) => f.endsWith('.kiro.hook'));

			hookFiles.forEach((file) => {
				const sourcePath = path.join(hooksSourceDir, file);
				const targetPath = path.join(hooksTargetDir, file);

				fs.copyFileSync(sourcePath, targetPath);
			});

			if (hookFiles.length > 0) {
				log(
					'info',
					`[Kiro] Installed ${hookFiles.length} Taskmaster hooks in .kiro/hooks/`
				);
			}
		}
	}
});

```

--------------------------------------------------------------------------------
/apps/extension/src/services/notification-preferences.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Notification Preferences Service
 * Manages user preferences for notifications
 */

import * as vscode from 'vscode';
import { ErrorCategory, ErrorSeverity } from './error-handler';

export enum NotificationLevel {
	ALL = 'all',
	ERRORS_ONLY = 'errors_only',
	CRITICAL_ONLY = 'critical_only',
	NONE = 'none'
}

interface NotificationRule {
	category: ErrorCategory;
	minSeverity: ErrorSeverity;
	enabled: boolean;
}

export class NotificationPreferences {
	private defaultRules: NotificationRule[] = [
		{
			category: ErrorCategory.MCP_CONNECTION,
			minSeverity: ErrorSeverity.HIGH,
			enabled: true
		},
		{
			category: ErrorCategory.CONFIGURATION,
			minSeverity: ErrorSeverity.MEDIUM,
			enabled: true
		},
		{
			category: ErrorCategory.TASK_LOADING,
			minSeverity: ErrorSeverity.HIGH,
			enabled: true
		},
		{
			category: ErrorCategory.NETWORK,
			minSeverity: ErrorSeverity.HIGH,
			enabled: true
		},
		{
			category: ErrorCategory.INTERNAL,
			minSeverity: ErrorSeverity.CRITICAL,
			enabled: true
		}
	];

	/**
	 * Check if a notification should be shown
	 */
	shouldShowNotification(
		category: ErrorCategory,
		severity: ErrorSeverity
	): boolean {
		// Get user's notification level preference
		const level = this.getNotificationLevel();

		if (level === NotificationLevel.NONE) {
			return false;
		}

		if (
			level === NotificationLevel.CRITICAL_ONLY &&
			severity !== ErrorSeverity.CRITICAL
		) {
			return false;
		}

		if (
			level === NotificationLevel.ERRORS_ONLY &&
			severity !== ErrorSeverity.CRITICAL &&
			severity !== ErrorSeverity.HIGH
		) {
			return false;
		}

		// Check category-specific rules
		const rule = this.defaultRules.find((r) => r.category === category);
		if (!rule || !rule.enabled) {
			return false;
		}

		// Check if severity meets minimum threshold
		return this.compareSeverity(severity, rule.minSeverity) >= 0;
	}

	/**
	 * Get user's notification level preference
	 */
	private getNotificationLevel(): NotificationLevel {
		const config = vscode.workspace.getConfiguration('taskmaster');
		return config.get<NotificationLevel>(
			'notifications.level',
			NotificationLevel.ERRORS_ONLY
		);
	}

	/**
	 * Compare severity levels
	 */
	private compareSeverity(a: ErrorSeverity, b: ErrorSeverity): number {
		const severityOrder = {
			[ErrorSeverity.LOW]: 0,
			[ErrorSeverity.MEDIUM]: 1,
			[ErrorSeverity.HIGH]: 2,
			[ErrorSeverity.CRITICAL]: 3
		};
		return severityOrder[a] - severityOrder[b];
	}

	/**
	 * Get toast notification duration based on severity
	 */
	getToastDuration(severity: ErrorSeverity): number {
		switch (severity) {
			case ErrorSeverity.CRITICAL:
				return 10000; // 10 seconds
			case ErrorSeverity.HIGH:
				return 7000; // 7 seconds
			case ErrorSeverity.MEDIUM:
				return 5000; // 5 seconds
			case ErrorSeverity.LOW:
				return 3000; // 3 seconds
		}
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/expand-task.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/expand-task.js
 * Tool to expand a task into subtasks
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { expandTaskDirect } from '../core/task-master-core.js';
import {
	findTasksPath,
	findComplexityReportPath
} from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the expand-task tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerExpandTaskTool(server) {
	server.addTool({
		name: 'expand_task',
		description: 'Expand a task into subtasks for detailed implementation',
		parameters: z.object({
			id: z.string().describe('ID of task to expand'),
			num: z.string().optional().describe('Number of subtasks to generate'),
			research: z
				.boolean()
				.optional()
				.default(false)
				.describe('Use research role for generation'),
			prompt: z
				.string()
				.optional()
				.describe('Additional context for subtask generation'),
			file: z
				.string()
				.optional()
				.describe(
					'Path to the tasks file relative to project root (e.g., tasks/tasks.json)'
				),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			force: z
				.boolean()
				.optional()
				.default(false)
				.describe('Force expansion even if subtasks exist'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				log.info(`Starting expand-task with args: ${JSON.stringify(args)}`);
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});
				// Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot)
				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				const complexityReportPath = findComplexityReportPath(
					{ ...args, tag: resolvedTag },
					log
				);

				const result = await expandTaskDirect(
					{
						tasksJsonPath: tasksJsonPath,
						id: args.id,
						num: args.num,
						research: args.research,
						prompt: args.prompt,
						force: args.force,
						complexityReportPath,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				return handleApiResult(
					result,
					log,
					'Error expanding task',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in expand-task tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/apps/extension/src/utils/task-master-api/types/index.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * TaskMaster API Types
 * All type definitions for the TaskMaster API
 */

// MCP Response Types
export interface MCPTaskResponse {
	data?: {
		tasks?: Array<{
			id: number | string;
			title: string;
			description: string;
			status: string;
			priority: string;
			details?: string;
			testStrategy?: string;
			dependencies?: Array<number | string>;
			complexityScore?: number;
			subtasks?: Array<{
				id: number;
				title: string;
				description?: string;
				status: string;
				details?: string;
				dependencies?: Array<number | string>;
			}>;
		}>;
		tag?: {
			currentTag: string;
			availableTags: string[];
		};
	};
	version?: {
		version: string;
		name: string;
	};
	error?: string;
}

// Internal Task Interface
export interface TaskMasterTask {
	id: string;
	title: string;
	description: string;
	status:
		| 'pending'
		| 'in-progress'
		| 'review'
		| 'done'
		| 'deferred'
		| 'cancelled';
	priority: 'high' | 'medium' | 'low';
	details?: string;
	testStrategy?: string;
	dependencies?: string[];
	complexityScore?: number;
	subtasks?: Array<{
		id: number;
		title: string;
		description?: string;
		status: string;
		details?: string;
		testStrategy?: string;
		dependencies?: Array<number | string>;
	}>;
}

// API Response Wrapper
export interface TaskMasterApiResponse<T = any> {
	success: boolean;
	data?: T;
	error?: string;
	requestDuration?: number;
}

// API Configuration
export interface TaskMasterApiConfig {
	timeout: number;
	retryAttempts: number;
	cacheDuration: number;
	projectRoot?: string;
	cache?: CacheConfig;
}

export interface CacheConfig {
	maxSize: number;
	enableBackgroundRefresh: boolean;
	refreshInterval: number;
	enableAnalytics: boolean;
	enablePrefetch: boolean;
	compressionEnabled: boolean;
	persistToDisk: boolean;
}

// Cache Types
export interface CacheEntry {
	data: any;
	timestamp: number;
	accessCount: number;
	lastAccessed: number;
	size: number;
	ttl?: number;
	tags: string[];
}

export interface CacheAnalytics {
	hits: number;
	misses: number;
	evictions: number;
	refreshes: number;
	totalSize: number;
	averageAccessTime: number;
	hitRate: number;
}

// Method Options
export interface GetTasksOptions {
	status?: string;
	withSubtasks?: boolean;
	tag?: string;
	projectRoot?: string;
}

export interface UpdateTaskStatusOptions {
	projectRoot?: string;
}

export interface UpdateTaskOptions {
	projectRoot?: string;
	append?: boolean;
	research?: boolean;
}

export interface UpdateSubtaskOptions {
	projectRoot?: string;
	research?: boolean;
}

export interface AddSubtaskOptions {
	projectRoot?: string;
}

export interface TaskUpdate {
	title?: string;
	description?: string;
	details?: string;
	priority?: 'high' | 'medium' | 'low';
	testStrategy?: string;
	dependencies?: string[];
}

export interface SubtaskData {
	title: string;
	description?: string;
	dependencies?: string[];
	status?: string;
}

```

--------------------------------------------------------------------------------
/tests/helpers/tool-counts.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tool-counts.js
 * Shared helper for validating tool counts across tests and validation scripts
 */

import {
	getToolCounts,
	getToolCategories
} from '../../mcp-server/src/tools/tool-registry.js';

/**
 * Expected tool counts - update these when tools are added/removed
 * These serve as the canonical source of truth for expected counts
 */
export const EXPECTED_TOOL_COUNTS = {
	core: 7,
	standard: 15,
	total: 44
};

/**
 * Expected core tools list for validation
 */
export const EXPECTED_CORE_TOOLS = [
	'get_tasks',
	'next_task',
	'get_task',
	'set_task_status',
	'update_subtask',
	'parse_prd',
	'expand_task'
];

/**
 * Validate that actual tool counts match expected counts
 * @returns {Object} Validation result with isValid flag and details
 */
export function validateToolCounts() {
	const actual = getToolCounts();
	const expected = EXPECTED_TOOL_COUNTS;

	const isValid =
		actual.core === expected.core &&
		actual.standard === expected.standard &&
		actual.total === expected.total;

	return {
		isValid,
		actual,
		expected,
		differences: {
			core: actual.core - expected.core,
			standard: actual.standard - expected.standard,
			total: actual.total - expected.total
		}
	};
}

/**
 * Validate that tool categories have correct structure and content
 * @returns {Object} Validation result
 */
export function validateToolStructure() {
	const categories = getToolCategories();
	const counts = getToolCounts();

	// Check that core tools are subset of standard tools
	const coreInStandard = categories.core.every((tool) =>
		categories.standard.includes(tool)
	);

	// Check that standard tools are subset of all tools
	const standardInAll = categories.standard.every((tool) =>
		categories.all.includes(tool)
	);

	// Check that expected core tools match actual
	const expectedCoreMatch =
		EXPECTED_CORE_TOOLS.every((tool) => categories.core.includes(tool)) &&
		categories.core.every((tool) => EXPECTED_CORE_TOOLS.includes(tool));

	// Check array lengths match counts
	const lengthsMatch =
		categories.core.length === counts.core &&
		categories.standard.length === counts.standard &&
		categories.all.length === counts.total;

	return {
		isValid:
			coreInStandard && standardInAll && expectedCoreMatch && lengthsMatch,
		details: {
			coreInStandard,
			standardInAll,
			expectedCoreMatch,
			lengthsMatch
		},
		categories,
		counts
	};
}

/**
 * Get a detailed report of all tool information
 * @returns {Object} Comprehensive tool information
 */
export function getToolReport() {
	const counts = getToolCounts();
	const categories = getToolCategories();
	const validation = validateToolCounts();
	const structure = validateToolStructure();

	return {
		counts,
		categories,
		validation,
		structure,
		summary: {
			totalValid: validation.isValid && structure.isValid,
			countsValid: validation.isValid,
			structureValid: structure.isValid
		}
	};
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/remove-dependency.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Direct function wrapper for removeDependency
 */

import { removeDependency } from '../../../../scripts/modules/dependency-manager.js';
import {
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';

/**
 * Remove a dependency from a task
 * @param {Object} args - Function arguments
 * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file.
 * @param {string|number} args.id - Task ID to remove dependency from
 * @param {string|number} args.dependsOn - Task ID to remove as a dependency
 * @param {string} args.projectRoot - Project root path (for MCP/env fallback)
 * @param {string} args.tag - Tag for the task (optional)
 * @param {Object} log - Logger object
 * @returns {Promise<{success: boolean, data?: Object, error?: {code: string, message: string}}>}
 */
export async function removeDependencyDirect(args, log) {
	// Destructure expected args
	const { tasksJsonPath, id, dependsOn, projectRoot, tag } = args;
	try {
		log.info(`Removing dependency with args: ${JSON.stringify(args)}`);

		// Check if tasksJsonPath was provided
		if (!tasksJsonPath) {
			log.error('removeDependencyDirect called without tasksJsonPath');
			return {
				success: false,
				error: {
					code: 'MISSING_ARGUMENT',
					message: 'tasksJsonPath is required'
				}
			};
		}

		// Validate required parameters
		if (!id) {
			return {
				success: false,
				error: {
					code: 'INPUT_VALIDATION_ERROR',
					message: 'Task ID (id) is required'
				}
			};
		}

		if (!dependsOn) {
			return {
				success: false,
				error: {
					code: 'INPUT_VALIDATION_ERROR',
					message: 'Dependency ID (dependsOn) is required'
				}
			};
		}

		// Use provided path
		const tasksPath = tasksJsonPath;

		// Format IDs for the core function
		const taskId =
			id && id.includes && id.includes('.') ? id : parseInt(id, 10);
		const dependencyId =
			dependsOn && dependsOn.includes && dependsOn.includes('.')
				? dependsOn
				: parseInt(dependsOn, 10);

		log.info(
			`Removing dependency: task ${taskId} no longer depends on ${dependencyId}`
		);

		// Enable silent mode to prevent console logs from interfering with JSON response
		enableSilentMode();

		// Call the core function using the provided tasksPath
		await removeDependency(tasksPath, taskId, dependencyId, {
			projectRoot,
			tag
		});

		// Restore normal logging
		disableSilentMode();

		return {
			success: true,
			data: {
				message: `Successfully removed dependency: Task ${taskId} no longer depends on ${dependencyId}`,
				taskId: taskId,
				dependencyId: dependencyId
			}
		};
	} catch (error) {
		// Make sure to restore normal logging even if there's an error
		disableSilentMode();

		log.error(`Error in removeDependencyDirect: ${error.message}`);
		return {
			success: false,
			error: {
				code: 'CORE_FUNCTION_ERROR',
				message: error.message
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/delete-tag.js:
--------------------------------------------------------------------------------

```javascript
/**
 * delete-tag.js
 * Direct function implementation for deleting a tag
 */

import { deleteTag } from '../../../../scripts/modules/task-manager/tag-management.js';
import {
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';
import { createLogWrapper } from '../../tools/utils.js';

/**
 * Direct function wrapper for deleting a tag with error handling.
 *
 * @param {Object} args - Command arguments
 * @param {string} args.name - Name of the tag to delete
 * @param {boolean} [args.yes=false] - Skip confirmation prompts
 * @param {string} [args.tasksJsonPath] - Path to the tasks.json file (resolved by tool)
 * @param {string} [args.projectRoot] - Project root path
 * @param {Object} log - Logger object
 * @param {Object} context - Additional context (session)
 * @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
 */
export async function deleteTagDirect(args, log, context = {}) {
	// Destructure expected args
	const { tasksJsonPath, name, yes = false, projectRoot } = args;
	const { session } = context;

	// Enable silent mode to prevent console logs from interfering with JSON response
	enableSilentMode();

	// Create logger wrapper using the utility
	const mcpLog = createLogWrapper(log);

	try {
		// Check if tasksJsonPath was provided
		if (!tasksJsonPath) {
			log.error('deleteTagDirect called without tasksJsonPath');
			disableSilentMode();
			return {
				success: false,
				error: {
					code: 'MISSING_ARGUMENT',
					message: 'tasksJsonPath is required'
				}
			};
		}

		// Check required parameters
		if (!name || typeof name !== 'string') {
			log.error('Missing required parameter: name');
			disableSilentMode();
			return {
				success: false,
				error: {
					code: 'MISSING_PARAMETER',
					message: 'Tag name is required and must be a string'
				}
			};
		}

		log.info(`Deleting tag: ${name}`);

		// Prepare options
		const options = {
			yes // For MCP, we always skip confirmation prompts
		};

		// Call the deleteTag function
		const result = await deleteTag(
			tasksJsonPath,
			name,
			options,
			{
				session,
				mcpLog,
				projectRoot
			},
			'json' // outputFormat - use 'json' to suppress CLI UI
		);

		// Restore normal logging
		disableSilentMode();

		return {
			success: true,
			data: {
				tagName: result.tagName,
				deleted: result.deleted,
				tasksDeleted: result.tasksDeleted,
				wasCurrentTag: result.wasCurrentTag,
				switchedToMaster: result.switchedToMaster,
				message: `Successfully deleted tag "${result.tagName}"`
			}
		};
	} catch (error) {
		// Make sure to restore normal logging even if there's an error
		disableSilentMode();

		log.error(`Error in deleteTagDirect: ${error.message}`);
		return {
			success: false,
			error: {
				code: error.code || 'DELETE_TAG_ERROR',
				message: error.message
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/tests/unit/ai-providers/codex-cli.test.js:
--------------------------------------------------------------------------------

```javascript
import { jest } from '@jest/globals';

// Mock the ai module
jest.unstable_mockModule('ai', () => ({
	generateObject: jest.fn(),
	generateText: jest.fn(),
	streamText: jest.fn()
}));

// Mock the codex-cli SDK module
jest.unstable_mockModule('ai-sdk-provider-codex-cli', () => ({
	createCodexCli: jest.fn((options) => {
		const provider = (modelId, settings) => ({ id: modelId, settings });
		provider.languageModel = jest.fn((id, settings) => ({ id, settings }));
		provider.chat = provider.languageModel;
		return provider;
	})
}));

// Mock config getters
jest.unstable_mockModule('../../../scripts/modules/config-manager.js', () => ({
	getCodexCliSettingsForCommand: jest.fn(() => ({ allowNpx: true })),
	getSupportedModelsForProvider: jest.fn(() => ['gpt-5', 'gpt-5-codex']),
	// Provide commonly imported getters to satisfy other module imports if any
	getDebugFlag: jest.fn(() => false),
	getLogLevel: jest.fn(() => 'info')
}));

// Mock base provider
jest.unstable_mockModule('../../../src/ai-providers/base-provider.js', () => ({
	BaseAIProvider: class {
		constructor() {
			this.name = 'Base Provider';
		}
		handleError(_ctx, err) {
			throw err;
		}
		validateParams(params) {
			if (!params.modelId) throw new Error('Model ID is required');
		}
		validateMessages(msgs) {
			if (!Array.isArray(msgs)) throw new Error('Invalid messages array');
		}
	}
}));

const { CodexCliProvider } = await import(
	'../../../src/ai-providers/codex-cli.js'
);
const { createCodexCli } = await import('ai-sdk-provider-codex-cli');
const { getCodexCliSettingsForCommand } = await import(
	'../../../scripts/modules/config-manager.js'
);

describe('CodexCliProvider', () => {
	let provider;

	beforeEach(() => {
		jest.clearAllMocks();
		provider = new CodexCliProvider();
	});

	it('sets provider name and supported models', () => {
		expect(provider.name).toBe('Codex CLI');
		expect(provider.supportedModels).toEqual(['gpt-5', 'gpt-5-codex']);
	});

	it('does not require API key', () => {
		expect(provider.isRequiredApiKey()).toBe(false);
	});

	it('creates client with merged default settings', async () => {
		const client = await provider.getClient({ commandName: 'parse-prd' });
		expect(client).toBeDefined();
		expect(createCodexCli).toHaveBeenCalledWith({
			defaultSettings: expect.objectContaining({ allowNpx: true })
		});
		expect(getCodexCliSettingsForCommand).toHaveBeenCalledWith('parse-prd');
	});

	it('injects OPENAI_API_KEY only when apiKey provided', async () => {
		const client = await provider.getClient({
			commandName: 'expand',
			apiKey: 'sk-test'
		});
		const call = createCodexCli.mock.calls[0][0];
		expect(call.defaultSettings.env.OPENAI_API_KEY).toBe('sk-test');
		// Ensure env is not set when apiKey not provided
		await provider.getClient({ commandName: 'expand' });
		const second = createCodexCli.mock.calls[1][0];
		expect(second.defaultSettings.env).toBeUndefined();
	});
});

```

--------------------------------------------------------------------------------
/apps/docs/archive/cursor-setup.mdx:
--------------------------------------------------------------------------------

```markdown
---
title: "Cursor AI Integration"
description: "Learn how to set up and use Task Master with Cursor AI"
---

## Setting up Cursor AI Integration

<Check>
  Task Master is designed to work seamlessly with [Cursor AI](https://www.cursor.so/), providing a structured workflow for AI-driven development.
</Check>

<AccordionGroup>
  <Accordion title="Using Cursor with MCP (Recommended)" icon="sparkles">
    If you've already set up Task Master with MCP in Cursor, the integration is automatic. You can simply use natural language to interact with Task Master:

    ```
    What tasks are available to work on next?
    Can you analyze the complexity of our tasks?
    I'd like to implement task 4. What does it involve?
    ```
  </Accordion>
  <Accordion title="Manual Cursor Setup">
    If you're not using MCP, you can still set up Cursor integration:

    <Steps>
      <Step title="After initializing your project, open it in Cursor">
        The `.cursor/rules/dev_workflow.mdc` file is automatically loaded by Cursor, providing the AI with knowledge about the task management system
      </Step>
      <Step title="Place your PRD document in the scripts/ directory (e.g., scripts/prd.txt)">
        
      </Step>
      <Step title="Open Cursor's AI chat and switch to Agent mode">
        
      </Step>
    </Steps>
  </Accordion>
  <Accordion title="Alternative MCP Setup in Cursor">
    <Steps>
      <Step title="Go to Cursor settings">
        
      </Step>
      <Step title="Navigate to the MCP section">
        
      </Step>
      <Step title="Click on 'Add New MCP Server'">
        
      </Step>
      <Step title="Configure with the following details:">
        - Name: "Task Master"
        - Type: "Command"
        - Command: "npx -y task-master-ai"
      </Step>
      <Step title="Save Settings">
        
      </Step>
    </Steps>
    Once configured, you can interact with Task Master's task management commands directly through Cursor's interface, providing a more integrated experience.
  </Accordion>
</AccordionGroup>

## Initial Task Generation

In Cursor's AI chat, instruct the agent to generate tasks from your PRD:

```
Please use the task-master parse-prd command to generate tasks from my PRD. The PRD is located at scripts/prd.txt.
```

The agent will execute:

```bash
task-master parse-prd scripts/prd.txt
```

This will:

- Parse your PRD document
- Generate a structured `tasks.json` file with tasks, dependencies, priorities, and test strategies
- The agent will understand this process due to the Cursor rules

### Generate Individual Task Files

Next, ask the agent to generate individual task files:

```
Please generate individual task files from tasks.json
```

The agent will execute:

```bash
task-master generate
```

This creates individual task files in the `tasks/` directory (e.g., `task_001.txt`, `task_002.txt`), making it easier to reference specific tasks.

```

--------------------------------------------------------------------------------
/tests/unit/profiles/rule-transformer-gemini.test.js:
--------------------------------------------------------------------------------

```javascript
import { jest } from '@jest/globals';
import { getRulesProfile } from '../../../src/utils/rule-transformer.js';
import { geminiProfile } from '../../../src/profiles/gemini.js';

describe('Rule Transformer - Gemini Profile', () => {
	test('should have correct profile configuration', () => {
		const geminiProfile = getRulesProfile('gemini');

		expect(geminiProfile).toBeDefined();
		expect(geminiProfile.profileName).toBe('gemini');
		expect(geminiProfile.displayName).toBe('Gemini');
		expect(geminiProfile.profileDir).toBe('.gemini');
		expect(geminiProfile.rulesDir).toBe('.');
		expect(geminiProfile.mcpConfig).toBe(true);
		expect(geminiProfile.mcpConfigName).toBe('settings.json');
		expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
		expect(geminiProfile.includeDefaultRules).toBe(false);
		expect(geminiProfile.fileMap).toEqual({
			'AGENT.md': 'AGENTS.md',
			'GEMINI.md': 'GEMINI.md'
		});
	});

	test('should have minimal profile implementation', () => {
		// Verify that gemini.js is minimal (no lifecycle functions)
		expect(geminiProfile.onAddRulesProfile).toBeUndefined();
		expect(geminiProfile.onRemoveRulesProfile).toBeUndefined();
		expect(geminiProfile.onPostConvertRulesProfile).toBeUndefined();
	});

	test('should use settings.json instead of mcp.json', () => {
		const geminiProfile = getRulesProfile('gemini');
		expect(geminiProfile.mcpConfigName).toBe('settings.json');
		expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
	});

	test('should not include default rules', () => {
		const geminiProfile = getRulesProfile('gemini');
		expect(geminiProfile.includeDefaultRules).toBe(false);
	});

	test('should have correct file mapping', () => {
		const geminiProfile = getRulesProfile('gemini');
		expect(geminiProfile.fileMap).toEqual({
			'AGENT.md': 'AGENTS.md',
			'GEMINI.md': 'GEMINI.md'
		});
	});

	test('should place AGENTS.md and GEMINI.md in root directory', () => {
		const geminiProfile = getRulesProfile('gemini');
		// rulesDir determines where fileMap files go
		expect(geminiProfile.rulesDir).toBe('.');
		// This means both AGENTS.md and GEMINI.md will be placed in the root
		// Both files are auto-loaded by Gemini CLI
	});

	test('should place settings.json in .gemini directory', () => {
		const geminiProfile = getRulesProfile('gemini');
		// profileDir + mcpConfigName determines MCP config location
		expect(geminiProfile.profileDir).toBe('.gemini');
		expect(geminiProfile.mcpConfigName).toBe('settings.json');
		expect(geminiProfile.mcpConfigPath).toBe('.gemini/settings.json');
	});

	test('should have proper conversion config', () => {
		const geminiProfile = getRulesProfile('gemini');
		// Gemini should have the standard conversion config
		expect(geminiProfile.conversionConfig).toBeDefined();
		expect(geminiProfile.globalReplacements).toBeDefined();
		expect(Array.isArray(geminiProfile.globalReplacements)).toBe(true);
	});
});

```

--------------------------------------------------------------------------------
/mcp-server/src/custom-sdk/json-extractor.js:
--------------------------------------------------------------------------------

```javascript
/**
 * @fileoverview Extract JSON from MCP response, handling markdown blocks and other formatting
 */

/**
 * Extract JSON from MCP AI response
 * @param {string} text - The text to extract JSON from
 * @returns {string} - The extracted JSON string
 */
export function extractJson(text) {
	// Remove markdown code blocks if present
	let jsonText = text.trim();

	// Remove ```json blocks
	jsonText = jsonText.replace(/^```json\s*/gm, '');
	jsonText = jsonText.replace(/^```\s*/gm, '');
	jsonText = jsonText.replace(/```\s*$/gm, '');

	// Remove common TypeScript/JavaScript patterns
	jsonText = jsonText.replace(/^const\s+\w+\s*=\s*/, ''); // Remove "const varName = "
	jsonText = jsonText.replace(/^let\s+\w+\s*=\s*/, ''); // Remove "let varName = "
	jsonText = jsonText.replace(/^var\s+\w+\s*=\s*/, ''); // Remove "var varName = "
	jsonText = jsonText.replace(/;?\s*$/, ''); // Remove trailing semicolons

	// Remove explanatory text before JSON (common with AI responses)
	jsonText = jsonText.replace(/^.*?(?=\{|\[)/s, '');

	// Remove explanatory text after JSON
	const lines = jsonText.split('\n');
	let jsonEndIndex = -1;
	let braceCount = 0;
	let inString = false;
	let escapeNext = false;

	// Find the end of the JSON by tracking braces
	for (let i = 0; i < jsonText.length; i++) {
		const char = jsonText[i];

		if (escapeNext) {
			escapeNext = false;
			continue;
		}

		if (char === '\\') {
			escapeNext = true;
			continue;
		}

		if (char === '"' && !escapeNext) {
			inString = !inString;
			continue;
		}

		if (!inString) {
			if (char === '{' || char === '[') {
				braceCount++;
			} else if (char === '}' || char === ']') {
				braceCount--;
				if (braceCount === 0) {
					jsonEndIndex = i;
					break;
				}
			}
		}
	}

	if (jsonEndIndex > -1) {
		jsonText = jsonText.substring(0, jsonEndIndex + 1);
	}

	// Try to extract JSON object or array if previous method didn't work
	if (jsonEndIndex === -1) {
		const objectMatch = jsonText.match(/{[\s\S]*}/);
		const arrayMatch = jsonText.match(/\[[\s\S]*\]/);

		if (objectMatch) {
			jsonText = objectMatch[0];
		} else if (arrayMatch) {
			jsonText = arrayMatch[0];
		}
	}

	// First try to parse as valid JSON
	try {
		JSON.parse(jsonText);
		return jsonText;
	} catch {
		// If it's not valid JSON, it might be a JavaScript object literal
		// Try to convert it to valid JSON
		try {
			// This is a simple conversion that handles basic cases
			// Replace unquoted keys with quoted keys
			const converted = jsonText
				.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":')
				// Replace single quotes with double quotes
				.replace(/'/g, '"')
				// Handle trailing commas
				.replace(/,\s*([}\]])/g, '$1');

			// Validate the converted JSON
			JSON.parse(converted);
			return converted;
		} catch {
			// If all else fails, return the original text
			// The calling code will handle the error appropriately
			return text;
		}
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/update-subtask.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/update-subtask.js
 * Tool to append additional information to a specific subtask
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { updateSubtaskByIdDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the update-subtask tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerUpdateSubtaskTool(server) {
	server.addTool({
		name: 'update_subtask',
		description:
			'Appends timestamped information to a specific subtask without replacing existing content. If you just want to update the subtask status, use set_task_status instead.',
		parameters: z.object({
			id: z
				.string()
				.describe(
					'ID of the subtask to update in format "parentId.subtaskId" (e.g., "5.2"). Parent ID is the ID of the task that contains the subtask.'
				),
			prompt: z.string().describe('Information to add to the subtask'),
			research: z
				.boolean()
				.optional()
				.describe('Use Perplexity AI for research-backed updates'),
			file: z.string().optional().describe('Absolute path to the tasks file'),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			const toolName = 'update_subtask';

			try {
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});
				log.info(`Updating subtask with args: ${JSON.stringify(args)}`);

				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath(
						{ projectRoot: args.projectRoot, file: args.file },
						log
					);
				} catch (error) {
					log.error(`${toolName}: Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json: ${error.message}`
					);
				}

				const result = await updateSubtaskByIdDirect(
					{
						tasksJsonPath: tasksJsonPath,
						id: args.id,
						prompt: args.prompt,
						research: args.research,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				if (result.success) {
					log.info(`Successfully updated subtask with ID ${args.id}`);
				} else {
					log.error(
						`Failed to update subtask: ${result.error?.message || 'Unknown error'}`
					);
				}

				return handleApiResult(
					result,
					log,
					'Error updating subtask',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(
					`Critical error in ${toolName} tool execute: ${error.message}`
				);
				return createErrorResponse(
					`Internal tool error (${toolName}): ${error.message}`
				);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/tests/unit/profiles/trae-integration.test.js:
--------------------------------------------------------------------------------

```javascript
import { jest } from '@jest/globals';
import fs from 'fs';
import path from 'path';
import os from 'os';

// Mock external modules
jest.mock('child_process', () => ({
	execSync: jest.fn()
}));

// Mock console methods
jest.mock('console', () => ({
	log: jest.fn(),
	info: jest.fn(),
	warn: jest.fn(),
	error: jest.fn(),
	clear: jest.fn()
}));

describe('Trae Integration', () => {
	let tempDir;

	beforeEach(() => {
		jest.clearAllMocks();

		// Create a temporary directory for testing
		tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'task-master-test-'));

		// Spy on fs methods
		jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {});
		jest.spyOn(fs, 'readFileSync').mockImplementation((filePath) => {
			if (filePath.toString().includes('.trae')) {
				return 'Existing trae rules content';
			}
			return '{}';
		});
		jest.spyOn(fs, 'existsSync').mockImplementation(() => false);
		jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {});
	});

	afterEach(() => {
		// Clean up the temporary directory
		try {
			fs.rmSync(tempDir, { recursive: true, force: true });
		} catch (err) {
			console.error(`Error cleaning up: ${err.message}`);
		}
	});

	// Test function that simulates the createProjectStructure behavior for Trae files
	function mockCreateTraeStructure() {
		// Create main .trae directory
		fs.mkdirSync(path.join(tempDir, '.trae'), { recursive: true });

		// Create rules directory
		fs.mkdirSync(path.join(tempDir, '.trae', 'rules'), { recursive: true });

		// Create rule files
		const ruleFiles = [
			'dev_workflow.md',
			'taskmaster.md',
			'architecture.md',
			'commands.md',
			'dependencies.md'
		];

		for (const ruleFile of ruleFiles) {
			fs.writeFileSync(
				path.join(tempDir, '.trae', 'rules', ruleFile),
				`Content for ${ruleFile}`
			);
		}
	}

	test('creates all required .trae directories', () => {
		// Act
		mockCreateTraeStructure();

		// Assert
		expect(fs.mkdirSync).toHaveBeenCalledWith(path.join(tempDir, '.trae'), {
			recursive: true
		});
		expect(fs.mkdirSync).toHaveBeenCalledWith(
			path.join(tempDir, '.trae', 'rules'),
			{ recursive: true }
		);
	});

	test('creates rule files for Trae', () => {
		// Act
		mockCreateTraeStructure();

		// Assert - check rule files are created
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.trae', 'rules', 'dev_workflow.md'),
			expect.any(String)
		);
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.trae', 'rules', 'taskmaster.md'),
			expect.any(String)
		);
		expect(fs.writeFileSync).toHaveBeenCalledWith(
			path.join(tempDir, '.trae', 'rules', 'architecture.md'),
			expect.any(String)
		);
	});

	test('does not create MCP configuration files', () => {
		// Act
		mockCreateTraeStructure();

		// Assert - Trae doesn't use MCP configuration
		expect(fs.writeFileSync).not.toHaveBeenCalledWith(
			path.join(tempDir, '.trae', 'mcp.json'),
			expect.any(String)
		);
	});
});

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/update.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/update.js
 * Tool to update tasks based on new context/prompt
 */

import { z } from 'zod';
import {
	handleApiResult,
	createErrorResponse,
	withNormalizedProjectRoot
} from './utils.js';
import { updateTasksDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the update tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerUpdateTool(server) {
	server.addTool({
		name: 'update',
		description:
			"Update multiple upcoming tasks (with ID >= 'from' ID) based on new context or changes provided in the prompt. Use 'update_task' instead for a single specific task or 'update_subtask' for subtasks.",
		parameters: z.object({
			from: z
				.string()
				.describe(
					"Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'"
				),
			prompt: z
				.string()
				.describe('Explanation of changes or new context to apply'),
			research: z
				.boolean()
				.optional()
				.describe('Use Perplexity AI for research-backed updates'),
			file: z
				.string()
				.optional()
				.describe('Path to the tasks file relative to project root'),
			projectRoot: z
				.string()
				.optional()
				.describe(
					'The directory of the project. (Optional, usually from session)'
				),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			const toolName = 'update';
			const { from, prompt, research, file, projectRoot, tag } = args;

			const resolvedTag = resolveTag({
				projectRoot: args.projectRoot,
				tag: args.tag
			});

			try {
				log.info(
					`Executing ${toolName} tool with normalized root: ${projectRoot}`
				);

				let tasksJsonPath;
				try {
					tasksJsonPath = findTasksPath({ projectRoot, file }, log);
					log.info(`${toolName}: Resolved tasks path: ${tasksJsonPath}`);
				} catch (error) {
					log.error(`${toolName}: Error finding tasks.json: ${error.message}`);
					return createErrorResponse(
						`Failed to find tasks.json within project root '${projectRoot}': ${error.message}`
					);
				}

				const result = await updateTasksDirect(
					{
						tasksJsonPath: tasksJsonPath,
						from: from,
						prompt: prompt,
						research: research,
						projectRoot: projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				log.info(
					`${toolName}: Direct function result: success=${result.success}`
				);
				return handleApiResult(
					result,
					log,
					'Error updating tasks',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(
					`Critical error in ${toolName} tool execute: ${error.message}`
				);
				return createErrorResponse(
					`Internal tool error (${toolName}): ${error.message}`
				);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/add-dependency.js:
--------------------------------------------------------------------------------

```javascript
/**
 * add-dependency.js
 * Direct function implementation for adding a dependency to a task
 */

import { addDependency } from '../../../../scripts/modules/dependency-manager.js';
import {
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';

/**
 * Direct function wrapper for addDependency with error handling.
 *
 * @param {Object} args - Command arguments
 * @param {string} args.tasksJsonPath - Explicit path to the tasks.json file.
 * @param {string|number} args.id - Task ID to add dependency to
 * @param {string|number} args.dependsOn - Task ID that will become a dependency
 * @param {string} args.tag - Tag for the task (optional)
 * @param {string} args.projectRoot - Project root path (for MCP/env fallback)
 * @param {Object} log - Logger object
 * @returns {Promise<Object>} - Result object with success status and data/error information
 */
export async function addDependencyDirect(args, log) {
	// Destructure expected args
	const { tasksJsonPath, id, dependsOn, tag, projectRoot } = args;
	try {
		log.info(`Adding dependency with args: ${JSON.stringify(args)}`);

		// Check if tasksJsonPath was provided
		if (!tasksJsonPath) {
			log.error('addDependencyDirect called without tasksJsonPath');
			return {
				success: false,
				error: {
					code: 'MISSING_ARGUMENT',
					message: 'tasksJsonPath is required'
				}
			};
		}

		// Validate required parameters
		if (!id) {
			return {
				success: false,
				error: {
					code: 'INPUT_VALIDATION_ERROR',
					message: 'Task ID (id) is required'
				}
			};
		}

		if (!dependsOn) {
			return {
				success: false,
				error: {
					code: 'INPUT_VALIDATION_ERROR',
					message: 'Dependency ID (dependsOn) is required'
				}
			};
		}

		// Use provided path
		const tasksPath = tasksJsonPath;

		// Format IDs for the core function
		const taskId =
			id && id.includes && id.includes('.') ? id : parseInt(id, 10);
		const dependencyId =
			dependsOn && dependsOn.includes && dependsOn.includes('.')
				? dependsOn
				: parseInt(dependsOn, 10);

		log.info(
			`Adding dependency: task ${taskId} will depend on ${dependencyId}`
		);

		// Enable silent mode to prevent console logs from interfering with JSON response
		enableSilentMode();

		// Create context object
		const context = { projectRoot, tag };

		// Call the core function using the provided path
		await addDependency(tasksPath, taskId, dependencyId, context);

		// Restore normal logging
		disableSilentMode();

		return {
			success: true,
			data: {
				message: `Successfully added dependency: Task ${taskId} now depends on ${dependencyId}`,
				taskId: taskId,
				dependencyId: dependencyId
			}
		};
	} catch (error) {
		// Make sure to restore normal logging even if there's an error
		disableSilentMode();

		log.error(`Error in addDependencyDirect: ${error.message}`);
		return {
			success: false,
			error: {
				code: 'CORE_FUNCTION_ERROR',
				message: error.message
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/core/direct-functions/complexity-report.js:
--------------------------------------------------------------------------------

```javascript
/**
 * complexity-report.js
 * Direct function implementation for displaying complexity analysis report
 */

import {
	readComplexityReport,
	enableSilentMode,
	disableSilentMode
} from '../../../../scripts/modules/utils.js';

/**
 * Direct function wrapper for displaying the complexity report with error handling and caching.
 *
 * @param {Object} args - Command arguments containing reportPath.
 * @param {string} args.reportPath - Explicit path to the complexity report file.
 * @param {Object} log - Logger object
 * @returns {Promise<Object>} - Result object with success status and data/error information
 */
export async function complexityReportDirect(args, log) {
	// Destructure expected args
	const { reportPath } = args;
	try {
		log.info(`Getting complexity report with args: ${JSON.stringify(args)}`);

		// Check if reportPath was provided
		if (!reportPath) {
			log.error('complexityReportDirect called without reportPath');
			return {
				success: false,
				error: { code: 'MISSING_ARGUMENT', message: 'reportPath is required' }
			};
		}

		// Use the provided report path
		log.info(`Looking for complexity report at: ${reportPath}`);

		// Generate cache key based on report path
		const cacheKey = `complexityReport:${reportPath}`;

		// Define the core action function to read the report
		const coreActionFn = async () => {
			try {
				// Enable silent mode to prevent console logs from interfering with JSON response
				enableSilentMode();

				const report = readComplexityReport(reportPath);

				// Restore normal logging
				disableSilentMode();

				if (!report) {
					log.warn(`No complexity report found at ${reportPath}`);
					return {
						success: false,
						error: {
							code: 'FILE_NOT_FOUND_ERROR',
							message: `No complexity report found at ${reportPath}. Run 'analyze-complexity' first.`
						}
					};
				}

				return {
					success: true,
					data: {
						report,
						reportPath
					}
				};
			} catch (error) {
				// Make sure to restore normal logging even if there's an error
				disableSilentMode();

				log.error(`Error reading complexity report: ${error.message}`);
				return {
					success: false,
					error: {
						code: 'READ_ERROR',
						message: error.message
					}
				};
			}
		};

		// Use the caching utility
		try {
			const result = await coreActionFn();
			log.info('complexityReportDirect completed');
			return result;
		} catch (error) {
			// Ensure silent mode is disabled
			disableSilentMode();

			log.error(`Unexpected error during complexityReport: ${error.message}`);
			return {
				success: false,
				error: {
					code: 'UNEXPECTED_ERROR',
					message: error.message
				}
			};
		}
	} catch (error) {
		// Ensure silent mode is disabled if an outer error occurs
		disableSilentMode();

		log.error(`Error in complexityReportDirect: ${error.message}`);
		return {
			success: false,
			error: {
				code: 'UNEXPECTED_ERROR',
				message: error.message
			}
		};
	}
}

```

--------------------------------------------------------------------------------
/mcp-server/src/logger.js:
--------------------------------------------------------------------------------

```javascript
import chalk from 'chalk';
import { isSilentMode } from '../../scripts/modules/utils.js';
import { getLogLevel } from '../../scripts/modules/config-manager.js';

// Define log levels
const LOG_LEVELS = {
	debug: 0,
	info: 1,
	warn: 2,
	error: 3,
	success: 4
};

// Get log level from config manager or default to info
const LOG_LEVEL = LOG_LEVELS[getLogLevel().toLowerCase()] ?? LOG_LEVELS.info;

/**
 * Logs a message with the specified level
 * @param {string} level - The log level (debug, info, warn, error, success)
 * @param  {...any} args - Arguments to log
 */
function log(level, ...args) {
	// Skip logging if silent mode is enabled
	if (isSilentMode()) {
		return;
	}

	// Use text prefixes instead of emojis
	const prefixes = {
		debug: chalk.gray('[DEBUG]'),
		info: chalk.blue('[INFO]'),
		warn: chalk.yellow('[WARN]'),
		error: chalk.red('[ERROR]'),
		success: chalk.green('[SUCCESS]')
	};

	if (LOG_LEVELS[level] !== undefined && LOG_LEVELS[level] >= LOG_LEVEL) {
		const prefix = prefixes[level] || '';
		let coloredArgs = args;

		try {
			switch (level) {
				case 'error':
					coloredArgs = args.map((arg) =>
						typeof arg === 'string' ? chalk.red(arg) : arg
					);
					break;
				case 'warn':
					coloredArgs = args.map((arg) =>
						typeof arg === 'string' ? chalk.yellow(arg) : arg
					);
					break;
				case 'success':
					coloredArgs = args.map((arg) =>
						typeof arg === 'string' ? chalk.green(arg) : arg
					);
					break;
				case 'info':
					coloredArgs = args.map((arg) =>
						typeof arg === 'string' ? chalk.blue(arg) : arg
					);
					break;
				case 'debug':
					coloredArgs = args.map((arg) =>
						typeof arg === 'string' ? chalk.gray(arg) : arg
					);
					break;
				// default: use original args (no color)
			}
		} catch (colorError) {
			// Fallback if chalk fails on an argument
			// Use console.error here for internal logger errors, separate from normal logging
			console.error('Internal Logger Error applying chalk color:', colorError);
			coloredArgs = args;
		}

		// Revert to console.log - FastMCP's context logger (context.log)
		// is responsible for directing logs correctly (e.g., to stderr)
		// during tool execution without upsetting the client connection.
		// Logs outside of tool execution (like startup) will go to stdout.
		console.error(prefix, ...coloredArgs);
	}
}

/**
 * Create a logger object with methods for different log levels
 * @returns {Object} Logger object with info, error, debug, warn, and success methods
 */
export function createLogger() {
	const createLogMethod =
		(level) =>
		(...args) =>
			log(level, ...args);

	return {
		debug: createLogMethod('debug'),
		info: createLogMethod('info'),
		warn: createLogMethod('warn'),
		error: createLogMethod('error'),
		success: createLogMethod('success'),
		log: log // Also expose the raw log function
	};
}

// Export a default logger instance
const logger = createLogger();

export default logger;
export { log, LOG_LEVELS };

```

--------------------------------------------------------------------------------
/apps/extension/src/webview/App.tsx:
--------------------------------------------------------------------------------

```typescript
/**
 * Main App Component
 */

import React, { useReducer, useState, useEffect, useRef } from 'react';
import { VSCodeContext } from './contexts/VSCodeContext';
import { QueryProvider } from './providers/QueryProvider';
import { AppContent } from './components/AppContent';
import { ToastContainer } from './components/ToastContainer';
import { ErrorBoundary } from './components/ErrorBoundary';
import { appReducer, initialState } from './reducers/appReducer';
import { useWebviewHeight } from './hooks/useWebviewHeight';
import { useVSCodeMessages } from './hooks/useVSCodeMessages';
import {
	showSuccessToast,
	showInfoToast,
	showWarningToast,
	showErrorToast,
	createToast
} from './utils/toast';

export const App: React.FC = () => {
	const [state, dispatch] = useReducer(appReducer, initialState);
	const [vscode] = useState(() => window.acquireVsCodeApi?.());
	const availableHeight = useWebviewHeight();
	const { sendMessage } = useVSCodeMessages(vscode, state, dispatch);
	const hasInitialized = useRef(false);

	// Initialize the webview
	useEffect(() => {
		if (hasInitialized.current) return;
		hasInitialized.current = true;

		if (!vscode) {
			console.warn('⚠️ VS Code API not available - running in standalone mode');
			dispatch({
				type: 'SET_CONNECTION_STATUS',
				payload: { isConnected: false, status: 'Standalone Mode' }
			});
			return;
		}

		console.log('🔄 Initializing webview...');

		// Notify extension that webview is ready
		vscode.postMessage({ type: 'ready' });

		// React Query will handle task fetching, so we only need to load tags data
		sendMessage({ type: 'getTags' })
			.then((tagsData) => {
				if (tagsData?.tags && tagsData?.currentTag) {
					const tagNames = tagsData.tags.map((tag: any) => tag.name || tag);
					dispatch({
						type: 'SET_TAG_DATA',
						payload: {
							currentTag: tagsData.currentTag,
							availableTags: tagNames
						}
					});
				}
			})
			.catch((error) => {
				console.error('❌ Failed to load tags:', error);
			});
	}, [vscode, sendMessage, dispatch]);

	const contextValue = {
		vscode,
		state,
		dispatch,
		sendMessage,
		availableHeight,
		// Toast notification functions
		showSuccessToast: showSuccessToast(dispatch),
		showInfoToast: showInfoToast(dispatch),
		showWarningToast: showWarningToast(dispatch),
		showErrorToast: showErrorToast(dispatch)
	};

	return (
		<QueryProvider>
			<VSCodeContext.Provider value={contextValue}>
				<ErrorBoundary
					onError={(error) => {
						// Handle React errors and show appropriate toast
						dispatch({
							type: 'ADD_TOAST',
							payload: createToast(
								'error',
								'Component Error',
								`A React component crashed: ${error.message}`,
								10000
							)
						});
					}}
				>
					<AppContent />
					<ToastContainer
						notifications={state.toastNotifications}
						onDismiss={(id) => dispatch({ type: 'REMOVE_TOAST', payload: id })}
					/>
				</ErrorBoundary>
			</VSCodeContext.Provider>
		</QueryProvider>
	);
};

```

--------------------------------------------------------------------------------
/mcp-server/src/tools/research.js:
--------------------------------------------------------------------------------

```javascript
/**
 * tools/research.js
 * Tool to perform AI-powered research queries with project context
 */

import { z } from 'zod';
import {
	createErrorResponse,
	handleApiResult,
	withNormalizedProjectRoot
} from './utils.js';
import { researchDirect } from '../core/task-master-core.js';
import { resolveTag } from '../../../scripts/modules/utils.js';

/**
 * Register the research tool with the MCP server
 * @param {Object} server - FastMCP server instance
 */
export function registerResearchTool(server) {
	server.addTool({
		name: 'research',
		description: 'Perform AI-powered research queries with project context',

		parameters: z.object({
			query: z.string().describe('Research query/prompt (required)'),
			taskIds: z
				.string()
				.optional()
				.describe(
					'Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17")'
				),
			filePaths: z
				.string()
				.optional()
				.describe(
					'Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md")'
				),
			customContext: z
				.string()
				.optional()
				.describe('Additional custom context text to include in the research'),
			includeProjectTree: z
				.boolean()
				.optional()
				.describe(
					'Include project file tree structure in context (default: false)'
				),
			detailLevel: z
				.enum(['low', 'medium', 'high'])
				.optional()
				.describe('Detail level for the research response (default: medium)'),
			saveTo: z
				.string()
				.optional()
				.describe(
					'Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")'
				),
			saveToFile: z
				.boolean()
				.optional()
				.describe(
					'Save research results to .taskmaster/docs/research/ directory (default: false)'
				),
			projectRoot: z
				.string()
				.describe('The directory of the project. Must be an absolute path.'),
			tag: z.string().optional().describe('Tag context to operate on')
		}),
		execute: withNormalizedProjectRoot(async (args, { log, session }) => {
			try {
				const resolvedTag = resolveTag({
					projectRoot: args.projectRoot,
					tag: args.tag
				});
				log.info(
					`Starting research with query: "${args.query.substring(0, 100)}${args.query.length > 100 ? '...' : ''}"`
				);

				// Call the direct function
				const result = await researchDirect(
					{
						query: args.query,
						taskIds: args.taskIds,
						filePaths: args.filePaths,
						customContext: args.customContext,
						includeProjectTree: args.includeProjectTree || false,
						detailLevel: args.detailLevel || 'medium',
						saveTo: args.saveTo,
						saveToFile: args.saveToFile || false,
						projectRoot: args.projectRoot,
						tag: resolvedTag
					},
					log,
					{ session }
				);

				return handleApiResult(
					result,
					log,
					'Error performing research',
					undefined,
					args.projectRoot
				);
			} catch (error) {
				log.error(`Error in research tool: ${error.message}`);
				return createErrorResponse(error.message);
			}
		})
	});
}

```

--------------------------------------------------------------------------------
/apps/mcp/src/tools/autopilot/finalize.tool.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview autopilot-finalize MCP tool
 * Finalize and complete the workflow with working tree validation
 */

import { z } from 'zod';
import {
	handleApiResult,
	withNormalizedProjectRoot
} from '../../shared/utils.js';
import type { MCPContext } from '../../shared/types.js';
import { WorkflowService } from '@tm/core';
import type { FastMCP } from 'fastmcp';

const FinalizeSchema = z.object({
	projectRoot: z
		.string()
		.describe('Absolute path to the project root directory')
});

type FinalizeArgs = z.infer<typeof FinalizeSchema>;

/**
 * Register the autopilot_finalize tool with the MCP server
 */
export function registerAutopilotFinalizeTool(server: FastMCP) {
	server.addTool({
		name: 'autopilot_finalize',
		description:
			'Finalize and complete the workflow. Validates that all changes are committed and working tree is clean before marking workflow as complete.',
		parameters: FinalizeSchema,
		execute: withNormalizedProjectRoot(
			async (args: FinalizeArgs, context: MCPContext) => {
				const { projectRoot } = args;

				try {
					context.log.info(`Finalizing workflow in ${projectRoot}`);

					const workflowService = new WorkflowService(projectRoot);

					// Check if workflow exists
					if (!(await workflowService.hasWorkflow())) {
						return handleApiResult({
							result: {
								success: false,
								error: {
									message:
										'No active workflow found. Start a workflow with autopilot_start'
								}
							},
							log: context.log,
							projectRoot
						});
					}

					// Resume workflow
					await workflowService.resumeWorkflow();
					const currentStatus = workflowService.getStatus();

					// Verify we're in FINALIZE phase
					if (currentStatus.phase !== 'FINALIZE') {
						return handleApiResult({
							result: {
								success: false,
								error: {
									message: `Cannot finalize: workflow is in ${currentStatus.phase} phase. Complete all subtasks first.`
								}
							},
							log: context.log,
							projectRoot
						});
					}

					// Finalize workflow (validates clean working tree)
					const newStatus = await workflowService.finalizeWorkflow();

					context.log.info('Workflow finalized successfully');

					// Get next action
					const nextAction = workflowService.getNextAction();

					return handleApiResult({
						result: {
							success: true,
							data: {
								message: 'Workflow completed successfully',
								...newStatus,
								nextAction: nextAction.action,
								nextSteps: nextAction.nextSteps
							}
						},
						log: context.log,
						projectRoot
					});
				} catch (error: any) {
					context.log.error(`Error in autopilot-finalize: ${error.message}`);
					if (error.stack) {
						context.log.debug(error.stack);
					}
					return handleApiResult({
						result: {
							success: false,
							error: {
								message: `Failed to finalize workflow: ${error.message}`
							}
						},
						log: context.log,
						projectRoot
					});
				}
			}
		)
	});
}

```

--------------------------------------------------------------------------------
/apps/docs/archive/Installation.mdx:
--------------------------------------------------------------------------------

```markdown
---
title: "Installation(2)"
description: "This guide walks you through setting up Task Master in your development environment."
---

## Initial Setup

<Tip>
  MCP (Model Control Protocol) provides the easiest way to get started with Task Master directly in your editor.
</Tip>

<AccordionGroup>
  <Accordion title="Option 1: Using MCP (Recommended)" icon="sparkles">
    <Steps>
      <Step title="Add the MCP config to your editor">
        <Link href="https://cursor.sh">Cursor</Link> recommended, but it works with other text editors
        ```json
        {
        	"mcpServers": {
        		"taskmaster-ai": {
        			"command": "npx",
        			"args": ["-y", "task-master-ai"],
        			"env": {
        				"ANTHROPIC_API_KEY": "YOUR_ANTHROPIC_API_KEY_HERE",
        				"PERPLEXITY_API_KEY": "YOUR_PERPLEXITY_API_KEY_HERE",
        				"MODEL": "claude-3-7-sonnet-20250219",
        				"PERPLEXITY_MODEL": "sonar-pro",
        				"MAX_TOKENS": 128000,
        				"TEMPERATURE": 0.2,
        				"DEFAULT_SUBTASKS": 5,
        				"DEFAULT_PRIORITY": "medium"
        			}
        		}
        	}
        }
        ```
      </Step>
      <Step title="Enable the MCP in your editor settings">
        
      </Step>
      <Step title="Prompt the AI to initialize Task Master">
        > "Can you please initialize taskmaster-ai into my project?"

        **The AI will:**

        1. Create necessary project structure
        2. Set up initial configuration files
        3. Guide you through the rest of the process
        4. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`)
        5. **Use natural language commands** to interact with Task Master:

           > "Can you parse my PRD at scripts/prd.txt?"
           >
           > "What's the next task I should work on?"
           >
           > "Can you help me implement task 3?"
      </Step>
    </Steps>
  </Accordion>
  <Accordion title="Option 2: Manual Installation">
    If you prefer to use the command line interface directly:

    <Steps>
      <Step title="Install">
        <CodeGroup>

        ```bash Global
        npm install -g task-master-ai
        ```

        
        ```bash Local
        npm install task-master-ai
        ```

        </CodeGroup>
      </Step>
      <Step title="Initialize a new project">
        <CodeGroup>

        ```bash Global
        task-master init
        ```

        
        ```bash Local
        npx task-master-init
        ```

        </CodeGroup>
      </Step>
    </Steps>
    This will prompt you for project details and set up a new project with the necessary files and structure.
  </Accordion>
</AccordionGroup>

## Common Commands

<Tip>
  After setting up Task Master, you can use these commands (either via AI prompts or CLI)
</Tip>

```bash
# Parse a PRD and generate tasks
task-master parse-prd your-prd.txt

# List all tasks
task-master list

# Show the next task to work on
task-master next

# Generate task files
task-master generate 

```

--------------------------------------------------------------------------------
/packages/tm-core/src/common/constants/paths.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Path constants for Task Master Core
 * Defines all file paths and directory structure constants
 */

// .taskmaster directory structure paths
export const TASKMASTER_DIR = '.taskmaster';
export const TASKMASTER_TASKS_DIR = '.taskmaster/tasks';
export const TASKMASTER_DOCS_DIR = '.taskmaster/docs';
export const TASKMASTER_REPORTS_DIR = '.taskmaster/reports';
export const TASKMASTER_TEMPLATES_DIR = '.taskmaster/templates';

// Task Master configuration files
export const TASKMASTER_CONFIG_FILE = '.taskmaster/config.json';
export const TASKMASTER_STATE_FILE = '.taskmaster/state.json';
export const LEGACY_CONFIG_FILE = '.taskmasterconfig';

// Task Master report files
export const COMPLEXITY_REPORT_FILE =
	'.taskmaster/reports/task-complexity-report.json';
export const LEGACY_COMPLEXITY_REPORT_FILE =
	'scripts/task-complexity-report.json';

// Task Master PRD file paths
export const PRD_FILE = '.taskmaster/docs/prd.txt';
export const LEGACY_PRD_FILE = 'scripts/prd.txt';

// Task Master template files
export const EXAMPLE_PRD_FILE = '.taskmaster/templates/example_prd.txt';
export const LEGACY_EXAMPLE_PRD_FILE = 'scripts/example_prd.txt';

// Task Master task file paths
export const TASKMASTER_TASKS_FILE = '.taskmaster/tasks/tasks.json';
export const LEGACY_TASKS_FILE = 'tasks/tasks.json';

// General project files (not Task Master specific but commonly used)
export const ENV_EXAMPLE_FILE = '.env.example';
export const GITIGNORE_FILE = '.gitignore';

// Task file naming pattern
export const TASK_FILE_PREFIX = 'task_';
export const TASK_FILE_EXTENSION = '.txt';

/**
 * Task Master specific markers (absolute highest priority)
 * ONLY truly Task Master-specific markers that uniquely identify a Task Master project
 */
export const TASKMASTER_PROJECT_MARKERS = [
	'.taskmaster', // Task Master directory
	TASKMASTER_CONFIG_FILE, // .taskmaster/config.json
	TASKMASTER_TASKS_FILE, // .taskmaster/tasks/tasks.json
	LEGACY_CONFIG_FILE // .taskmasterconfig (legacy but still Task Master-specific)
] as const;

/**
 * Other project markers (only checked if no Task Master markers found)
 * Includes generic task files that could belong to any task runner/build system
 */
export const OTHER_PROJECT_MARKERS = [
	LEGACY_TASKS_FILE, // tasks/tasks.json (NOT Task Master-specific)
	'tasks.json', // Generic tasks file (NOT Task Master-specific)
	'.git', // Git repository
	'.svn', // SVN repository
	'package.json', // Node.js project
	'yarn.lock', // Yarn project
	'package-lock.json', // npm project
	'pnpm-lock.yaml', // pnpm project
	'Cargo.toml', // Rust project
	'go.mod', // Go project
	'pyproject.toml', // Python project
	'requirements.txt', // Python project
	'Gemfile', // Ruby project
	'composer.json' // PHP project
] as const;

/**
 * All project markers combined (for backward compatibility)
 * @deprecated Use TASKMASTER_PROJECT_MARKERS and OTHER_PROJECT_MARKERS separately
 */
export const PROJECT_MARKERS = [
	...TASKMASTER_PROJECT_MARKERS,
	...OTHER_PROJECT_MARKERS
] as const;

```

--------------------------------------------------------------------------------
/packages/tm-core/src/common/constants/index.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Constants for Task Master Core
 * Single source of truth for all constant values
 */

import type {
	TaskComplexity,
	TaskPriority,
	TaskStatus
} from '../types/index.js';

// Import from root package.json (monorepo root) for version info
import packageJson from '../../../../../package.json' with { type: 'json' };

/**
 * Task Master version from root package.json
 * Centralized to avoid fragile relative paths throughout the codebase
 */
export const TASKMASTER_VERSION = packageJson.version || 'unknown';

/**
 * Package name from root package.json
 */
export const PACKAGE_NAME = packageJson.name || 'task-master-ai';

/**
 * Valid task status values
 */
export const TASK_STATUSES: readonly TaskStatus[] = [
	'pending',
	'in-progress',
	'done',
	'deferred',
	'cancelled',
	'blocked',
	'review'
] as const;

/**
 * Terminal complete statuses - tasks that are finished and satisfy dependencies
 * These statuses indicate a task is in a final state and:
 * - Should count toward completion percentage
 * - Should be considered satisfied for dependency resolution
 * - Should not be selected as "next task"
 *
 * Note: 'completed' is a workflow-specific alias for 'done' used in some contexts
 */
export const TERMINAL_COMPLETE_STATUSES: readonly TaskStatus[] = [
	'done',
	'completed',
	'cancelled'
] as const;

/**
 * Check if a task status represents a terminal complete state
 *
 * @param status - The task status to check
 * @returns true if the status represents a completed/terminal task
 *
 * @example
 * ```typescript
 * isTaskComplete('done')      // true
 * isTaskComplete('completed') // true
 * isTaskComplete('cancelled') // true
 * isTaskComplete('pending')   // false
 * ```
 */
export function isTaskComplete(status: TaskStatus): boolean {
	return TERMINAL_COMPLETE_STATUSES.includes(status);
}

/**
 * Valid task priority values
 */
export const TASK_PRIORITIES: readonly TaskPriority[] = [
	'low',
	'medium',
	'high',
	'critical'
] as const;

/**
 * Valid task complexity values
 */
export const TASK_COMPLEXITIES: readonly TaskComplexity[] = [
	'simple',
	'moderate',
	'complex',
	'very-complex'
] as const;

/**
 * Valid output formats for task display
 */
export const OUTPUT_FORMATS = ['text', 'json', 'compact'] as const;
export type OutputFormat = (typeof OUTPUT_FORMATS)[number];

/**
 * Status icons for display
 */
export const STATUS_ICONS: Record<TaskStatus, string> = {
	done: '✓',
	completed: '✓',
	'in-progress': '►',
	blocked: '⭕',
	pending: '○',
	deferred: '⏸',
	cancelled: '✗',
	review: '👁'
} as const;

/**
 * Status colors for display (using chalk color names)
 */
export const STATUS_COLORS: Record<TaskStatus, string> = {
	pending: 'yellow',
	'in-progress': 'blue',
	done: 'green',
	deferred: 'gray',
	cancelled: 'red',
	blocked: 'magenta',
	review: 'cyan',
	completed: 'green'
} as const;

/**
 * Provider constants - AI model providers
 */
export * from './providers.js';

/**
 * Path constants - file paths and directory structure
 */
export * from './paths.js';

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/workflow/types.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Workflow phase definitions
 */
export type WorkflowPhase =
	| 'PREFLIGHT'
	| 'BRANCH_SETUP'
	| 'SUBTASK_LOOP'
	| 'FINALIZE'
	| 'COMPLETE';

/**
 * TDD cycle phases within subtask loop
 */
export type TDDPhase = 'RED' | 'GREEN' | 'COMMIT';

/**
 * Workflow state context
 */
export interface WorkflowContext {
	taskId: string;
	subtasks: SubtaskInfo[];
	currentSubtaskIndex: number;
	currentTDDPhase?: TDDPhase;
	branchName?: string;
	errors: WorkflowError[];
	metadata: Record<string, unknown>;
	lastTestResults?: TestResult;
}

/**
 * Test result from test execution
 */
export interface TestResult {
	total: number;
	passed: number;
	failed: number;
	skipped: number;
	phase: 'RED' | 'GREEN';
}

/**
 * Subtask information
 */
export interface SubtaskInfo {
	id: string;
	title: string;
	status: 'pending' | 'in-progress' | 'completed' | 'failed';
	attempts: number;
	maxAttempts?: number;
}

/**
 * Workflow error information
 */
export interface WorkflowError {
	phase: WorkflowPhase;
	message: string;
	timestamp: Date;
	recoverable: boolean;
}

/**
 * State machine state
 */
export interface WorkflowState {
	phase: WorkflowPhase;
	context: WorkflowContext;
}

/**
 * State transition event types
 */
export type WorkflowEvent =
	| { type: 'PREFLIGHT_COMPLETE' }
	| { type: 'BRANCH_CREATED'; branchName: string }
	| { type: 'SUBTASK_START'; subtaskId: string }
	| { type: 'RED_PHASE_COMPLETE'; testResults?: TestResult }
	| { type: 'GREEN_PHASE_COMPLETE'; testResults?: TestResult }
	| { type: 'COMMIT_COMPLETE' }
	| { type: 'SUBTASK_COMPLETE' }
	| { type: 'ALL_SUBTASKS_COMPLETE' }
	| { type: 'FINALIZE_COMPLETE' }
	| { type: 'ERROR'; error: WorkflowError }
	| { type: 'RETRY' }
	| { type: 'ABORT' };

/**
 * State transition definition
 */
export interface StateTransition {
	from: WorkflowPhase;
	to: WorkflowPhase;
	event: WorkflowEvent['type'];
	guard?: (context: WorkflowContext) => boolean;
}

/**
 * State machine configuration
 */
export interface StateMachineConfig {
	initialPhase: WorkflowPhase;
	transitions: StateTransition[];
}

/**
 * Workflow event listener
 */
export type WorkflowEventListener = (event: WorkflowEventData) => void;

/**
 * Comprehensive event data for workflow events
 */
export interface WorkflowEventData {
	type: WorkflowEventType;
	timestamp: Date;
	phase: WorkflowPhase;
	tddPhase?: TDDPhase;
	subtaskId?: string;
	data?: Record<string, unknown>;
}

/**
 * All possible workflow event types
 */
export type WorkflowEventType =
	| 'workflow:started'
	| 'workflow:completed'
	| 'workflow:error'
	| 'workflow:resumed'
	| 'phase:entered'
	| 'phase:exited'
	| 'tdd:feature-already-implemented'
	| 'tdd:red:started'
	| 'tdd:red:completed'
	| 'tdd:green:started'
	| 'tdd:green:completed'
	| 'tdd:commit:started'
	| 'tdd:commit:completed'
	| 'subtask:started'
	| 'subtask:completed'
	| 'subtask:failed'
	| 'test:run'
	| 'test:passed'
	| 'test:failed'
	| 'git:branch:created'
	| 'git:commit:created'
	| 'error:occurred'
	| 'state:persisted'
	| 'progress:updated'
	| 'adapter:configured';

```
Page 6/50FirstPrevNextLast