#
tokens: 49202/50000 16/975 files (page 19/50)
lines: off (toggle) GitHub
raw markdown copy
This is page 19 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

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/integration/clients/supabase-client.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Supabase authentication client for CLI auth flows
 */

import {
	Session,
	SupabaseClient as SupabaseJSClient,
	User,
	createClient
} from '@supabase/supabase-js';
import { getLogger } from '../../../common/logger/index.js';
import { SupabaseSessionStorage } from '../../auth/services/supabase-session-storage.js';
import { AuthenticationError } from '../../auth/types.js';

export class SupabaseAuthClient {
	private client: SupabaseJSClient | null = null;
	private sessionStorage: SupabaseSessionStorage;
	private logger = getLogger('SupabaseAuthClient');

	constructor() {
		this.sessionStorage = new SupabaseSessionStorage();
	}

	/**
	 * Get Supabase client with proper session management
	 */
	getClient(): SupabaseJSClient {
		if (!this.client) {
			// Get Supabase configuration from environment
			// Runtime vars (TM_*) take precedence over build-time vars (TM_PUBLIC_*)
			const supabaseUrl =
				process.env.TM_SUPABASE_URL || process.env.TM_PUBLIC_SUPABASE_URL;
			const supabaseAnonKey =
				process.env.TM_SUPABASE_ANON_KEY ||
				process.env.TM_PUBLIC_SUPABASE_ANON_KEY;

			if (!supabaseUrl || !supabaseAnonKey) {
				throw new AuthenticationError(
					'Supabase configuration missing. Please set TM_SUPABASE_URL and TM_SUPABASE_ANON_KEY (runtime) or TM_PUBLIC_SUPABASE_URL and TM_PUBLIC_SUPABASE_ANON_KEY (build-time) environment variables.',
					'CONFIG_MISSING'
				);
			}

			// Create client with custom storage adapter (similar to React Native AsyncStorage)
			this.client = createClient(supabaseUrl, supabaseAnonKey, {
				auth: {
					storage: this.sessionStorage,
					autoRefreshToken: true,
					persistSession: true,
					detectSessionInUrl: false
				}
			});
		}

		return this.client;
	}

	/**
	 * Initialize the client and restore session if available
	 */
	async initialize(): Promise<Session | null> {
		const client = this.getClient();

		try {
			// Get the current session from storage
			const {
				data: { session },
				error
			} = await client.auth.getSession();

			if (error) {
				this.logger.warn('Failed to restore session:', error);
				return null;
			}

			if (session) {
				this.logger.info('Session restored successfully');
			}

			return session;
		} catch (error) {
			this.logger.error('Error initializing session:', error);
			return null;
		}
	}

	/**
	 * Sign in with PKCE flow (for CLI auth)
	 */
	async signInWithPKCE(): Promise<{ url: string; codeVerifier: string }> {
		const client = this.getClient();

		try {
			// Generate PKCE challenge
			const { data, error } = await client.auth.signInWithOAuth({
				provider: 'github',
				options: {
					redirectTo:
						process.env.TM_AUTH_CALLBACK_URL ||
						'http://localhost:3421/auth/callback',
					scopes: 'email'
				}
			});

			if (error) {
				throw new AuthenticationError(
					`Failed to initiate PKCE flow: ${error.message}`,
					'PKCE_INIT_FAILED'
				);
			}

			if (!data?.url) {
				throw new AuthenticationError(
					'No authorization URL returned',
					'INVALID_RESPONSE'
				);
			}

			// Extract code_verifier from the URL or generate it
			// Note: Supabase handles PKCE internally, we just need to handle the callback
			return {
				url: data.url,
				codeVerifier: '' // Supabase manages this internally
			};
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Failed to start PKCE flow: ${(error as Error).message}`,
				'PKCE_FAILED'
			);
		}
	}

	/**
	 * Exchange authorization code for session (PKCE flow)
	 */
	async exchangeCodeForSession(code: string): Promise<Session> {
		const client = this.getClient();

		try {
			const { data, error } = await client.auth.exchangeCodeForSession(code);

			if (error) {
				throw new AuthenticationError(
					`Failed to exchange code: ${error.message}`,
					'CODE_EXCHANGE_FAILED'
				);
			}

			if (!data?.session) {
				throw new AuthenticationError(
					'No session returned from code exchange',
					'INVALID_RESPONSE'
				);
			}

			this.logger.info('Successfully exchanged code for session');
			return data.session;
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Code exchange failed: ${(error as Error).message}`,
				'CODE_EXCHANGE_FAILED'
			);
		}
	}

	/**
	 * Get the current session
	 */
	async getSession(): Promise<Session | null> {
		const client = this.getClient();

		try {
			const {
				data: { session },
				error
			} = await client.auth.getSession();

			if (error) {
				this.logger.warn('Failed to get session:', error);
				return null;
			}

			return session;
		} catch (error) {
			this.logger.error('Error getting session:', error);
			return null;
		}
	}

	/**
	 * Refresh the current session
	 */
	async refreshSession(): Promise<Session | null> {
		const client = this.getClient();

		try {
			this.logger.info('Refreshing session...');

			// Supabase will automatically use the stored refresh token
			const {
				data: { session },
				error
			} = await client.auth.refreshSession();

			if (error) {
				this.logger.error('Failed to refresh session:', error);
				throw new AuthenticationError(
					`Failed to refresh session: ${error.message}`,
					'REFRESH_FAILED'
				);
			}

			if (session) {
				this.logger.info('Successfully refreshed session');
			}

			return session;
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Failed to refresh session: ${(error as Error).message}`,
				'REFRESH_FAILED'
			);
		}
	}

	/**
	 * Get current user from session
	 */
	async getUser(): Promise<User | null> {
		const client = this.getClient();

		try {
			const {
				data: { user },
				error
			} = await client.auth.getUser();

			if (error) {
				this.logger.warn('Failed to get user:', error);
				return null;
			}

			return user;
		} catch (error) {
			this.logger.error('Error getting user:', error);
			return null;
		}
	}

	/**
	 * Sign out and clear session
	 */
	async signOut(): Promise<void> {
		const client = this.getClient();

		try {
			// Sign out with global scope to revoke all refresh tokens
			const { error } = await client.auth.signOut({ scope: 'global' });

			if (error) {
				this.logger.warn('Failed to sign out:', error);
			}

			// Clear cached session data
			this.sessionStorage.clear();
		} catch (error) {
			this.logger.error('Error during sign out:', error);
		}
	}

	/**
	 * Set session from external auth (e.g., from server callback)
	 */
	async setSession(session: Session): Promise<void> {
		const client = this.getClient();

		try {
			const { error } = await client.auth.setSession({
				access_token: session.access_token,
				refresh_token: session.refresh_token
			});

			if (error) {
				throw new AuthenticationError(
					`Failed to set session: ${error.message}`,
					'SESSION_SET_FAILED'
				);
			}

			this.logger.info('Session set successfully');
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Failed to set session: ${(error as Error).message}`,
				'SESSION_SET_FAILED'
			);
		}
	}

	/**
	 * Verify a one-time token and create a session
	 * Used for CLI authentication with pre-generated tokens
	 */
	async verifyOneTimeCode(token: string): Promise<Session> {
		const client = this.getClient();

		try {
			this.logger.info('Verifying authentication token...');

			// Use Supabase's verifyOtp for token verification
			// Using token_hash with magiclink type doesn't require email
			const { data, error } = await client.auth.verifyOtp({
				token_hash: token,
				type: 'magiclink'
			});

			if (error) {
				this.logger.error('Failed to verify token:', error);
				throw new AuthenticationError(
					`Failed to verify token: ${error.message}`,
					'INVALID_CODE'
				);
			}

			if (!data?.session) {
				throw new AuthenticationError(
					'No session returned from token verification',
					'INVALID_RESPONSE'
				);
			}

			this.logger.info('Successfully verified authentication token');
			return data.session;
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Token verification failed: ${(error as Error).message}`,
				'CODE_AUTH_FAILED'
			);
		}
	}
}

```

--------------------------------------------------------------------------------
/packages/tm-core/src/common/utils/project-root-finder.spec.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Tests for project root finder utilities
 */

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import path from 'node:path';
import fs from 'node:fs';
import os from 'node:os';
import {
	findProjectRoot,
	normalizeProjectRoot
} from './project-root-finder.js';

describe('findProjectRoot', () => {
	let tempDir: string;
	let originalCwd: string;

	beforeEach(() => {
		// Save original working directory
		originalCwd = process.cwd();
		// Create a temporary directory for testing
		tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tm-test-'));
	});

	afterEach(() => {
		// Restore original working directory
		process.chdir(originalCwd);
		// Clean up temp directory
		if (fs.existsSync(tempDir)) {
			fs.rmSync(tempDir, { recursive: true, force: true });
		}
	});

	describe('Task Master marker detection', () => {
		it('should find .taskmaster directory in current directory', () => {
			const taskmasterDir = path.join(tempDir, '.taskmaster');
			fs.mkdirSync(taskmasterDir);

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find .taskmaster directory in parent directory', () => {
			const parentDir = tempDir;
			const childDir = path.join(tempDir, 'child');
			const taskmasterDir = path.join(parentDir, '.taskmaster');

			fs.mkdirSync(taskmasterDir);
			fs.mkdirSync(childDir);

			const result = findProjectRoot(childDir);
			expect(result).toBe(parentDir);
		});

		it('should find .taskmaster/config.json marker', () => {
			const configDir = path.join(tempDir, '.taskmaster');
			fs.mkdirSync(configDir);
			fs.writeFileSync(path.join(configDir, 'config.json'), '{}');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find .taskmaster/tasks/tasks.json marker', () => {
			const tasksDir = path.join(tempDir, '.taskmaster', 'tasks');
			fs.mkdirSync(tasksDir, { recursive: true });
			fs.writeFileSync(path.join(tasksDir, 'tasks.json'), '{}');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find .taskmasterconfig (legacy) marker', () => {
			fs.writeFileSync(path.join(tempDir, '.taskmasterconfig'), '{}');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});
	});

	describe('Monorepo behavior - Task Master markers take precedence', () => {
		it('should find .taskmaster in parent when starting from apps subdirectory', () => {
			// Simulate exact user scenario:
			// /project/.taskmaster exists
			// Starting from /project/apps
			const projectRoot = tempDir;
			const appsDir = path.join(tempDir, 'apps');
			const taskmasterDir = path.join(projectRoot, '.taskmaster');

			fs.mkdirSync(taskmasterDir);
			fs.mkdirSync(appsDir);

			// When called from apps directory
			const result = findProjectRoot(appsDir);
			// Should return project root (one level up)
			expect(result).toBe(projectRoot);
		});

		it('should prioritize .taskmaster in parent over .git in child', () => {
			// Create structure: /parent/.taskmaster and /parent/child/.git
			const parentDir = tempDir;
			const childDir = path.join(tempDir, 'child');
			const gitDir = path.join(childDir, '.git');
			const taskmasterDir = path.join(parentDir, '.taskmaster');

			fs.mkdirSync(taskmasterDir);
			fs.mkdirSync(childDir);
			fs.mkdirSync(gitDir);

			// When called from child directory
			const result = findProjectRoot(childDir);
			// Should return parent (with .taskmaster), not child (with .git)
			expect(result).toBe(parentDir);
		});

		it('should prioritize .taskmaster in grandparent over package.json in child', () => {
			// Create structure: /grandparent/.taskmaster and /grandparent/parent/child/package.json
			const grandparentDir = tempDir;
			const parentDir = path.join(tempDir, 'parent');
			const childDir = path.join(parentDir, 'child');
			const taskmasterDir = path.join(grandparentDir, '.taskmaster');

			fs.mkdirSync(taskmasterDir);
			fs.mkdirSync(parentDir);
			fs.mkdirSync(childDir);
			fs.writeFileSync(path.join(childDir, 'package.json'), '{}');

			const result = findProjectRoot(childDir);
			expect(result).toBe(grandparentDir);
		});

		it('should prioritize .taskmaster over multiple other project markers', () => {
			// Create structure with many markers
			const parentDir = tempDir;
			const childDir = path.join(tempDir, 'packages', 'my-package');
			const taskmasterDir = path.join(parentDir, '.taskmaster');

			fs.mkdirSync(taskmasterDir);
			fs.mkdirSync(childDir, { recursive: true });

			// Add multiple other project markers in child
			fs.mkdirSync(path.join(childDir, '.git'));
			fs.writeFileSync(path.join(childDir, 'package.json'), '{}');
			fs.writeFileSync(path.join(childDir, 'go.mod'), '');
			fs.writeFileSync(path.join(childDir, 'Cargo.toml'), '');

			const result = findProjectRoot(childDir);
			// Should still return parent with .taskmaster
			expect(result).toBe(parentDir);
		});
	});

	describe('Other project marker detection (when no Task Master markers)', () => {
		it('should find .git directory', () => {
			const gitDir = path.join(tempDir, '.git');
			fs.mkdirSync(gitDir);

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find package.json', () => {
			fs.writeFileSync(path.join(tempDir, 'package.json'), '{}');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find go.mod', () => {
			fs.writeFileSync(path.join(tempDir, 'go.mod'), '');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find Cargo.toml (Rust)', () => {
			fs.writeFileSync(path.join(tempDir, 'Cargo.toml'), '');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});

		it('should find pyproject.toml (Python)', () => {
			fs.writeFileSync(path.join(tempDir, 'pyproject.toml'), '');

			const result = findProjectRoot(tempDir);
			expect(result).toBe(tempDir);
		});
	});

	describe('Edge cases', () => {
		it('should return current directory if no markers found', () => {
			const result = findProjectRoot(tempDir);
			// Should fall back to process.cwd()
			expect(result).toBe(process.cwd());
		});

		it('should handle permission errors gracefully', () => {
			// This test is hard to implement portably, but the function should handle it
			const result = findProjectRoot(tempDir);
			expect(typeof result).toBe('string');
		});

		it('should not traverse more than 50 levels', () => {
			// Create a deep directory structure
			let deepDir = tempDir;
			for (let i = 0; i < 60; i++) {
				deepDir = path.join(deepDir, `level${i}`);
			}
			// Don't actually create it, just test the function doesn't hang
			const result = findProjectRoot(deepDir);
			expect(typeof result).toBe('string');
		});

		it('should handle being called from filesystem root', () => {
			const rootDir = path.parse(tempDir).root;
			const result = findProjectRoot(rootDir);
			expect(typeof result).toBe('string');
		});
	});
});

describe('normalizeProjectRoot', () => {
	it('should remove .taskmaster from path', () => {
		const result = normalizeProjectRoot('/project/.taskmaster');
		expect(result).toBe('/project');
	});

	it('should remove .taskmaster/subdirectory from path', () => {
		const result = normalizeProjectRoot('/project/.taskmaster/tasks');
		expect(result).toBe('/project');
	});

	it('should return unchanged path if no .taskmaster', () => {
		const result = normalizeProjectRoot('/project/src');
		expect(result).toBe('/project/src');
	});

	it('should handle paths with native separators', () => {
		// Use native path separators for the test
		const testPath = ['project', '.taskmaster', 'tasks'].join(path.sep);
		const expectedPath = 'project';
		const result = normalizeProjectRoot(testPath);
		expect(result).toBe(expectedPath);
	});

	it('should handle empty string', () => {
		const result = normalizeProjectRoot('');
		expect(result).toBe('');
	});

	it('should handle null', () => {
		const result = normalizeProjectRoot(null);
		expect(result).toBe('');
	});

	it('should handle undefined', () => {
		const result = normalizeProjectRoot(undefined);
		expect(result).toBe('');
	});

	it('should handle root .taskmaster', () => {
		const sep = path.sep;
		const result = normalizeProjectRoot(`${sep}.taskmaster`);
		expect(result).toBe(sep);
	});
});

```

--------------------------------------------------------------------------------
/tests/e2e/parse_llm_output.cjs:
--------------------------------------------------------------------------------

```
#!/usr/bin/env node

// Note: We will use dynamic import() inside the async callback due to project being type: module

const readline = require('readline');
const path = require('path'); // Import path module

let inputData = '';

const rl = readline.createInterface({
	input: process.stdin,
	output: process.stdout,
	terminal: false
});

rl.on('line', (line) => {
	inputData += line;
});

// Make the callback async to allow await for dynamic imports
rl.on('close', async () => {
	let chalk, boxen, Table;
	try {
		// Dynamically import libraries
		chalk = (await import('chalk')).default;
		boxen = (await import('boxen')).default;
		Table = (await import('cli-table3')).default;

		// 1. Parse the initial API response body
		const apiResponse = JSON.parse(inputData);

		// 2. Extract the text content containing the nested JSON
		// Robust check for content structure
		const textContent = apiResponse?.content?.[0]?.text;
		if (!textContent) {
			console.error(
				chalk.red(
					"Error: Could not find '.content[0].text' in the API response JSON."
				)
			);
			process.exit(1);
		}

		// 3. Find the start of the actual JSON block
		const jsonStart = textContent.indexOf('{');
		const jsonEnd = textContent.lastIndexOf('}');

		if (jsonStart === -1 || jsonEnd === -1 || jsonEnd < jsonStart) {
			console.error(
				chalk.red(
					'Error: Could not find JSON block starting with { and ending with } in the extracted text content.'
				)
			);
			process.exit(1);
		}
		const jsonString = textContent.substring(jsonStart, jsonEnd + 1);

		// 4. Parse the extracted JSON string
		let reportData;
		try {
			reportData = JSON.parse(jsonString);
		} catch (parseError) {
			console.error(
				chalk.red('Error: Failed to parse the extracted JSON block.')
			);
			console.error(chalk.red('Parse Error:'), parseError.message);
			process.exit(1);
		}

		// Ensure reportData is an object
		if (typeof reportData !== 'object' || reportData === null) {
			console.error(
				chalk.red('Error: Parsed report data is not a valid object.')
			);
			process.exit(1);
		}

		// --- Get Log File Path and Format Timestamp ---
		const logFilePath = process.argv[2]; // Get the log file path argument
		let formattedTime = 'Unknown';
		if (logFilePath) {
			const logBasename = path.basename(logFilePath);
			const timestampMatch = logBasename.match(/e2e_run_(\d{8}_\d{6})\.log$/);
			if (timestampMatch && timestampMatch[1]) {
				const ts = timestampMatch[1]; // YYYYMMDD_HHMMSS
				// Format into YYYY-MM-DD HH:MM:SS
				formattedTime = `${ts.substring(0, 4)}-${ts.substring(4, 6)}-${ts.substring(6, 8)} ${ts.substring(9, 11)}:${ts.substring(11, 13)}:${ts.substring(13, 15)}`;
			}
		}
		// --------------------------------------------

		// 5. Generate CLI Report (with defensive checks)
		console.log(
			'\n' +
				chalk.cyan.bold(
					boxen(
						`TASKMASTER E2E Log Analysis Report\nRun Time: ${chalk.yellow(formattedTime)}`, // Display formatted time
						{
							padding: 1,
							borderStyle: 'double',
							borderColor: 'cyan',
							textAlign: 'center' // Center align title
						}
					)
				) +
				'\n'
		);

		// Overall Status
		let statusColor = chalk.white;
		const overallStatus = reportData.overall_status || 'Unknown'; // Default if missing
		if (overallStatus === 'Success') statusColor = chalk.green.bold;
		if (overallStatus === 'Warning') statusColor = chalk.yellow.bold;
		if (overallStatus === 'Failure') statusColor = chalk.red.bold;
		console.log(
			boxen(`Overall Status: ${statusColor(overallStatus)}`, {
				padding: { left: 1, right: 1 },
				margin: { bottom: 1 },
				borderColor: 'blue'
			})
		);

		// LLM Summary Points
		console.log(chalk.blue.bold('📋 Summary Points:'));
		if (
			Array.isArray(reportData.llm_summary_points) &&
			reportData.llm_summary_points.length > 0
		) {
			reportData.llm_summary_points.forEach((point) => {
				console.log(chalk.white(`  - ${point || 'N/A'}`)); // Handle null/undefined points
			});
		} else {
			console.log(chalk.gray('  No summary points provided.'));
		}
		console.log();

		// Verified Steps
		console.log(chalk.green.bold('✅ Verified Steps:'));
		if (
			Array.isArray(reportData.verified_steps) &&
			reportData.verified_steps.length > 0
		) {
			reportData.verified_steps.forEach((step) => {
				console.log(chalk.green(`  - ${step || 'N/A'}`)); // Handle null/undefined steps
			});
		} else {
			console.log(chalk.gray('  No verified steps listed.'));
		}
		console.log();

		// Provider Add-Task Comparison
		console.log(chalk.magenta.bold('🔄 Provider Add-Task Comparison:'));
		const comp = reportData.provider_add_task_comparison;
		if (typeof comp === 'object' && comp !== null) {
			console.log(
				chalk.white(`  Prompt Used: ${comp.prompt_used || 'Not specified'}`)
			);
			console.log();

			if (
				typeof comp.provider_results === 'object' &&
				comp.provider_results !== null &&
				Object.keys(comp.provider_results).length > 0
			) {
				const providerTable = new Table({
					head: ['Provider', 'Status', 'Task ID', 'Score', 'Notes'].map((h) =>
						chalk.magenta.bold(h)
					),
					colWidths: [15, 18, 10, 12, 45],
					style: { head: [], border: [] },
					wordWrap: true
				});

				for (const provider in comp.provider_results) {
					const result = comp.provider_results[provider] || {}; // Default to empty object if provider result is null/undefined
					const status = result.status || 'Unknown';
					const isSuccess = status === 'Success';
					const statusIcon = isSuccess ? chalk.green('✅') : chalk.red('❌');
					const statusText = isSuccess
						? chalk.green(status)
						: chalk.red(status);
					providerTable.push([
						chalk.white(provider),
						`${statusIcon} ${statusText}`,
						chalk.white(result.task_id || 'N/A'),
						chalk.white(result.score || 'N/A'),
						chalk.dim(result.notes || 'N/A')
					]);
				}
				console.log(providerTable.toString());
				console.log();
			} else {
				console.log(chalk.gray('  No provider results available.'));
				console.log();
			}
			console.log(chalk.white.bold(`  Comparison Summary:`));
			console.log(chalk.white(`  ${comp.comparison_summary || 'N/A'}`));
		} else {
			console.log(chalk.gray('  Provider comparison data not found.'));
		}
		console.log();

		// Detected Issues
		console.log(chalk.red.bold('🚨 Detected Issues:'));
		if (
			Array.isArray(reportData.detected_issues) &&
			reportData.detected_issues.length > 0
		) {
			reportData.detected_issues.forEach((issue, index) => {
				if (typeof issue !== 'object' || issue === null) return; // Skip invalid issue entries

				const severity = issue.severity || 'Unknown';
				let boxColor = 'blue';
				let icon = 'ℹ️';
				if (severity === 'Error') {
					boxColor = 'red';
					icon = '❌';
				}
				if (severity === 'Warning') {
					boxColor = 'yellow';
					icon = '⚠️';
				}

				let issueContent = `${chalk.bold('Description:')} ${chalk.white(issue.description || 'N/A')}`;
				// Only add log context if it exists and is not empty
				if (issue.log_context && String(issue.log_context).trim()) {
					issueContent += `\n${chalk.bold('Log Context:')} \n${chalk.dim(String(issue.log_context).trim())}`;
				}

				console.log(
					boxen(issueContent, {
						title: `${icon} Issue ${index + 1}: [${severity}]`,
						padding: 1,
						margin: { top: 1, bottom: 0 },
						borderColor: boxColor,
						borderStyle: 'round'
					})
				);
			});
			console.log(); // Add final newline if issues exist
		} else {
			console.log(chalk.green('  No specific issues detected by the LLM.'));
		}
		console.log();

		console.log(chalk.cyan.bold('========================================'));
		console.log(chalk.cyan.bold('          End of LLM Report'));
		console.log(chalk.cyan.bold('========================================\n'));
	} catch (error) {
		// Ensure chalk is available for error reporting, provide fallback
		const errorChalk = chalk || { red: (t) => t, yellow: (t) => t };
		console.error(
			errorChalk.red('Error processing LLM response:'),
			error.message
		);
		// Avoid printing potentially huge inputData here unless necessary for debugging
		// console.error(errorChalk.yellow('Raw input data (first 500 chars):'), inputData.substring(0, 500));
		process.exit(1);
	}
});

// Handle potential errors during stdin reading
process.stdin.on('error', (err) => {
	console.error('Error reading standard input:', err);
	process.exit(1);
});

```

--------------------------------------------------------------------------------
/apps/extension/src/services/error-handler.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Error Handler Service
 * Centralized error handling with categorization and recovery strategies
 */

import * as vscode from 'vscode';
import type { ExtensionLogger } from '../utils/logger';

export enum ErrorSeverity {
	LOW = 'low',
	MEDIUM = 'medium',
	HIGH = 'high',
	CRITICAL = 'critical'
}

export enum ErrorCategory {
	MCP_CONNECTION = 'mcp_connection',
	CONFIGURATION = 'configuration',
	TASK_LOADING = 'task_loading',
	NETWORK = 'network',
	INTERNAL = 'internal'
}

export interface ErrorContext {
	category: ErrorCategory;
	severity: ErrorSeverity;
	message: string;
	originalError?: Error | unknown;
	operation?: string;
	taskId?: string;
	isRecoverable?: boolean;
	suggestedActions?: string[];
}

export class ErrorHandler {
	private errorLog: Map<string, ErrorContext> = new Map();
	private errorId = 0;

	constructor(private logger: ExtensionLogger) {}

	/**
	 * Handle an error with appropriate logging and user notification
	 */
	handleError(context: ErrorContext): string {
		const errorId = `error_${++this.errorId}`;
		this.errorLog.set(errorId, context);

		// Log to extension logger
		this.logError(context);

		// Show user notification if appropriate
		this.notifyUser(context);

		return errorId;
	}

	/**
	 * Log error based on severity
	 */
	private logError(context: ErrorContext): void {
		const logMessage = `[${context.category}] ${context.message}`;
		const details = {
			operation: context.operation,
			taskId: context.taskId,
			error: context.originalError
		};

		switch (context.severity) {
			case ErrorSeverity.CRITICAL:
			case ErrorSeverity.HIGH:
				this.logger.error(logMessage, details);
				break;
			case ErrorSeverity.MEDIUM:
				this.logger.warn(logMessage, details);
				break;
			case ErrorSeverity.LOW:
				this.logger.debug(logMessage, details);
				break;
		}
	}

	/**
	 * Show user notification based on severity and category
	 */
	/**
	 * Validate if an action is allowed
	 */
	private isValidAction(action: string): boolean {
		// Define predefined valid actions
		const predefinedActions = [
			'Retry',
			'Settings',
			'Reload',
			'Dismiss',
			'View Logs',
			'Report Issue'
		];

		// Check if it's a predefined action or a TaskMaster command
		return predefinedActions.includes(action) || action.startsWith('tm.');
	}

	/**
	 * Filter and validate suggested actions
	 */
	private getValidActions(actions: string[]): string[] {
		return actions.filter((action) => this.isValidAction(action));
	}

	private notifyUser(context: ErrorContext): void {
		// Don't show low severity errors to users
		if (context.severity === ErrorSeverity.LOW) {
			return;
		}

		// Validate and filter suggested actions
		const rawActions = context.suggestedActions || [];
		const actions = this.getValidActions(rawActions);

		// Log if any actions were filtered out
		if (rawActions.length !== actions.length) {
			this.logger.warn('Invalid actions filtered out:', {
				original: rawActions,
				filtered: actions,
				removed: rawActions.filter((a) => !actions.includes(a))
			});
		}

		switch (context.severity) {
			case ErrorSeverity.CRITICAL:
				vscode.window
					.showErrorMessage(`TaskMaster: ${context.message}`, ...actions)
					.then((action) => {
						if (action) {
							this.handleUserAction(action, context);
						}
					});
				break;

			case ErrorSeverity.HIGH:
				if (context.category === ErrorCategory.MCP_CONNECTION) {
					// Use validated actions or default actions for MCP connection
					const mcpActions =
						actions.length > 0 ? actions : ['Retry', 'Settings'];
					vscode.window
						.showWarningMessage(`TaskMaster: ${context.message}`, ...mcpActions)
						.then((action) => {
							if (action === 'Retry') {
								vscode.commands.executeCommand('tm.reconnect');
							} else if (action === 'Settings') {
								vscode.commands.executeCommand('tm.openSettings');
							} else if (action) {
								this.handleUserAction(action, context);
							}
						});
				} else {
					// Show warning with validated actions
					if (actions.length > 0) {
						vscode.window
							.showWarningMessage(`TaskMaster: ${context.message}`, ...actions)
							.then((action) => {
								if (action) {
									this.handleUserAction(action, context);
								}
							});
					} else {
						vscode.window.showWarningMessage(`TaskMaster: ${context.message}`);
					}
				}
				break;

			case ErrorSeverity.MEDIUM:
				// Only show medium errors for important categories
				if (
					[ErrorCategory.CONFIGURATION, ErrorCategory.TASK_LOADING].includes(
						context.category
					)
				) {
					if (actions.length > 0) {
						vscode.window
							.showInformationMessage(
								`TaskMaster: ${context.message}`,
								...actions
							)
							.then((action) => {
								if (action) {
									this.handleUserAction(action, context);
								}
							});
					} else {
						vscode.window.showInformationMessage(
							`TaskMaster: ${context.message}`
						);
					}
				}
				break;
		}
	}

	/**
	 * Handle user action from notification
	 */
	private handleUserAction(action: string, context: ErrorContext): void {
		this.logger.debug(`User selected action: ${action}`, {
			errorContext: context
		});

		// Handle predefined actions
		switch (action) {
			case 'Retry':
				if (context.category === ErrorCategory.MCP_CONNECTION) {
					vscode.commands.executeCommand('tm.reconnect');
				} else {
					vscode.commands.executeCommand('tm.refreshTasks');
				}
				break;

			case 'Settings':
				vscode.commands.executeCommand('tm.openSettings');
				break;

			case 'Reload':
				vscode.commands.executeCommand('workbench.action.reloadWindow');
				break;

			case 'View Logs':
				// Show error details in a modal dialog instead of output channel
				this.showErrorDetails(context);
				break;

			case 'Report Issue':
				const issueUrl = this.generateIssueUrl(context);
				vscode.env.openExternal(vscode.Uri.parse(issueUrl));
				break;

			case 'Dismiss':
				// No action needed
				break;

			default:
				// Handle TaskMaster commands (tm.*)
				if (action.startsWith('tm.')) {
					void vscode.commands.executeCommand(action).then(
						() => {},
						(error: unknown) => {
							this.logger.error(`Failed to execute command: ${action}`, error);
						}
					);
				}
				break;
		}
	}

	/**
	 * Show detailed error information in a modal dialog
	 */
	private showErrorDetails(context: ErrorContext): void {
		const details = [
			`**Error Details**`,
			``,
			`Category: ${context.category}`,
			`Severity: ${context.severity}`,
			`Message: ${context.message}`,
			context.operation ? `Operation: ${context.operation}` : '',
			context.taskId ? `Task ID: ${context.taskId}` : '',
			context.originalError ? `\nOriginal Error:\n${context.originalError}` : ''
		]
			.filter(Boolean)
			.join('\n');

		vscode.window.showInformationMessage(details, {
			modal: true,
			detail: details
		});
	}

	/**
	 * Generate GitHub issue URL with pre-filled information
	 */
	private generateIssueUrl(context: ErrorContext): string {
		const title = encodeURIComponent(`[Extension Error] ${context.message}`);
		const body = encodeURIComponent(
			[
				`**Error Details:**`,
				`- Category: ${context.category}`,
				`- Severity: ${context.severity}`,
				`- Message: ${context.message}`,
				context.operation ? `- Operation: ${context.operation}` : '',
				context.taskId ? `- Task ID: ${context.taskId}` : '',
				``,
				`**Context:**`,
				'```json',
				JSON.stringify(context, null, 2),
				'```',
				``,
				`**Environment:**`,
				`- VS Code Version: ${vscode.version}`,
				`- Extension Version: ${vscode.extensions.getExtension('Hamster.taskmaster')?.packageJSON.version || 'Unknown'}`,
				``,
				`**Steps to Reproduce:**`,
				`1. [Please describe the steps that led to this error]`,
				``,
				`**Expected Behavior:**`,
				`[What should have happened instead]`
			]
				.filter(Boolean)
				.join('\n')
		);

		return `https://github.com/eyaltoledano/claude-task-master/issues/new?title=${title}&body=${body}`;
	}

	/**
	 * Get error by ID
	 */
	getError(errorId: string): ErrorContext | undefined {
		return this.errorLog.get(errorId);
	}

	/**
	 * Clear old errors (keep last 100)
	 */
	clearOldErrors(): void {
		if (this.errorLog.size > 100) {
			const entriesToKeep = Array.from(this.errorLog.entries()).slice(-100);
			this.errorLog.clear();
			entriesToKeep.forEach(([id, error]) => this.errorLog.set(id, error));
		}
	}
}

```

--------------------------------------------------------------------------------
/tests/unit/scripts/modules/task-manager/scope-adjustment.test.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Tests for scope-adjustment.js module
 */
import { jest } from '@jest/globals';

// Mock dependencies using unstable_mockModule for ES modules
jest.unstable_mockModule('../../../../../scripts/modules/utils.js', () => ({
	log: jest.fn(),
	readJSON: jest.fn(),
	writeJSON: jest.fn(),
	getCurrentTag: jest.fn(() => 'master'),
	readComplexityReport: jest.fn(),
	findTaskInComplexityReport: jest.fn(),
	findProjectRoot: jest.fn()
}));

jest.unstable_mockModule(
	'../../../../../scripts/modules/ai-services-unified.js',
	() => ({
		generateObjectService: jest.fn(),
		generateTextService: jest.fn()
	})
);

jest.unstable_mockModule(
	'../../../../../scripts/modules/task-manager.js',
	() => ({
		findTaskById: jest.fn(),
		taskExists: jest.fn()
	})
);

jest.unstable_mockModule(
	'../../../../../scripts/modules/task-manager/analyze-task-complexity.js',
	() => ({
		default: jest.fn()
	})
);

jest.unstable_mockModule('../../../../../src/utils/path-utils.js', () => ({
	findComplexityReportPath: jest.fn()
}));

// Import modules after mocking
const {
	log,
	readJSON,
	writeJSON,
	readComplexityReport,
	findTaskInComplexityReport
} = await import('../../../../../scripts/modules/utils.js');
const { generateObjectService } = await import(
	'../../../../../scripts/modules/ai-services-unified.js'
);
const { findTaskById, taskExists } = await import(
	'../../../../../scripts/modules/task-manager.js'
);
const { scopeUpTask, scopeDownTask, validateStrength } = await import(
	'../../../../../scripts/modules/task-manager/scope-adjustment.js'
);

describe('Scope Adjustment Commands', () => {
	beforeEach(() => {
		jest.clearAllMocks();
	});

	describe('scopeUpTask', () => {
		it('should increase task complexity with regular strength', async () => {
			// Mock existing task data
			const mockTasksData = {
				tasks: [
					{
						id: 1,
						title: 'Simple Task',
						description: 'Basic description',
						details: 'Basic implementation details',
						status: 'pending'
					}
				]
			};

			const mockTask = {
				id: 1,
				title: 'Simple Task',
				description: 'Basic description',
				details: 'Basic implementation details',
				status: 'pending'
			};

			readJSON.mockReturnValue(mockTasksData);
			taskExists.mockReturnValue(true);
			findTaskById.mockReturnValue({ task: mockTask });
			generateObjectService.mockResolvedValue({
				mainResult: {
					title: 'Complex Task with Advanced Features',
					description: 'Enhanced description with more requirements',
					details:
						'Detailed implementation with error handling, validation, and advanced features',
					testStrategy:
						'Comprehensive testing including unit, integration, and edge cases'
				},
				telemetryData: { tokens: 100, cost: 0.01 }
			});

			const context = {
				projectRoot: '/test/project',
				tag: 'master',
				commandName: 'scope-up',
				outputType: 'cli'
			};

			const result = await scopeUpTask(
				'/test/tasks.json',
				[1],
				'regular',
				null, // no custom prompt
				context,
				'text'
			);

			expect(result).toBeDefined();
			expect(result.updatedTasks).toHaveLength(1);
			expect(result.telemetryData).toBeDefined();
			expect(writeJSON).toHaveBeenCalledWith(
				'/test/tasks.json',
				expect.objectContaining({
					tasks: expect.arrayContaining([
						expect.objectContaining({
							id: 1,
							title: 'Complex Task with Advanced Features'
						})
					])
				}),
				'/test/project',
				'master'
			);
		});

		it('should handle custom prompts for targeted scope adjustments', async () => {
			const mockTasksData = {
				tasks: [
					{
						id: 1,
						title: 'Simple Task',
						description: 'Basic description',
						details: 'Basic implementation details',
						status: 'pending'
					}
				]
			};

			const mockTask = {
				id: 1,
				title: 'Simple Task',
				description: 'Basic description',
				details: 'Basic implementation details',
				status: 'pending'
			};

			readJSON.mockReturnValue(mockTasksData);
			taskExists.mockReturnValue(true);
			findTaskById.mockReturnValue({ task: mockTask });
			generateObjectService.mockResolvedValue({
				mainResult: {
					title: 'Task with Enhanced Security',
					description: 'Description with security considerations',
					details: 'Implementation with security validation and encryption',
					testStrategy: 'Security-focused testing strategy'
				},
				telemetryData: { tokens: 120, cost: 0.012 }
			});

			const context = {
				projectRoot: '/test/project',
				tag: 'master',
				commandName: 'scope-up',
				outputType: 'cli'
			};

			const customPrompt = 'Focus on adding security features and validation';

			const result = await scopeUpTask(
				'/test/tasks.json',
				[1],
				'heavy',
				customPrompt,
				context,
				'text'
			);

			expect(result).toBeDefined();
			expect(generateObjectService).toHaveBeenCalledWith(
				expect.objectContaining({
					prompt: expect.stringContaining(
						'Focus on adding security features and validation'
					)
				})
			);
		});
	});

	describe('scopeDownTask', () => {
		it('should decrease task complexity with regular strength', async () => {
			const mockTasksData = {
				tasks: [
					{
						id: 1,
						title: 'Complex Task with Many Features',
						description: 'Comprehensive description with multiple requirements',
						details:
							'Detailed implementation with advanced features, error handling, validation',
						status: 'pending'
					}
				]
			};

			const mockTask = {
				id: 1,
				title: 'Complex Task with Many Features',
				description: 'Comprehensive description with multiple requirements',
				details:
					'Detailed implementation with advanced features, error handling, validation',
				status: 'pending'
			};

			readJSON.mockReturnValue(mockTasksData);
			taskExists.mockReturnValue(true);
			findTaskById.mockReturnValue({ task: mockTask });
			generateObjectService.mockResolvedValue({
				mainResult: {
					title: 'Simple Task',
					description: 'Basic description',
					details: 'Basic implementation focusing on core functionality',
					testStrategy: 'Simple unit tests for core functionality'
				},
				telemetryData: { tokens: 80, cost: 0.008 }
			});

			const context = {
				projectRoot: '/test/project',
				tag: 'master',
				commandName: 'scope-down',
				outputType: 'cli'
			};

			const result = await scopeDownTask(
				'/test/tasks.json',
				[1],
				'regular',
				null,
				context,
				'text'
			);

			expect(result).toBeDefined();
			expect(result.updatedTasks).toHaveLength(1);
			expect(writeJSON).toHaveBeenCalled();
		});
	});

	describe('strength level validation', () => {
		it('should validate strength parameter correctly', () => {
			expect(validateStrength('light')).toBe(true);
			expect(validateStrength('regular')).toBe(true);
			expect(validateStrength('heavy')).toBe(true);
			expect(validateStrength('invalid')).toBe(false);
			expect(validateStrength('')).toBe(false);
			expect(validateStrength(null)).toBe(false);
		});
	});

	describe('multiple task IDs handling', () => {
		it('should handle comma-separated task IDs', async () => {
			const mockTasksData = {
				tasks: [
					{
						id: 1,
						title: 'Task 1',
						description: 'Desc 1',
						details: 'Details 1',
						status: 'pending'
					},
					{
						id: 2,
						title: 'Task 2',
						description: 'Desc 2',
						details: 'Details 2',
						status: 'pending'
					}
				]
			};

			readJSON.mockReturnValue(mockTasksData);
			taskExists.mockReturnValue(true);
			findTaskById
				.mockReturnValueOnce({
					task: {
						id: 1,
						title: 'Task 1',
						description: 'Desc 1',
						details: 'Details 1',
						status: 'pending'
					}
				})
				.mockReturnValueOnce({
					task: {
						id: 2,
						title: 'Task 2',
						description: 'Desc 2',
						details: 'Details 2',
						status: 'pending'
					}
				});

			generateObjectService.mockResolvedValue({
				mainResult: {
					title: 'Enhanced Task',
					description: 'Enhanced description',
					details: 'Enhanced details',
					testStrategy: 'Enhanced testing'
				},
				telemetryData: { tokens: 100, cost: 0.01 }
			});

			const context = {
				projectRoot: '/test/project',
				tag: 'master',
				commandName: 'scope-up',
				outputType: 'cli'
			};

			const result = await scopeUpTask(
				'/test/tasks.json',
				[1, 2],
				'regular',
				null,
				context,
				'text'
			);

			expect(result.updatedTasks).toHaveLength(2);
			expect(generateObjectService).toHaveBeenCalledTimes(2);
		});
	});
});

```

--------------------------------------------------------------------------------
/apps/cli/src/commands/show.command.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview ShowCommand using Commander's native class pattern
 * Extends Commander.Command for better integration with the framework
 */

import { type Task, type TmCore, createTmCore } from '@tm/core';
import type { StorageType, Subtask } from '@tm/core';
import boxen from 'boxen';
import chalk from 'chalk';
import { Command } from 'commander';
import { displayTaskDetails } from '../ui/components/task-detail.component.js';
import { displayCommandHeader } from '../utils/display-helpers.js';
import { displayError } from '../utils/error-handler.js';
import * as ui from '../utils/ui.js';
import { getProjectRoot } from '../utils/project-root.js';

/**
 * Options interface for the show command
 */
export interface ShowCommandOptions {
	id?: string;
	status?: string;
	format?: 'text' | 'json';
	json?: boolean;
	silent?: boolean;
	project?: string;
}

/**
 * Result type from show command
 */
export interface ShowTaskResult {
	task: Task | Subtask | null;
	found: boolean;
	storageType: Exclude<StorageType, 'auto'>;
	originalTaskId?: string; // The original task ID requested (for subtasks like "104.1")
}

/**
 * Result type for multiple tasks
 */
export interface ShowMultipleTasksResult {
	tasks: (Task | Subtask)[];
	notFound: string[];
	storageType: Exclude<StorageType, 'auto'>;
}

/**
 * ShowCommand extending Commander's Command class
 * This is a thin presentation layer over @tm/core
 */
export class ShowCommand extends Command {
	private tmCore?: TmCore;
	private lastResult?: ShowTaskResult | ShowMultipleTasksResult;

	constructor(name?: string) {
		super(name || 'show');

		// Configure the command
		this.description('Display detailed information about one or more tasks')
			.argument('[id]', 'Task ID(s) to show (comma-separated for multiple)')
			.option(
				'-i, --id <id>',
				'Task ID(s) to show (comma-separated for multiple)'
			)
			.option('-s, --status <status>', 'Filter subtasks by status')
			.option('-f, --format <format>', 'Output format (text, json)', 'text')
			.option('--json', 'Output in JSON format (shorthand for --format json)')
			.option('--silent', 'Suppress output (useful for programmatic usage)')
			.option(
				'-p, --project <path>',
				'Project root directory (auto-detected if not provided)'
			)
			.action(
				async (taskId: string | undefined, options: ShowCommandOptions) => {
					await this.executeCommand(taskId, options);
				}
			);
	}

	/**
	 * Execute the show command
	 */
	private async executeCommand(
		taskId: string | undefined,
		options: ShowCommandOptions
	): Promise<void> {
		try {
			// Validate options
			if (!this.validateOptions(options)) {
				process.exit(1);
			}

			// Initialize tm-core
			await this.initializeCore(getProjectRoot(options.project));

			// Get the task ID from argument or option
			const idArg = taskId || options.id;
			if (!idArg) {
				console.error(chalk.red('Error: Please provide a task ID'));
				process.exit(1);
			}

			// Check if multiple IDs are provided (comma-separated)
			const taskIds = idArg
				.split(',')
				.map((id) => id.trim())
				.filter((id) => id.length > 0);

			// Get tasks from core
			const result =
				taskIds.length > 1
					? await this.getMultipleTasks(taskIds, options)
					: await this.getSingleTask(taskIds[0], options);

			// Store result for programmatic access
			this.setLastResult(result);

			// Display results
			if (!options.silent) {
				this.displayResults(result, options);
			}
		} catch (error: any) {
			displayError(error);
		}
	}

	/**
	 * Validate command options
	 */
	private validateOptions(options: ShowCommandOptions): boolean {
		// Validate format
		if (options.format && !['text', 'json'].includes(options.format)) {
			console.error(chalk.red(`Invalid format: ${options.format}`));
			console.error(chalk.gray(`Valid formats: text, json`));
			return false;
		}

		return true;
	}

	/**
	 * Initialize TmCore
	 */
	private async initializeCore(projectRoot: string): Promise<void> {
		if (!this.tmCore) {
			this.tmCore = await createTmCore({ projectPath: projectRoot });
		}
	}

	/**
	 * Get a single task from tm-core
	 */
	private async getSingleTask(
		taskId: string,
		_options: ShowCommandOptions
	): Promise<ShowTaskResult> {
		if (!this.tmCore) {
			throw new Error('TmCore not initialized');
		}

		// Get the task
		const result = await this.tmCore.tasks.get(taskId);

		// Get storage type
		const storageType = this.tmCore.tasks.getStorageType();

		return {
			task: result.task,
			found: result.task !== null,
			storageType: storageType as Exclude<StorageType, 'auto'>,
			originalTaskId: result.isSubtask ? taskId : undefined
		};
	}

	/**
	 * Get multiple tasks from tm-core
	 */
	private async getMultipleTasks(
		taskIds: string[],
		_options: ShowCommandOptions
	): Promise<ShowMultipleTasksResult> {
		if (!this.tmCore) {
			throw new Error('TmCore not initialized');
		}

		const tasks: (Task | Subtask)[] = [];
		const notFound: string[] = [];

		// Get each task individually
		for (const taskId of taskIds) {
			const result = await this.tmCore.tasks.get(taskId);
			if (result.task) {
				tasks.push(result.task);
			} else {
				notFound.push(taskId);
			}
		}

		// Get storage type (resolved, not config value)
		const storageType = this.tmCore.tasks.getStorageType();

		return {
			tasks,
			notFound,
			storageType
		};
	}

	/**
	 * Display results based on format
	 */
	private displayResults(
		result: ShowTaskResult | ShowMultipleTasksResult,
		options: ShowCommandOptions
	): void {
		// If --json flag is set, override format to 'json'
		const format = options.json ? 'json' : options.format || 'text';

		switch (format) {
			case 'json':
				this.displayJson(result);
				break;

			case 'text':
			default:
				if ('task' in result) {
					// Single task result
					this.displaySingleTask(result, options);
				} else {
					// Multiple tasks result
					this.displayMultipleTasks(result, options);
				}
				break;
		}
	}

	/**
	 * Display in JSON format
	 */
	private displayJson(result: ShowTaskResult | ShowMultipleTasksResult): void {
		console.log(JSON.stringify(result, null, 2));
	}

	/**
	 * Display a single task in text format
	 */
	private displaySingleTask(
		result: ShowTaskResult,
		options: ShowCommandOptions
	): void {
		if (!result.found || !result.task) {
			console.log(
				boxen(chalk.yellow(`Task not found!`), {
					padding: { top: 0, bottom: 0, left: 1, right: 1 },
					borderColor: 'yellow',
					borderStyle: 'round',
					margin: { top: 1 }
				})
			);
			return;
		}

		// Display header with storage info
		const activeTag = this.tmCore?.config.getActiveTag() || 'master';
		displayCommandHeader(this.tmCore, {
			tag: activeTag,
			storageType: result.storageType
		});

		console.log(); // Add spacing

		// Use the global task details display function
		// Pass the original requested ID if it's a subtask
		displayTaskDetails(result.task, {
			statusFilter: options.status,
			showSuggestedActions: true,
			originalTaskId: result.originalTaskId,
			storageType: result.storageType
		});
	}

	/**
	 * Display multiple tasks in text format
	 */
	private displayMultipleTasks(
		result: ShowMultipleTasksResult,
		_options: ShowCommandOptions
	): void {
		// Display header with storage info
		const activeTag = this.tmCore?.config.getActiveTag() || 'master';
		displayCommandHeader(this.tmCore, {
			tag: activeTag,
			storageType: result.storageType
		});

		if (result.notFound.length > 0) {
			console.log(chalk.yellow(`\n⚠️ Not found: ${result.notFound.join(', ')}`));
		}

		if (result.tasks.length === 0) {
			ui.displayWarning('No tasks found matching the criteria.');
			return;
		}

		// Task table
		console.log(chalk.blue.bold(`\n📋 Tasks:\n`));
		console.log(
			ui.createTaskTable(result.tasks, {
				showSubtasks: true,
				showDependencies: true
			})
		);
	}

	/**
	 * Set the last result for programmatic access
	 */
	private setLastResult(
		result: ShowTaskResult | ShowMultipleTasksResult
	): void {
		this.lastResult = result;
	}

	/**
	 * Get the last result (for programmatic usage)
	 */
	getLastResult(): ShowTaskResult | ShowMultipleTasksResult | undefined {
		return this.lastResult;
	}

	/**
	 * Clean up resources
	 */
	async cleanup(): Promise<void> {
		if (this.tmCore) {
			this.tmCore = undefined;
		}
	}

	/**
	 * Register this command on an existing program
	 */
	static register(program: Command, name?: string): ShowCommand {
		const showCommand = new ShowCommand(name);
		program.addCommand(showCommand);
		return showCommand;
	}
}

```

--------------------------------------------------------------------------------
/tests/unit/scripts/modules/task-manager/remove-subtask.test.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Tests for the removeSubtask function
 */
import { jest } from '@jest/globals';
import path from 'path';

// Mock dependencies
const mockReadJSON = jest.fn();
const mockWriteJSON = jest.fn();
const mockGenerateTaskFiles = jest.fn();

// Mock path module
jest.mock('path', () => ({
	dirname: jest.fn()
}));

// Define test version of the removeSubtask function
const testRemoveSubtask = (
	tasksPath,
	subtaskId,
	convertToTask = false,
	generateFiles = true,
	context = { tag: 'master' }
) => {
	const { projectRoot = undefined, tag = 'master' } = context;
	// Read the existing tasks
	const data = mockReadJSON(tasksPath, projectRoot, tag);
	if (!data || !data.tasks) {
		throw new Error(`Invalid or missing tasks file at ${tasksPath}`);
	}

	// Parse the subtask ID (format: "parentId.subtaskId")
	if (!subtaskId.includes('.')) {
		throw new Error(`Invalid subtask ID format: ${subtaskId}`);
	}

	const [parentIdStr, subtaskIdStr] = subtaskId.split('.');
	const parentId = parseInt(parentIdStr, 10);
	const subtaskIdNum = parseInt(subtaskIdStr, 10);

	// Find the parent task
	const parentTask = data.tasks.find((t) => t.id === parentId);
	if (!parentTask) {
		throw new Error(`Parent task with ID ${parentId} not found`);
	}

	// Check if parent has subtasks
	if (!parentTask.subtasks || parentTask.subtasks.length === 0) {
		throw new Error(`Parent task ${parentId} has no subtasks`);
	}

	// Find the subtask to remove
	const subtaskIndex = parentTask.subtasks.findIndex(
		(st) => st.id === subtaskIdNum
	);
	if (subtaskIndex === -1) {
		throw new Error(`Subtask ${subtaskId} not found`);
	}

	// Get a copy of the subtask before removing it
	const removedSubtask = { ...parentTask.subtasks[subtaskIndex] };

	// Remove the subtask from the parent
	parentTask.subtasks.splice(subtaskIndex, 1);

	// If parent has no more subtasks, remove the subtasks array
	if (parentTask.subtasks.length === 0) {
		delete parentTask.subtasks;
	}

	let convertedTask = null;

	// Convert the subtask to a standalone task if requested
	if (convertToTask) {
		// Find the highest task ID to determine the next ID
		const highestId = Math.max(...data.tasks.map((t) => t.id));
		const newTaskId = highestId + 1;

		// Create the new task from the subtask
		convertedTask = {
			id: newTaskId,
			title: removedSubtask.title,
			description: removedSubtask.description || '',
			details: removedSubtask.details || '',
			status: removedSubtask.status || 'pending',
			dependencies: removedSubtask.dependencies || [],
			priority: parentTask.priority || 'medium' // Inherit priority from parent
		};

		// Add the parent task as a dependency if not already present
		if (!convertedTask.dependencies.includes(parentId)) {
			convertedTask.dependencies.push(parentId);
		}

		// Add the converted task to the tasks array
		data.tasks.push(convertedTask);
	}

	// Write the updated tasks back to the file
	mockWriteJSON(tasksPath, data, projectRoot, tag);

	// Generate task files if requested
	if (generateFiles) {
		mockGenerateTaskFiles(tasksPath, path.dirname(tasksPath));
	}

	return convertedTask;
};

describe('removeSubtask function', () => {
	// Reset mocks before each test
	beforeEach(() => {
		jest.clearAllMocks();

		// Default mock implementations
		mockReadJSON.mockImplementation((p, root, tag) => {
			expect(tag).toBeDefined();
			expect(tag).toBe('master');
			return {
				tasks: [
					{
						id: 1,
						title: 'Parent Task',
						description: 'This is a parent task',
						status: 'pending',
						dependencies: [],
						subtasks: [
							{
								id: 1,
								title: 'Subtask 1',
								description: 'This is subtask 1',
								status: 'pending',
								dependencies: [],
								parentTaskId: 1
							},
							{
								id: 2,
								title: 'Subtask 2',
								description: 'This is subtask 2',
								status: 'in-progress',
								dependencies: [1], // Depends on subtask 1
								parentTaskId: 1
							}
						]
					},
					{
						id: 2,
						title: 'Another Task',
						description: 'This is another task',
						status: 'pending',
						dependencies: [1]
					}
				]
			};
		});

		// Setup success write response
		mockWriteJSON.mockImplementation((path, data, root, tag) => {
			expect(tag).toBe('master');
			return data;
		});
	});

	test('should remove a subtask from its parent task', async () => {
		// Execute the test version of removeSubtask to remove subtask 1.1
		testRemoveSubtask('tasks/tasks.json', '1.1', false, true, {
			tag: 'master'
		});

		// Verify readJSON was called with the correct path
		expect(mockReadJSON).toHaveBeenCalledWith(
			'tasks/tasks.json',
			undefined,
			'master'
		);

		// Verify writeJSON was called with updated data
		expect(mockWriteJSON).toHaveBeenCalled();

		// Verify generateTaskFiles was called
		// expect(mockGenerateTaskFiles).toHaveBeenCalled();
	});

	test('should convert a subtask to a standalone task', async () => {
		// Execute the test version of removeSubtask to convert subtask 1.1 to a standalone task
		const result = testRemoveSubtask('tasks/tasks.json', '1.1', true, true, {
			tag: 'master'
		});

		// Verify the result is the new task
		expect(result).toBeDefined();
		expect(result.id).toBe(3);
		expect(result.title).toBe('Subtask 1');
		expect(result.dependencies).toContain(1);

		// Verify writeJSON was called
		expect(mockWriteJSON).toHaveBeenCalled();

		// Verify generateTaskFiles was called
		// expect(mockGenerateTaskFiles).toHaveBeenCalled();
	});

	test('should throw an error if subtask ID format is invalid', async () => {
		// Expect an error for invalid subtask ID format
		expect(() =>
			testRemoveSubtask('tasks/tasks.json', '1', false, true, { tag: 'master' })
		).toThrow(/Invalid subtask ID format/);

		// Verify writeJSON was not called
		expect(mockWriteJSON).not.toHaveBeenCalled();
	});

	test('should throw an error if parent task does not exist', async () => {
		// Expect an error for non-existent parent task
		expect(() =>
			testRemoveSubtask('tasks/tasks.json', '999.1', false, true, {
				tag: 'master'
			})
		).toThrow(/Parent task with ID 999 not found/);

		// Verify writeJSON was not called
		expect(mockWriteJSON).not.toHaveBeenCalled();
	});

	test('should throw an error if subtask does not exist', async () => {
		// Expect an error for non-existent subtask
		expect(() =>
			testRemoveSubtask('tasks/tasks.json', '1.999', false, true, {
				tag: 'master'
			})
		).toThrow(/Subtask 1.999 not found/);

		// Verify writeJSON was not called
		expect(mockWriteJSON).not.toHaveBeenCalled();
	});

	test('should remove subtasks array if last subtask is removed', async () => {
		// Create a data object with just one subtask
		mockReadJSON.mockImplementationOnce((p, root, tag) => {
			expect(tag).toBe('master');
			return {
				tasks: [
					{
						id: 1,
						title: 'Parent Task',
						description: 'This is a parent task',
						status: 'pending',
						dependencies: [],
						subtasks: [
							{
								id: 1,
								title: 'Last Subtask',
								description: 'This is the last subtask',
								status: 'pending',
								dependencies: [],
								parentTaskId: 1
							}
						]
					},
					{
						id: 2,
						title: 'Another Task',
						description: 'This is another task',
						status: 'pending',
						dependencies: [1]
					}
				]
			};
		});

		// Mock the behavior of writeJSON to capture the updated tasks data
		const updatedTasksData = { tasks: [] };
		mockWriteJSON.mockImplementation((path, data, root, tag) => {
			expect(tag).toBe('master');
			// Store the data for assertions
			updatedTasksData.tasks = [...data.tasks];
			return data;
		});

		// Remove the last subtask
		testRemoveSubtask('tasks/tasks.json', '1.1', false, true, {
			tag: 'master'
		});

		// Verify writeJSON was called
		expect(mockWriteJSON).toHaveBeenCalled();

		// Verify the subtasks array was removed completely
		const parentTask = updatedTasksData.tasks.find((t) => t.id === 1);
		expect(parentTask).toBeDefined();
		expect(parentTask.subtasks).toBeUndefined();

		// Verify generateTaskFiles was called
		// expect(mockGenerateTaskFiles).toHaveBeenCalled();
	});

	test('should not regenerate task files if generateFiles is false', async () => {
		// Execute the test version of removeSubtask with generateFiles = false
		testRemoveSubtask('tasks/tasks.json', '1.1', false, false, {
			tag: 'master'
		});

		// Verify writeJSON was called
		expect(mockWriteJSON).toHaveBeenCalled();

		// Verify task files were not regenerated
		expect(mockGenerateTaskFiles).not.toHaveBeenCalled();
	});
});

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/storage/services/storage-factory.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Storage factory for creating appropriate storage implementations
 */

import {
	ERROR_CODES,
	TaskMasterError
} from '../../../common/errors/task-master-error.js';
import type {
	IConfiguration,
	RuntimeStorageConfig,
	StorageSettings
} from '../../../common/interfaces/configuration.interface.js';
import type { IStorage } from '../../../common/interfaces/storage.interface.js';
import { getLogger } from '../../../common/logger/index.js';
import { AuthManager } from '../../auth/managers/auth-manager.js';
import { SupabaseAuthClient } from '../../integration/clients/supabase-client.js';
import { ApiStorage } from '../adapters/api-storage.js';
import { FileStorage } from '../adapters/file-storage/index.js';

/**
 * Factory for creating storage implementations based on configuration
 */
export class StorageFactory {
	/**
	 * Create a storage implementation from runtime storage config
	 * This is the preferred method when you have a RuntimeStorageConfig
	 * @param storageConfig - Runtime storage configuration
	 * @param projectPath - Project root path (for file storage)
	 * @returns Storage implementation
	 */
	static async createFromStorageConfig(
		storageConfig: RuntimeStorageConfig,
		projectPath: string
	): Promise<IStorage> {
		// Wrap the storage config in the expected format, including projectPath
		// This ensures ApiStorage receives the projectPath for projectId
		return StorageFactory.create(
			{ storage: storageConfig, projectPath } as Partial<IConfiguration>,
			projectPath
		);
	}

	/**
	 * Create a storage implementation based on configuration
	 * @param config - Configuration object
	 * @param projectPath - Project root path (for file storage)
	 * @returns Storage implementation
	 */
	static async create(
		config: Partial<IConfiguration>,
		projectPath: string
	): Promise<IStorage> {
		const storageType = config.storage?.type || 'auto';

		const logger = getLogger('StorageFactory');

		switch (storageType) {
			case 'file':
				logger.debug('📁 Using local file storage');
				return StorageFactory.createFileStorage(projectPath, config);

			case 'api':
				if (!StorageFactory.isHamsterAvailable(config)) {
					const missing: string[] = [];
					if (!config.storage?.apiEndpoint) missing.push('apiEndpoint');
					if (!config.storage?.apiAccessToken) missing.push('apiAccessToken');

					// Check if authenticated via AuthManager
					const authManager = AuthManager.getInstance();
					const hasSession = await authManager.hasValidSession();
					if (!hasSession) {
						throw new TaskMasterError(
							`API storage not fully configured (${missing.join(', ') || 'credentials missing'}). Run: tm auth login, or set the missing field(s).`,
							ERROR_CODES.MISSING_CONFIGURATION,
							{ storageType: 'api', missing }
						);
					}
					// Use auth token from AuthManager
					const accessToken = await authManager.getAccessToken();
					if (accessToken) {
						// Merge with existing storage config, ensuring required fields
						const nextStorage: StorageSettings = {
							...(config.storage as StorageSettings),
							type: 'api',
							apiAccessToken: accessToken,
							apiEndpoint:
								config.storage?.apiEndpoint ||
								process.env.TM_BASE_DOMAIN ||
								process.env.TM_PUBLIC_BASE_DOMAIN ||
								'https://tryhamster.com/api'
						};

						// Validate that apiEndpoint is defined
						if (!nextStorage.apiEndpoint) {
							throw new TaskMasterError(
								'API endpoint could not be determined.',
								ERROR_CODES.MISSING_CONFIGURATION,
								{ storageType: 'api' }
							);
						}

						config.storage = nextStorage;
					}
				}
				logger.info('☁️  Using API storage');
				return StorageFactory.createApiStorage(config);

			case 'auto':
				// Auto-detect based on authentication status
				const authManager = AuthManager.getInstance();

				// First check if API credentials are explicitly configured
				if (StorageFactory.isHamsterAvailable(config)) {
					logger.info('☁️  Using API storage (configured)');
					return StorageFactory.createApiStorage(config);
				}

				// Then check if authenticated via Supabase
				const hasSession = await authManager.hasValidSession();
				if (hasSession) {
					const accessToken = await authManager.getAccessToken();
					const context = authManager.getContext();

					// Validate we have the necessary context for API storage
					if (!context?.briefId) {
						logger.debug(
							'📁 User authenticated but no brief selected, using file storage'
						);
						return StorageFactory.createFileStorage(projectPath, config);
					}

					if (accessToken) {
						// Configure API storage with Supabase session token
						const nextStorage: StorageSettings = {
							...(config.storage as StorageSettings),
							type: 'api',
							apiAccessToken: accessToken,
							apiEndpoint:
								config.storage?.apiEndpoint ||
								process.env.TM_BASE_DOMAIN ||
								process.env.TM_PUBLIC_BASE_DOMAIN ||
								'https://tryhamster.com/api'
						};
						config.storage = nextStorage;
						logger.info('☁️  Using API storage (authenticated)');
						return StorageFactory.createApiStorage(config);
					}
				}

				// Default to file storage
				logger.debug('📁 Using local file storage');
				return StorageFactory.createFileStorage(projectPath, config);

			default:
				throw new TaskMasterError(
					`Unknown storage type: ${storageType}`,
					ERROR_CODES.INVALID_INPUT,
					{ storageType }
				);
		}
	}

	/**
	 * Create file storage implementation
	 */
	private static createFileStorage(
		projectPath: string,
		config: Partial<IConfiguration>
	): FileStorage {
		const basePath = config.storage?.basePath || projectPath;
		return new FileStorage(basePath);
	}

	/**
	 * Create API storage implementation
	 */
	private static createApiStorage(config: Partial<IConfiguration>): ApiStorage {
		// Use our SupabaseAuthClient instead of creating a raw Supabase client
		const supabaseAuthClient = new SupabaseAuthClient();
		const supabaseClient = supabaseAuthClient.getClient();

		return new ApiStorage({
			supabaseClient,
			projectId: config.projectPath || '',
			enableRetry: config.retry?.retryOnNetworkError,
			maxRetries: config.retry?.retryAttempts
		});
	}

	/**
	 * Detect optimal storage type based on available configuration
	 */
	static detectOptimalStorage(config: Partial<IConfiguration>): 'file' | 'api' {
		// If API credentials are provided, prefer API storage (Hamster)
		if (config.storage?.apiEndpoint && config.storage?.apiAccessToken) {
			return 'api';
		}

		// Default to file storage
		return 'file';
	}

	/**
	 * Validate storage configuration
	 */
	static validateStorageConfig(config: Partial<IConfiguration>): {
		isValid: boolean;
		errors: string[];
	} {
		const errors: string[] = [];
		const storageType = config.storage?.type;

		if (!storageType) {
			errors.push('Storage type is not specified');
			return { isValid: false, errors };
		}

		switch (storageType) {
			case 'api':
				if (!config.storage?.apiEndpoint) {
					errors.push('API endpoint is required for API storage');
				}
				if (!config.storage?.apiAccessToken) {
					errors.push('API access token is required for API storage');
				}
				break;

			case 'file':
				// File storage doesn't require additional config
				break;

			case 'auto':
				// Auto storage is valid - it will determine the actual type at runtime
				// No specific validation needed as it will fall back to file if API not configured
				break;

			default:
				errors.push(`Unknown storage type: ${storageType}`);
		}

		return {
			isValid: errors.length === 0,
			errors
		};
	}

	/**
	 * Check if Hamster (API storage) is available
	 */
	static isHamsterAvailable(config: Partial<IConfiguration>): boolean {
		return !!(config.storage?.apiEndpoint && config.storage?.apiAccessToken);
	}

	/**
	 * Create a storage implementation with fallback
	 * Tries API storage first, falls back to file storage
	 */
	static async createWithFallback(
		config: Partial<IConfiguration>,
		projectPath: string
	): Promise<IStorage> {
		// Try API storage if configured
		if (StorageFactory.isHamsterAvailable(config)) {
			try {
				const apiStorage = StorageFactory.createApiStorage(config);
				await apiStorage.initialize();
				return apiStorage;
			} catch (error) {
				const logger = getLogger('StorageFactory');
				logger.warn(
					'Failed to initialize API storage, falling back to file storage:',
					error
				);
			}
		}

		// Fallback to file storage
		return StorageFactory.createFileStorage(projectPath, config);
	}
}

```

--------------------------------------------------------------------------------
/apps/extension/src/components/ConfigView.tsx:
--------------------------------------------------------------------------------

```typescript
import { ArrowLeft, RefreshCw, Settings } from 'lucide-react';
import type React from 'react';
import { useEffect, useState, useCallback } from 'react';
import { Badge } from './ui/badge';
import { Button } from './ui/button';
import {
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle
} from './ui/card';
import { ScrollArea } from './ui/scroll-area';
import { Separator } from './ui/separator';

interface ModelConfig {
	provider: string;
	modelId: string;
	maxTokens: number;
	temperature: number;
}

interface ConfigData {
	models?: {
		main?: ModelConfig;
		research?: ModelConfig;
		fallback?: ModelConfig;
	};
	global?: {
		defaultNumTasks?: number;
		defaultSubtasks?: number;
		defaultPriority?: string;
		projectName?: string;
		responseLanguage?: string;
	};
}

interface ConfigViewProps {
	sendMessage: (message: any) => Promise<any>;
	onNavigateBack: () => void;
}

export const ConfigView: React.FC<ConfigViewProps> = ({
	sendMessage,
	onNavigateBack
}) => {
	const [config, setConfig] = useState<ConfigData | null>(null);
	const [loading, setLoading] = useState(true);
	const [error, setError] = useState<string | null>(null);

	const loadConfig = useCallback(async () => {
		setLoading(true);
		setError(null);
		try {
			const response = await sendMessage({ type: 'getConfig' });
			setConfig(response);
		} catch (err) {
			setError('Failed to load configuration');
			console.error('Error loading config:', err);
		} finally {
			setLoading(false);
		}
	}, [sendMessage]);

	useEffect(() => {
		loadConfig();
	}, [loadConfig]);

	const modelLabels = {
		main: {
			label: 'Main Model',
			icon: '🤖',
			description: 'Primary model for task generation'
		},
		research: {
			label: 'Research Model',
			icon: '🔍',
			description: 'Model for research-backed operations'
		},
		fallback: {
			label: 'Fallback Model',
			icon: '🔄',
			description: 'Backup model if primary fails'
		}
	};

	return (
		<div className="flex flex-col h-full bg-vscode-editor-background">
			{/* Header */}
			<div className="flex items-center justify-between px-4 py-3 border-b border-vscode-border">
				<div className="flex items-center gap-3">
					<Button
						variant="ghost"
						size="icon"
						onClick={onNavigateBack}
						className="h-8 w-8"
					>
						<ArrowLeft className="h-4 w-4" />
					</Button>
					<div className="flex items-center gap-2">
						<Settings className="w-5 h-5" />
						<h1 className="text-lg font-semibold">Task Master Configuration</h1>
					</div>
				</div>
				<Button
					variant="ghost"
					size="icon"
					onClick={loadConfig}
					className="h-8 w-8"
				>
					<RefreshCw className="h-4 w-4" />
				</Button>
			</div>

			{/* Content */}
			<ScrollArea className="flex-1 overflow-hidden">
				<div className="p-6 pb-12">
					{loading ? (
						<div className="flex items-center justify-center py-8">
							<RefreshCw className="w-6 h-6 animate-spin text-vscode-foreground/50" />
						</div>
					) : error ? (
						<div className="text-red-500 text-center py-8">{error}</div>
					) : config ? (
						<div className="space-y-6 max-w-4xl mx-auto">
							{/* Models Section */}
							<Card>
								<CardHeader>
									<CardTitle>AI Models</CardTitle>
									<CardDescription>
										Models configured for different Task Master operations
									</CardDescription>
								</CardHeader>
								<CardContent className="space-y-4">
									{config.models &&
										Object.entries(config.models).map(([key, modelConfig]) => {
											const label =
												modelLabels[key as keyof typeof modelLabels];
											if (!label || !modelConfig) return null;

											return (
												<div key={key} className="space-y-2">
													<div className="flex items-center gap-2">
														<span className="text-lg">{label.icon}</span>
														<div>
															<h4 className="font-medium">{label.label}</h4>
															<p className="text-xs text-vscode-foreground/60">
																{label.description}
															</p>
														</div>
													</div>
													<div className="bg-vscode-input/20 rounded-md p-3 space-y-1">
														<div className="flex justify-between">
															<span className="text-sm text-vscode-foreground/80">
																Provider:
															</span>
															<Badge variant="secondary">
																{modelConfig.provider}
															</Badge>
														</div>
														<div className="flex justify-between">
															<span className="text-sm text-vscode-foreground/80">
																Model:
															</span>
															<code className="text-xs font-mono bg-vscode-input/30 px-2 py-1 rounded">
																{modelConfig.modelId}
															</code>
														</div>
														<div className="flex justify-between">
															<span className="text-sm text-vscode-foreground/80">
																Max Tokens:
															</span>
															<span className="text-sm">
																{modelConfig.maxTokens.toLocaleString()}
															</span>
														</div>
														<div className="flex justify-between">
															<span className="text-sm text-vscode-foreground/80">
																Temperature:
															</span>
															<span className="text-sm">
																{modelConfig.temperature}
															</span>
														</div>
													</div>
												</div>
											);
										})}
								</CardContent>
							</Card>

							{/* Task Defaults Section */}
							{config.global && (
								<Card>
									<CardHeader>
										<CardTitle>Task Defaults</CardTitle>
										<CardDescription>
											Default values for new tasks and subtasks
										</CardDescription>
									</CardHeader>
									<CardContent>
										<div className="space-y-3">
											<div className="flex justify-between items-center">
												<span className="text-sm font-medium">
													Default Number of Tasks
												</span>
												<Badge variant="outline">
													{config.global.defaultNumTasks || 10}
												</Badge>
											</div>
											<Separator />
											<div className="flex justify-between items-center">
												<span className="text-sm font-medium">
													Default Number of Subtasks
												</span>
												<Badge variant="outline">
													{config.global.defaultSubtasks || 5}
												</Badge>
											</div>
											<Separator />
											<div className="flex justify-between items-center">
												<span className="text-sm font-medium">
													Default Priority
												</span>
												<Badge
													variant={
														config.global.defaultPriority === 'high'
															? 'destructive'
															: config.global.defaultPriority === 'low'
																? 'secondary'
																: 'default'
													}
												>
													{config.global.defaultPriority || 'medium'}
												</Badge>
											</div>
											{config.global.projectName && (
												<>
													<Separator />
													<div className="flex justify-between items-center">
														<span className="text-sm font-medium">
															Project Name
														</span>
														<span className="text-sm text-vscode-foreground/80">
															{config.global.projectName}
														</span>
													</div>
												</>
											)}
											{config.global.responseLanguage && (
												<>
													<Separator />
													<div className="flex justify-between items-center">
														<span className="text-sm font-medium">
															Response Language
														</span>
														<span className="text-sm text-vscode-foreground/80">
															{config.global.responseLanguage}
														</span>
													</div>
												</>
											)}
										</div>
									</CardContent>
								</Card>
							)}

							{/* Info Card */}
							<Card>
								<CardContent className="pt-6">
									<p className="text-sm text-vscode-foreground/60">
										To modify these settings, go to{' '}
										<code className="bg-vscode-input/30 px-1 py-0.5 rounded">
											.taskmaster/config.json
										</code>{' '}
										and modify them, or use the MCP.
									</p>
								</CardContent>
							</Card>
						</div>
					) : (
						<div className="text-center py-8 text-vscode-foreground/50">
							No configuration found. Please run `task-master init` in your
							project.
						</div>
					)}
				</div>
			</ScrollArea>
		</div>
	);
};

```

--------------------------------------------------------------------------------
/src/prompts/expand-task.json:
--------------------------------------------------------------------------------

```json
{
	"id": "expand-task",
	"version": "1.0.0",
	"description": "Break down a task into detailed subtasks",
	"metadata": {
		"author": "system",
		"created": "2024-01-01T00:00:00Z",
		"updated": "2024-01-01T00:00:00Z",
		"tags": ["expansion", "subtasks", "breakdown"]
	},
	"parameters": {
		"subtaskCount": {
			"type": "number",
			"required": true,
			"description": "Number of subtasks to generate"
		},
		"task": {
			"type": "object",
			"required": true,
			"description": "The task to expand"
		},
		"nextSubtaskId": {
			"type": "number",
			"required": true,
			"description": "Starting ID for new subtasks"
		},
		"useResearch": {
			"type": "boolean",
			"default": false,
			"description": "Use research mode"
		},
		"expansionPrompt": {
			"type": "string",
			"required": false,
			"description": "Expansion prompt from complexity report"
		},
		"additionalContext": {
			"type": "string",
			"required": false,
			"default": "",
			"description": "Additional context for task expansion"
		},
		"complexityReasoningContext": {
			"type": "string",
			"required": false,
			"default": "",
			"description": "Complexity analysis reasoning context"
		},
		"gatheredContext": {
			"type": "string",
			"required": false,
			"default": "",
			"description": "Gathered project context"
		},
		"hasCodebaseAnalysis": {
			"type": "boolean",
			"required": false,
			"default": false,
			"description": "Whether codebase analysis is available"
		},
		"projectRoot": {
			"type": "string",
			"required": false,
			"default": "",
			"description": "Project root path for context"
		}
	},
	"prompts": {
		"complexity-report": {
			"condition": "expansionPrompt",
			"system": "You are an AI assistant helping with task breakdown. Generate {{#if (gt subtaskCount 0)}}exactly {{subtaskCount}}{{else}}an appropriate number of{{/if}} subtasks based on the provided prompt and context.\n\nIMPORTANT: Your response MUST be a JSON object with a \"subtasks\" property containing an array of subtask objects. Each subtask must include ALL of the following fields:\n- id: MUST be sequential integers starting EXACTLY from {{nextSubtaskId}}. First subtask id={{nextSubtaskId}}, second id={{nextSubtaskId}}+1, etc. DO NOT use any other numbering pattern!\n- title: A clear, actionable title (5-200 characters)\n- description: A detailed description (minimum 10 characters)\n- dependencies: An array of task IDs this subtask depends on (can be empty [])\n- details: Implementation details (minimum 20 characters)\n- status: Must be \"pending\" for new subtasks\n- testStrategy: Testing approach (can be null)\n\nYou may optionally include a \"metadata\" object. Do not include any other top-level properties.",

			"user": "Break down the following task:\n\nParent Task:\nID: {{task.id}}\nTitle: {{task.title}}\nDescription: {{task.description}}\nCurrent details: {{#if task.details}}{{task.details}}{{else}}None{{/if}}\n\n{{expansionPrompt}}{{#if additionalContext}}\n\n{{additionalContext}}{{/if}}{{#if complexityReasoningContext}}\n\n{{complexityReasoningContext}}{{/if}}{{#if gatheredContext}}\n\n# Project Context\n\n{{gatheredContext}}{{/if}}\n\nGenerate {{#if (gt subtaskCount 0)}}exactly {{subtaskCount}}{{else}}an appropriate number of{{/if}} subtasks. CRITICAL: Use sequential IDs starting from {{nextSubtaskId}} (first={{nextSubtaskId}}, second={{nextSubtaskId}}+1, etc.)."
		},
		"research": {
			"condition": "useResearch === true && !expansionPrompt",
			"system": "You are an AI assistant with research capabilities analyzing and breaking down software development tasks.\n\nIMPORTANT: Your response MUST be a JSON object with a \"subtasks\" property containing an array of subtask objects. Each subtask must include ALL of the following fields:\n- id: MUST be sequential integers starting EXACTLY from {{nextSubtaskId}}. First subtask id={{nextSubtaskId}}, second id={{nextSubtaskId}}+1, etc. DO NOT use any other numbering pattern!\n- title: A clear, actionable title (5-200 characters)\n- description: A detailed description (minimum 10 characters)\n- dependencies: An array of task IDs this subtask depends on (can be empty [])\n- details: Implementation details (minimum 20 characters)\n- status: Must be \"pending\" for new subtasks\n- testStrategy: Testing approach (can be null)\n\nYou may optionally include a \"metadata\" object. Do not include any other top-level properties.",
			"user": "{{#if hasCodebaseAnalysis}}## IMPORTANT: Codebase Analysis Required\n\nYou have access to powerful codebase analysis tools. Before generating subtasks:\n\n1. Use the Glob tool to explore relevant files for this task (e.g., \"**/*.js\", \"src/**/*.ts\")\n2. Use the Grep tool to search for existing implementations related to this task\n3. Use the Read tool to examine files that would be affected by this task\n4. Understand the current implementation state and patterns used\n\nBased on your analysis:\n- Identify existing code that relates to this task\n- Understand patterns and conventions to follow\n- Generate subtasks that integrate smoothly with existing code\n- Ensure subtasks are specific and actionable based on the actual codebase\n\nProject Root: {{projectRoot}}\n\n{{/if}}Analyze the following task and break it down into {{#if (gt subtaskCount 0)}}exactly {{subtaskCount}}{{else}}an appropriate number of{{/if}} specific subtasks. Each subtask should be actionable and well-defined.\n\nParent Task:\nID: {{task.id}}\nTitle: {{task.title}}\nDescription: {{task.description}}\nCurrent details: {{#if task.details}}{{task.details}}{{else}}None{{/if}}{{#if additionalContext}}\nConsider this context: {{additionalContext}}{{/if}}{{#if complexityReasoningContext}}\nComplexity Analysis Reasoning: {{complexityReasoningContext}}{{/if}}{{#if gatheredContext}}\n\n# Project Context\n\n{{gatheredContext}}{{/if}}\n\nCRITICAL: You MUST use sequential IDs starting from {{nextSubtaskId}}. The first subtask MUST have id={{nextSubtaskId}}, the second MUST have id={{nextSubtaskId}}+1, and so on. Do NOT use parent task ID in subtask numbering!"
		},
		"default": {
			"system": "You are an AI assistant helping with task breakdown for software development. Break down high-level tasks into specific, actionable subtasks that can be implemented sequentially.\n\nIMPORTANT: Your response MUST be a JSON object with a \"subtasks\" property containing an array of subtask objects. Each subtask must include ALL of the following fields:\n- id: MUST be sequential integers starting EXACTLY from {{nextSubtaskId}}. First subtask id={{nextSubtaskId}}, second id={{nextSubtaskId}}+1, etc. DO NOT use any other numbering pattern!\n- title: A clear, actionable title (5-200 characters)\n- description: A detailed description (minimum 10 characters)\n- dependencies: An array of task IDs this subtask depends on (can be empty [])\n- details: Implementation details (minimum 20 characters)\n- status: Must be \"pending\" for new subtasks\n- testStrategy: Testing approach (can be null)\n\nYou may optionally include a \"metadata\" object. Do not include any other top-level properties.",
			"user": "{{#if hasCodebaseAnalysis}}## IMPORTANT: Codebase Analysis Required\n\nYou have access to powerful codebase analysis tools. Before generating subtasks:\n\n1. Use the Glob tool to explore relevant files for this task (e.g., \"**/*.js\", \"src/**/*.ts\")\n2. Use the Grep tool to search for existing implementations related to this task\n3. Use the Read tool to examine files that would be affected by this task\n4. Understand the current implementation state and patterns used\n\nBased on your analysis:\n- Identify existing code that relates to this task\n- Understand patterns and conventions to follow\n- Generate subtasks that integrate smoothly with existing code\n- Ensure subtasks are specific and actionable based on the actual codebase\n\nProject Root: {{projectRoot}}\n\n{{/if}}Break down this task into {{#if (gt subtaskCount 0)}}exactly {{subtaskCount}}{{else}}an appropriate number of{{/if}} specific subtasks:\n\nTask ID: {{task.id}}\nTitle: {{task.title}}\nDescription: {{task.description}}\nCurrent details: {{#if task.details}}{{task.details}}{{else}}None{{/if}}{{#if additionalContext}}\nAdditional context: {{additionalContext}}{{/if}}{{#if complexityReasoningContext}}\nComplexity Analysis Reasoning: {{complexityReasoningContext}}{{/if}}{{#if gatheredContext}}\n\n# Project Context\n\n{{gatheredContext}}{{/if}}\n\nCRITICAL: You MUST use sequential IDs starting from {{nextSubtaskId}}. The first subtask MUST have id={{nextSubtaskId}}, the second MUST have id={{nextSubtaskId}}+1, and so on. Do NOT use parent task ID in subtask numbering!"
		}
	}
}

```

--------------------------------------------------------------------------------
/.taskmaster/reports/task-complexity-report_tdd-phase-1-core-rails.json:
--------------------------------------------------------------------------------

```json
{
	"meta": {
		"generatedAt": "2025-10-09T12:47:27.960Z",
		"tasksAnalyzed": 10,
		"totalTasks": 10,
		"analysisCount": 10,
		"thresholdScore": 5,
		"projectName": "Taskmaster",
		"usedResearch": false
	},
	"complexityAnalysis": [
		{
			"taskId": 1,
			"taskTitle": "Design and Implement Global Storage System",
			"complexityScore": 7,
			"recommendedSubtasks": 6,
			"expansionPrompt": "Break down the global storage system implementation into: 1) Path normalization utilities with cross-platform support, 2) Run ID generation and validation, 3) Manifest.json structure and management, 4) Activity.jsonl append-only logging, 5) State.json mutable checkpoint handling, and 6) Directory structure creation and cleanup. Focus on robust error handling, atomic operations, and isolation between different runs.",
			"reasoning": "Complex system requiring cross-platform path handling, multiple file formats (JSON/JSONL), atomic operations, and state management. The existing codebase shows sophisticated file operations infrastructure but this extends beyond current patterns. Implementation involves filesystem operations, concurrency concerns, and data integrity."
		},
		{
			"taskId": 2,
			"taskTitle": "Build GitAdapter with Safety Checks",
			"complexityScore": 8,
			"recommendedSubtasks": 7,
			"expansionPrompt": "Decompose GitAdapter into: 1) Git repository detection and validation, 2) Working tree status checking with detailed reporting, 3) Branch operations (create, checkout, list) with safety guards, 4) Commit operations with metadata embedding, 5) Default branch detection and protection logic, 6) Push operations with conflict handling, and 7) Branch name generation from patterns. Emphasize safety checks, confirmation gates, and comprehensive error messages.",
			"reasoning": "High complexity due to git operations safety requirements, multiple git commands integration, error handling for various git states, and safety mechanisms. The PRD emphasizes never allowing commits on default branch and requiring clean working tree - critical safety features that need robust implementation."
		},
		{
			"taskId": 3,
			"taskTitle": "Implement Test Result Validator",
			"complexityScore": 5,
			"recommendedSubtasks": 4,
			"expansionPrompt": "Split test validation into: 1) Input validation and schema definition for test results, 2) RED phase validation logic (ensuring failures exist), 3) GREEN phase validation logic (ensuring all tests pass), and 4) Coverage threshold validation with configurable limits. Include comprehensive validation messages and suggestions for common failure scenarios.",
			"reasoning": "Moderate complexity focused on business logic validation. The validator is framework-agnostic (only validates reported numbers), has clear validation rules, and well-defined input/output. The existing codebase shows validation patterns that can be leveraged."
		},
		{
			"taskId": 4,
			"taskTitle": "Develop WorkflowOrchestrator State Machine",
			"complexityScore": 9,
			"recommendedSubtasks": 8,
			"expansionPrompt": "Structure the orchestrator into: 1) State machine definition and transitions (Preflight → BranchSetup → SubtaskLoop → Finalize), 2) Event emission system with comprehensive event types, 3) State persistence and recovery mechanisms, 4) Phase coordination and validation, 5) Subtask iteration and progress tracking, 6) Error handling and recovery strategies, 7) Resume functionality from checkpoints, and 8) Integration points for Git, Test, and other adapters.",
			"reasoning": "Very high complexity as the central coordination component. Must orchestrate multiple adapters, handle state transitions, event emission, persistence, and recovery. The state machine needs to be robust, resumable, and coordinate all other components. Critical for the entire workflow's reliability."
		},
		{
			"taskId": 5,
			"taskTitle": "Create Enhanced Commit Message Generator",
			"complexityScore": 4,
			"recommendedSubtasks": 3,
			"expansionPrompt": "Organize commit message generation into: 1) Template parsing and variable substitution with configurable templates, 2) Scope detection from changed files with intelligent categorization, and 3) Metadata embedding (task context, test results, coverage) with conventional commits compliance. Ensure messages are parseable and contain all required task metadata.",
			"reasoning": "Relatively straightforward text processing and template system. The conventional commits format is well-defined, and the metadata requirements are clear. The existing package.json shows commander dependency for CLI patterns that can be leveraged."
		},
		{
			"taskId": 6,
			"taskTitle": "Implement Subtask TDD Loop",
			"complexityScore": 8,
			"recommendedSubtasks": 6,
			"expansionPrompt": "Break down the TDD loop into: 1) RED phase orchestration with test generation coordination, 2) GREEN phase orchestration with implementation guidance, 3) COMMIT phase with file staging and commit creation, 4) Attempt tracking and maximum retry logic, 5) Phase transition validation and state updates, and 6) Activity logging for all phase transitions. Focus on robust state management and clear error recovery paths.",
			"reasoning": "High complexity due to coordinating multiple phases, state transitions, retry logic, and integration with multiple adapters (Git, Test, State). This is the core workflow execution engine requiring careful orchestration and error handling."
		},
		{
			"taskId": 7,
			"taskTitle": "Build CLI Commands for AI Agent Orchestration",
			"complexityScore": 6,
			"recommendedSubtasks": 5,
			"expansionPrompt": "Structure CLI commands into: 1) Command registration and argument parsing setup, 2) `start` and `resume` commands with initialization logic, 3) `next` and `status` commands with JSON output formatting, 4) `complete` command with result validation integration, and 5) `commit` and `abort` commands with git operation coordination. Ensure consistent JSON output for machine parsing and comprehensive error handling.",
			"reasoning": "Moderate complexity leveraging existing CLI infrastructure. The codebase shows commander usage patterns and CLI structure. Main complexity is in JSON output formatting, argument validation, and integration with the orchestrator component."
		},
		{
			"taskId": 8,
			"taskTitle": "Develop MCP Tools for AI Agent Integration",
			"complexityScore": 6,
			"recommendedSubtasks": 5,
			"expansionPrompt": "Organize MCP tools into: 1) Tool schema definition and parameter validation, 2) `autopilot_start` and `autopilot_resume` tool implementation, 3) `autopilot_next` and `autopilot_status` tools with context provision, 4) `autopilot_complete_phase` tool with validation integration, and 5) `autopilot_commit` tool with git operations. Ensure parity with CLI functionality and proper error handling.",
			"reasoning": "Moderate complexity building on existing MCP infrastructure. The codebase shows extensive MCP tooling patterns. Main work is adapting CLI functionality to MCP interface patterns and ensuring consistent behavior between CLI and MCP interfaces."
		},
		{
			"taskId": 9,
			"taskTitle": "Write AI Agent Integration Documentation and Templates",
			"complexityScore": 2,
			"recommendedSubtasks": 2,
			"expansionPrompt": "Structure documentation into: 1) Comprehensive workflow documentation with step-by-step examples, command usage, and integration patterns, and 2) Template creation for CLAUDE.md integration, example prompts, and troubleshooting guides. Focus on clear examples and practical integration guidance.",
			"reasoning": "Low complexity documentation task. Requires understanding of the implemented system but primarily involves writing clear instructions and examples. The existing codebase shows good documentation patterns that can be followed."
		},
		{
			"taskId": 10,
			"taskTitle": "Implement Configuration System and Project Hygiene",
			"complexityScore": 5,
			"recommendedSubtasks": 4,
			"expansionPrompt": "Structure configuration into: 1) Configuration schema definition with comprehensive validation using ajv, 2) Default configuration setup and loading mechanisms, 3) Gitignore management and project directory hygiene rules, and 4) Configuration validation and error reporting. Ensure configurations are validated on startup and provide clear error messages for invalid settings.",
			"reasoning": "Moderate complexity involving schema validation, file operations, and configuration management. The package.json shows ajv dependency is available. Configuration systems require careful validation and user-friendly error reporting, but follow established patterns."
		}
	]
}

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/auth/services/organization.service.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * @fileoverview Organization and Brief management service
 * Handles fetching and managing organizations and briefs from the API
 */

import type { SupabaseClient } from '@supabase/supabase-js';
import {
	ERROR_CODES,
	TaskMasterError
} from '../../../common/errors/task-master-error.js';
import { getLogger } from '../../../common/logger/index.js';
import type { Database } from '../../../common/types/database.types.js';
import type { Brief } from '../../briefs/types.js';

/**
 * Organization data structure
 */
export interface Organization {
	id: string;
	name: string;
	slug: string;
}

/**
 * Task data structure from the remote database
 */
export interface RemoteTask {
	id: string;
	briefId: string;
	documentId: string;
	position: number | null;
	subtaskPosition: number | null;
	status: string;
	createdAt: string;
	updatedAt: string;
	// Document details from join
	document?: {
		id: string;
		document_name: string;
		title: string;
		description: string;
	};
}

/**
 * Service for managing organizations and briefs
 */
export class OrganizationService {
	private logger = getLogger('OrganizationService');

	constructor(private supabaseClient: SupabaseClient<Database>) {}

	/**
	 * Get all organizations for the authenticated user
	 */
	async getOrganizations(): Promise<Organization[]> {
		try {
			// The user is already authenticated via the Authorization header
			// Query the user_accounts view/table (filtered by RLS for current user)
			const { data, error } = await this.supabaseClient
				.from('user_accounts')
				.select(`
					id,
					name,
					slug
				`);

			if (error) {
				throw new TaskMasterError(
					`Failed to fetch organizations: ${error.message}`,
					ERROR_CODES.API_ERROR,
					{ operation: 'getOrganizations' },
					error
				);
			}

			if (!data || data.length === 0) {
				this.logger.debug('No organizations found for user');
				return [];
			}

			// Map to our Organization interface
			return data.map((org) => ({
				id: org.id ?? '',
				name: org.name ?? '',
				slug: org.slug ?? org.id ?? '' // Use ID as fallback if slug is null
			}));
		} catch (error) {
			if (error instanceof TaskMasterError) {
				throw error;
			}
			throw new TaskMasterError(
				'Failed to fetch organizations',
				ERROR_CODES.API_ERROR,
				{ operation: 'getOrganizations' },
				error as Error
			);
		}
	}

	/**
	 * Get a specific organization by ID
	 */
	async getOrganization(orgId: string): Promise<Organization | null> {
		try {
			const { data, error } = await this.supabaseClient
				.from('accounts')
				.select(`
					id,
					name,
					slug
				`)
				.eq('id', orgId)
				.single();

			if (error) {
				if (error.code === 'PGRST116') {
					// No rows found
					return null;
				}
				throw new TaskMasterError(
					`Failed to fetch organization: ${error.message}`,
					ERROR_CODES.API_ERROR,
					{ operation: 'getOrganization', orgId },
					error
				);
			}

			if (!data) {
				return null;
			}

			const accountData =
				data as Database['public']['Tables']['accounts']['Row'];
			return {
				id: accountData.id,
				name: accountData.name,
				slug: accountData.slug || accountData.id
			};
		} catch (error) {
			if (error instanceof TaskMasterError) {
				throw error;
			}
			throw new TaskMasterError(
				'Failed to fetch organization',
				ERROR_CODES.API_ERROR,
				{ operation: 'getOrganization', orgId },
				error as Error
			);
		}
	}

	/**
	 * Get all briefs for a specific organization
	 */
	async getBriefs(orgId: string): Promise<Brief[]> {
		try {
			const { data, error } = await this.supabaseClient
				.from('brief')
				.select(`
					id,
					account_id,
					document_id,
					status,
					created_at,
					updated_at,
					tasks(count),
					document:document_id (
						id,
						document_name,
						title
					)
				`)
				.eq('account_id', orgId)
				.order('updated_at', { ascending: false });

			if (error) {
				throw new TaskMasterError(
					`Failed to fetch briefs: ${error.message}`,
					ERROR_CODES.API_ERROR,
					{ operation: 'getBriefs', orgId },
					error
				);
			}

			if (!data || data.length === 0) {
				this.logger.debug(`No briefs found for organization ${orgId}`);
				return [];
			}

			// Map to our Brief interface
			return data.map((brief: any) => ({
				id: brief.id,
				accountId: brief.account_id,
				documentId: brief.document_id,
				status: brief.status,
				createdAt: brief.created_at,
				updatedAt: brief.updated_at,
				taskCount: Array.isArray(brief.tasks)
					? (brief.tasks[0]?.count ?? 0)
					: 0,
				document: brief.document
					? {
							id: brief.document.id,
							document_name: brief.document.document_name,
							title: brief.document.title
						}
					: undefined
			}));
		} catch (error) {
			if (error instanceof TaskMasterError) {
				throw error;
			}
			throw new TaskMasterError(
				'Failed to fetch briefs',
				ERROR_CODES.API_ERROR,
				{ operation: 'getBriefs', orgId },
				error as Error
			);
		}
	}

	/**
	 * Get a specific brief by ID
	 */
	async getBrief(briefId: string): Promise<Brief | null> {
		try {
			const { data, error } = await this.supabaseClient
				.from('brief')
				.select(`
					id,
					account_id,
					document_id,
					status,
					created_at,
					updated_at,
					document:document_id (
						id,
						document_name,
						title,
						description
					)
				`)
				.eq('id', briefId)
				.single();

			if (error) {
				if (error.code === 'PGRST116') {
					// No rows found
					return null;
				}
				throw new TaskMasterError(
					`Failed to fetch brief: ${error.message}`,
					ERROR_CODES.API_ERROR,
					{ operation: 'getBrief', briefId },
					error
				);
			}

			if (!data) {
				return null;
			}

			const briefData = data as any;
			return {
				id: briefData.id,
				accountId: briefData.account_id,
				documentId: briefData.document_id,
				status: briefData.status,
				createdAt: briefData.created_at,
				updatedAt: briefData.updated_at,
				document: briefData.document
					? {
							id: briefData.document.id,
							document_name: briefData.document.document_name,
							title: briefData.document.title,
							description: briefData.document.description
						}
					: undefined
			};
		} catch (error) {
			if (error instanceof TaskMasterError) {
				throw error;
			}
			throw new TaskMasterError(
				'Failed to fetch brief',
				ERROR_CODES.API_ERROR,
				{ operation: 'getBrief', briefId },
				error as Error
			);
		}
	}

	/**
	 * Validate that a user has access to an organization
	 */
	async validateOrgAccess(orgId: string): Promise<boolean> {
		try {
			const org = await this.getOrganization(orgId);
			return org !== null;
		} catch (error) {
			this.logger.error(`Failed to validate org access: ${error}`);
			return false;
		}
	}

	/**
	 * Validate that a user has access to a brief
	 */
	async validateBriefAccess(briefId: string): Promise<boolean> {
		try {
			const brief = await this.getBrief(briefId);
			return brief !== null;
		} catch (error) {
			this.logger.error(`Failed to validate brief access: ${error}`);
			return false;
		}
	}

	/**
	 * Get all tasks for a specific brief
	 */
	async getTasks(briefId: string): Promise<RemoteTask[]> {
		try {
			const { data, error } = await this.supabaseClient
				.from('tasks')
				.select(`
					*,
					document:document_id (
						id,
						document_name,
						title,
						description
					)
				`)
				.eq('brief_id', briefId)
				.order('position', { ascending: true })
				.order('subtask_position', { ascending: true })
				.order('created_at', { ascending: true });

			if (error) {
				throw new TaskMasterError(
					`Failed to fetch tasks: ${error.message}`,
					ERROR_CODES.API_ERROR,
					{ operation: 'getTasks', briefId },
					error
				);
			}

			if (!data || data.length === 0) {
				this.logger.debug(`No tasks found for brief ${briefId}`);
				return [];
			}

			// Map to our RemoteTask interface
			return data.map((task: any) => ({
				id: task.id,
				briefId: task.brief_id,
				documentId: task.document_id,
				position: task.position,
				subtaskPosition: task.subtask_position,
				status: task.status,
				createdAt: task.created_at,
				updatedAt: task.updated_at,
				document: task.document
					? {
							id: task.document.id,
							document_name: task.document.document_name,
							title: task.document.title,
							description: task.document.description
						}
					: undefined
			}));
		} catch (error) {
			if (error instanceof TaskMasterError) {
				throw error;
			}
			throw new TaskMasterError(
				'Failed to fetch tasks',
				ERROR_CODES.API_ERROR,
				{ operation: 'getTasks', briefId },
				error as Error
			);
		}
	}
}

```

--------------------------------------------------------------------------------
/packages/tm-core/src/modules/tasks/repositories/supabase/supabase-repository.ts:
--------------------------------------------------------------------------------

```typescript
import { SupabaseClient } from '@supabase/supabase-js';
import { Task } from '../../../../common/types/index.js';
import { Database, Json } from '../../../../common/types/database.types.js';
import { TaskMapper } from '../../../../common/mappers/TaskMapper.js';
import { AuthManager } from '../../../auth/managers/auth-manager.js';
import { DependencyFetcher } from './dependency-fetcher.js';
import {
	TaskWithRelations,
	TaskDatabaseUpdate
} from '../../../../common/types/repository-types.js';
import { LoadTasksOptions } from '../../../../common/interfaces/storage.interface.js';
import { Brief } from '../task-repository.interface.js';
import { z } from 'zod';

// Zod schema for task status validation
const TaskStatusSchema = z.enum([
	'pending',
	'in-progress',
	'done',
	'review',
	'deferred',
	'cancelled',
	'blocked'
]);

// Zod schema for task updates
const TaskUpdateSchema = z
	.object({
		title: z.string().min(1).optional(),
		description: z.string().optional(),
		status: TaskStatusSchema.optional(),
		priority: z.enum(['low', 'medium', 'high', 'critical']).optional(),
		details: z.string().optional(),
		testStrategy: z.string().optional()
	})
	.partial();

export class SupabaseRepository {
	private dependencyFetcher: DependencyFetcher;
	private authManager: AuthManager;

	constructor(private supabase: SupabaseClient<Database>) {
		this.dependencyFetcher = new DependencyFetcher(supabase);
		this.authManager = AuthManager.getInstance();
	}

	/**
	 * Gets the current brief ID from auth context
	 * @throws {Error} If no brief is selected
	 */
	private getBriefIdOrThrow(): string {
		const context = this.authManager.getContext();
		if (!context?.briefId) {
			throw new Error(
				'No brief selected. Please select a brief first using: tm context brief'
			);
		}
		return context.briefId;
	}

	async getTasks(
		_projectId?: string,
		options?: LoadTasksOptions
	): Promise<Task[]> {
		const briefId = this.getBriefIdOrThrow();

		// Build query with filters
		let query = this.supabase
			.from('tasks')
			.select(`
        *,
        document:document_id (
          id,
          document_name,
          title,
          description
        )
      `)
			.eq('brief_id', briefId);

		// Apply status filter at database level if specified
		if (options?.status) {
			const dbStatus = this.mapStatusToDatabase(options.status);
			query = query.eq('status', dbStatus);
		}

		// Apply subtask exclusion at database level if specified
		if (options?.excludeSubtasks) {
			// Only fetch parent tasks (where parent_task_id is null)
			query = query.is('parent_task_id', null);
		}

		// Execute query with ordering
		const { data: tasks, error } = await query
			.order('position', { ascending: true })
			.order('subtask_position', { ascending: true })
			.order('created_at', { ascending: true });

		if (error) {
			throw new Error(`Failed to fetch tasks: ${error.message}`);
		}

		if (!tasks || tasks.length === 0) {
			return [];
		}

		// Type-safe task ID extraction
		const typedTasks = tasks as TaskWithRelations[];
		const taskIds = typedTasks.map((t) => t.id);
		const dependenciesMap =
			await this.dependencyFetcher.fetchDependenciesWithDisplayIds(taskIds);

		// Use mapper to convert to internal format
		return TaskMapper.mapDatabaseTasksToTasks(tasks, dependenciesMap);
	}

	async getTask(_projectId: string, taskId: string): Promise<Task | null> {
		const briefId = this.getBriefIdOrThrow();

		const { data, error } = await this.supabase
			.from('tasks')
			.select('*')
			.eq('brief_id', briefId)
			.eq('display_id', taskId.toUpperCase())
			.single();

		if (error) {
			if (error.code === 'PGRST116') {
				return null; // Not found
			}
			throw new Error(`Failed to fetch task: ${error.message}`);
		}

		// Get subtasks if this is a parent task
		const { data: subtasksData } = await this.supabase
			.from('tasks')
			.select('*')
			.eq('parent_task_id', data.id)
			.order('subtask_position', { ascending: true });

		// Get all task IDs (parent + subtasks) to fetch dependencies
		const allTaskIds = [data.id, ...(subtasksData?.map((st) => st.id) || [])];

		// Fetch dependencies using the dedicated fetcher
		const dependenciesByTaskId =
			await this.dependencyFetcher.fetchDependenciesWithDisplayIds(allTaskIds);

		// Use mapper to convert single task
		return TaskMapper.mapDatabaseTaskToTask(
			data,
			subtasksData || [],
			dependenciesByTaskId
		);
	}

	/**
	 * Get brief information by ID
	 * Note: This doesn't use getBriefIdOrThrow() because we may need to fetch
	 * briefs other than the current context brief
	 */
	async getBrief(briefId: string): Promise<Brief | null> {
		const { data, error } = await this.supabase
			.from('brief')
			.select(`
				*,
				document:document_id (
					id,
					title,
					description
				)
			`)
			.eq('id', briefId)
			.single();

		if (error) {
			if (error.code === 'PGRST116') {
				return null; // Not found
			}
			throw new Error(`Failed to fetch brief: ${error.message}`);
		}

		if (!data) {
			return null;
		}

		// Extract document data if available
		const document = data.document as any;

		// Map database fields to Brief interface
		return {
			id: data.id,
			accountId: data.account_id,
			createdAt: data.created_at,
			name: document?.title || undefined,
			description: document?.description || undefined,
			status: data.status || undefined
		};
	}

	async updateTask(
		projectId: string,
		taskId: string,
		updates: Partial<Task>
	): Promise<Task> {
		const briefId = this.getBriefIdOrThrow();

		// Validate updates using Zod schema
		try {
			TaskUpdateSchema.parse(updates);
		} catch (error) {
			if (error instanceof z.ZodError) {
				const errorMessages = error.issues
					.map((err) => `${err.path.join('.')}: ${err.message}`)
					.join(', ');
				throw new Error(`Invalid task update data: ${errorMessages}`);
			}
			throw error;
		}

		// Convert Task fields to database fields with proper typing
		const dbUpdates: TaskDatabaseUpdate = {};

		if (updates.title !== undefined) dbUpdates.title = updates.title;
		if (updates.description !== undefined)
			dbUpdates.description = updates.description;
		if (updates.status !== undefined)
			dbUpdates.status = this.mapStatusToDatabase(updates.status);
		if (updates.priority !== undefined)
			dbUpdates.priority = this.mapPriorityToDatabase(updates.priority);

		// Handle metadata fields (details, testStrategy, etc.)
		// Load existing metadata to preserve fields not being updated
		const { data: existingMetadataRow, error: existingMetadataError } =
			await this.supabase
				.from('tasks')
				.select('metadata')
				.eq('brief_id', briefId)
				.eq('display_id', taskId.toUpperCase())
				.single();

		if (existingMetadataError) {
			throw new Error(
				`Failed to load existing task metadata: ${existingMetadataError.message}`
			);
		}

		const metadata: Record<string, unknown> = {
			...((existingMetadataRow?.metadata as Record<string, unknown>) ?? {})
		};

		if (updates.details !== undefined) metadata.details = updates.details;
		if (updates.testStrategy !== undefined)
			metadata.testStrategy = updates.testStrategy;

		if (Object.keys(metadata).length > 0) {
			dbUpdates.metadata = metadata as Json;
		}

		// Update the task
		const { error } = await this.supabase
			.from('tasks')
			.update(dbUpdates)
			.eq('brief_id', briefId)
			.eq('display_id', taskId.toUpperCase());

		if (error) {
			throw new Error(`Failed to update task: ${error.message}`);
		}

		// Return the updated task by fetching it
		const updatedTask = await this.getTask(projectId, taskId);
		if (!updatedTask) {
			throw new Error(`Failed to retrieve updated task ${taskId}`);
		}

		return updatedTask;
	}

	/**
	 * Maps internal status to database status
	 */
	private mapStatusToDatabase(
		status: string
	): Database['public']['Enums']['task_status'] {
		switch (status) {
			case 'pending':
				return 'todo';
			case 'in-progress':
			case 'in_progress': // Accept both formats
				return 'in_progress';
			case 'done':
				return 'done';
			default:
				throw new Error(
					`Invalid task status: ${status}. Valid statuses are: pending, in-progress, done`
				);
		}
	}

	/**
	 * Maps internal priority to database priority
	 * Task Master uses 'critical', database uses 'urgent'
	 */
	private mapPriorityToDatabase(
		priority: string
	): Database['public']['Enums']['task_priority'] {
		switch (priority) {
			case 'critical':
				return 'urgent';
			case 'low':
			case 'medium':
			case 'high':
				return priority as Database['public']['Enums']['task_priority'];
			default:
				throw new Error(
					`Invalid task priority: ${priority}. Valid priorities are: low, medium, high, critical`
				);
		}
	}
}

```

--------------------------------------------------------------------------------
/src/profiles/claude.js:
--------------------------------------------------------------------------------

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

// Helper function to recursively copy directory (adopted from Roo profile)
function copyRecursiveSync(src, dest) {
	const exists = fs.existsSync(src);
	const stats = exists && fs.statSync(src);
	const isDirectory = exists && stats.isDirectory();
	if (isDirectory) {
		if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
		fs.readdirSync(src).forEach((childItemName) => {
			copyRecursiveSync(
				path.join(src, childItemName),
				path.join(dest, childItemName)
			);
		});
	} else {
		fs.copyFileSync(src, dest);
	}
}

// Helper function to recursively remove directory
function removeDirectoryRecursive(dirPath) {
	if (fs.existsSync(dirPath)) {
		try {
			fs.rmSync(dirPath, { recursive: true, force: true });
			return true;
		} catch (err) {
			log('error', `Failed to remove directory ${dirPath}: ${err.message}`);
			return false;
		}
	}
	return true;
}

// Lifecycle functions for Claude Code profile
function onAddRulesProfile(targetDir, assetsDir) {
	// Note: Commands and agents are now distributed via Claude Code plugin
	// Legacy .claude directory copying has been deprecated
	log(
		'info',
		'[Claude] Commands and agents are now available via the Task Master plugin'
	);
	log('info', '[Claude] Install with: /plugin marketplace add taskmaster');
	log('info', '[Claude] Then: /plugin install taskmaster@taskmaster');

	// Handle CLAUDE.md import for non-destructive integration
	const sourceFile = path.join(assetsDir, 'AGENTS.md');
	const userClaudeFile = path.join(targetDir, 'CLAUDE.md');
	const taskMasterClaudeFile = path.join(targetDir, '.taskmaster', 'CLAUDE.md');
	const importLine = '@./.taskmaster/CLAUDE.md';
	const importSection = `\n## Task Master AI Instructions\n**Import Task Master's development workflow commands and guidelines, treat as if import is in the main CLAUDE.md file.**\n${importLine}`;

	if (fs.existsSync(sourceFile)) {
		try {
			// Ensure .taskmaster directory exists
			const taskMasterDir = path.join(targetDir, '.taskmaster');
			if (!fs.existsSync(taskMasterDir)) {
				fs.mkdirSync(taskMasterDir, { recursive: true });
			}

			// Copy Task Master instructions to .taskmaster/CLAUDE.md
			fs.copyFileSync(sourceFile, taskMasterClaudeFile);
			log(
				'debug',
				`[Claude] Created Task Master instructions at ${taskMasterClaudeFile}`
			);

			// Handle user's CLAUDE.md
			if (fs.existsSync(userClaudeFile)) {
				// Check if import already exists
				const content = fs.readFileSync(userClaudeFile, 'utf8');
				if (!content.includes(importLine)) {
					// Append import section at the end
					const updatedContent = content.trim() + '\n' + importSection + '\n';
					fs.writeFileSync(userClaudeFile, updatedContent);
					log(
						'info',
						`[Claude] Added Task Master import to existing ${userClaudeFile}`
					);
				} else {
					log(
						'info',
						`[Claude] Task Master import already present in ${userClaudeFile}`
					);
				}
			} else {
				// Create minimal CLAUDE.md with the import section
				const minimalContent = `# Claude Code Instructions\n${importSection}\n`;
				fs.writeFileSync(userClaudeFile, minimalContent);
				log(
					'info',
					`[Claude] Created ${userClaudeFile} with Task Master import`
				);
			}
		} catch (err) {
			log(
				'error',
				`[Claude] Failed to set up Claude instructions: ${err.message}`
			);
		}
	}
}

function onRemoveRulesProfile(targetDir) {
	// Note: .claude directory (commands/agents) are now managed by Claude Code plugin
	// We no longer remove them here - users should uninstall the plugin separately
	log(
		'info',
		'[Claude] To remove Task Master commands/agents, uninstall the plugin with: /plugin uninstall taskmaster'
	);

	// Clean up CLAUDE.md import
	const userClaudeFile = path.join(targetDir, 'CLAUDE.md');
	const taskMasterClaudeFile = path.join(targetDir, '.taskmaster', 'CLAUDE.md');
	const importLine = '@./.taskmaster/CLAUDE.md';

	try {
		// Remove Task Master CLAUDE.md from .taskmaster
		if (fs.existsSync(taskMasterClaudeFile)) {
			fs.rmSync(taskMasterClaudeFile, { force: true });
			log('debug', `[Claude] Removed ${taskMasterClaudeFile}`);
		}

		// Clean up import from user's CLAUDE.md
		if (fs.existsSync(userClaudeFile)) {
			const content = fs.readFileSync(userClaudeFile, 'utf8');
			const lines = content.split('\n');
			const filteredLines = [];
			let skipNextLines = 0;

			// Remove the Task Master section
			for (let i = 0; i < lines.length; i++) {
				if (skipNextLines > 0) {
					skipNextLines--;
					continue;
				}

				// Check if this is the start of our Task Master section
				if (lines[i].includes('## Task Master AI Instructions')) {
					// Skip this line and the next two lines (bold text and import)
					skipNextLines = 2;
					continue;
				}

				// Also remove standalone import lines (for backward compatibility)
				if (lines[i].trim() === importLine) {
					continue;
				}

				filteredLines.push(lines[i]);
			}

			// Join back and clean up excessive newlines
			let updatedContent = filteredLines
				.join('\n')
				.replace(/\n{3,}/g, '\n\n')
				.trim();

			// Check if file only contained our minimal template
			if (
				updatedContent === '# Claude Code Instructions' ||
				updatedContent === ''
			) {
				// File only contained our import, remove it
				fs.rmSync(userClaudeFile, { force: true });
				log('debug', `[Claude] Removed empty ${userClaudeFile}`);
			} else {
				// Write back without the import
				fs.writeFileSync(userClaudeFile, updatedContent + '\n');
				log(
					'debug',
					`[Claude] Removed Task Master import from ${userClaudeFile}`
				);
			}
		}
	} catch (err) {
		log(
			'error',
			`[Claude] Failed to remove Claude instructions: ${err.message}`
		);
	}
}

/**
 * Transform standard MCP config format to Claude format
 * @param {Object} mcpConfig - Standard MCP configuration object
 * @returns {Object} - Transformed Claude configuration object
 */
function transformToClaudeFormat(mcpConfig) {
	const claudeConfig = {};

	// Transform mcpServers to servers (keeping the same structure but adding type)
	if (mcpConfig.mcpServers) {
		claudeConfig.mcpServers = {};

		for (const [serverName, serverConfig] of Object.entries(
			mcpConfig.mcpServers
		)) {
			// Transform server configuration with type as first key
			const reorderedServer = {};

			// Add type: "stdio" as the first key
			reorderedServer.type = 'stdio';

			// Then add the rest of the properties in order
			if (serverConfig.command) reorderedServer.command = serverConfig.command;
			if (serverConfig.args) reorderedServer.args = serverConfig.args;
			if (serverConfig.env) reorderedServer.env = serverConfig.env;

			// Add any other properties that might exist
			Object.keys(serverConfig).forEach((key) => {
				if (!['command', 'args', 'env', 'type'].includes(key)) {
					reorderedServer[key] = serverConfig[key];
				}
			});

			claudeConfig.mcpServers[serverName] = reorderedServer;
		}
	}

	return claudeConfig;
}

function onPostConvertRulesProfile(targetDir, assetsDir) {
	// For Claude, post-convert is the same as add since we don't transform rules
	onAddRulesProfile(targetDir, assetsDir);

	// Transform MCP configuration to Claude format
	const mcpConfigPath = path.join(targetDir, '.mcp.json');
	if (fs.existsSync(mcpConfigPath)) {
		try {
			const mcpConfig = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf8'));
			const claudeConfig = transformToClaudeFormat(mcpConfig);

			// Write back the transformed configuration
			fs.writeFileSync(
				mcpConfigPath,
				JSON.stringify(claudeConfig, null, '\t') + '\n'
			);
			log(
				'debug',
				`[Claude] Transformed MCP configuration to Claude format at ${mcpConfigPath}`
			);
		} catch (err) {
			log(
				'error',
				`[Claude] Failed to transform MCP configuration: ${err.message}`
			);
		}
	}
}

// Create and export claude profile using the base factory
export const claudeProfile = createProfile({
	name: 'claude',
	displayName: 'Claude Code',
	url: 'claude.ai',
	docsUrl: 'docs.anthropic.com/en/docs/claude-code',
	profileDir: '.', // Root directory
	rulesDir: '.', // No specific rules directory needed
	mcpConfigName: '.mcp.json', // Place MCP config in project root
	includeDefaultRules: false,
	fileMap: {
		'AGENTS.md': '.taskmaster/CLAUDE.md'
	},
	onAdd: onAddRulesProfile,
	onRemove: onRemoveRulesProfile,
	onPostConvert: onPostConvertRulesProfile
});

// Export lifecycle functions separately to avoid naming conflicts
export { onAddRulesProfile, onRemoveRulesProfile, onPostConvertRulesProfile };

```

--------------------------------------------------------------------------------
/apps/extension/src/webview/hooks/useTaskQueries.ts:
--------------------------------------------------------------------------------

```typescript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useVSCodeContext } from '../contexts/VSCodeContext';
import type { TaskMasterTask, TaskUpdates } from '../types';

// Query keys factory
export const taskKeys = {
	all: ['tasks'] as const,
	lists: () => [...taskKeys.all, 'list'] as const,
	list: (filters: { tag?: string; status?: string }) =>
		[...taskKeys.lists(), filters] as const,
	details: () => [...taskKeys.all, 'detail'] as const,
	detail: (id: string) => [...taskKeys.details(), id] as const
};

// Hook to fetch all tasks
export function useTasks(options?: { tag?: string; status?: string }) {
	const { sendMessage } = useVSCodeContext();

	return useQuery({
		queryKey: taskKeys.list(options || {}),
		queryFn: async () => {
			console.log('🔍 Fetching tasks with options:', options);
			const response = await sendMessage({
				type: 'getTasks',
				data: {
					tag: options?.tag,
					withSubtasks: true
				}
			});
			console.log('📋 Tasks fetched:', response);
			return response as TaskMasterTask[];
		},
		staleTime: 0 // Consider data stale immediately
	});
}

// Hook to fetch a single task with full details
export function useTaskDetails(taskId: string) {
	const { sendMessage } = useVSCodeContext();

	return useQuery({
		queryKey: taskKeys.detail(taskId),
		queryFn: async () => {
			const response = await sendMessage({
				type: 'mcpRequest',
				tool: 'get_task',
				params: {
					id: taskId
				}
			});

			// Parse the MCP response
			let fullTaskData = null;
			if (response?.data?.content?.[0]?.text) {
				try {
					const parsed = JSON.parse(response.data.content[0].text);
					fullTaskData = parsed.data;
				} catch (e) {
					console.error('Failed to parse MCP response:', e);
				}
			} else if (response?.data?.data) {
				fullTaskData = response.data.data;
			}

			return fullTaskData as TaskMasterTask;
		},
		enabled: !!taskId
	});
}

// Hook to update task status
export function useUpdateTaskStatus() {
	const { sendMessage } = useVSCodeContext();
	const queryClient = useQueryClient();

	return useMutation({
		mutationFn: async ({
			taskId,
			newStatus
		}: {
			taskId: string;
			newStatus: TaskMasterTask['status'];
		}) => {
			const response = await sendMessage({
				type: 'updateTaskStatus',
				data: { taskId, newStatus }
			});
			return { taskId, newStatus, response };
		},
		// Optimistic update to prevent snap-back
		onMutate: async ({ taskId, newStatus }) => {
			// Cancel any outgoing refetches
			await queryClient.cancelQueries({ queryKey: taskKeys.all });

			// Snapshot the previous value
			const previousTasks = queryClient.getQueriesData({
				queryKey: taskKeys.all
			});

			// Optimistically update all task queries
			queryClient.setQueriesData({ queryKey: taskKeys.all }, (old: any) => {
				if (!old) return old;

				// Handle both array and object responses
				if (Array.isArray(old)) {
					return old.map((task: TaskMasterTask) =>
						task.id === taskId ? { ...task, status: newStatus } : task
					);
				}

				return old;
			});

			// Return a context object with the snapshot
			return { previousTasks };
		},
		// If the mutation fails, roll back to the previous value
		onError: (err, variables, context) => {
			if (context?.previousTasks) {
				context.previousTasks.forEach(([queryKey, data]) => {
					queryClient.setQueryData(queryKey, data);
				});
			}
		},
		// Always refetch after error or success to ensure consistency
		onSettled: () => {
			queryClient.invalidateQueries({ queryKey: taskKeys.all });
		}
	});
}

// Hook to update task content
export function useUpdateTask() {
	const { sendMessage } = useVSCodeContext();
	const queryClient = useQueryClient();

	return useMutation({
		mutationFn: async ({
			taskId,
			updates,
			options = {}
		}: {
			taskId: string;
			updates: TaskUpdates | { description: string };
			options?: { append?: boolean; research?: boolean };
		}) => {
			console.log('🔄 Updating task:', taskId, updates, options);

			const response = await sendMessage({
				type: 'updateTask',
				data: { taskId, updates, options }
			});

			console.log('📥 Update task response:', response);

			// Check for error in response
			if (response && typeof response === 'object' && 'error' in response) {
				throw new Error(response.error || 'Failed to update task');
			}

			return response;
		},
		onSuccess: async (data, variables) => {
			console.log('✅ Task update successful, invalidating all task queries');
			console.log('Response data:', data);
			console.log('Task ID:', variables.taskId);

			// Invalidate ALL task-related queries (same as handleRefresh)
			await queryClient.invalidateQueries({
				queryKey: taskKeys.all
			});

			console.log(
				'🔄 All task queries invalidated for task:',
				variables.taskId
			);
		}
	});
}

// Hook to update subtask
export function useUpdateSubtask() {
	const { sendMessage } = useVSCodeContext();
	const queryClient = useQueryClient();

	return useMutation({
		mutationFn: async ({
			taskId,
			prompt,
			options = {}
		}: {
			taskId: string;
			prompt: string;
			options?: { research?: boolean };
		}) => {
			console.log('🔄 Updating subtask:', taskId, prompt, options);

			const response = await sendMessage({
				type: 'updateSubtask',
				data: { taskId, prompt, options }
			});

			console.log('📥 Update subtask response:', response);

			// Check for error in response
			if (response && typeof response === 'object' && 'error' in response) {
				throw new Error(response.error || 'Failed to update subtask');
			}

			return response;
		},
		onSuccess: async (data, variables) => {
			console.log(
				'✅ Subtask update successful, invalidating all task queries'
			);
			console.log('Subtask ID:', variables.taskId);

			// Invalidate ALL task-related queries (same as handleRefresh)
			await queryClient.invalidateQueries({
				queryKey: taskKeys.all
			});

			console.log(
				'🔄 All task queries invalidated for subtask:',
				variables.taskId
			);
		}
	});
}

// Hook to scope up task complexity
export function useScopeUpTask() {
	const { sendMessage } = useVSCodeContext();
	const queryClient = useQueryClient();

	return useMutation({
		mutationFn: async ({
			taskId,
			strength = 'regular',
			prompt,
			options = {}
		}: {
			taskId: string;
			strength?: 'light' | 'regular' | 'heavy';
			prompt?: string;
			options?: { research?: boolean };
		}) => {
			console.log('🔄 Scoping up task:', taskId, strength, prompt, options);

			const response = await sendMessage({
				type: 'mcpRequest',
				tool: 'scope_up_task',
				params: {
					id: String(taskId),
					strength,
					prompt,
					research: options.research || false
				}
			});

			console.log('📥 Scope up task response:', response);

			// Check for error in response
			if (response && typeof response === 'object' && 'error' in response) {
				throw new Error(response.error || 'Failed to scope up task');
			}

			return response;
		},
		onSuccess: async (data, variables) => {
			console.log('✅ Task scope up successful, invalidating all task queries');
			console.log('Task ID:', variables.taskId);

			// Invalidate ALL task-related queries
			await queryClient.invalidateQueries({
				queryKey: taskKeys.all
			});

			console.log(
				'🔄 All task queries invalidated for scoped up task:',
				variables.taskId
			);
		}
	});
}

// Hook to scope down task complexity
export function useScopeDownTask() {
	const { sendMessage } = useVSCodeContext();
	const queryClient = useQueryClient();

	return useMutation({
		mutationFn: async ({
			taskId,
			strength = 'regular',
			prompt,
			options = {}
		}: {
			taskId: string;
			strength?: 'light' | 'regular' | 'heavy';
			prompt?: string;
			options?: { research?: boolean };
		}) => {
			console.log('🔄 Scoping down task:', taskId, strength, prompt, options);

			const response = await sendMessage({
				type: 'mcpRequest',
				tool: 'scope_down_task',
				params: {
					id: String(taskId),
					strength,
					prompt,
					research: options.research || false
				}
			});

			console.log('📥 Scope down task response:', response);

			// Check for error in response
			if (response && typeof response === 'object' && 'error' in response) {
				throw new Error(response.error || 'Failed to scope down task');
			}

			return response;
		},
		onSuccess: async (data, variables) => {
			console.log(
				'✅ Task scope down successful, invalidating all task queries'
			);
			console.log('Task ID:', variables.taskId);

			// Invalidate ALL task-related queries
			await queryClient.invalidateQueries({
				queryKey: taskKeys.all
			});

			console.log(
				'🔄 All task queries invalidated for scoped down task:',
				variables.taskId
			);
		}
	});
}

```

--------------------------------------------------------------------------------
/src/profiles/base-profile.js:
--------------------------------------------------------------------------------

```javascript
// Base profile factory for rule-transformer
import path from 'path';

/**
 * Creates a standardized profile configuration for different editors
 * @param {Object} editorConfig - Editor-specific configuration
 * @param {string} editorConfig.name - Profile name (e.g., 'cursor', 'vscode')
 * @param {string} [editorConfig.displayName] - Display name for the editor (defaults to name)
 * @param {string} editorConfig.url - Editor website URL
 * @param {string} editorConfig.docsUrl - Editor documentation URL
 * @param {string} editorConfig.profileDir - Directory for profile configuration
 * @param {string} [editorConfig.rulesDir] - Directory for rules files (defaults to profileDir/rules)
 * @param {boolean} [editorConfig.mcpConfig=true] - Whether to create MCP configuration
 * @param {string} [editorConfig.mcpConfigName='mcp.json'] - Name of MCP config file
 * @param {string} [editorConfig.fileExtension='.mdc'] - Source file extension
 * @param {string} [editorConfig.targetExtension='.md'] - Target file extension
 * @param {Object} [editorConfig.toolMappings={}] - Tool name mappings
 * @param {Array} [editorConfig.customReplacements=[]] - Custom text replacements
 * @param {Object} [editorConfig.fileMap={}] - Custom file name mappings
 * @param {boolean} [editorConfig.supportsRulesSubdirectories=false] - Whether to use taskmaster/ subdirectory for taskmaster-specific rules (only Cursor uses this by default)
 * @param {boolean} [editorConfig.includeDefaultRules=true] - Whether to include default rule files
 * @param {Function} [editorConfig.onAdd] - Lifecycle hook for profile addition
 * @param {Function} [editorConfig.onRemove] - Lifecycle hook for profile removal
 * @param {Function} [editorConfig.onPostConvert] - Lifecycle hook for post-conversion
 * @returns {Object} - Complete profile configuration
 */
export function createProfile(editorConfig) {
	const {
		name,
		displayName = name,
		url,
		docsUrl,
		profileDir = `.${name.toLowerCase()}`,
		rulesDir = `${profileDir}/rules`,
		mcpConfig = true,
		mcpConfigName = mcpConfig ? 'mcp.json' : null,
		fileExtension = '.mdc',
		targetExtension = '.md',
		toolMappings = {},
		customReplacements = [],
		fileMap = {},
		supportsRulesSubdirectories = false,
		includeDefaultRules = true,
		onAdd,
		onRemove,
		onPostConvert
	} = editorConfig;

	const mcpConfigPath = mcpConfigName
		? path.join(profileDir, mcpConfigName)
		: null;

	// Standard file mapping with custom overrides
	// Use taskmaster subdirectory only if profile supports it
	const taskmasterPrefix = supportsRulesSubdirectories ? 'taskmaster/' : '';
	const defaultFileMap = {
		'rules/cursor_rules.mdc': `${name.toLowerCase()}_rules${targetExtension}`,
		'rules/dev_workflow.mdc': `${taskmasterPrefix}dev_workflow${targetExtension}`,
		'rules/self_improve.mdc': `self_improve${targetExtension}`,
		'rules/taskmaster.mdc': `${taskmasterPrefix}taskmaster${targetExtension}`
	};

	// Build final fileMap - merge defaults with custom entries when includeDefaultRules is true
	const finalFileMap = includeDefaultRules
		? { ...defaultFileMap, ...fileMap }
		: fileMap;

	// Base global replacements that work for all editors
	const baseGlobalReplacements = [
		// Handle URLs in any context
		{ from: /cursor\.so/gi, to: url },
		{ from: /cursor\s*\.\s*so/gi, to: url },
		{ from: /https?:\/\/cursor\.so/gi, to: `https://${url}` },
		{ from: /https?:\/\/www\.cursor\.so/gi, to: `https://www.${url}` },

		// Handle tool references
		{ from: /\bedit_file\b/gi, to: toolMappings.edit_file || 'edit_file' },
		{
			from: /\bsearch tool\b/gi,
			to: `${toolMappings.search || 'search'} tool`
		},
		{ from: /\bSearch Tool\b/g, to: `${toolMappings.search || 'Search'} Tool` },

		// Handle basic terms with proper case handling
		{
			from: /\bcursor\b/gi,
			to: (match) =>
				match.charAt(0) === 'C' ? displayName : name.toLowerCase()
		},
		{ from: /Cursor/g, to: displayName },
		{ from: /CURSOR/g, to: displayName.toUpperCase() },

		// Handle file extensions if different
		...(targetExtension !== fileExtension
			? [
					{
						from: new RegExp(`\\${fileExtension}(?!\\])\\b`, 'g'),
						to: targetExtension
					}
				]
			: []),

		// Handle documentation URLs
		{ from: /docs\.cursor\.com/gi, to: docsUrl },

		// Custom editor-specific replacements
		...customReplacements
	];

	// Standard tool mappings
	const defaultToolMappings = {
		search: 'search',
		read_file: 'read_file',
		edit_file: 'edit_file',
		create_file: 'create_file',
		run_command: 'run_command',
		terminal_command: 'terminal_command',
		use_mcp: 'use_mcp',
		switch_mode: 'switch_mode',
		...toolMappings
	};

	// Create conversion config
	const conversionConfig = {
		// Profile name replacements
		profileTerms: [
			{ from: /cursor\.so/g, to: url },
			{ from: /\[cursor\.so\]/g, to: `[${url}]` },
			{ from: /href="https:\/\/cursor\.so/g, to: `href="https://${url}` },
			{ from: /\(https:\/\/cursor\.so/g, to: `(https://${url}` },
			{
				from: /\bcursor\b/gi,
				to: (match) => (match === 'Cursor' ? displayName : name.toLowerCase())
			},
			{ from: /Cursor/g, to: displayName }
		],

		// File extension replacements
		fileExtensions:
			targetExtension !== fileExtension
				? [
						{
							from: new RegExp(`\\${fileExtension}\\b`, 'g'),
							to: targetExtension
						}
					]
				: [],

		// Documentation URL replacements
		docUrls: [
			{
				from: new RegExp(`https:\\/\\/docs\\.cursor\\.com\\/[^\\s)'\"]+`, 'g'),
				to: (match) => match.replace('docs.cursor.com', docsUrl)
			},
			{
				from: new RegExp(`https:\\/\\/${docsUrl}\\/`, 'g'),
				to: `https://${docsUrl}/`
			}
		],

		// Tool references - direct replacements
		toolNames: defaultToolMappings,

		// Tool references in context - more specific replacements
		toolContexts: Object.entries(defaultToolMappings).flatMap(
			([original, mapped]) => [
				{
					from: new RegExp(`\\b${original} tool\\b`, 'g'),
					to: `${mapped} tool`
				},
				{ from: new RegExp(`\\bthe ${original}\\b`, 'g'), to: `the ${mapped}` },
				{ from: new RegExp(`\\bThe ${original}\\b`, 'g'), to: `The ${mapped}` },
				{
					from: new RegExp(`\\bCursor ${original}\\b`, 'g'),
					to: `${displayName} ${mapped}`
				}
			]
		),

		// Tool group and category names
		toolGroups: [
			{ from: /\bSearch tools\b/g, to: 'Read Group tools' },
			{ from: /\bEdit tools\b/g, to: 'Edit Group tools' },
			{ from: /\bRun tools\b/g, to: 'Command Group tools' },
			{ from: /\bMCP servers\b/g, to: 'MCP Group tools' },
			{ from: /\bSearch Group\b/g, to: 'Read Group' },
			{ from: /\bEdit Group\b/g, to: 'Edit Group' },
			{ from: /\bRun Group\b/g, to: 'Command Group' }
		],

		// File references in markdown links
		fileReferences: {
			pathPattern: /\[(.+?)\]\(mdc:\.cursor\/rules\/(.+?)\.mdc\)/g,
			replacement: (match, text, filePath) => {
				const baseName = path.basename(filePath, '.mdc');
				const newFileName =
					finalFileMap[`rules/${baseName}.mdc`] ||
					`${baseName}${targetExtension}`;
				// Update the link text to match the new filename (strip directory path for display)
				const newLinkText = path.basename(newFileName);
				// For Cursor, keep the mdc: protocol; for others, use standard relative paths
				if (name.toLowerCase() === 'cursor') {
					return `[${newLinkText}](mdc:${rulesDir}/${newFileName})`;
				} else {
					return `[${newLinkText}](${rulesDir}/${newFileName})`;
				}
			}
		}
	};

	function getTargetRuleFilename(sourceFilename) {
		if (finalFileMap[sourceFilename]) {
			return finalFileMap[sourceFilename];
		}
		return targetExtension !== fileExtension
			? sourceFilename.replace(
					new RegExp(`\\${fileExtension}$`),
					targetExtension
				)
			: sourceFilename;
	}

	return {
		profileName: name, // Use name for programmatic access (tests expect this)
		displayName: displayName, // Keep displayName for UI purposes
		profileDir,
		rulesDir,
		mcpConfig,
		mcpConfigName,
		mcpConfigPath,
		supportsRulesSubdirectories,
		includeDefaultRules,
		fileMap: finalFileMap,
		globalReplacements: baseGlobalReplacements,
		conversionConfig,
		getTargetRuleFilename,
		targetExtension,
		// Optional lifecycle hooks
		...(onAdd && { onAddRulesProfile: onAdd }),
		...(onRemove && { onRemoveRulesProfile: onRemove }),
		...(onPostConvert && { onPostConvertRulesProfile: onPostConvert })
	};
}

// Common tool mappings for editors that share similar tool sets
export const COMMON_TOOL_MAPPINGS = {
	// Most editors (Cursor, Cline, Windsurf) keep original tool names
	STANDARD: {},

	// Roo Code uses different tool names
	ROO_STYLE: {
		edit_file: 'apply_diff',
		search: 'search_files',
		create_file: 'write_to_file',
		run_command: 'execute_command',
		terminal_command: 'execute_command',
		use_mcp: 'use_mcp_tool'
	}
};

```
Page 19/50FirstPrevNextLast