#
tokens: 40376/50000 2/975 files (page 54/69)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 54 of 69. Use http://codebase.md/eyaltoledano/claude-task-master?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── README.md
├── .claude
│   ├── 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

--------------------------------------------------------------------------------
/scripts/modules/task-manager/list-tasks.js:
--------------------------------------------------------------------------------

```javascript
   1 | import chalk from 'chalk';
   2 | import boxen from 'boxen';
   3 | import Table from 'cli-table3';
   4 | 
   5 | import {
   6 | 	log,
   7 | 	readJSON,
   8 | 	truncate,
   9 | 	readComplexityReport,
  10 | 	addComplexityToTask
  11 | } from '../utils.js';
  12 | import findNextTask from './find-next-task.js';
  13 | 
  14 | import {
  15 | 	displayBanner,
  16 | 	getStatusWithColor,
  17 | 	formatDependenciesWithStatus,
  18 | 	getComplexityWithColor,
  19 | 	createProgressBar
  20 | } from '../ui.js';
  21 | import { createTmCore } from '@tm/core';
  22 | 
  23 | /**
  24 |  * List all tasks
  25 |  * @param {string} tasksPath - Path to the tasks.json file
  26 |  * @param {string} statusFilter - Filter by status (single status or comma-separated list, e.g., 'pending' or 'blocked,deferred')
  27 |  * @param {string} reportPath - Path to the complexity report
  28 |  * @param {boolean} withSubtasks - Whether to show subtasks
  29 |  * @param {string} outputFormat - Output format (text or json)
  30 |  * @param {Object} context - Context object (required)
  31 |  * @param {string} context.projectRoot - Project root path
  32 |  * @param {string} context.tag - Tag for the task
  33 |  * @returns {Object} - Task list result for json format
  34 |  */
  35 | async function listTasks(
  36 | 	tasksPath,
  37 | 	statusFilter,
  38 | 	reportPath = null,
  39 | 	withSubtasks = false,
  40 | 	outputFormat = 'text',
  41 | 	context = {}
  42 | ) {
  43 | 	const { projectRoot, tag } = context;
  44 | 	try {
  45 | 		// BRIDGE: Initialize tm-core for unified task access
  46 | 		let data;
  47 | 		try {
  48 | 			const tmCore = await createTmCore({
  49 | 				projectPath: projectRoot || process.cwd()
  50 | 			});
  51 | 
  52 | 			// Load tasks via tm-core tasks domain (supports both file and API storage)
  53 | 			const result = await tmCore.tasks.list({ tag });
  54 | 			data = { tasks: result.tasks };
  55 | 
  56 | 			log(
  57 | 				'debug',
  58 | 				`Loaded ${result.tasks.length} tasks via tm-core (${result.storageType} storage)`
  59 | 			);
  60 | 		} catch (storageError) {
  61 | 			log(
  62 | 				'warn',
  63 | 				`TmCore failed, falling back to legacy readJSON: ${storageError.message}`
  64 | 			);
  65 | 			// Fallback to old readJSON if tm-core fails
  66 | 			data = readJSON(tasksPath, projectRoot, tag);
  67 | 		}
  68 | 
  69 | 		if (!data || !data.tasks) {
  70 | 			throw new Error(`No valid tasks found in ${tasksPath}`);
  71 | 		}
  72 | 
  73 | 		// Add complexity scores to tasks if report exists
  74 | 		// `reportPath` is already tag-aware (resolved at the CLI boundary).
  75 | 		const complexityReport = readComplexityReport(reportPath);
  76 | 		// Apply complexity scores to tasks
  77 | 		if (complexityReport && complexityReport.complexityAnalysis) {
  78 | 			data.tasks.forEach((task) => addComplexityToTask(task, complexityReport));
  79 | 		}
  80 | 
  81 | 		// Filter tasks by status if specified - now supports comma-separated statuses
  82 | 		let filteredTasks;
  83 | 		if (statusFilter && statusFilter.toLowerCase() !== 'all') {
  84 | 			// Handle comma-separated statuses
  85 | 			const allowedStatuses = statusFilter
  86 | 				.split(',')
  87 | 				.map((s) => s.trim().toLowerCase())
  88 | 				.filter((s) => s.length > 0); // Remove empty strings
  89 | 
  90 | 			filteredTasks = data.tasks.filter(
  91 | 				(task) =>
  92 | 					task.status && allowedStatuses.includes(task.status.toLowerCase())
  93 | 			);
  94 | 		} else {
  95 | 			// Default to all tasks if no filter or filter is 'all'
  96 | 			filteredTasks = data.tasks;
  97 | 		}
  98 | 
  99 | 		// Calculate completion statistics
 100 | 		const totalTasks = data.tasks.length;
 101 | 		const completedTasks = data.tasks.filter(
 102 | 			(task) => task.status === 'done' || task.status === 'completed'
 103 | 		).length;
 104 | 		const completionPercentage =
 105 | 			totalTasks > 0 ? (completedTasks / totalTasks) * 100 : 0;
 106 | 
 107 | 		// Count statuses for tasks
 108 | 		const doneCount = completedTasks;
 109 | 		const inProgressCount = data.tasks.filter(
 110 | 			(task) => task.status === 'in-progress'
 111 | 		).length;
 112 | 		const pendingCount = data.tasks.filter(
 113 | 			(task) => task.status === 'pending'
 114 | 		).length;
 115 | 		const blockedCount = data.tasks.filter(
 116 | 			(task) => task.status === 'blocked'
 117 | 		).length;
 118 | 		const deferredCount = data.tasks.filter(
 119 | 			(task) => task.status === 'deferred'
 120 | 		).length;
 121 | 		const cancelledCount = data.tasks.filter(
 122 | 			(task) => task.status === 'cancelled'
 123 | 		).length;
 124 | 		const reviewCount = data.tasks.filter(
 125 | 			(task) => task.status === 'review'
 126 | 		).length;
 127 | 
 128 | 		// Count subtasks and their statuses
 129 | 		let totalSubtasks = 0;
 130 | 		let completedSubtasks = 0;
 131 | 		let inProgressSubtasks = 0;
 132 | 		let pendingSubtasks = 0;
 133 | 		let blockedSubtasks = 0;
 134 | 		let deferredSubtasks = 0;
 135 | 		let cancelledSubtasks = 0;
 136 | 		let reviewSubtasks = 0;
 137 | 
 138 | 		data.tasks.forEach((task) => {
 139 | 			if (task.subtasks && task.subtasks.length > 0) {
 140 | 				totalSubtasks += task.subtasks.length;
 141 | 				completedSubtasks += task.subtasks.filter(
 142 | 					(st) => st.status === 'done' || st.status === 'completed'
 143 | 				).length;
 144 | 				inProgressSubtasks += task.subtasks.filter(
 145 | 					(st) => st.status === 'in-progress'
 146 | 				).length;
 147 | 				pendingSubtasks += task.subtasks.filter(
 148 | 					(st) => st.status === 'pending'
 149 | 				).length;
 150 | 				blockedSubtasks += task.subtasks.filter(
 151 | 					(st) => st.status === 'blocked'
 152 | 				).length;
 153 | 				deferredSubtasks += task.subtasks.filter(
 154 | 					(st) => st.status === 'deferred'
 155 | 				).length;
 156 | 				cancelledSubtasks += task.subtasks.filter(
 157 | 					(st) => st.status === 'cancelled'
 158 | 				).length;
 159 | 				reviewSubtasks += task.subtasks.filter(
 160 | 					(st) => st.status === 'review'
 161 | 				).length;
 162 | 			}
 163 | 		});
 164 | 
 165 | 		const subtaskCompletionPercentage =
 166 | 			totalSubtasks > 0 ? (completedSubtasks / totalSubtasks) * 100 : 0;
 167 | 
 168 | 		// Calculate dependency statistics (moved up to be available for all output formats)
 169 | 		const completedTaskIds = new Set(
 170 | 			data.tasks
 171 | 				.filter((t) => t.status === 'done' || t.status === 'completed')
 172 | 				.map((t) => t.id)
 173 | 		);
 174 | 
 175 | 		const tasksWithNoDeps = data.tasks.filter(
 176 | 			(t) =>
 177 | 				t.status !== 'done' &&
 178 | 				t.status !== 'completed' &&
 179 | 				(!t.dependencies || t.dependencies.length === 0)
 180 | 		).length;
 181 | 
 182 | 		const tasksWithAllDepsSatisfied = data.tasks.filter(
 183 | 			(t) =>
 184 | 				t.status !== 'done' &&
 185 | 				t.status !== 'completed' &&
 186 | 				t.dependencies &&
 187 | 				t.dependencies.length > 0 &&
 188 | 				t.dependencies.every((depId) => completedTaskIds.has(depId))
 189 | 		).length;
 190 | 
 191 | 		const tasksWithUnsatisfiedDeps = data.tasks.filter(
 192 | 			(t) =>
 193 | 				t.status !== 'done' &&
 194 | 				t.status !== 'completed' &&
 195 | 				t.dependencies &&
 196 | 				t.dependencies.length > 0 &&
 197 | 				!t.dependencies.every((depId) => completedTaskIds.has(depId))
 198 | 		).length;
 199 | 
 200 | 		// Calculate total tasks ready to work on (no deps + satisfied deps)
 201 | 		const tasksReadyToWork = tasksWithNoDeps + tasksWithAllDepsSatisfied;
 202 | 
 203 | 		// Calculate most depended-on tasks
 204 | 		const dependencyCount = {};
 205 | 		data.tasks.forEach((task) => {
 206 | 			if (task.dependencies && task.dependencies.length > 0) {
 207 | 				task.dependencies.forEach((depId) => {
 208 | 					dependencyCount[depId] = (dependencyCount[depId] || 0) + 1;
 209 | 				});
 210 | 			}
 211 | 		});
 212 | 
 213 | 		// Find the most depended-on task
 214 | 		let mostDependedOnTaskId = null;
 215 | 		let maxDependents = 0;
 216 | 
 217 | 		for (const [taskId, count] of Object.entries(dependencyCount)) {
 218 | 			if (count > maxDependents) {
 219 | 				maxDependents = count;
 220 | 				mostDependedOnTaskId = parseInt(taskId);
 221 | 			}
 222 | 		}
 223 | 
 224 | 		// Get the most depended-on task
 225 | 		const mostDependedOnTask =
 226 | 			mostDependedOnTaskId !== null
 227 | 				? data.tasks.find((t) => t.id === mostDependedOnTaskId)
 228 | 				: null;
 229 | 
 230 | 		// Calculate average dependencies per task
 231 | 		const totalDependencies = data.tasks.reduce(
 232 | 			(sum, task) => sum + (task.dependencies ? task.dependencies.length : 0),
 233 | 			0
 234 | 		);
 235 | 		const avgDependenciesPerTask = totalDependencies / data.tasks.length;
 236 | 
 237 | 		// Find next task to work on, passing the complexity report
 238 | 		const nextItem = findNextTask(data.tasks, complexityReport);
 239 | 
 240 | 		// For JSON output, return structured data
 241 | 		if (outputFormat === 'json') {
 242 | 			// *** Modification: Remove 'details' field for JSON output ***
 243 | 			const tasksWithoutDetails = filteredTasks.map((task) => {
 244 | 				// <-- USES filteredTasks!
 245 | 				// Omit 'details' from the parent task
 246 | 				const { details, ...taskRest } = task;
 247 | 
 248 | 				// If subtasks exist, omit 'details' from them too
 249 | 				if (taskRest.subtasks && Array.isArray(taskRest.subtasks)) {
 250 | 					taskRest.subtasks = taskRest.subtasks.map((subtask) => {
 251 | 						const { details: subtaskDetails, ...subtaskRest } = subtask;
 252 | 						return subtaskRest;
 253 | 					});
 254 | 				}
 255 | 				return taskRest;
 256 | 			});
 257 | 			// *** End of Modification ***
 258 | 
 259 | 			return {
 260 | 				tasks: tasksWithoutDetails, // <--- THIS IS THE ARRAY BEING RETURNED
 261 | 				filter: statusFilter || 'all', // Return the actual filter used
 262 | 				stats: {
 263 | 					total: totalTasks,
 264 | 					completed: doneCount,
 265 | 					inProgress: inProgressCount,
 266 | 					pending: pendingCount,
 267 | 					blocked: blockedCount,
 268 | 					deferred: deferredCount,
 269 | 					cancelled: cancelledCount,
 270 | 					review: reviewCount,
 271 | 					completionPercentage,
 272 | 					subtasks: {
 273 | 						total: totalSubtasks,
 274 | 						completed: completedSubtasks,
 275 | 						inProgress: inProgressSubtasks,
 276 | 						pending: pendingSubtasks,
 277 | 						blocked: blockedSubtasks,
 278 | 						deferred: deferredSubtasks,
 279 | 						cancelled: cancelledSubtasks,
 280 | 						completionPercentage: subtaskCompletionPercentage
 281 | 					}
 282 | 				}
 283 | 			};
 284 | 		}
 285 | 
 286 | 		// For markdown-readme output, return formatted markdown
 287 | 		if (outputFormat === 'markdown-readme') {
 288 | 			return generateMarkdownOutput(data, filteredTasks, {
 289 | 				totalTasks,
 290 | 				completedTasks,
 291 | 				completionPercentage,
 292 | 				doneCount,
 293 | 				inProgressCount,
 294 | 				pendingCount,
 295 | 				blockedCount,
 296 | 				deferredCount,
 297 | 				cancelledCount,
 298 | 				totalSubtasks,
 299 | 				completedSubtasks,
 300 | 				subtaskCompletionPercentage,
 301 | 				inProgressSubtasks,
 302 | 				pendingSubtasks,
 303 | 				blockedSubtasks,
 304 | 				deferredSubtasks,
 305 | 				cancelledSubtasks,
 306 | 				reviewSubtasks,
 307 | 				tasksWithNoDeps,
 308 | 				tasksReadyToWork,
 309 | 				tasksWithUnsatisfiedDeps,
 310 | 				mostDependedOnTask,
 311 | 				mostDependedOnTaskId,
 312 | 				maxDependents,
 313 | 				avgDependenciesPerTask,
 314 | 				complexityReport,
 315 | 				withSubtasks,
 316 | 				nextItem
 317 | 			});
 318 | 		}
 319 | 
 320 | 		// For compact output, return minimal one-line format
 321 | 		if (outputFormat === 'compact') {
 322 | 			return renderCompactOutput(filteredTasks, withSubtasks);
 323 | 		}
 324 | 
 325 | 		// ... existing code for text output ...
 326 | 
 327 | 		// Calculate status breakdowns as percentages of total
 328 | 		const taskStatusBreakdown = {
 329 | 			'in-progress': totalTasks > 0 ? (inProgressCount / totalTasks) * 100 : 0,
 330 | 			pending: totalTasks > 0 ? (pendingCount / totalTasks) * 100 : 0,
 331 | 			blocked: totalTasks > 0 ? (blockedCount / totalTasks) * 100 : 0,
 332 | 			deferred: totalTasks > 0 ? (deferredCount / totalTasks) * 100 : 0,
 333 | 			cancelled: totalTasks > 0 ? (cancelledCount / totalTasks) * 100 : 0,
 334 | 			review: totalTasks > 0 ? (reviewCount / totalTasks) * 100 : 0
 335 | 		};
 336 | 
 337 | 		const subtaskStatusBreakdown = {
 338 | 			'in-progress':
 339 | 				totalSubtasks > 0 ? (inProgressSubtasks / totalSubtasks) * 100 : 0,
 340 | 			pending: totalSubtasks > 0 ? (pendingSubtasks / totalSubtasks) * 100 : 0,
 341 | 			blocked: totalSubtasks > 0 ? (blockedSubtasks / totalSubtasks) * 100 : 0,
 342 | 			deferred:
 343 | 				totalSubtasks > 0 ? (deferredSubtasks / totalSubtasks) * 100 : 0,
 344 | 			cancelled:
 345 | 				totalSubtasks > 0 ? (cancelledSubtasks / totalSubtasks) * 100 : 0,
 346 | 			review: totalSubtasks > 0 ? (reviewSubtasks / totalSubtasks) * 100 : 0
 347 | 		};
 348 | 
 349 | 		// Create progress bars with status breakdowns
 350 | 		const taskProgressBar = createProgressBar(
 351 | 			completionPercentage,
 352 | 			30,
 353 | 			taskStatusBreakdown
 354 | 		);
 355 | 		const subtaskProgressBar = createProgressBar(
 356 | 			subtaskCompletionPercentage,
 357 | 			30,
 358 | 			subtaskStatusBreakdown
 359 | 		);
 360 | 
 361 | 		// Get terminal width - more reliable method
 362 | 		let terminalWidth;
 363 | 		try {
 364 | 			// Try to get the actual terminal columns
 365 | 			terminalWidth = process.stdout.columns;
 366 | 		} catch (e) {
 367 | 			// Fallback if columns cannot be determined
 368 | 			log('debug', 'Could not determine terminal width, using default');
 369 | 		}
 370 | 		// Ensure we have a reasonable default if detection fails
 371 | 		terminalWidth = terminalWidth || 80;
 372 | 
 373 | 		// Ensure terminal width is at least a minimum value to prevent layout issues
 374 | 		terminalWidth = Math.max(terminalWidth, 80);
 375 | 
 376 | 		// Create dashboard content
 377 | 		const projectDashboardContent =
 378 | 			chalk.white.bold('Project Dashboard') +
 379 | 			'\n' +
 380 | 			`Tasks Progress: ${chalk.greenBright(taskProgressBar)} ${completionPercentage.toFixed(0)}%\n` +
 381 | 			`Done: ${chalk.green(doneCount)}  In Progress: ${chalk.blue(inProgressCount)}  Pending: ${chalk.yellow(pendingCount)}  Blocked: ${chalk.red(blockedCount)}  Deferred: ${chalk.gray(deferredCount)}  Cancelled: ${chalk.gray(cancelledCount)}\n\n` +
 382 | 			`Subtasks Progress: ${chalk.cyan(subtaskProgressBar)} ${subtaskCompletionPercentage.toFixed(0)}%\n` +
 383 | 			`Completed: ${chalk.green(completedSubtasks)}/${totalSubtasks}  In Progress: ${chalk.blue(inProgressSubtasks)}  Pending: ${chalk.yellow(pendingSubtasks)}  Blocked: ${chalk.red(blockedSubtasks)}  Deferred: ${chalk.gray(deferredSubtasks)}  Cancelled: ${chalk.gray(cancelledSubtasks)}\n\n` +
 384 | 			chalk.cyan.bold('Priority Breakdown:') +
 385 | 			'\n' +
 386 | 			`${chalk.red('•')} ${chalk.white('High priority:')} ${data.tasks.filter((t) => t.priority === 'high').length}\n` +
 387 | 			`${chalk.yellow('•')} ${chalk.white('Medium priority:')} ${data.tasks.filter((t) => t.priority === 'medium').length}\n` +
 388 | 			`${chalk.green('•')} ${chalk.white('Low priority:')} ${data.tasks.filter((t) => t.priority === 'low').length}`;
 389 | 
 390 | 		const dependencyDashboardContent =
 391 | 			chalk.white.bold('Dependency Status & Next Task') +
 392 | 			'\n' +
 393 | 			chalk.cyan.bold('Dependency Metrics:') +
 394 | 			'\n' +
 395 | 			`${chalk.green('•')} ${chalk.white('Tasks with no dependencies:')} ${tasksWithNoDeps}\n` +
 396 | 			`${chalk.green('•')} ${chalk.white('Tasks ready to work on:')} ${tasksReadyToWork}\n` +
 397 | 			`${chalk.yellow('•')} ${chalk.white('Tasks blocked by dependencies:')} ${tasksWithUnsatisfiedDeps}\n` +
 398 | 			`${chalk.magenta('•')} ${chalk.white('Most depended-on task:')} ${mostDependedOnTask ? chalk.cyan(`#${mostDependedOnTaskId} (${maxDependents} dependents)`) : chalk.gray('None')}\n` +
 399 | 			`${chalk.blue('•')} ${chalk.white('Avg dependencies per task:')} ${avgDependenciesPerTask.toFixed(1)}\n\n` +
 400 | 			chalk.cyan.bold('Next Task to Work On:') +
 401 | 			'\n' +
 402 | 			`ID: ${chalk.cyan(nextItem ? nextItem.id : 'N/A')} - ${nextItem ? chalk.white.bold(truncate(nextItem.title, 40)) : chalk.yellow('No task available')}
 403 | ` +
 404 | 			`Priority: ${nextItem ? chalk.white(nextItem.priority || 'medium') : ''}  Dependencies: ${nextItem ? formatDependenciesWithStatus(nextItem.dependencies, data.tasks, true, complexityReport) : ''}
 405 | ` +
 406 | 			`Complexity: ${nextItem && nextItem.complexityScore ? getComplexityWithColor(nextItem.complexityScore) : chalk.gray('N/A')}`;
 407 | 
 408 | 		// Calculate width for side-by-side display
 409 | 		// Box borders, padding take approximately 4 chars on each side
 410 | 		const minDashboardWidth = 50; // Minimum width for dashboard
 411 | 		const minDependencyWidth = 50; // Minimum width for dependency dashboard
 412 | 		const totalMinWidth = minDashboardWidth + minDependencyWidth + 4; // Extra 4 chars for spacing
 413 | 
 414 | 		// If terminal is wide enough, show boxes side by side with responsive widths
 415 | 		if (terminalWidth >= totalMinWidth) {
 416 | 			// Calculate widths proportionally for each box - use exact 50% width each
 417 | 			const availableWidth = terminalWidth;
 418 | 			const halfWidth = Math.floor(availableWidth / 2);
 419 | 
 420 | 			// Account for border characters (2 chars on each side)
 421 | 			const boxContentWidth = halfWidth - 4;
 422 | 
 423 | 			// Create boxen options with precise widths
 424 | 			const dashboardBox = boxen(projectDashboardContent, {
 425 | 				padding: 1,
 426 | 				borderColor: 'blue',
 427 | 				borderStyle: 'round',
 428 | 				width: boxContentWidth,
 429 | 				dimBorder: false
 430 | 			});
 431 | 
 432 | 			const dependencyBox = boxen(dependencyDashboardContent, {
 433 | 				padding: 1,
 434 | 				borderColor: 'magenta',
 435 | 				borderStyle: 'round',
 436 | 				width: boxContentWidth,
 437 | 				dimBorder: false
 438 | 			});
 439 | 
 440 | 			// Create a better side-by-side layout with exact spacing
 441 | 			const dashboardLines = dashboardBox.split('\n');
 442 | 			const dependencyLines = dependencyBox.split('\n');
 443 | 
 444 | 			// Make sure both boxes have the same height
 445 | 			const maxHeight = Math.max(dashboardLines.length, dependencyLines.length);
 446 | 
 447 | 			// For each line of output, pad the dashboard line to exactly halfWidth chars
 448 | 			// This ensures the dependency box starts at exactly the right position
 449 | 			const combinedLines = [];
 450 | 			for (let i = 0; i < maxHeight; i++) {
 451 | 				// Get the dashboard line (or empty string if we've run out of lines)
 452 | 				const dashLine = i < dashboardLines.length ? dashboardLines[i] : '';
 453 | 				// Get the dependency line (or empty string if we've run out of lines)
 454 | 				const depLine = i < dependencyLines.length ? dependencyLines[i] : '';
 455 | 
 456 | 				// Remove any trailing spaces from dashLine before padding to exact width
 457 | 				const trimmedDashLine = dashLine.trimEnd();
 458 | 				// Pad the dashboard line to exactly halfWidth chars with no extra spaces
 459 | 				const paddedDashLine = trimmedDashLine.padEnd(halfWidth, ' ');
 460 | 
 461 | 				// Join the lines with no space in between
 462 | 				combinedLines.push(paddedDashLine + depLine);
 463 | 			}
 464 | 
 465 | 			// Join all lines and output
 466 | 			console.log(combinedLines.join('\n'));
 467 | 		} else {
 468 | 			// Terminal too narrow, show boxes stacked vertically
 469 | 			const dashboardBox = boxen(projectDashboardContent, {
 470 | 				padding: 1,
 471 | 				borderColor: 'blue',
 472 | 				borderStyle: 'round',
 473 | 				margin: { top: 0, bottom: 1 }
 474 | 			});
 475 | 
 476 | 			const dependencyBox = boxen(dependencyDashboardContent, {
 477 | 				padding: 1,
 478 | 				borderColor: 'magenta',
 479 | 				borderStyle: 'round',
 480 | 				margin: { top: 0, bottom: 1 }
 481 | 			});
 482 | 
 483 | 			// Display stacked vertically
 484 | 			console.log(dashboardBox);
 485 | 			console.log(dependencyBox);
 486 | 		}
 487 | 
 488 | 		if (filteredTasks.length === 0) {
 489 | 			console.log(
 490 | 				boxen(
 491 | 					statusFilter
 492 | 						? chalk.yellow(`No tasks with status '${statusFilter}' found`)
 493 | 						: chalk.yellow('No tasks found'),
 494 | 					{ padding: 1, borderColor: 'yellow', borderStyle: 'round' }
 495 | 				)
 496 | 			);
 497 | 			return;
 498 | 		}
 499 | 
 500 | 		// COMPLETELY REVISED TABLE APPROACH
 501 | 		// Define percentage-based column widths and calculate actual widths
 502 | 		// Adjust percentages based on content type and user requirements
 503 | 
 504 | 		// Adjust ID width if showing subtasks (subtask IDs are longer: e.g., "1.2")
 505 | 		const idWidthPct = withSubtasks ? 10 : 7;
 506 | 
 507 | 		// Calculate max status length to accommodate "in-progress"
 508 | 		const statusWidthPct = 15;
 509 | 
 510 | 		// Increase priority column width as requested
 511 | 		const priorityWidthPct = 12;
 512 | 
 513 | 		// Make dependencies column smaller as requested (-20%)
 514 | 		const depsWidthPct = 20;
 515 | 
 516 | 		const complexityWidthPct = 10;
 517 | 
 518 | 		// Calculate title/description width as remaining space (+20% from dependencies reduction)
 519 | 		const titleWidthPct =
 520 | 			100 -
 521 | 			idWidthPct -
 522 | 			statusWidthPct -
 523 | 			priorityWidthPct -
 524 | 			depsWidthPct -
 525 | 			complexityWidthPct;
 526 | 
 527 | 		// Allow 10 characters for borders and padding
 528 | 		const availableWidth = terminalWidth - 10;
 529 | 
 530 | 		// Calculate actual column widths based on percentages
 531 | 		const idWidth = Math.floor(availableWidth * (idWidthPct / 100));
 532 | 		const statusWidth = Math.floor(availableWidth * (statusWidthPct / 100));
 533 | 		const priorityWidth = Math.floor(availableWidth * (priorityWidthPct / 100));
 534 | 		const depsWidth = Math.floor(availableWidth * (depsWidthPct / 100));
 535 | 		const complexityWidth = Math.floor(
 536 | 			availableWidth * (complexityWidthPct / 100)
 537 | 		);
 538 | 		const titleWidth = Math.floor(availableWidth * (titleWidthPct / 100));
 539 | 
 540 | 		// Create a table with correct borders and spacing
 541 | 		const table = new Table({
 542 | 			head: [
 543 | 				chalk.cyan.bold('ID'),
 544 | 				chalk.cyan.bold('Title'),
 545 | 				chalk.cyan.bold('Status'),
 546 | 				chalk.cyan.bold('Priority'),
 547 | 				chalk.cyan.bold('Dependencies'),
 548 | 				chalk.cyan.bold('Complexity')
 549 | 			],
 550 | 			colWidths: [
 551 | 				idWidth,
 552 | 				titleWidth,
 553 | 				statusWidth,
 554 | 				priorityWidth,
 555 | 				depsWidth,
 556 | 				complexityWidth // Added complexity column width
 557 | 			],
 558 | 			style: {
 559 | 				head: [], // No special styling for header
 560 | 				border: [], // No special styling for border
 561 | 				compact: false // Use default spacing
 562 | 			},
 563 | 			wordWrap: true,
 564 | 			wrapOnWordBoundary: true
 565 | 		});
 566 | 
 567 | 		// Process tasks for the table
 568 | 		filteredTasks.forEach((task) => {
 569 | 			// Format dependencies with status indicators (colored)
 570 | 			let depText = 'None';
 571 | 			if (task.dependencies && task.dependencies.length > 0) {
 572 | 				// Use the proper formatDependenciesWithStatus function for colored status
 573 | 				depText = formatDependenciesWithStatus(
 574 | 					task.dependencies,
 575 | 					data.tasks,
 576 | 					true,
 577 | 					complexityReport
 578 | 				);
 579 | 			} else {
 580 | 				depText = chalk.gray('None');
 581 | 			}
 582 | 
 583 | 			// Clean up any ANSI codes or confusing characters
 584 | 			const cleanTitle = task.title.replace(/\n/g, ' ');
 585 | 
 586 | 			// Get priority color
 587 | 			const priorityColor =
 588 | 				{
 589 | 					high: chalk.red,
 590 | 					medium: chalk.yellow,
 591 | 					low: chalk.gray
 592 | 				}[task.priority || 'medium'] || chalk.white;
 593 | 
 594 | 			// Format status
 595 | 			const status = getStatusWithColor(task.status, true);
 596 | 
 597 | 			// Add the row without truncating dependencies
 598 | 			table.push([
 599 | 				task.id.toString(),
 600 | 				truncate(cleanTitle, titleWidth - 3),
 601 | 				status,
 602 | 				priorityColor(truncate(task.priority || 'medium', priorityWidth - 2)),
 603 | 				depText,
 604 | 				task.complexityScore
 605 | 					? getComplexityWithColor(task.complexityScore)
 606 | 					: chalk.gray('N/A')
 607 | 			]);
 608 | 
 609 | 			// Add subtasks if requested
 610 | 			if (withSubtasks && task.subtasks && task.subtasks.length > 0) {
 611 | 				task.subtasks.forEach((subtask) => {
 612 | 					// Format subtask dependencies with status indicators
 613 | 					let subtaskDepText = 'None';
 614 | 					if (subtask.dependencies && subtask.dependencies.length > 0) {
 615 | 						// Handle both subtask-to-subtask and subtask-to-task dependencies
 616 | 						const formattedDeps = subtask.dependencies
 617 | 							.map((depId) => {
 618 | 								// Check if it's a dependency on another subtask
 619 | 								if (typeof depId === 'number' && depId < 100) {
 620 | 									const foundSubtask = task.subtasks.find(
 621 | 										(st) => st.id === depId
 622 | 									);
 623 | 									if (foundSubtask) {
 624 | 										const isDone =
 625 | 											foundSubtask.status === 'done' ||
 626 | 											foundSubtask.status === 'completed';
 627 | 										const isInProgress = foundSubtask.status === 'in-progress';
 628 | 
 629 | 										// Use consistent color formatting instead of emojis
 630 | 										if (isDone) {
 631 | 											return chalk.green.bold(`${task.id}.${depId}`);
 632 | 										} else if (isInProgress) {
 633 | 											return chalk.hex('#FFA500').bold(`${task.id}.${depId}`);
 634 | 										} else {
 635 | 											return chalk.red.bold(`${task.id}.${depId}`);
 636 | 										}
 637 | 									}
 638 | 								}
 639 | 								// Default to regular task dependency
 640 | 								const depTask = data.tasks.find((t) => t.id === depId);
 641 | 								if (depTask) {
 642 | 									// Add complexity to depTask before checking status
 643 | 									addComplexityToTask(depTask, complexityReport);
 644 | 									const isDone =
 645 | 										depTask.status === 'done' || depTask.status === 'completed';
 646 | 									const isInProgress = depTask.status === 'in-progress';
 647 | 									// Use the same color scheme as in formatDependenciesWithStatus
 648 | 									if (isDone) {
 649 | 										return chalk.green.bold(`${depId}`);
 650 | 									} else if (isInProgress) {
 651 | 										return chalk.hex('#FFA500').bold(`${depId}`);
 652 | 									} else {
 653 | 										return chalk.red.bold(`${depId}`);
 654 | 									}
 655 | 								}
 656 | 								return chalk.cyan(depId.toString());
 657 | 							})
 658 | 							.join(', ');
 659 | 
 660 | 						subtaskDepText = formattedDeps || chalk.gray('None');
 661 | 					}
 662 | 
 663 | 					// Add the subtask row without truncating dependencies
 664 | 					table.push([
 665 | 						`${task.id}.${subtask.id}`,
 666 | 						chalk.dim(`└─ ${truncate(subtask.title, titleWidth - 5)}`),
 667 | 						getStatusWithColor(subtask.status, true),
 668 | 						chalk.dim('-'),
 669 | 						subtaskDepText,
 670 | 						subtask.complexityScore
 671 | 							? chalk.gray(`${subtask.complexityScore}`)
 672 | 							: chalk.gray('N/A')
 673 | 					]);
 674 | 				});
 675 | 			}
 676 | 		});
 677 | 
 678 | 		// Ensure we output the table even if it had to wrap
 679 | 		try {
 680 | 			console.log(table.toString());
 681 | 		} catch (err) {
 682 | 			log('error', `Error rendering table: ${err.message}`);
 683 | 
 684 | 			// Fall back to simpler output
 685 | 			console.log(
 686 | 				chalk.yellow(
 687 | 					'\nFalling back to simple task list due to terminal width constraints:'
 688 | 				)
 689 | 			);
 690 | 			filteredTasks.forEach((task) => {
 691 | 				console.log(
 692 | 					`${chalk.cyan(task.id)}: ${chalk.white(task.title)} - ${getStatusWithColor(task.status)}`
 693 | 				);
 694 | 			});
 695 | 		}
 696 | 
 697 | 		// Show filter info if applied
 698 | 		if (statusFilter) {
 699 | 			console.log(chalk.yellow(`\nFiltered by status: ${statusFilter}`));
 700 | 			console.log(
 701 | 				chalk.yellow(`Showing ${filteredTasks.length} of ${totalTasks} tasks`)
 702 | 			);
 703 | 		}
 704 | 
 705 | 		// Define priority colors
 706 | 		const priorityColors = {
 707 | 			high: chalk.red.bold,
 708 | 			medium: chalk.yellow,
 709 | 			low: chalk.gray
 710 | 		};
 711 | 
 712 | 		// Show next task box in a prominent color
 713 | 		if (nextItem) {
 714 | 			// Prepare subtasks section if they exist (Only tasks have .subtasks property)
 715 | 			let subtasksSection = '';
 716 | 			// Check if the nextItem is a top-level task before looking for subtasks
 717 | 			const parentTaskForSubtasks = data.tasks.find(
 718 | 				(t) => String(t.id) === String(nextItem.id)
 719 | 			); // Find the original task object
 720 | 			if (
 721 | 				parentTaskForSubtasks &&
 722 | 				parentTaskForSubtasks.subtasks &&
 723 | 				parentTaskForSubtasks.subtasks.length > 0
 724 | 			) {
 725 | 				subtasksSection = `\n\n${chalk.white.bold('Subtasks:')}\n`;
 726 | 				subtasksSection += parentTaskForSubtasks.subtasks
 727 | 					.map((subtask) => {
 728 | 						// Add complexity to subtask before display
 729 | 						addComplexityToTask(subtask, complexityReport);
 730 | 						// Using a more simplified format for subtask status display
 731 | 						const status = subtask.status || 'pending';
 732 | 						const statusColors = {
 733 | 							done: chalk.green,
 734 | 							completed: chalk.green,
 735 | 							pending: chalk.yellow,
 736 | 							'in-progress': chalk.blue,
 737 | 							deferred: chalk.gray,
 738 | 							blocked: chalk.red,
 739 | 							cancelled: chalk.gray
 740 | 						};
 741 | 						const statusColor =
 742 | 							statusColors[status.toLowerCase()] || chalk.white;
 743 | 						// Ensure subtask ID is displayed correctly using parent ID from the original task object
 744 | 						return `${chalk.cyan(`${parentTaskForSubtasks.id}.${subtask.id}`)} [${statusColor(status)}] ${subtask.title}`;
 745 | 					})
 746 | 					.join('\n');
 747 | 			}
 748 | 
 749 | 			console.log(
 750 | 				boxen(
 751 | 					chalk.hex('#FF8800').bold(
 752 | 						// Use nextItem.id and nextItem.title
 753 | 						`🔥 Next Task to Work On: #${nextItem.id} - ${nextItem.title}`
 754 | 					) +
 755 | 						'\n\n' +
 756 | 						// Use nextItem.priority, nextItem.status, nextItem.dependencies
 757 | 						`${chalk.white('Priority:')} ${priorityColors[nextItem.priority || 'medium'](nextItem.priority || 'medium')}   ${chalk.white('Status:')} ${getStatusWithColor(nextItem.status, true)}\n` +
 758 | 						`${chalk.white('Dependencies:')} ${nextItem.dependencies && nextItem.dependencies.length > 0 ? formatDependenciesWithStatus(nextItem.dependencies, data.tasks, true, complexityReport) : chalk.gray('None')}\n\n` +
 759 | 						// Use nextTask.description (Note: findNextTask doesn't return description, need to fetch original task/subtask for this)
 760 | 						// *** Fetching original item for description and details ***
 761 | 						`${chalk.white('Description:')} ${getWorkItemDescription(nextItem, data.tasks)}` +
 762 | 						subtasksSection + // <-- Subtasks are handled above now
 763 | 						'\n\n' +
 764 | 						// Use nextItem.id
 765 | 						`${chalk.cyan('Start working:')} ${chalk.yellow(`task-master set-status --id=${nextItem.id} --status=in-progress`)}\n` +
 766 | 						// Use nextItem.id
 767 | 						`${chalk.cyan('View details:')} ${chalk.yellow(`task-master show ${nextItem.id}`)}`,
 768 | 					{
 769 | 						padding: { left: 2, right: 2, top: 1, bottom: 1 },
 770 | 						borderColor: '#FF8800',
 771 | 						borderStyle: 'round',
 772 | 						margin: { top: 1, bottom: 1 },
 773 | 						title: '⚡ RECOMMENDED NEXT TASK ⚡',
 774 | 						titleAlignment: 'center',
 775 | 						width: terminalWidth - 4,
 776 | 						fullscreen: false
 777 | 					}
 778 | 				)
 779 | 			);
 780 | 		} else {
 781 | 			console.log(
 782 | 				boxen(
 783 | 					chalk.hex('#FF8800').bold('No eligible next task found') +
 784 | 						'\n\n' +
 785 | 						'All pending tasks have dependencies that are not yet completed, or all tasks are done.',
 786 | 					{
 787 | 						padding: 1,
 788 | 						borderColor: '#FF8800',
 789 | 						borderStyle: 'round',
 790 | 						margin: { top: 1, bottom: 1 },
 791 | 						title: '⚡ NEXT TASK ⚡',
 792 | 						titleAlignment: 'center',
 793 | 						width: terminalWidth - 4 // Use full terminal width minus a small margin
 794 | 					}
 795 | 				)
 796 | 			);
 797 | 		}
 798 | 
 799 | 		// Show next steps
 800 | 		console.log(
 801 | 			boxen(
 802 | 				chalk.white.bold('Suggested Next Steps:') +
 803 | 					'\n\n' +
 804 | 					`${chalk.cyan('1.')} Run ${chalk.yellow('task-master next')} to see what to work on next\n` +
 805 | 					`${chalk.cyan('2.')} Run ${chalk.yellow('task-master expand --id=<id>')} to break down a task into subtasks\n` +
 806 | 					`${chalk.cyan('3.')} Run ${chalk.yellow('task-master set-status --id=<id> --status=done')} to mark a task as complete`,
 807 | 				{
 808 | 					padding: 1,
 809 | 					borderColor: 'gray',
 810 | 					borderStyle: 'round',
 811 | 					margin: { top: 1 }
 812 | 				}
 813 | 			)
 814 | 		);
 815 | 	} catch (error) {
 816 | 		log('error', `Error listing tasks: ${error.message}`);
 817 | 
 818 | 		if (outputFormat === 'json') {
 819 | 			// Return structured error for JSON output
 820 | 			throw {
 821 | 				code: 'TASK_LIST_ERROR',
 822 | 				message: error.message,
 823 | 				details: error.stack
 824 | 			};
 825 | 		}
 826 | 
 827 | 		console.error(chalk.red(`Error: ${error.message}`));
 828 | 		process.exit(1);
 829 | 	}
 830 | }
 831 | 
 832 | // *** Helper function to get description for task or subtask ***
 833 | function getWorkItemDescription(item, allTasks) {
 834 | 	if (!item) return 'N/A';
 835 | 	if (item.parentId) {
 836 | 		// It's a subtask
 837 | 		const parent = allTasks.find((t) => t.id === item.parentId);
 838 | 		const subtask = parent?.subtasks?.find(
 839 | 			(st) => `${parent.id}.${st.id}` === item.id
 840 | 		);
 841 | 		return subtask?.description || 'No description available.';
 842 | 	} else {
 843 | 		// It's a top-level task
 844 | 		const task = allTasks.find((t) => String(t.id) === String(item.id));
 845 | 		return task?.description || 'No description available.';
 846 | 	}
 847 | }
 848 | 
 849 | /**
 850 |  * Generate markdown-formatted output for README files
 851 |  * @param {Object} data - Full tasks data
 852 |  * @param {Array} filteredTasks - Filtered tasks array
 853 |  * @param {Object} stats - Statistics object
 854 |  * @returns {string} - Formatted markdown string
 855 |  */
 856 | function generateMarkdownOutput(data, filteredTasks, stats) {
 857 | 	const {
 858 | 		totalTasks,
 859 | 		completedTasks,
 860 | 		completionPercentage,
 861 | 		doneCount,
 862 | 		inProgressCount,
 863 | 		pendingCount,
 864 | 		blockedCount,
 865 | 		deferredCount,
 866 | 		cancelledCount,
 867 | 		totalSubtasks,
 868 | 		completedSubtasks,
 869 | 		subtaskCompletionPercentage,
 870 | 		inProgressSubtasks,
 871 | 		pendingSubtasks,
 872 | 		blockedSubtasks,
 873 | 		deferredSubtasks,
 874 | 		cancelledSubtasks,
 875 | 		tasksWithNoDeps,
 876 | 		tasksReadyToWork,
 877 | 		tasksWithUnsatisfiedDeps,
 878 | 		mostDependedOnTask,
 879 | 		mostDependedOnTaskId,
 880 | 		maxDependents,
 881 | 		avgDependenciesPerTask,
 882 | 		complexityReport,
 883 | 		withSubtasks,
 884 | 		nextItem
 885 | 	} = stats;
 886 | 
 887 | 	let markdown = '';
 888 | 
 889 | 	// Create progress bars for markdown (using Unicode block characters)
 890 | 	const createMarkdownProgressBar = (percentage, width = 20) => {
 891 | 		const filled = Math.round((percentage / 100) * width);
 892 | 		const empty = width - filled;
 893 | 		return '█'.repeat(filled) + '░'.repeat(empty);
 894 | 	};
 895 | 
 896 | 	const taskProgressBar = createMarkdownProgressBar(completionPercentage, 20);
 897 | 	const subtaskProgressBar = createMarkdownProgressBar(
 898 | 		subtaskCompletionPercentage,
 899 | 		20
 900 | 	);
 901 | 
 902 | 	// Dashboard section
 903 | 	// markdown += '```\n';
 904 | 	markdown += '| Project Dashboard |  |\n';
 905 | 	markdown += '| :-                |:-|\n';
 906 | 	markdown += `| Task Progress     | ${taskProgressBar} ${Math.round(completionPercentage)}% |\n`;
 907 | 	markdown += `| Done | ${doneCount} |\n`;
 908 | 	markdown += `| In Progress | ${inProgressCount} |\n`;
 909 | 	markdown += `| Pending | ${pendingCount} |\n`;
 910 | 	markdown += `| Deferred | ${deferredCount} |\n`;
 911 | 	markdown += `| Cancelled | ${cancelledCount} |\n`;
 912 | 	markdown += `|-|-|\n`;
 913 | 	markdown += `| Subtask Progress | ${subtaskProgressBar} ${Math.round(subtaskCompletionPercentage)}% |\n`;
 914 | 	markdown += `| Completed | ${completedSubtasks} |\n`;
 915 | 	markdown += `| In Progress | ${inProgressSubtasks} |\n`;
 916 | 	markdown += `| Pending | ${pendingSubtasks} |\n`;
 917 | 
 918 | 	markdown += '\n\n';
 919 | 
 920 | 	// Tasks table
 921 | 	markdown +=
 922 | 		'| ID | Title | Status | Priority | Dependencies | Complexity |\n';
 923 | 	markdown +=
 924 | 		'| :- | :-    | :-     | :-       | :-           | :-         |\n';
 925 | 
 926 | 	// Helper function to format status with symbols
 927 | 	const getStatusSymbol = (status) => {
 928 | 		switch (status) {
 929 | 			case 'done':
 930 | 			case 'completed':
 931 | 				return '✓&nbsp;done';
 932 | 			case 'in-progress':
 933 | 				return '►&nbsp;in-progress';
 934 | 			case 'pending':
 935 | 				return '○&nbsp;pending';
 936 | 			case 'blocked':
 937 | 				return '⭕&nbsp;blocked';
 938 | 			case 'deferred':
 939 | 				return 'x&nbsp;deferred';
 940 | 			case 'cancelled':
 941 | 				return 'x&nbsp;cancelled';
 942 | 			case 'review':
 943 | 				return '?&nbsp;review';
 944 | 			default:
 945 | 				return status || 'pending';
 946 | 		}
 947 | 	};
 948 | 
 949 | 	// Helper function to format dependencies without color codes
 950 | 	const formatDependenciesForMarkdown = (deps, allTasks) => {
 951 | 		if (!deps || deps.length === 0) return 'None';
 952 | 		return deps
 953 | 			.map((depId) => {
 954 | 				const depTask = allTasks.find((t) => t.id === depId);
 955 | 				return depTask ? depId.toString() : depId.toString();
 956 | 			})
 957 | 			.join(', ');
 958 | 	};
 959 | 
 960 | 	// Process all tasks
 961 | 	filteredTasks.forEach((task) => {
 962 | 		const taskTitle = task.title; // No truncation for README
 963 | 		const statusSymbol = getStatusSymbol(task.status);
 964 | 		const priority = task.priority || 'medium';
 965 | 		const deps = formatDependenciesForMarkdown(task.dependencies, data.tasks);
 966 | 		const complexity = task.complexityScore
 967 | 			? `● ${task.complexityScore}`
 968 | 			: 'N/A';
 969 | 
 970 | 		markdown += `| ${task.id} | ${taskTitle} | ${statusSymbol} | ${priority} | ${deps} | ${complexity} |\n`;
 971 | 
 972 | 		// Add subtasks if requested
 973 | 		if (withSubtasks && task.subtasks && task.subtasks.length > 0) {
 974 | 			task.subtasks.forEach((subtask) => {
 975 | 				const subtaskTitle = `${subtask.title}`; // No truncation
 976 | 				const subtaskStatus = getStatusSymbol(subtask.status);
 977 | 				const subtaskDeps = formatDependenciesForMarkdown(
 978 | 					subtask.dependencies,
 979 | 					data.tasks
 980 | 				);
 981 | 				const subtaskComplexity = subtask.complexityScore
 982 | 					? subtask.complexityScore.toString()
 983 | 					: 'N/A';
 984 | 
 985 | 				markdown += `| ${task.id}.${subtask.id} | ${subtaskTitle} | ${subtaskStatus} | -            | ${subtaskDeps} | ${subtaskComplexity} |\n`;
 986 | 			});
 987 | 		}
 988 | 	});
 989 | 
 990 | 	return markdown;
 991 | }
 992 | 
 993 | /**
 994 |  * Format dependencies for compact output with truncation and coloring
 995 |  * @param {Array} dependencies - Array of dependency IDs
 996 |  * @returns {string} - Formatted dependency string with arrow prefix
 997 |  */
 998 | function formatCompactDependencies(dependencies) {
 999 | 	if (!dependencies || dependencies.length === 0) {
1000 | 		return '';
1001 | 	}
1002 | 
1003 | 	if (dependencies.length > 5) {
1004 | 		const visible = dependencies.slice(0, 5).join(',');
1005 | 		const remaining = dependencies.length - 5;
1006 | 		return ` → ${chalk.cyan(visible)}${chalk.gray('... (+' + remaining + ' more)')}`;
1007 | 	} else {
1008 | 		return ` → ${chalk.cyan(dependencies.join(','))}`;
1009 | 	}
1010 | }
1011 | 
1012 | /**
1013 |  * Format a single task in compact one-line format
1014 |  * @param {Object} task - Task object
1015 |  * @param {number} maxTitleLength - Maximum title length before truncation
1016 |  * @returns {string} - Formatted task line
1017 |  */
1018 | function formatCompactTask(task, maxTitleLength = 50) {
1019 | 	const status = task.status || 'pending';
1020 | 	const priority = task.priority || 'medium';
1021 | 	const title = truncate(task.title || 'Untitled', maxTitleLength);
1022 | 
1023 | 	// Use colored status from existing function
1024 | 	const coloredStatus = getStatusWithColor(status, true);
1025 | 
1026 | 	// Color priority based on level
1027 | 	const priorityColors = {
1028 | 		high: chalk.red,
1029 | 		medium: chalk.yellow,
1030 | 		low: chalk.gray
1031 | 	};
1032 | 	const priorityColor = priorityColors[priority] || chalk.white;
1033 | 
1034 | 	// Format dependencies using shared helper
1035 | 	const depsText = formatCompactDependencies(task.dependencies);
1036 | 
1037 | 	return `${chalk.cyan(task.id)} ${coloredStatus} ${chalk.white(title)} ${priorityColor('(' + priority + ')')}${depsText}`;
1038 | }
1039 | 
1040 | /**
1041 |  * Format a subtask in compact format with indentation
1042 |  * @param {Object} subtask - Subtask object
1043 |  * @param {string|number} parentId - Parent task ID
1044 |  * @param {number} maxTitleLength - Maximum title length before truncation
1045 |  * @returns {string} - Formatted subtask line
1046 |  */
1047 | function formatCompactSubtask(subtask, parentId, maxTitleLength = 47) {
1048 | 	const status = subtask.status || 'pending';
1049 | 	const title = truncate(subtask.title || 'Untitled', maxTitleLength);
1050 | 
1051 | 	// Use colored status from existing function
1052 | 	const coloredStatus = getStatusWithColor(status, true);
1053 | 
1054 | 	// Format dependencies using shared helper
1055 | 	const depsText = formatCompactDependencies(subtask.dependencies);
1056 | 
1057 | 	return `  ${chalk.cyan(parentId + '.' + subtask.id)} ${coloredStatus} ${chalk.dim(title)}${depsText}`;
1058 | }
1059 | 
1060 | /**
1061 |  * Render complete compact output
1062 |  * @param {Array} filteredTasks - Tasks to display
1063 |  * @param {boolean} withSubtasks - Whether to include subtasks
1064 |  * @returns {void} - Outputs directly to console
1065 |  */
1066 | function renderCompactOutput(filteredTasks, withSubtasks) {
1067 | 	if (filteredTasks.length === 0) {
1068 | 		console.log('No tasks found');
1069 | 		return;
1070 | 	}
1071 | 
1072 | 	const output = [];
1073 | 
1074 | 	filteredTasks.forEach((task) => {
1075 | 		output.push(formatCompactTask(task));
1076 | 
1077 | 		if (withSubtasks && task.subtasks && task.subtasks.length > 0) {
1078 | 			task.subtasks.forEach((subtask) => {
1079 | 				output.push(formatCompactSubtask(subtask, task.id));
1080 | 			});
1081 | 		}
1082 | 	});
1083 | 
1084 | 	console.log(output.join('\n'));
1085 | }
1086 | 
1087 | export default listTasks;
1088 | 
```

--------------------------------------------------------------------------------
/.taskmaster/docs/tdd-workflow-phase-1-core-rails.md:
--------------------------------------------------------------------------------

```markdown
   1 | # Phase 1: Core Rails - Autonomous TDD Workflow
   2 | 
   3 | ## Objective
   4 | Implement the core autonomous TDD workflow with safe git operations, test generation/execution, and commit gating.
   5 | 
   6 | ## Scope
   7 | - WorkflowOrchestrator with event stream
   8 | - GitAdapter and TestResultValidator
   9 | - Subtask loop (RED → GREEN → COMMIT)
  10 | - CLI commands for AI agent orchestration
  11 | - MCP tools for AI agent orchestration
  12 | - Test result validation (AI reports, TaskMaster validates)
  13 | - Commit creation with enhanced metadata
  14 | - Branch/tag mapping
  15 | - Global storage for state and activity logs
  16 | - Framework-agnostic design (AI runs tests, not TaskMaster)
  17 | - Run report persistence
  18 | 
  19 | ## Key Design Decisions
  20 | 
  21 | ### Global Storage (`~/.taskmaster/`)
  22 | - **Why:** Keeps project directory clean, client-friendly, no tooling evidence in PRs
  23 | - **What:** All runtime state, logs, and throwaway artifacts
  24 | - **Where:** `~/.taskmaster/projects/<project-path>/runs/<run-id>/`
  25 | 
  26 | ### Dual System: State + Activity Log
  27 | - **State (`state.json`):** For orchestration, tells AI what to do next, mutable
  28 | - **Activity Log (`activity.jsonl`):** For debugging/audit, append-only event stream
  29 | - **Separation:** Optimizes for different use cases (fast reads vs. complete history)
  30 | 
  31 | ### Enhanced Commit Messages
  32 | - **Why:** Enables future task-checker bot validation without external dependencies
  33 | - **What:** Embeds task ID, phase, tag, test counts, coverage in commit body
  34 | - **Benefit:** PR contains full context for review and automated validation
  35 | 
  36 | ### Worktree Support
  37 | - **Why:** Enables parallel autonomous agents on different branches
  38 | - **How:** Each worktree has independent global state directory
  39 | - **Isolation:** No conflicts, complete separation
  40 | 
  41 | ### Framework-Agnostic Test Execution
  42 | - **AI runs tests:** AI agent knows project context and test framework (npm test, pytest, go test)
  43 | - **TaskMaster validates:** Only checks that RED fails and GREEN passes
  44 | - **No framework detection:** TaskMaster doesn't need to know Jest vs Vitest vs pytest
  45 | - **Trust but verify:** AI reports results, TaskMaster validates they make sense
  46 | - **Language agnostic:** Works with any language/framework without TaskMaster changes
  47 | 
  48 | ### AI Agent Orchestration Model
  49 | - **Who executes:** User's AI agent (Claude Code, Cursor, Windsurf, etc.) - not TaskMaster
  50 | - **TaskMaster's role:** Workflow orchestration, validation, commit creation
  51 | - **AI agent's role:** Code generation, test execution, result reporting
  52 | - **Communication:** Via CLI commands or MCP tools
  53 | - **State-driven:** AI agent reads `state.json` to know what to do next
  54 | 
  55 | **Separation of Concerns:**
  56 | 
  57 | | TaskMaster Responsibilities | AI Agent Responsibilities |
  58 | |----------------------------|---------------------------|
  59 | | Workflow state machine | Generate tests |
  60 | | Validate phase transitions | Run tests (knows test framework) |
  61 | | Create commits with metadata | Implement code |
  62 | | Store activity logs | Report test results |
  63 | | Manage git operations | Understand project context |
  64 | | Track progress | Choose appropriate test commands |
  65 | 
  66 | **Flow:**
  67 | ```
  68 | AI Agent                                    TaskMaster
  69 |    │                                            │
  70 |    ├──► tm autopilot start 1                    │
  71 |    │                                            ├──► Creates state, branch
  72 |    │                                            ├──► Returns: "next action: RED phase for 1.1"
  73 |    │                                            │
  74 |    ├──► tm autopilot next                       │
  75 |    │                                            ├──► Reads state.json
  76 |    │                                            ├──► Returns: { phase: "red", subtask: "1.1", context: {...} }
  77 |    │                                            │
  78 |    │    Generate tests (AI does this)           │
  79 |    │    npm test (AI runs this)                 │
  80 |    │    Results: 3 failed, 0 passed             │
  81 |    │                                            │
  82 |    ├──► tm autopilot complete red 1.1 \         │
  83 |    │    --results="failed:3,passed:0"           │
  84 |    │                                            ├──► Validates: tests failed ✓
  85 |    │                                            ├──► Updates state to GREEN
  86 |    │                                            ├──► Returns: "next action: GREEN phase"
  87 |    │                                            │
  88 |    ├──► tm autopilot next                       │
  89 |    │                                            ├──► Returns: { phase: "green", subtask: "1.1" }
  90 |    │                                            │
  91 |    │    Implement code (AI does this)           │
  92 |    │    npm test (AI runs this)                 │
  93 |    │    Results: 3 passed, 0 failed             │
  94 |    │                                            │
  95 |    ├──► tm autopilot complete green 1.1 \       │
  96 |    │    --results="passed:3,failed:0"           │
  97 |    │                                            ├──► Validates: tests passed ✓
  98 |    │                                            ├──► Updates state to COMMIT
  99 |    │                                            ├──► Returns: "next action: COMMIT phase"
 100 |    │                                            │
 101 |    ├──► tm autopilot commit 1.1                 │
 102 |    │                                            ├──► Detects changed files (git status)
 103 |    │                                            ├──► Stages files
 104 |    │                                            ├──► Creates commit with metadata
 105 |    │                                            ├──► Updates state to next subtask
 106 |    │                                            ├──► Returns: { sha: "a1b2c3d", nextAction: {...} }
 107 |    │                                            │
 108 |    └──► Loop continues...                        │
 109 | ```
 110 | 
 111 | **Key principle:** AI agent is the domain expert (knows the codebase, frameworks, tools). TaskMaster is the workflow expert (knows TDD process, state management, git operations).
 112 | 
 113 | ## Deliverables
 114 | 
 115 | ### 1. WorkflowOrchestrator (`packages/tm-core/src/services/workflow-orchestrator.ts`)
 116 | 
 117 | **Responsibilities:**
 118 | - State machine driving phases: Preflight → Branch/Tag → SubtaskIter → Finalize
 119 | - Event emission for progress tracking
 120 | - Coordination of Git, Test, and Executor adapters
 121 | - Run state persistence
 122 | 
 123 | **API:**
 124 | ```typescript
 125 | class WorkflowOrchestrator {
 126 |   async executeTask(taskId: string, options: AutopilotOptions): Promise<RunResult>
 127 |   async resume(runId: string): Promise<RunResult>
 128 |   on(event: string, handler: (data: any) => void): void
 129 | 
 130 |   // Events emitted:
 131 |   // - 'phase:start' { phase, timestamp }
 132 |   // - 'phase:complete' { phase, status, timestamp }
 133 |   // - 'subtask:start' { subtaskId, phase }
 134 |   // - 'subtask:complete' { subtaskId, phase, status }
 135 |   // - 'test:run' { subtaskId, phase, results }
 136 |   // - 'commit:created' { subtaskId, sha, message }
 137 |   // - 'error' { phase, error, recoverable }
 138 | }
 139 | ```
 140 | 
 141 | **State Machine Phases:**
 142 | 1. Preflight - validate environment
 143 | 2. BranchSetup - create branch, set tag
 144 | 3. SubtaskLoop - for each subtask: RED → GREEN → COMMIT
 145 | 4. Finalize - full test suite, coverage check
 146 | 5. Complete - run report, cleanup
 147 | 
 148 | ### 2. GitAdapter (`packages/tm-core/src/services/git-adapter.ts`)
 149 | 
 150 | **Responsibilities:**
 151 | - All git operations with safety checks
 152 | - Branch name generation from tag/task
 153 | - Confirmation gates for destructive operations
 154 | 
 155 | **API:**
 156 | ```typescript
 157 | class GitAdapter {
 158 |   async isWorkingTreeClean(): Promise<boolean>
 159 |   async getCurrentBranch(): Promise<string>
 160 |   async getDefaultBranch(): Promise<string>
 161 |   async createBranch(name: string): Promise<void>
 162 |   async checkoutBranch(name: string): Promise<void>
 163 |   async commit(message: string, files?: string[]): Promise<string>
 164 |   async push(branch: string, remote?: string): Promise<void>
 165 | 
 166 |   // Safety checks
 167 |   async assertNotOnDefaultBranch(): Promise<void>
 168 |   async assertCleanOrConfirm(): Promise<void>
 169 | 
 170 |   // Branch naming
 171 |   generateBranchName(tag: string, taskId: string, slug: string): string
 172 | }
 173 | ```
 174 | 
 175 | **Guardrails:**
 176 | - Never allow commits on default branch
 177 | - Always check working tree before branch creation
 178 | - Confirm destructive operations unless `--no-confirm` flag
 179 | 
 180 | ### 3. Test Result Validator (`packages/tm-core/src/services/test-result-validator.ts`)
 181 | 
 182 | **Responsibilities:**
 183 | - Validate test results reported by AI agent
 184 | - Ensure RED phase has failing tests
 185 | - Ensure GREEN phase has passing tests
 186 | - Enforce coverage thresholds (if provided)
 187 | 
 188 | **API:**
 189 | ```typescript
 190 | class TestResultValidator {
 191 |   async validateRedPhase(results: TestResults): Promise<ValidationResult>
 192 |   async validateGreenPhase(results: TestResults, coverage?: number): Promise<ValidationResult>
 193 |   async meetsThresholds(coverage: number): Promise<boolean>
 194 | }
 195 | 
 196 | interface TestResults {
 197 |   passed: number
 198 |   failed: number
 199 |   skipped?: number
 200 |   total: number
 201 | }
 202 | 
 203 | interface ValidationResult {
 204 |   valid: boolean
 205 |   message: string
 206 |   suggestion?: string
 207 | }
 208 | ```
 209 | 
 210 | **Validation Logic:**
 211 | ```typescript
 212 | async function validateRedPhase(results: TestResults): ValidationResult {
 213 |   if (results.failed === 0) {
 214 |     return {
 215 |       valid: false,
 216 |       message: "RED phase requires failing tests. All tests passed.",
 217 |       suggestion: "Verify tests are checking expected behavior. Tests should fail before implementation."
 218 |     }
 219 |   }
 220 | 
 221 |   if (results.passed > 0) {
 222 |     return {
 223 |       valid: true,
 224 |       message: `RED phase valid: ${results.failed} failing, ${results.passed} passing (existing tests)`,
 225 |       warning: "Some tests passing - ensure new tests are failing"
 226 |     }
 227 |   }
 228 | 
 229 |   return {
 230 |     valid: true,
 231 |     message: `RED phase complete: ${results.failed} tests failing as expected`
 232 |   }
 233 | }
 234 | 
 235 | async function validateGreenPhase(results: TestResults): ValidationResult {
 236 |   if (results.failed > 0) {
 237 |     return {
 238 |       valid: false,
 239 |       message: `GREEN phase incomplete: ${results.failed} tests still failing`,
 240 |       suggestion: "Continue implementing until all tests pass or retry GREEN phase"
 241 |     }
 242 |   }
 243 | 
 244 |   return {
 245 |     valid: true,
 246 |     message: `GREEN phase complete: ${results.passed} tests passing`
 247 |   }
 248 | }
 249 | ```
 250 | 
 251 | **Note:** AI agent is responsible for:
 252 | - Running test commands (knows npm test vs pytest vs go test)
 253 | - Parsing test output
 254 | - Reporting results to TaskMaster
 255 | 
 256 | TaskMaster only validates the reported numbers make sense for the phase.
 257 | 
 258 | ### 4. Test Generation Integration
 259 | 
 260 | **Use Surgical Test Generator:**
 261 | - Load prompt from `.claude/agents/surgical-test-generator.md`
 262 | - Compose with task/subtask context
 263 | - Generate tests via executor (Claude)
 264 | - Write test files to detected locations
 265 | 
 266 | **Prompt Composition:**
 267 | ```typescript
 268 | async function composeRedPrompt(subtask: Subtask, context: ProjectContext): Promise<string> {
 269 |   const systemPrompts = [
 270 |     loadFile('.cursor/rules/git_workflow.mdc'),
 271 |     loadFile('.cursor/rules/test_workflow.mdc'),
 272 |     loadFile('.claude/agents/surgical-test-generator.md')
 273 |   ]
 274 | 
 275 |   const taskContext = formatTaskContext(subtask)
 276 |   const instruction = formatRedInstruction(subtask, context)
 277 | 
 278 |   return [
 279 |     ...systemPrompts,
 280 |     '<TASK CONTEXT>',
 281 |     taskContext,
 282 |     '<INSTRUCTION>',
 283 |     instruction
 284 |   ].join('\n\n')
 285 | }
 286 | ```
 287 | 
 288 | ### 5. Subtask Loop Implementation
 289 | 
 290 | **RED Phase:**
 291 | 1. TaskMaster returns RED action with subtask context
 292 | 2. AI agent generates tests (TaskMaster not involved)
 293 | 3. AI agent writes test files (TaskMaster not involved)
 294 | 4. AI agent runs tests using project's test command (e.g., npm test)
 295 | 5. AI agent reports results: `tm autopilot complete red <id> --results="failed:3,passed:0"`
 296 | 6. TaskMaster validates: tests should have failures
 297 | 7. If validation fails (tests passed), return error with suggestion
 298 | 8. If validation passes, update state to GREEN, store results in activity log
 299 | 9. Return next action (GREEN phase)
 300 | 
 301 | **GREEN Phase:**
 302 | 1. TaskMaster returns GREEN action with subtask context
 303 | 2. AI agent implements code (TaskMaster not involved)
 304 | 3. AI agent runs tests using project's test command
 305 | 4. AI agent reports results: `tm autopilot complete green <id> --results="passed:5,failed:0" --coverage="85"`
 306 | 5. TaskMaster validates: all tests should pass
 307 | 6. If validation fails (tests still failing):
 308 |    - Increment attempt counter
 309 |    - If under max attempts: return GREEN action again with attempt number
 310 |    - If max attempts reached: save state, emit pause event, return resumable checkpoint
 311 | 7. If validation passes: update state to COMMIT, store results in activity log
 312 | 8. Return next action (COMMIT phase)
 313 | 
 314 | **COMMIT Phase:**
 315 | 1. TaskMaster receives commit command: `tm autopilot commit <id>`
 316 | 2. Detect changed files: `git status --porcelain`
 317 | 3. Validate coverage meets thresholds (if provided and threshold configured)
 318 | 4. Generate conventional commit message with task metadata
 319 | 5. Stage files: `git add <files>`
 320 | 6. Create commit: `git commit -m "<message>"`
 321 | 7. Update subtask status to 'done' in tasks.json
 322 | 8. Log commit event to activity.jsonl
 323 | 9. Update state to next subtask's RED phase
 324 | 10. Return next action
 325 | 
 326 | **Key changes from original design:**
 327 | - AI agent runs all test commands (framework agnostic)
 328 | - TaskMaster only validates reported results
 329 | - No test framework detection needed
 330 | - No test execution by TaskMaster
 331 | - AI agent is trusted to report accurate results
 332 | 
 333 | ### 6. Branch & Tag Management
 334 | 
 335 | **Integration with existing tag system:**
 336 | - Use `scripts/modules/task-manager/tag-management.js`
 337 | - Explicit tag switching when branch created
 338 | - Store branch ↔ tag mapping in run state
 339 | 
 340 | **Branch Naming:**
 341 | - Pattern from config: `{tag}/task-{id}-{slug}`
 342 | - Default: `analytics/task-42-user-metrics`
 343 | - Sanitize: lowercase, replace spaces with hyphens
 344 | 
 345 | ### 7. Global Storage & State Management
 346 | 
 347 | **Philosophy:**
 348 | - All runtime state, logs, and throwaway artifacts stored globally in `~/.taskmaster/`
 349 | - Project directory stays clean - only code changes and tasks.json versioned
 350 | - Enables single-player autonomous mode without polluting PRs
 351 | - Client-friendly: no evidence of tooling in source code
 352 | 
 353 | **Global directory structure:**
 354 | ```
 355 | ~/.taskmaster/
 356 | ├── projects/
 357 | │   └── <project-path-normalized>/
 358 | │       ├── runs/
 359 | │       │   └── <tag>__task-<id>__<timestamp>/
 360 | │       │       ├── manifest.json          # run metadata
 361 | │       │       ├── activity.jsonl         # event stream (debugging)
 362 | │       │       ├── state.json             # resumable checkpoint
 363 | │       │       ├── commits.txt            # commit SHAs
 364 | │       │       └── test-results/
 365 | │       │           ├── subtask-1.1-red.json
 366 | │       │           ├── subtask-1.1-green.json
 367 | │       │           └── final-suite.json
 368 | │       └── tags/
 369 | │           └── <tag-name>/
 370 | │               └── current-run.json       # active run pointer
 371 | └── cache/
 372 |     └── templates/                          # shared templates
 373 | ```
 374 | 
 375 | **Project path normalization:**
 376 | ```typescript
 377 | function getProjectStoragePath(projectRoot: string): string {
 378 |   const normalized = projectRoot
 379 |     .replace(/\//g, '-')
 380 |     .replace(/^-/, '')
 381 | 
 382 |   return path.join(os.homedir(), '.taskmaster', 'projects', normalized)
 383 |   // Example: ~/.taskmaster/projects/-Volumes-Workspace-contrib-task-master-claude-task-master
 384 | }
 385 | ```
 386 | 
 387 | **Run ID generation:**
 388 | ```typescript
 389 | function generateRunId(tag: string, taskId: string): string {
 390 |   const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
 391 |   return `${tag}__task-${taskId}__${timestamp}`
 392 |   // Example: tdd-workflow-phase-0__task-1__2025-10-07T14-30-00-000Z
 393 | }
 394 | ```
 395 | 
 396 | **manifest.json:**
 397 | ```json
 398 | {
 399 |   "runId": "tdd-workflow-phase-0__task-1__2025-10-07T14-30-00-000Z",
 400 |   "projectRoot": "/Volumes/Workspace/contrib/task-master/claude-task-master",
 401 |   "taskId": "1",
 402 |   "tag": "tdd-workflow-phase-0",
 403 |   "branch": "tdd-phase-0-implementation",
 404 |   "startTime": "2025-10-07T14:30:00Z",
 405 |   "endTime": null,
 406 |   "status": "in-progress",
 407 |   "currentPhase": "subtask-loop",
 408 |   "currentSubtask": "1.2",
 409 |   "subtasksCompleted": ["1.1"],
 410 |   "subtasksFailed": [],
 411 |   "totalCommits": 1
 412 | }
 413 | ```
 414 | 
 415 | **state.json** (orchestration state):
 416 | ```json
 417 | {
 418 |   "runId": "tdd-workflow-phase-0__task-1__2025-10-07T14-30-00-000Z",
 419 |   "taskId": "1",
 420 |   "tag": "tdd-workflow-phase-0",
 421 |   "branch": "tdd-phase-0-implementation",
 422 |   "currentSubtask": "1.2",
 423 |   "currentPhase": "green",
 424 |   "attemptNumber": 1,
 425 |   "maxAttempts": 3,
 426 |   "completedSubtasks": ["1.1"],
 427 |   "pendingSubtasks": ["1.2", "1.3", "1.4"],
 428 |   "nextAction": {
 429 |     "type": "implement",
 430 |     "subtask": "1.2",
 431 |     "phase": "green",
 432 |     "context": {
 433 |       "testFile": "src/__tests__/preflight.test.ts",
 434 |       "failingTests": [
 435 |         "should detect test runner from package.json",
 436 |         "should validate git working tree"
 437 |       ],
 438 |       "implementationFiles": ["src/services/preflight-checker.ts"]
 439 |     }
 440 |   },
 441 |   "lastUpdated": "2025-10-07T14:31:45Z",
 442 |   "canResume": true
 443 | }
 444 | ```
 445 | 
 446 | **activity.jsonl** (append-only event log):
 447 | ```jsonl
 448 | {"ts":"2025-10-07T14:30:00Z","event":"phase:start","phase":"preflight","status":"ok"}
 449 | {"ts":"2025-10-07T14:30:15Z","event":"phase:complete","phase":"preflight","checks":{"git":true,"test":true,"tools":true}}
 450 | {"ts":"2025-10-07T14:30:20Z","event":"branch:created","branch":"tdd-phase-0-implementation"}
 451 | {"ts":"2025-10-07T14:30:22Z","event":"tag:switched","from":"master","to":"tdd-workflow-phase-0"}
 452 | {"ts":"2025-10-07T14:30:25Z","event":"subtask:start","subtaskId":"1.1","phase":"red"}
 453 | {"ts":"2025-10-07T14:31:10Z","event":"test:generated","files":["src/__tests__/autopilot.test.ts"],"testCount":3}
 454 | {"ts":"2025-10-07T14:31:15Z","event":"test:run","subtaskId":"1.1","phase":"red","passed":0,"failed":3,"status":"expected"}
 455 | {"ts":"2025-10-07T14:31:20Z","event":"phase:transition","from":"red","to":"green"}
 456 | {"ts":"2025-10-07T14:32:45Z","event":"code:modified","files":["src/commands/autopilot.ts"],"linesChanged":"+58,-0"}
 457 | {"ts":"2025-10-07T14:33:00Z","event":"test:run","subtaskId":"1.1","phase":"green","attempt":1,"passed":3,"failed":0,"status":"success"}
 458 | {"ts":"2025-10-07T14:33:15Z","event":"commit:created","subtaskId":"1.1","sha":"a1b2c3d","message":"feat(cli): add autopilot command skeleton (task 1.1)"}
 459 | {"ts":"2025-10-07T14:33:20Z","event":"subtask:complete","subtaskId":"1.1","duration":"180s"}
 460 | ```
 461 | 
 462 | **current-run.json** (active run pointer):
 463 | ```json
 464 | {
 465 |   "runId": "tdd-workflow-phase-0__task-1__2025-10-07T14-30-00-000Z",
 466 |   "taskId": "1",
 467 |   "tag": "tdd-workflow-phase-0",
 468 |   "startTime": "2025-10-07T14:30:00Z",
 469 |   "status": "in-progress"
 470 | }
 471 | ```
 472 | 
 473 | **What stays in project (versioned):**
 474 | ```
 475 | <project>/
 476 | ├── .taskmaster/
 477 | │   ├── tasks/
 478 | │   │   └── tasks.json              # ✅ Versioned (task definitions)
 479 | │   └── config.json                 # ✅ Versioned (shared config)
 480 | └── .gitignore                       # Add: .taskmaster/state/, .taskmaster/reports/
 481 | ```
 482 | 
 483 | **State vs Activity Log:**
 484 | 
 485 | | State File (state.json) | Activity Log (activity.jsonl) |
 486 | |------------------------|-------------------------------|
 487 | | Current position | Full history |
 488 | | What to do next | What happened |
 489 | | Mutable (updated) | Immutable (append-only) |
 490 | | For orchestration | For debugging/audit |
 491 | | Single JSON object | Line-delimited JSON |
 492 | | Small (~2KB) | Can grow large |
 493 | 
 494 | **Resume logic:**
 495 | ```typescript
 496 | async function resumeWorkflow(): Promise<void> {
 497 |   // 1. Find active run
 498 |   const currentRun = await loadJSON('~/.taskmaster/projects/<project>/tags/<tag>/current-run.json')
 499 | 
 500 |   // 2. Load state from that run
 501 |   const state = await loadJSON(`~/.taskmaster/projects/<project>/runs/${currentRun.runId}/state.json`)
 502 | 
 503 |   // 3. Continue from checkpoint
 504 |   return orchestrator.resumeFrom(state)
 505 | }
 506 | ```
 507 | 
 508 | ### 8. Enhanced Commit Message Format
 509 | 
 510 | **Purpose:**
 511 | - Embed task context in commits for future validation
 512 | - Enable task-checker bot to verify alignment
 513 | - Provide audit trail without needing external logs in PR
 514 | 
 515 | **Commit message template:**
 516 | ```
 517 | {type}({scope}): {summary} (task {taskId})
 518 | 
 519 | {detailed description}
 520 | 
 521 | Task: #{taskId} - {taskTitle}
 522 | Phase: {phaseName}
 523 | Tag: {tagName}
 524 | 
 525 | Tests: {testCount} passing
 526 | Coverage: {coveragePercent}% lines
 527 | ```
 528 | 
 529 | **Example commit:**
 530 | ```
 531 | feat(cli): add autopilot command skeleton (task 1.1)
 532 | 
 533 | Implements AutopilotCommand class with Commander.js integration.
 534 | Adds argument parsing for task ID and dry-run flag. Includes basic
 535 | command registration and help text following existing CLI patterns.
 536 | 
 537 | Task: #1.1 - Create command structure
 538 | Phase: Phase 0 - Spike
 539 | Tag: tdd-workflow-phase-0
 540 | 
 541 | Tests: 3 passing
 542 | Coverage: 92% lines
 543 | ```
 544 | 
 545 | **Conventional commit types:**
 546 | - `feat` - New feature or capability
 547 | - `fix` - Bug fix
 548 | - `test` - Test-only changes
 549 | - `refactor` - Code restructuring without behavior change
 550 | - `docs` - Documentation updates
 551 | - `chore` - Build/tooling changes
 552 | 
 553 | **Scope determination:**
 554 | ```typescript
 555 | function determineScope(files: string[]): string {
 556 |   // Extract common scope from changed files
 557 |   const scopes = files.map(f => {
 558 |     if (f.startsWith('apps/cli/')) return 'cli'
 559 |     if (f.startsWith('packages/tm-core/')) return 'core'
 560 |     if (f.startsWith('packages/tm-mcp/')) return 'mcp'
 561 |     return 'misc'
 562 |   })
 563 | 
 564 |   // Use most common scope
 565 |   return mode(scopes)
 566 | }
 567 | ```
 568 | 
 569 | **Commit validation (future task-checker bot):**
 570 | ```typescript
 571 | async function validateCommit(commit: Commit, task: Task): Promise<ValidationResult> {
 572 |   const taskId = extractTaskId(commit.message)  // "1.1"
 573 |   const task = await loadTask(taskId)
 574 | 
 575 |   return aiChecker.validate({
 576 |     commitDiff: commit.diff,
 577 |     commitMessage: commit.message,
 578 |     taskDescription: task.description,
 579 |     acceptanceCriteria: task.acceptanceCriteria,
 580 |     testStrategy: task.testStrategy
 581 |   })
 582 | }
 583 | ```
 584 | 
 585 | ### 9. CLI Commands for AI Agent Orchestration
 586 | 
 587 | **New CLI commands** (all under `tm autopilot` namespace):
 588 | 
 589 | ```bash
 590 | # Start workflow - creates branch, initializes state
 591 | tm autopilot start <taskId> [options]
 592 |   --branch <name>       # Override branch name
 593 |   --no-confirm          # Skip confirmations
 594 |   --max-attempts <n>    # Override max GREEN attempts
 595 | 
 596 | # Get next action from state
 597 | tm autopilot next [options]
 598 |   --json                # Output as JSON for parsing
 599 | 
 600 | # Complete a phase and report test results
 601 | tm autopilot complete <phase> <subtaskId> --results="<passed:n,failed:n>" [options]
 602 |   # phase: red | green
 603 |   --results <passed:n,failed:n>  # Required: test results from AI
 604 |   --coverage <percentage>        # Optional: coverage percentage
 605 |   --files <file1,file2>          # Optional: files changed (auto-detected if omitted)
 606 | 
 607 | # Create commit (called by AI after GREEN passes)
 608 | tm autopilot commit <subtaskId> [options]
 609 |   --message <msg>       # Override commit message
 610 | 
 611 | # Resume from interrupted run
 612 | tm autopilot resume [options]
 613 |   --run-id <id>         # Specific run to resume
 614 | 
 615 | # Get current status
 616 | tm autopilot status
 617 |   --json                # Output as JSON
 618 | 
 619 | # Watch activity log in real-time
 620 | tm autopilot watch
 621 | 
 622 | # Abort current run
 623 | tm autopilot abort [options]
 624 |   --cleanup             # Delete branch and state
 625 | ```
 626 | 
 627 | **Command details:**
 628 | 
 629 | **`tm autopilot start <taskId>`**
 630 | - Creates global state directory
 631 | - Creates feature branch
 632 | - Switches tag
 633 | - Initializes state.json with first subtask
 634 | - Returns next action (RED phase for first subtask)
 635 | 
 636 | **`tm autopilot next`**
 637 | - Reads `~/.taskmaster/projects/<project>/tags/<tag>/current-run.json`
 638 | - Reads `~/.taskmaster/projects/<project>/runs/<run-id>/state.json`
 639 | - Returns next action with full context
 640 | 
 641 | Output:
 642 | ```json
 643 | {
 644 |   "action": "red",
 645 |   "subtask": {
 646 |     "id": "1.1",
 647 |     "title": "Create command structure",
 648 |     "description": "...",
 649 |     "testStrategy": "..."
 650 |   },
 651 |   "context": {
 652 |     "projectRoot": "/path/to/project",
 653 |     "testPattern": "**/*.test.ts",
 654 |     "existingTests": []
 655 |   },
 656 |   "instructions": "Generate tests for this subtask. Tests should fail initially."
 657 | }
 658 | ```
 659 | 
 660 | **`tm autopilot complete <phase> <subtaskId>`**
 661 | - Receives test results from AI agent
 662 | - Validates phase completion:
 663 |   - **RED**: Ensures reported results show failures
 664 |   - **GREEN**: Ensures reported results show all tests passing
 665 | - Updates state to next phase
 666 | - Logs event to activity.jsonl with test results
 667 | - Returns next action
 668 | 
 669 | **Examples:**
 670 | ```bash
 671 | # After AI generates tests and runs them
 672 | tm autopilot complete red 1.1 --results="failed:3,passed:0"
 673 | 
 674 | # After AI implements code and runs tests
 675 | tm autopilot complete green 1.1 --results="passed:3,failed:0" --coverage="92"
 676 | 
 677 | # With existing passing tests
 678 | tm autopilot complete red 1.1 --results="failed:3,passed:12"
 679 | ```
 680 | 
 681 | **`tm autopilot commit <subtaskId>`**
 682 | - Generates commit message from template
 683 | - Stages files
 684 | - Creates commit with enhanced message
 685 | - Updates subtask status to 'done'
 686 | - Updates state to next subtask
 687 | - Returns next action
 688 | 
 689 | **`tm autopilot status`**
 690 | ```json
 691 | {
 692 |   "runId": "tdd-workflow-phase-0__task-1__2025-10-07T14-30-00-000Z",
 693 |   "taskId": "1",
 694 |   "currentSubtask": "1.2",
 695 |   "currentPhase": "green",
 696 |   "attemptNumber": 1,
 697 |   "progress": {
 698 |     "completed": ["1.1"],
 699 |     "current": "1.2",
 700 |     "remaining": ["1.3", "1.4"]
 701 |   },
 702 |   "commits": 1,
 703 |   "startTime": "2025-10-07T14:30:00Z",
 704 |   "duration": "5m 30s"
 705 | }
 706 | ```
 707 | 
 708 | ### 10. MCP Tools for AI Agent Orchestration
 709 | 
 710 | **New MCP tools** (add to `packages/tm-mcp/src/tools/`):
 711 | 
 712 | ```typescript
 713 | // autopilot_start
 714 | {
 715 |   name: "autopilot_start",
 716 |   description: "Start autonomous TDD workflow for a task",
 717 |   parameters: {
 718 |     taskId: string,
 719 |     options?: {
 720 |       branch?: string,
 721 |       maxAttempts?: number
 722 |     }
 723 |   },
 724 |   returns: {
 725 |     runId: string,
 726 |     branch: string,
 727 |     nextAction: NextAction
 728 |   }
 729 | }
 730 | 
 731 | // autopilot_next
 732 | {
 733 |   name: "autopilot_next",
 734 |   description: "Get next action from workflow state",
 735 |   parameters: {
 736 |     projectRoot?: string  // defaults to current
 737 |   },
 738 |   returns: {
 739 |     action: "red" | "green" | "commit" | "complete",
 740 |     subtask: Subtask,
 741 |     context: Context,
 742 |     instructions: string
 743 |   }
 744 | }
 745 | 
 746 | // autopilot_complete_phase
 747 | {
 748 |   name: "autopilot_complete_phase",
 749 |   description: "Report test results and validate phase completion",
 750 |   parameters: {
 751 |     phase: "red" | "green",
 752 |     subtaskId: string,
 753 |     testResults: {
 754 |       passed: number,
 755 |       failed: number,
 756 |       skipped?: number
 757 |     },
 758 |     coverage?: number,  // Optional coverage percentage
 759 |     files?: string[]    // Optional, auto-detected if not provided
 760 |   },
 761 |   returns: {
 762 |     validated: boolean,
 763 |     message: string,
 764 |     suggestion?: string,
 765 |     nextAction: NextAction
 766 |   }
 767 | }
 768 | 
 769 | // autopilot_commit
 770 | {
 771 |   name: "autopilot_commit",
 772 |   description: "Create commit for completed subtask",
 773 |   parameters: {
 774 |     subtaskId: string,
 775 |     files?: string[],
 776 |     message?: string  // Override
 777 |   },
 778 |   returns: {
 779 |     commitSha: string,
 780 |     message: string,
 781 |     nextAction: NextAction
 782 |   }
 783 | }
 784 | 
 785 | // autopilot_status
 786 | {
 787 |   name: "autopilot_status",
 788 |   description: "Get current workflow status",
 789 |   parameters: {
 790 |     projectRoot?: string
 791 |   },
 792 |   returns: {
 793 |     runId: string,
 794 |     taskId: string,
 795 |     currentSubtask: string,
 796 |     currentPhase: string,
 797 |     progress: Progress,
 798 |     commits: number
 799 |   }
 800 | }
 801 | 
 802 | // autopilot_resume
 803 | {
 804 |   name: "autopilot_resume",
 805 |   description: "Resume interrupted workflow",
 806 |   parameters: {
 807 |     runId?: string  // defaults to current
 808 |   },
 809 |   returns: {
 810 |     resumed: boolean,
 811 |     nextAction: NextAction
 812 |   }
 813 | }
 814 | ```
 815 | 
 816 | **MCP tool usage example (Claude Code session):**
 817 | 
 818 | ```javascript
 819 | // AI agent calls MCP tools
 820 | const { runId, nextAction } = await mcp.autopilot_start({ taskId: "1" })
 821 | 
 822 | while (nextAction.action !== "complete") {
 823 |   const action = await mcp.autopilot_next()
 824 | 
 825 |   if (action.action === "red") {
 826 |     // AI generates tests
 827 |     const tests = await generateTests(action.subtask, action.context)
 828 |     await writeFiles(tests)
 829 | 
 830 |     // AI runs tests (using project's test command)
 831 |     const testOutput = await runCommand("npm test")  // or pytest, go test, etc.
 832 |     const results = parseTestOutput(testOutput)
 833 | 
 834 |     // Report results to TaskMaster
 835 |     const validation = await mcp.autopilot_complete_phase({
 836 |       phase: "red",
 837 |       subtaskId: action.subtask.id,
 838 |       testResults: {
 839 |         passed: results.passed,
 840 |         failed: results.failed,
 841 |         skipped: results.skipped
 842 |       }
 843 |     })
 844 | 
 845 |     if (!validation.validated) {
 846 |       console.error(validation.message)
 847 |       // Handle validation failure
 848 |     }
 849 |   }
 850 | 
 851 |   if (action.action === "green") {
 852 |     // AI implements code
 853 |     const impl = await implementCode(action.subtask, action.context)
 854 |     await writeFiles(impl)
 855 | 
 856 |     // AI runs tests again
 857 |     const testOutput = await runCommand("npm test")
 858 |     const results = parseTestOutput(testOutput)
 859 |     const coverage = parseCoverage(testOutput)
 860 | 
 861 |     // Report results to TaskMaster
 862 |     const validation = await mcp.autopilot_complete_phase({
 863 |       phase: "green",
 864 |       subtaskId: action.subtask.id,
 865 |       testResults: {
 866 |         passed: results.passed,
 867 |         failed: results.failed
 868 |       },
 869 |       coverage: coverage.lines
 870 |     })
 871 | 
 872 |     if (!validation.validated) {
 873 |       console.log(validation.message, validation.suggestion)
 874 |       // Retry or handle failure
 875 |     }
 876 |   }
 877 | 
 878 |   if (action.action === "commit") {
 879 |     // TaskMaster creates the commit
 880 |     const { commitSha, nextAction: next } = await mcp.autopilot_commit({
 881 |       subtaskId: action.subtask.id
 882 |     })
 883 | 
 884 |     nextAction = next
 885 |   }
 886 | }
 887 | ```
 888 | 
 889 | ### 11. AI Agent Instructions (CLAUDE.md integration)
 890 | 
 891 | Add to `.claude/CLAUDE.md` or `.cursor/rules/`:
 892 | 
 893 | ````markdown
 894 | ## TaskMaster Autonomous Workflow
 895 | 
 896 | When working on tasks with `tm autopilot`:
 897 | 
 898 | 1. **Start workflow:**
 899 |    ```bash
 900 |    tm autopilot start <taskId>
 901 |    ```
 902 | 
 903 | 2. **Loop until complete:**
 904 |    ```bash
 905 |    # Get next action
 906 |    NEXT=$(tm autopilot next --json)
 907 |    ACTION=$(echo $NEXT | jq -r '.action')
 908 |    SUBTASK=$(echo $NEXT | jq -r '.subtask.id')
 909 | 
 910 |    case $ACTION in
 911 |      red)
 912 |        # 1. Generate tests based on instructions
 913 |        # 2. Write test files
 914 |        # 3. Run tests yourself (you know the test command)
 915 |        npm test  # or pytest, go test, cargo test, etc.
 916 | 
 917 |        # 4. Report results to TaskMaster
 918 |        tm autopilot complete red $SUBTASK --results="failed:3,passed:0"
 919 |        ;;
 920 | 
 921 |      green)
 922 |        # 1. Implement code to pass tests
 923 |        # 2. Write implementation files
 924 |        # 3. Run tests yourself
 925 |        npm test
 926 | 
 927 |        # 4. Report results to TaskMaster (include coverage if available)
 928 |        tm autopilot complete green $SUBTASK --results="passed:3,failed:0" --coverage="92"
 929 |        ;;
 930 | 
 931 |      commit)
 932 |        # TaskMaster handles git operations
 933 |        tm autopilot commit $SUBTASK
 934 |        ;;
 935 | 
 936 |      complete)
 937 |        echo "Workflow complete!"
 938 |        ;;
 939 |    esac
 940 |    ```
 941 | 
 942 | 3. **State is preserved** - you can stop/resume anytime with `tm autopilot resume`
 943 | 
 944 | **Important:** You are responsible for:
 945 | - Running test commands (TaskMaster doesn't know your test framework)
 946 | - Parsing test output (passed/failed counts)
 947 | - Reporting accurate results
 948 | 
 949 | **Via MCP:**
 950 | Use `autopilot_*` tools for the same workflow with better integration.
 951 | ````
 952 | 
 953 | **Example AI agent prompt:**
 954 | 
 955 | ```markdown
 956 | You are working autonomously on Task Master tasks using the autopilot workflow.
 957 | 
 958 | Instructions:
 959 | 1. Call `tm autopilot next --json` to get your next action
 960 | 2. Read the action type and context
 961 | 3. Execute the action:
 962 |    - **RED**:
 963 |      * Generate tests that fail initially
 964 |      * Run tests: `npm test` (or appropriate test command)
 965 |      * Report: `tm autopilot complete red <id> --results="failed:n,passed:n"`
 966 |    - **GREEN**:
 967 |      * Implement code to pass the tests
 968 |      * Run tests: `npm test`
 969 |      * Report: `tm autopilot complete green <id> --results="passed:n,failed:n" --coverage="nn"`
 970 |    - **COMMIT**:
 971 |      * Call: `tm autopilot commit <id>` (TaskMaster handles git)
 972 | 4. Repeat until action is "complete"
 973 | 
 974 | Always:
 975 | - Follow TDD principles (RED → GREEN → COMMIT)
 976 | - YOU run the tests (TaskMaster doesn't know test frameworks)
 977 | - Report accurate test results (passed/failed counts)
 978 | - Write minimal code to pass tests
 979 | - Check `tm autopilot status` if unsure of current state
 980 | 
 981 | You are responsible for:
 982 | - Knowing which test command to run (npm test, pytest, go test, etc.)
 983 | - Parsing test output to get pass/fail counts
 984 | - Understanding the project's testing framework
 985 | - Running tests after generating/implementing code
 986 | 
 987 | TaskMaster is responsible for:
 988 | - Validating your reported results make sense (RED should fail, GREEN should pass)
 989 | - Creating properly formatted git commits
 990 | - Managing workflow state and transitions
 991 | ```
 992 | 
 993 | ## Success Criteria
 994 | - Can execute a simple task end-to-end without manual intervention
 995 | - All commits made on feature branch, never on default branch
 996 | - Tests are generated before implementation (RED → GREEN order enforced)
 997 | - Only commits when tests pass and coverage meets threshold
 998 | - Run state is persisted and can be inspected post-run
 999 | - Clear error messages when things go wrong
1000 | - Orchestrator events allow CLI to show live progress
1001 | 
1002 | ## Configuration
1003 | 
1004 | **Add to `.taskmaster/config.json` (versioned):**
1005 | ```json
1006 | {
1007 |   "autopilot": {
1008 |     "enabled": true,
1009 |     "requireCleanWorkingTree": true,
1010 |     "commitTemplate": "{type}({scope}): {msg} (task {taskId})",
1011 |     "defaultCommitType": "feat",
1012 |     "maxGreenAttempts": 3,
1013 |     "testTimeout": 300000,
1014 |     "storage": {
1015 |       "location": "global",
1016 |       "basePath": "~/.taskmaster"
1017 |     }
1018 |   },
1019 |   "test": {
1020 |     "runner": "auto",
1021 |     "coverageThresholds": {
1022 |       "lines": 80,
1023 |       "branches": 80,
1024 |       "functions": 80,
1025 |       "statements": 80
1026 |     },
1027 |     "targetedRunPattern": "**/*.test.js"
1028 |   },
1029 |   "git": {
1030 |     "branchPattern": "{tag}/task-{id}-{slug}",
1031 |     "defaultRemote": "origin"
1032 |   }
1033 | }
1034 | ```
1035 | 
1036 | **Update `.gitignore` (keep project clean):**
1037 | ```gitignore
1038 | # TaskMaster runtime artifacts (stored globally, not needed in repo)
1039 | .taskmaster/state/
1040 | .taskmaster/reports/
1041 | 
1042 | # Keep these versioned
1043 | !.taskmaster/tasks/
1044 | !.taskmaster/config.json
1045 | !.taskmaster/docs/
1046 | !.taskmaster/templates/
1047 | ```
1048 | 
1049 | ## Out of Scope (defer to Phase 2)
1050 | - PR creation (gh integration)
1051 | - Resume functionality (`--resume` flag)
1052 | - Lint/format step
1053 | - Multiple executor support (only Claude)
1054 | 
1055 | ## Implementation Order
1056 | 
1057 | ### Phase 1A: Infrastructure (Week 1)
1058 | 1. Global storage utilities (path normalization, run ID generation)
1059 | 2. Activity log writer (append-only JSONL)
1060 | 3. State manager (load/save/update state.json)
1061 | 4. GitAdapter with safety checks
1062 | 5. TestResultValidator (validate RED/GREEN phase results)
1063 | 
1064 | ### Phase 1B: Orchestration Core (Week 1-2)
1065 | 6. WorkflowOrchestrator state machine skeleton
1066 | 7. State transitions (Preflight → BranchSetup → SubtaskLoop → Finalize)
1067 | 8. Event emitter for activity logging
1068 | 9. Enhanced commit message generator
1069 | 
1070 | ### Phase 1C: TDD Loop (Week 2)
1071 | 10. RED phase validator (ensure tests fail)
1072 | 11. GREEN phase validator (ensure tests pass)
1073 | 12. COMMIT phase implementation (staging, committing)
1074 | 13. Subtask progression logic
1075 | 
1076 | ### Phase 1D: CLI Interface (Week 2-3)
1077 | 14. `tm autopilot start` command
1078 | 15. `tm autopilot next` command
1079 | 16. `tm autopilot complete` command
1080 | 17. `tm autopilot commit` command
1081 | 18. `tm autopilot status` command
1082 | 19. `tm autopilot resume` command
1083 | 
1084 | ### Phase 1E: MCP Interface (Week 3)
1085 | 20. `autopilot_start` tool
1086 | 21. `autopilot_next` tool
1087 | 22. `autopilot_complete_phase` tool
1088 | 23. `autopilot_commit` tool
1089 | 24. `autopilot_status` tool
1090 | 25. `autopilot_resume` tool
1091 | 
1092 | ### Phase 1F: Integration (Week 3)
1093 | 26. AI agent instruction templates
1094 | 27. Error handling and recovery
1095 | 28. Integration tests
1096 | 29. Documentation
1097 | 
1098 | ## Testing Strategy
1099 | - Unit tests for global storage (path normalization, state management)
1100 | - Unit tests for activity log (JSONL append, parsing)
1101 | - Unit tests for each adapter (mock git/test commands)
1102 | - Integration tests with real git repo (temporary directory)
1103 | - End-to-end test with sample task in test project
1104 | - Verify no commits on default branch (security test)
1105 | - Verify commit gating works (force test failure, ensure no commit)
1106 | - Verify enhanced commit messages include task context
1107 | - Test resume from state checkpoint
1108 | - Verify project directory stays clean (no runtime artifacts)
1109 | 
1110 | ## Dependencies
1111 | - Phase 0 completed (CLI skeleton, preflight checks)
1112 | - Existing TaskService and executor infrastructure
1113 | - Surgical Test Generator prompt file exists
1114 | 
1115 | ## Estimated Effort
1116 | 2-3 weeks
1117 | 
1118 | ## Risks & Mitigations
1119 | - **Risk:** Test generation produces invalid/wrong tests
1120 |   - **Mitigation:** Use Surgical Test Generator prompt, add manual review step in early iterations
1121 | 
1122 | - **Risk:** Implementation attempts timeout/fail repeatedly
1123 |   - **Mitigation:** Max attempts with pause/resume; store state for manual intervention
1124 | 
1125 | - **Risk:** Coverage parsing fails on different test frameworks
1126 |   - **Mitigation:** Start with one framework (vitest), add parsers incrementally
1127 | 
1128 | - **Risk:** Git operations fail (conflicts, permissions)
1129 |   - **Mitigation:** Detailed error messages, save state before destructive ops
1130 | 
1131 | ## Validation
1132 | Test with:
1133 | - Simple task (1 subtask, clear requirements)
1134 | - Medium task (3 subtasks with dependencies)
1135 | - Task requiring multiple GREEN attempts
1136 | - Task with dirty working tree (should error)
1137 | - Task on default branch (should error)
1138 | - Project without test command (should error with helpful message)
1139 | - Verify global storage created in `~/.taskmaster/projects/<project>/`
1140 | - Verify activity log is valid JSONL and streamable
1141 | - Verify state.json allows resumption
1142 | - Verify commit messages include task metadata
1143 | - Verify project directory contains no runtime artifacts after run
1144 | - Test with multiple worktrees (independent state per worktree)
1145 | 
```
Page 54/69FirstPrevNextLast