Skip to content

feat: implement export tasks#1260

Merged
Crunchyman-ralph merged 9 commits intonextfrom
ralph/feat/extract.tasks
Oct 6, 2025
Merged

feat: implement export tasks#1260
Crunchyman-ralph merged 9 commits intonextfrom
ralph/feat/extract.tasks

Conversation

@Crunchyman-ralph
Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph commented Oct 1, 2025

What type of PR is this?

  • 🐛 Bug fix
  • ✨ Feature
  • 🔌 Integration
  • 📝 Docs
  • 🧹 Refactor
  • Other:

Description

Related Issues

How to Test This

# Example commands or steps

Expected result:

Contributor Checklist

  • Created changeset: npm run changeset
  • Tests pass: npm test
  • Format check passes: npm run format-check (or npm run format to fix)
  • Addressed CodeRabbit comments (if any)
  • Linked related issues (if any)
  • Manually tested the changes

Changelog Entry


For Maintainers

  • PR title follows conventional commits
  • Target branch correct
  • Labels added
  • Milestone assigned (if applicable)

Summary by CodeRabbit

  • New Features

    • Added CLI “export” command to send tasks to external briefs with filters, confirmation, and rich summaries.
    • Introduced a centralized CLI command registry with category-based listing/registration.
    • Core now supports task export operations and context validation.
  • Improvements

    • Faster, more accurate task loading with storage/database-level status filtering and optional subtask exclusion.
    • Clearer error feedback, including NOT_FOUND handling.
    • Enhanced CLI UX with spinners, colored output, and consistent command registration.
  • Refactor

    • Unified command registration across CLI commands; deprecated alternate registration entry points.
  • Chores

    • Explicit environment loading for build tooling.

@changeset-bot
Copy link

changeset-bot bot commented Oct 1, 2025

⚠️ No Changeset found

Latest commit: 89aa6a6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 1, 2025

Walkthrough

Introduces a centralized CLI command registry, adds a new ExportCommand, standardizes CLI command registration APIs, integrates an ExportService into tm-core, extends storage/repository interfaces to support filtered task loading, adds a NOT_FOUND error code, updates public exports, and switches scripts to use the centralized registry.

Changes

Cohort / File(s) Summary
CLI Command Registry
apps/cli/src/command-registry.ts, apps/cli/src/index.ts
Adds CommandRegistry with metadata, registration/query/display utilities; provides helpers registerAllCommands/registerCommandsByCategory; exports registry and types via CLI index.
New Export Command
apps/cli/src/commands/export.command.ts
Adds ExportCommand with auth checks, brief resolution, confirmation, and export workflow; exposes ExportCommandResult; includes static register.
CLI Command API normalization
apps/cli/src/commands/auth.command.ts, .../context.command.ts, .../list.command.ts, .../set-status.command.ts, .../show.command.ts, .../start.command.ts
Removes static registerOn; standardizes to static register(program, name?) returning the command instance.
Scripts use centralized registration
scripts/modules/commands.js
Replaces per-command registrations with registerAllCommands(programInstance) from @tm/cli; removes individual command and various utility exports/imports.
Export Service introduction
packages/tm-core/src/services/export.service.ts, packages/tm-core/src/services/index.ts, packages/tm-core/src/index.ts
Adds ExportService with exportTasks, brief-input export, and context validation; exports ExportService, ExportTasksOptions, ExportResult via services and package index.
Core integration of export
packages/tm-core/src/task-master-core.ts
Integrates ExportService; adds public methods exportTasks, exportFromBriefInput, validateExportContext; re-exports related types.
Storage/repository filtering support
packages/tm-core/src/interfaces/storage.interface.ts, .../repositories/task-repository.interface.ts, .../storage/api-storage.ts, .../storage/file-storage/file-storage.ts, .../repositories/supabase/supabase-task-repository.ts, .../services/task-service.ts
Introduces LoadTasksOptions (status, excludeSubtasks); updates interfaces and implementations to accept options; pushes filters to storage/DB where possible; adjusts TaskService.getTaskList flow and logging.
Error codes update
packages/tm-core/src/errors/task-master-error.ts
Adds NOT_FOUND to ERROR_CODES; extends ErrorCode union implicitly.
Build config env loading
tsdown.config.ts
Switches to explicit dotenv config({ path: resolve(process.cwd(), '.env') }); no public API change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant C as CLI ExportCommand
  participant T as TaskMasterCore
  participant E as ExportService
  participant A as AuthManager
  participant FS as FileStorage
  participant API as External Brief API

  U->>C: tm export [briefOrUrl] [options]
  C->>A: Ensure authenticated
  alt Not authenticated
    C-->>U: Error: login required
  else Authenticated
    C->>T: exportTasks(options)
    T->>E: exportTasks(options)
    E->>A: Resolve context / brief (if input provided)
    alt Brief not found
      E-->>C: Error: NOT_FOUND
      C-->>U: Not found message
    else Context resolved
      E->>FS: loadTasks(tag, { status, excludeSubtasks })
      FS-->>E: Tasks
      alt No matching tasks
        E-->>C: Error: no tasks
        C-->>U: No tasks message
      else Has tasks
        E->>API: POST /bulk-import (transformed tasks + token)
        alt API success/partial
          API-->>E: ExportResult
          E-->>T: Result
          T-->>C: Result
          C-->>U: Success summary
        else API failure
          API-->>E: Error
          E-->>C: EXPORT_FAILED
          C-->>U: Error summary
        end
      end
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • eyaltoledano

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat: implement export tasks” succinctly captures the primary addition of export‐tasks functionality across both the CLI and core modules, directly reflecting the main change in the pull request without extraneous details.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ralph/feat/extract.tasks

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ea4bb6 and a2cd485.

📒 Files selected for processing (10)
  • apps/cli/src/command-registry.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • packages/tm-core/src/errors/task-master-error.ts (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
  • packages/tm-core/src/task-master-core.ts (6 hunks)
  • scripts/modules/commands.js (4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)

scripts/modules/commands.js: Centralize all LLM calls through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + manual parsing as a more robust alternative for structured data needs.

scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).

scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...

Files:

  • scripts/modules/commands.js
scripts/modules/**

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

When using the MCP server, restart it if core logic in scripts/modules or MCP tool/direct function definitions change.

Files:

  • scripts/modules/commands.js
scripts/modules/*

📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)

scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag

Files:

  • scripts/modules/commands.js
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/modules/commands.js
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
📚 Learning: 2025-09-26T19:05:47.526Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.526Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/src/task-master-core.ts
  • packages/tm-core/src/index.ts
  • packages/tm-core/src/services/index.ts
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/command-registry.ts
  • apps/cli/src/index.ts
  • scripts/modules/commands.js
  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI, create them in the current tag context (defaulting to 'master'), provide clear prompts to guide AI task generation, and validate/clean up AI-generated tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use tagged task system aware functions for task finding and manipulation, handle both task and subtask operations, and validate task IDs before operations.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/task-manager/*.js : Files in scripts/modules/task-manager/ should each handle a specific action related to task management (e.g., add-task.js, expand-task.js), supporting the tagged task lists system and backward compatibility.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Provide functions for updating task status within the current tag context, handling both individual tasks and subtasks, and considering subtask status when updating parent tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be accessed and updated through the tag resolution layer using getTasksForTag(data, tagName) and setTasksForTag(data, tagName, tasks); direct manipulation of the tagged structure in core functions is not allowed.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be organized into separate contexts (tags) within tasks.json, using the tagged format: {"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}. Legacy format {"tasks": [...]} must be silently migrated to the tagged format on first use.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use tag resolution functions to maintain backward compatibility, returning legacy format to core functions and not exposing the tagged structure to existing core logic.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/task-manager.js : Features that create, read, update, or delete tasks belong in 'scripts/modules/task-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/dependency-manager.js : Features that handle task relationships belong in 'scripts/modules/dependency-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Format dependency lists consistently for visualization

Applied to files:

  • scripts/modules/commands.js
🧬 Code graph analysis (6)
packages/tm-core/src/task-master-core.ts (3)
packages/tm-core/src/services/index.ts (3)
  • ExportService (8-8)
  • ExportTasksOptions (11-11)
  • ExportResult (12-12)
packages/tm-core/src/services/export.service.ts (3)
  • ExportService (87-502)
  • ExportTasksOptions (40-51)
  • ExportResult (56-72)
packages/tm-core/src/auth/auth-manager.ts (1)
  • AuthManager (26-280)
packages/tm-core/src/services/task-service.ts (2)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
apps/cli/src/command-registry.ts (2)
apps/cli/src/index.ts (11)
  • CommandMetadata (20-20)
  • CommandRegistry (17-17)
  • ListTasksCommand (7-7)
  • ShowCommand (8-8)
  • StartCommand (11-11)
  • SetStatusCommand (12-12)
  • ExportCommand (13-13)
  • AuthCommand (9-9)
  • ContextCommand (10-10)
  • registerAllCommands (18-18)
  • registerCommandsByCategory (19-19)
apps/cli/src/commands/export.command.ts (1)
  • ExportCommand (32-381)
packages/tm-core/src/services/export.service.ts (2)
packages/tm-core/src/task-master-core.ts (2)
  • ExportTasksOptions (57-57)
  • ExportResult (58-58)
packages/tm-core/src/services/task-service.ts (1)
  • TaskService (51-498)
scripts/modules/commands.js (2)
apps/cli/src/command-registry.ts (1)
  • registerAllCommands (238-240)
apps/cli/src/index.ts (1)
  • registerAllCommands (18-18)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (56-72)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (58-58)
  • TaskMasterCore (65-353)
🪛 GitHub Actions: CI
packages/tm-core/src/services/export.service.ts

[error] 6-6: TypeScript error TS6196: 'Subtask' is declared but never used.

🔇 Additional comments (7)
packages/tm-core/src/services/task-service.ts (1)

17-17: LGTM! Logging integration improves observability.

The addition of structured logging for the TaskService enhances error tracking and debugging. The logger initialization follows the correct pattern, and the error logging in the catch block provides valuable context before rethrowing the error.

Also applies to: 55-55, 126-126

packages/tm-core/src/index.ts (1)

14-16: LGTM! Public type exports are correctly positioned.

The new export-related types are properly exposed in the public API surface, following the existing pattern for other result types like ConflictCheckResult.

packages/tm-core/src/services/index.ts (1)

8-13: LGTM! Service exports follow established patterns.

The ExportService and its associated types are correctly exported from the services barrel file, maintaining consistency with the existing export structure.

packages/tm-core/src/task-master-core.ts (3)

17-22: LGTM! Import and field declarations follow established patterns.

The ExportService integration follows the same initialization pattern used by other services in TaskMasterCore (TaskService, TaskExecutionService).

Also applies to: 69-69, 94-94


125-131: LGTM! ExportService initialization is correctly ordered.

The ExportService is initialized after its dependencies (ConfigManager and TaskService) are ready. The use of AuthManager singleton is appropriate since ExportService validates authentication state in its methods.


265-290: Export API methods are well-structured.

The new export functionality is cleanly integrated into the TaskMasterCore facade with proper delegation and documentation. The method naming and structure align with the existing API patterns.

apps/cli/src/index.ts (1)

13-21: LGTM! CLI exports align with centralized command architecture.

The addition of ExportCommand and CommandRegistry exports properly exposes the new export functionality and centralized command registration pattern. This aligns with the coding guidelines to keep CLI setup clean and maintainable.

Based on learnings.

Comment on lines 148 to 159
let filteredTasks = rawTasks;
if (options.status) {
filteredTasks = rawTasks.filter((task) => task.status === options.status);
}

const taskListResult = {
tasks: filteredTasks,
total: rawTasks.length,
filtered: filteredTasks.length,
tag,
storageType: 'file' as const
};
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Honor includeSubtasks flag when preparing export payload.

The CLI passes includeSubtasks (via --with-subtasks), but we never branch on it—subtasks are always sent. That makes the option ineffective and forces users to export subtasks even when they explicitly disable them. Please strip subtasks when the flag is false.

Proposed diff:

 		let filteredTasks = rawTasks;
 		if (options.status) {
 			filteredTasks = rawTasks.filter((task) => task.status === options.status);
 		}
+
+		if (options.includeSubtasks === false) {
+			filteredTasks = filteredTasks.map((task) => ({
+				...task,
+				subtasks: []
+			}));
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let filteredTasks = rawTasks;
if (options.status) {
filteredTasks = rawTasks.filter((task) => task.status === options.status);
}
const taskListResult = {
tasks: filteredTasks,
total: rawTasks.length,
filtered: filteredTasks.length,
tag,
storageType: 'file' as const
};
let filteredTasks = rawTasks;
if (options.status) {
filteredTasks = rawTasks.filter((task) => task.status === options.status);
}
if (options.includeSubtasks === false) {
filteredTasks = filteredTasks.map((task) => ({
...task,
subtasks: []
}));
}
const taskListResult = {
tasks: filteredTasks,
total: rawTasks.length,
filtered: filteredTasks.length,
tag,
storageType: 'file' as const
};
🤖 Prompt for AI Agents
packages/tm-core/src/services/export.service.ts around lines 148 to 159: the
export payload ignores options.includeSubtasks so subtasks are always included;
when options.includeSubtasks is false, filter out subtasks (e.g., remove tasks
where task.parentId is truthy) before building taskListResult and update the
filtered count to reflect that filteredTasks.length (leave total as
rawTasks.length if you want total to remain the full set); implement the branch
so that when includeSubtasks is true behavior is unchanged, when false subtasks
are stripped from taskListResult.tasks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai we're doing an export, so we probably want the subtasks, maybe the user can have a flag to say he doesn't want the subtasks, in that case I might agree with you, but I think the default is that we want the subtasks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Crunchyman-ralph, the flag already exists! The ExportTasksOptions interface includes includeSubtasks?: boolean (line 49), and the CLI command implements --with-subtasks. Your point about defaulting to include subtasks is reasonable—since it's optional, undefined can mean "include them by default."

However, when a user explicitly passes --with-subtasks=false or sets includeSubtasks: false, that choice should be honored. Right now the code ignores it entirely, so subtasks are always exported regardless of what the user requests.

The fix remains the same: when options.includeSubtasks === false, filter out the subtasks before export. When undefined or true, keep the current behavior (include them).

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/extract.tasks branch from a2cd485 to f741960 Compare October 2, 2025 14:21
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/tm-core/src/services/export.service.ts (1)

140-179: Honor includeSubtasks flag

includeSubtasks is never applied—filteredTasks always includes subtasks, so even when the CLI leaves --with-subtasks off (Commander passes false), the export still pushes every subtask. That makes the flag misleading and breaks the “tasks only” use case.

Strip subtasks when options.includeSubtasks === false before calling performExport, e.g.:

 		let filteredTasks = rawTasks;
 		if (options.status) {
 			filteredTasks = rawTasks.filter((task) => task.status === options.status);
 		}
+
+		if (options.includeSubtasks === false) {
+			filteredTasks = filteredTasks.map((task) => ({
+				...task,
+				subtasks: []
+			}));
+		}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2cd485 and 3fcd645.

📒 Files selected for processing (10)
  • apps/cli/src/command-registry.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • packages/tm-core/src/errors/task-master-error.ts (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
  • packages/tm-core/src/task-master-core.ts (6 hunks)
  • scripts/modules/commands.js (4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)

scripts/modules/commands.js: Centralize all LLM calls through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + manual parsing as a more robust alternative for structured data needs.

scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).

scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...

Files:

  • scripts/modules/commands.js
scripts/modules/**

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

When using the MCP server, restart it if core logic in scripts/modules or MCP tool/direct function definitions change.

Files:

  • scripts/modules/commands.js
scripts/modules/*

📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)

scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag

Files:

  • scripts/modules/commands.js
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/modules/commands.js
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.555Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/src/index.ts
  • packages/tm-core/src/services/index.ts
  • packages/tm-core/src/task-master-core.ts
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/index.ts
  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/command-registry.ts
  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI, create them in the current tag context (defaulting to 'master'), provide clear prompts to guide AI task generation, and validate/clean up AI-generated tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use tagged task system aware functions for task finding and manipulation, handle both task and subtask operations, and validate task IDs before operations.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/task-manager/*.js : Files in scripts/modules/task-manager/ should each handle a specific action related to task management (e.g., add-task.js, expand-task.js), supporting the tagged task lists system and backward compatibility.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Provide functions for updating task status within the current tag context, handling both individual tasks and subtasks, and considering subtask status when updating parent tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be accessed and updated through the tag resolution layer using getTasksForTag(data, tagName) and setTasksForTag(data, tagName, tasks); direct manipulation of the tagged structure in core functions is not allowed.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be organized into separate contexts (tags) within tasks.json, using the tagged format: {"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}. Legacy format {"tasks": [...]} must be silently migrated to the tagged format on first use.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use tag resolution functions to maintain backward compatibility, returning legacy format to core functions and not exposing the tagged structure to existing core logic.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/task-manager.js : Features that create, read, update, or delete tasks belong in 'scripts/modules/task-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/dependency-manager.js : Features that handle task relationships belong in 'scripts/modules/dependency-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Format dependency lists consistently for visualization

Applied to files:

  • scripts/modules/commands.js
🧬 Code graph analysis (6)
packages/tm-core/src/services/task-service.ts (2)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (55-71)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (59-59)
  • TaskMasterCore (66-350)
apps/cli/src/command-registry.ts (1)
apps/cli/src/commands/export.command.ts (1)
  • ExportCommand (32-388)
scripts/modules/commands.js (2)
apps/cli/src/command-registry.ts (1)
  • registerAllCommands (238-240)
apps/cli/src/index.ts (1)
  • registerAllCommands (18-18)
packages/tm-core/src/task-master-core.ts (4)
packages/tm-core/src/services/export.service.ts (3)
  • ExportService (86-495)
  • ExportTasksOptions (39-50)
  • ExportResult (55-71)
packages/tm-core/src/services/index.ts (3)
  • ExportService (8-8)
  • ExportTasksOptions (11-11)
  • ExportResult (12-12)
packages/tm-core/src/auth/auth-manager.ts (1)
  • AuthManager (26-280)
packages/tm-core/src/auth/types.ts (1)
  • UserContext (16-22)
packages/tm-core/src/services/export.service.ts (2)
packages/tm-core/src/task-master-core.ts (2)
  • ExportTasksOptions (58-58)
  • ExportResult (59-59)
apps/cli/src/index.ts (2)
  • TaskStatus (37-37)
  • Task (36-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (13)
packages/tm-core/src/task-master-core.ts (8)

17-24: LGTM! Clean import organization.

The new imports for ExportService, AuthManager, and UserContext are well-organized and follow the existing import pattern in the file.


57-60: LGTM! Proper type re-exports.

Re-exporting ExportTasksOptions and ExportResult from the ExportService maintains a clean public API surface for consumers of TaskMasterCore.


70-70: LGTM! Consistent field declaration.

The exportService private field follows the same pattern as other service fields in the class.


95-95: LGTM! Consistent initialization pattern.

Setting exportService to null as any in the constructor is consistent with how other services are initialized (see lines 92-94), ensuring the field is set before the async initialize() completes.


126-128: LGTM! Proper service initialization.

The ExportService is correctly initialized with required dependencies (ConfigManager and AuthManager singleton). The initialization follows the established pattern in this method.


262-269: LGTM! Clean delegation to ExportService.

The exportTasks method properly delegates to the ExportService with clear JSDoc documentation and correct type signatures.


271-276: LGTM! Straightforward brief input handling.

The exportFromBriefInput method provides a convenient wrapper for exporting from a brief ID or URL, delegating appropriately to the ExportService.


281-287: Past review comment addressed: Type precision improved.

The return type now correctly specifies context: UserContext | null instead of any, which improves type safety for callers. This addresses the concern raised in the previous review.

apps/cli/src/command-registry.ts (5)

167-174: LGTM! Proper duplicate prevention.

The addCommand method correctly checks for duplicates before adding to the registry, preventing registration conflicts.


115-122: LGTM! Appropriate error handling.

The registerByName method throws a clear error when attempting to register a non-existent command, which is the correct behavior for this API.


238-240: LGTM! Clean helper functions.

The convenience functions registerAllCommands and registerCommandsByCategory provide a clean public API for common registration patterns, aligning with the retrieved learnings about keeping CLI setup code clean and maintainable.

Based on learnings.


129-145: Registration strategy compatibility confirmed. All command classes define both static registerOn and static register methods.


20-25: Improve type precision for commandClass.

The commandClass: typeof Command type is incorrect because it only accepts the base Commander Command class, not subclasses like ExportCommand or ListTasksCommand. This forces the code to use as any casts throughout (lines 39, 45, 51, 57, 63, 71, 77).

Apply this diff to fix the type definition:

 export interface CommandMetadata {
 	name: string;
 	description: string;
-	commandClass: typeof Command;
+	commandClass: new (name?: string) => Command;
 	category?: 'task' | 'auth' | 'utility' | 'development';
 }

This change:

  • Defines commandClass as a constructor signature that returns a Command instance
  • Accepts any class that extends Command (like your custom command classes)
  • Eliminates the need for as any casts in the commands array
  • Maintains type safety throughout the registry

After this change, you can remove all the as any casts in the static commands array (lines 39, 45, 51, 57, 63, 71, 77).

Likely an incorrect or invalid review comment.

Comment on lines +208 to +231
static getFormattedCommandList(): string {
const categories = {
task: 'Task Management',
auth: 'Authentication & Context',
utility: 'Utilities',
development: 'Development'
};

let output = '';

for (const [category, title] of Object.entries(categories)) {
const cmds = this.getCommandsByCategory(
category as keyof typeof categories
);
if (cmds.length > 0) {
output += `\n${title}:\n`;
for (const cmd of cmds) {
output += ` ${cmd.name.padEnd(20)} ${cmd.description}\n`;
}
}
}

return output;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider edge case for empty categories.

The getFormattedCommandList method iterates through all categories but only displays non-empty ones (line 222 check). This is correct behavior, but consider what happens if all categories are empty.

If you want to handle the empty-registry case explicitly, consider:

 static getFormattedCommandList(): string {
+	if (this.commands.length === 0) {
+		return '\nNo commands registered.\n';
+	}
+
 	const categories = {
 		task: 'Task Management',
 		auth: 'Authentication & Context',
 		utility: 'Utilities',
 		development: 'Development'
 	};
 
 	let output = '';
 
 	for (const [category, title] of Object.entries(categories)) {
 		const cmds = this.getCommandsByCategory(
 			category as keyof typeof categories
 		);
 		if (cmds.length > 0) {
 			output += `\n${title}:\n`;
 			for (const cmd of cmds) {
 				output += `  ${cmd.name.padEnd(20)} ${cmd.description}\n`;
 			}
 		}
 	}
 
 	return output;
 }

This adds a friendlier message if the registry is somehow empty, though this is unlikely in production usage.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static getFormattedCommandList(): string {
const categories = {
task: 'Task Management',
auth: 'Authentication & Context',
utility: 'Utilities',
development: 'Development'
};
let output = '';
for (const [category, title] of Object.entries(categories)) {
const cmds = this.getCommandsByCategory(
category as keyof typeof categories
);
if (cmds.length > 0) {
output += `\n${title}:\n`;
for (const cmd of cmds) {
output += ` ${cmd.name.padEnd(20)} ${cmd.description}\n`;
}
}
}
return output;
}
static getFormattedCommandList(): string {
if (this.commands.length === 0) {
return '\nNo commands registered.\n';
}
const categories = {
task: 'Task Management',
auth: 'Authentication & Context',
utility: 'Utilities',
development: 'Development'
};
let output = '';
for (const [category, title] of Object.entries(categories)) {
const cmds = this.getCommandsByCategory(
category as keyof typeof categories
);
if (cmds.length > 0) {
output += `\n${title}:\n`;
for (const cmd of cmds) {
output += ` ${cmd.name.padEnd(20)} ${cmd.description}\n`;
}
}
}
return output;
}
🤖 Prompt for AI Agents
In apps/cli/src/command-registry.ts around lines 208 to 231, the formatted
command list currently skips empty categories and will return an empty string if
no commands exist; add an explicit empty-registry fallback so the method returns
a friendly message (e.g., "No commands available.") when no categories contain
commands. Implement this by checking after the loop whether output is still
empty and, if so, set output to the fallback message before returning.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/extract.tasks branch from 3fcd645 to e041340 Compare October 3, 2025 08:47
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fcd645 and e041340.

📒 Files selected for processing (16)
  • apps/cli/src/command-registry.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • packages/tm-core/src/errors/task-master-error.ts (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/interfaces/storage.interface.ts (3 hunks)
  • packages/tm-core/src/repositories/supabase-task-repository.ts (4 hunks)
  • packages/tm-core/src/repositories/task-repository.interface.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
  • packages/tm-core/src/storage/api-storage.ts (3 hunks)
  • packages/tm-core/src/storage/file-storage/file-storage.ts (2 hunks)
  • packages/tm-core/src/task-master-core.ts (6 hunks)
  • scripts/modules/commands.js (4 hunks)
  • tsdown.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)

scripts/modules/commands.js: Centralize all LLM calls through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + manual parsing as a more robust alternative for structured data needs.

scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).

scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...

Files:

  • scripts/modules/commands.js
scripts/modules/**

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

When using the MCP server, restart it if core logic in scripts/modules or MCP tool/direct function definitions change.

Files:

  • scripts/modules/commands.js
scripts/modules/*

📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)

scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag

Files:

  • scripts/modules/commands.js
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/modules/commands.js
🧠 Learnings (17)
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.555Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/src/task-master-core.ts
  • packages/tm-core/src/index.ts
  • packages/tm-core/src/services/index.ts
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/index.ts
  • apps/cli/src/command-registry.ts
  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Allow filtering tasks by status within the current tag context, handle subtask display in lists, and use consistent table formats.

Applied to files:

  • packages/tm-core/src/services/task-service.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI, create them in the current tag context (defaulting to 'master'), provide clear prompts to guide AI task generation, and validate/clean up AI-generated tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use tagged task system aware functions for task finding and manipulation, handle both task and subtask operations, and validate task IDs before operations.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/task-manager/*.js : Files in scripts/modules/task-manager/ should each handle a specific action related to task management (e.g., add-task.js, expand-task.js), supporting the tagged task lists system and backward compatibility.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Provide functions for updating task status within the current tag context, handling both individual tasks and subtasks, and considering subtask status when updating parent tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be accessed and updated through the tag resolution layer using getTasksForTag(data, tagName) and setTasksForTag(data, tagName, tasks); direct manipulation of the tagged structure in core functions is not allowed.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be organized into separate contexts (tags) within tasks.json, using the tagged format: {"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}. Legacy format {"tasks": [...]} must be silently migrated to the tagged format on first use.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use tag resolution functions to maintain backward compatibility, returning legacy format to core functions and not exposing the tagged structure to existing core logic.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/task-manager.js : Features that create, read, update, or delete tasks belong in 'scripts/modules/task-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/dependency-manager.js : Features that handle task relationships belong in 'scripts/modules/dependency-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Format dependency lists consistently for visualization

Applied to files:

  • scripts/modules/commands.js
🧬 Code graph analysis (11)
packages/tm-core/src/task-master-core.ts (3)
packages/tm-core/src/services/export.service.ts (3)
  • ExportService (86-496)
  • ExportTasksOptions (39-50)
  • ExportResult (55-71)
packages/tm-core/src/auth/auth-manager.ts (1)
  • AuthManager (26-280)
packages/tm-core/src/auth/types.ts (1)
  • UserContext (16-22)
packages/tm-core/src/services/export.service.ts (1)
packages/tm-core/src/storage/file-storage/file-storage.ts (1)
  • FileStorage (19-618)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (55-71)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (59-59)
  • TaskMasterCore (66-350)
packages/tm-core/src/repositories/task-repository.interface.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-76)
packages/tm-core/src/storage/file-storage/file-storage.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-76)
packages/tm-core/src/storage/api-storage.ts (1)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/repositories/supabase-task-repository.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-76)
packages/tm-core/src/services/task-service.ts (3)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/entities/task.entity.ts (1)
  • TaskEntity (17-266)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
apps/cli/src/command-registry.ts (2)
apps/cli/src/index.ts (7)
  • CommandMetadata (20-20)
  • CommandRegistry (17-17)
  • ListTasksCommand (7-7)
  • ShowCommand (8-8)
  • ExportCommand (13-13)
  • registerAllCommands (18-18)
  • registerCommandsByCategory (19-19)
apps/cli/src/commands/export.command.ts (1)
  • ExportCommand (32-388)
packages/tm-core/src/interfaces/storage.interface.ts (1)
packages/tm-core/src/types/index.ts (2)
  • TaskStatus (20-28)
  • Task (57-76)
scripts/modules/commands.js (2)
apps/cli/src/command-registry.ts (1)
  • registerAllCommands (238-240)
apps/cli/src/index.ts (1)
  • registerAllCommands (18-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (19)
tsdown.config.ts (1)

3-7: LGTM! Explicit dotenv initialization improves clarity and robustness.

The explicit config() call with an absolute path ensures environment variables are loaded reliably before the build-time injection logic runs. This approach is more robust than relying on the shorthand import 'dotenv/config' and follows dotenv best practices of loading as early as possible in the startup sequence.

packages/tm-core/src/services/index.ts (1)

10-13: Types export verification succeeded The interfaces ExportTasksOptions (line 39) and ExportResult (line 55) are declared and exported in export.service.ts, matching the re-exports in index.ts.

apps/cli/src/commands/export.command.ts (6)

69-84: LGTM!

The lazy initialization pattern is implemented correctly, with proper error handling and clear error messages.


109-124: Verify the precedence of brief ID resolution.

Lines 109-110 resolve orgId and briefId from options first, then context as fallback. However, lines 113-124 override briefId and orgId when briefOrUrl is provided and options.brief is not set.

Confirm that this precedence is intentional:

  1. options.brief (highest priority)
  2. briefOrUrl argument (overrides context)
  3. context.briefId (lowest priority, fallback)

If the positional argument should have lower priority than options.brief, the current logic is correct. Otherwise, consider adjusting the precedence.


208-297: LGTM!

The brief resolution logic is comprehensive and handles various URL formats, path structures, and ID patterns. The separation of concerns (parsing, extraction, validation) is clean and maintainable.


302-335: LGTM!

The confirmation flow provides clear context to the user before proceeding with the export. The conditional display of names (when available) vs. IDs improves user experience.


340-355: LGTM!

Error handling appropriately distinguishes between authentication errors and generic errors, providing helpful guidance for common issues. Debug stack traces respect the DEBUG environment variable.


360-387: LGTM!

The public API methods follow established patterns for Commander.js command registration. The getLastResult method supports testing, and the cleanup method is appropriately documented as a no-op.

scripts/modules/commands.js (2)

17-23: LGTM!

The import of registerAllCommands from @tm/cli correctly integrates the centralized command registry. The comment clarifies the purpose of the imported utilities.


1670-1675: LGTM!

The centralized command registration via registerAllCommands aligns with coding guidelines to keep CLI setup clean and maintainable. This reduces duplication and centralizes command management.

Based on learnings.

apps/cli/src/command-registry.ts (5)

20-25: LGTM!

The CommandMetadata interface is well-defined with appropriate types. The optional category field provides flexibility while the union type ensures valid values.


30-80: LGTM!

The static commands array is properly initialized with all command metadata. The as any type assertion on commandClass is necessary to work around Commander.js type constraints.


86-145: LGTM!

The registration methods implement a flexible multi-strategy pattern that accommodates different command implementation styles. The error handling in registerByName provides clear feedback when a command is not found.


150-231: LGTM!

The query and management methods are well-implemented with appropriate error handling. The addCommand method prevents duplicate registrations, and removeCommand provides clear feedback via its boolean return value.

Note: A past review comment suggested handling the edge case where all categories are empty in getFormattedCommandList. Consider implementing that suggestion if you want a friendlier message when no commands are registered (though this is unlikely in production).


238-252: LGTM!

The convenience functions provide a clean API for common registration operations while delegating to the centralized registry.

apps/cli/src/index.ts (1)

13-21: LGTM!

The new exports correctly extend the public API surface to include the ExportCommand and the centralized command registry utilities. The type CommandMetadata export provides public access to the interface for type-safe integrations.

packages/tm-core/src/interfaces/storage.interface.ts (3)

8-16: LGTM!

The LoadTasksOptions interface is well-designed with clear documentation. The optional fields provide flexible filtering capabilities while maintaining backward compatibility.


34-39: LGTM!

The updated method signature maintains backward compatibility by making the new options parameter optional. The JSDoc correctly describes the enhanced filtering capabilities.


219-219: Approve changes: storage implementations updated
All concrete storage classes (api-storage.ts, file-storage.ts) now implement loadTasks(tag?: string, options?: LoadTasksOptions): Promise<Task[]>, matching the abstract signature.

Comment on lines +54 to +55
UNKNOWN_ERROR: 'UNKNOWN_ERROR',
NOT_FOUND: 'NOT_FOUND'
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Prefer specific error codes over generic NOT_FOUND.

The codebase already defines domain-specific "not found" error codes (TASK_NOT_FOUND, FILE_NOT_FOUND, PROVIDER_NOT_FOUND). Adding a generic NOT_FOUND creates ambiguity about which resource was not found and reduces error handling precision.

Consider using an existing specific error code or creating a new domain-specific one (e.g., EXPORT_NOT_FOUND, EXPORT_TASK_NOT_FOUND) that clearly indicates the resource type for the export feature.

Apply this diff to remove the generic NOT_FOUND and use domain-specific codes:

 	UNKNOWN_ERROR: 'UNKNOWN_ERROR',
-	NOT_FOUND: 'NOT_FOUND'

Then define a specific error code in the appropriate section, for example:

 	// Task management errors
 	TASK_NOT_FOUND: 'TASK_NOT_FOUND',
 	TASK_DEPENDENCY_ERROR: 'TASK_DEPENDENCY_ERROR',
 	TASK_STATUS_ERROR: 'TASK_STATUS_ERROR',
+	EXPORT_NOT_FOUND: 'EXPORT_NOT_FOUND',
🤖 Prompt for AI Agents
In packages/tm-core/src/errors/task-master-error.ts around lines 54-55, remove
the generic NOT_FOUND entry and replace it with a domain-specific code (e.g.,
EXPORT_NOT_FOUND or EXPORT_TASK_NOT_FOUND) in the same error codes block; then
search the codebase for places that currently use the generic NOT_FOUND for
export-related logic and update those references to the new specific code,
ensuring imports/types align with the updated enum/const name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai there is never a case where "export is not found" its a service that is always available, the error might be something else, but not export not found

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for NOT_FOUND usage in export service and related files
rg -nP --type=ts -C5 'NOT_FOUND' packages/tm-core/src/services/export.service.ts

# Also check for any other usage of NOT_FOUND in the codebase
rg -nP --type=ts -C3 'ERROR_CODES\.NOT_FOUND|NOT_FOUND'

Length of output: 4148


@Crunchyman-ralph, you're absolutely right—the export service is always available. I see now that NOT_FOUND is used when a brief cannot be found or accessed (line 216 in export.service.ts), not the export service itself.

To maintain consistency with existing error codes like TASK_NOT_FOUND, FILE_NOT_FOUND, and PROVIDER_NOT_FOUND, I'd suggest using BRIEF_NOT_FOUND instead of the generic NOT_FOUND. This makes it clearer what resource type was not found:

 	// Task management errors
 	TASK_NOT_FOUND: 'TASK_NOT_FOUND',
 	TASK_DEPENDENCY_ERROR: 'TASK_DEPENDENCY_ERROR',
 	TASK_STATUS_ERROR: 'TASK_STATUS_ERROR',
+	BRIEF_NOT_FOUND: 'BRIEF_NOT_FOUND',

Then update the usage in export.service.ts:

 		if (!brief) {
 			throw new TaskMasterError(
 				'Brief not found or you do not have access',
-				ERROR_CODES.NOT_FOUND
+				ERROR_CODES.BRIEF_NOT_FOUND
 			);
 		}

This follows the established pattern and makes error handling more precise. Would you like to make this change, or do you prefer keeping the generic NOT_FOUND?


🧬 Code Graph Analysis Results

[snippets]

File: packages/tm-core/src/errors/index.ts (relevant to the user comment)

  • Line 8
TaskMasterError
  • Line 9
ERROR_CODES
  • Line 10
type ErrorCode
  • Line 11
type ErrorContext
  • Line 12
type SerializableError

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/extract.tasks branch from e041340 to a508b01 Compare October 3, 2025 16:51
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (4)
packages/tm-core/src/errors/task-master-error.ts (1)

54-55: Replace generic NOT_FOUND with domain-specific error code.

The codebase already defines domain-specific "not found" error codes (TASK_NOT_FOUND, FILE_NOT_FOUND, PROVIDER_NOT_FOUND). Adding a generic NOT_FOUND creates ambiguity about which resource was not found and reduces error handling precision. When this code is used in export.service.ts (line 216) for brief lookup failures, it's unclear what resource is missing.

Define a specific error code for export/brief contexts:

 	// Task management errors
 	TASK_NOT_FOUND: 'TASK_NOT_FOUND',
 	TASK_DEPENDENCY_ERROR: 'TASK_DEPENDENCY_ERROR',
 	TASK_STATUS_ERROR: 'TASK_STATUS_ERROR',
+	BRIEF_NOT_FOUND: 'BRIEF_NOT_FOUND',

 	// Storage errors

Then update export.service.ts line 216:

-		throw new TaskMasterError(
-			'Brief not found or you do not have access',
-			ERROR_CODES.NOT_FOUND
-		);
+		throw new TaskMasterError(
+			'Brief not found or you do not have access',
+			ERROR_CODES.BRIEF_NOT_FOUND
+		);

And remove the generic NOT_FOUND:

 	UNKNOWN_ERROR: 'UNKNOWN_ERROR',
-	NOT_FOUND: 'NOT_FOUND'
apps/cli/src/command-registry.ts (1)

208-231: Consider handling empty registry edge case.

If all categories are empty (or registry is empty), getFormattedCommandList returns an empty string. While unlikely in production (commands are registered at lines 34-80), adding an explicit fallback improves robustness.

 static getFormattedCommandList(): string {
+	if (this.commands.length === 0) {
+		return '\nNo commands registered.\n';
+	}
+
 	const categories = {
 		task: 'Task Management',
 		auth: 'Authentication & Context',
 		utility: 'Utilities',
 		development: 'Development'
 	};

 	let output = '';

 	for (const [category, title] of Object.entries(categories)) {
 		const cmds = this.getCommandsByCategory(
 			category as keyof typeof categories
 		);
 		if (cmds.length > 0) {
 			output += `\n${title}:\n`;
 			for (const cmd of cmds) {
 				output += `  ${cmd.name.padEnd(20)} ${cmd.description}\n`;
 			}
 		}
 	}

+	if (!output) {
+		return '\nNo commands available.\n';
+	}
+
 	return output;
 }
apps/cli/src/commands/export.command.ts (1)

54-54: Fix inverted excludeSubtasks logic.

The option is named --exclude-subtasks, but line 163 passes excludeSubtasks: !options?.excludeSubtasks to the export service. This double negation inverts the behavior:

  • When --exclude-subtasks is provided, options.excludeSubtasks is true, but !true becomes false, so subtasks are included (wrong).
  • When --exclude-subtasks is omitted, options.excludeSubtasks is undefined, and !undefined is true, so subtasks are excluded by default (wrong).

Remove the negation on line 163:

 const exportResult = await this.taskMasterCore!.exportTasks({
 	orgId,
 	briefId,
 	tag: options?.tag,
 	status: options?.status,
-	excludeSubtasks: !options?.excludeSubtasks
+	excludeSubtasks: Boolean(options?.excludeSubtasks)
 });
packages/tm-core/src/services/task-service.ts (1)

95-123: The previous review concern about unsupported status filters remains unaddressed.

The storage-level filtering still pushes any single status directly to storage without checking if the underlying storage supports it. Supabase only accepts 'pending' | 'in-progress' | 'done', so statuses like 'blocked', 'review', or 'deferred' will throw "Invalid task status" errors instead of being filtered in-memory as they were before.

The suggested fix from the previous review should be applied to check storage type and validate supported statuses before pushing to storage.

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e041340 and a508b01.

📒 Files selected for processing (16)
  • apps/cli/src/command-registry.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • packages/tm-core/src/errors/task-master-error.ts (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/interfaces/storage.interface.ts (3 hunks)
  • packages/tm-core/src/repositories/supabase-task-repository.ts (4 hunks)
  • packages/tm-core/src/repositories/task-repository.interface.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
  • packages/tm-core/src/storage/api-storage.ts (3 hunks)
  • packages/tm-core/src/storage/file-storage/file-storage.ts (2 hunks)
  • packages/tm-core/src/task-master-core.ts (6 hunks)
  • scripts/modules/commands.js (4 hunks)
  • tsdown.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)

scripts/modules/commands.js: Centralize all LLM calls through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + manual parsing as a more robust alternative for structured data needs.

scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).

scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...

Files:

  • scripts/modules/commands.js
scripts/modules/**

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

When using the MCP server, restart it if core logic in scripts/modules or MCP tool/direct function definitions change.

Files:

  • scripts/modules/commands.js
scripts/modules/*

📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)

scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag

Files:

  • scripts/modules/commands.js
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/modules/commands.js
🧠 Learnings (17)
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/index.ts
  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/command-registry.ts
  • scripts/modules/commands.js
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.555Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/src/index.ts
  • packages/tm-core/src/services/index.ts
  • packages/tm-core/src/task-master-core.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Allow filtering tasks by status within the current tag context, handle subtask display in lists, and use consistent table formats.

Applied to files:

  • packages/tm-core/src/services/task-service.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI, create them in the current tag context (defaulting to 'master'), provide clear prompts to guide AI task generation, and validate/clean up AI-generated tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use tagged task system aware functions for task finding and manipulation, handle both task and subtask operations, and validate task IDs before operations.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/task-manager/*.js : Files in scripts/modules/task-manager/ should each handle a specific action related to task management (e.g., add-task.js, expand-task.js), supporting the tagged task lists system and backward compatibility.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Provide functions for updating task status within the current tag context, handling both individual tasks and subtasks, and considering subtask status when updating parent tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be accessed and updated through the tag resolution layer using getTasksForTag(data, tagName) and setTasksForTag(data, tagName, tasks); direct manipulation of the tagged structure in core functions is not allowed.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be organized into separate contexts (tags) within tasks.json, using the tagged format: {"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}. Legacy format {"tasks": [...]} must be silently migrated to the tagged format on first use.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use tag resolution functions to maintain backward compatibility, returning legacy format to core functions and not exposing the tagged structure to existing core logic.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/task-manager.js : Features that create, read, update, or delete tasks belong in 'scripts/modules/task-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/dependency-manager.js : Features that handle task relationships belong in 'scripts/modules/dependency-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Format dependency lists consistently for visualization

Applied to files:

  • scripts/modules/commands.js
🧬 Code graph analysis (11)
packages/tm-core/src/repositories/supabase-task-repository.ts (1)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/storage/file-storage/file-storage.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-82)
packages/tm-core/src/interfaces/storage.interface.ts (1)
packages/tm-core/src/types/index.ts (2)
  • TaskStatus (20-28)
  • Task (57-82)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (55-71)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (59-59)
  • TaskMasterCore (66-350)
packages/tm-core/src/services/task-service.ts (3)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/entities/task.entity.ts (1)
  • TaskEntity (17-275)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
apps/cli/src/command-registry.ts (1)
apps/cli/src/commands/export.command.ts (1)
  • ExportCommand (32-388)
packages/tm-core/src/repositories/task-repository.interface.ts (1)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
scripts/modules/commands.js (2)
apps/cli/src/command-registry.ts (1)
  • registerAllCommands (238-240)
apps/cli/src/index.ts (1)
  • registerAllCommands (18-18)
packages/tm-core/src/services/export.service.ts (1)
packages/tm-core/src/storage/file-storage/file-storage.ts (1)
  • FileStorage (20-662)
packages/tm-core/src/storage/api-storage.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-82)
packages/tm-core/src/task-master-core.ts (4)
packages/tm-core/src/services/export.service.ts (3)
  • ExportService (86-496)
  • ExportTasksOptions (39-50)
  • ExportResult (55-71)
packages/tm-core/src/services/index.ts (3)
  • ExportService (8-8)
  • ExportTasksOptions (11-11)
  • ExportResult (12-12)
packages/tm-core/src/auth/auth-manager.ts (1)
  • AuthManager (26-280)
packages/tm-core/src/auth/types.ts (1)
  • UserContext (16-22)
🪛 GitHub Actions: CI
packages/tm-core/src/services/task-service.ts

[error] 101-101: TS2339: Property 'complexity' does not exist on type 'TaskFilter'.

🔇 Additional comments (9)
tsdown.config.ts (1)

3-7: Approve explicit dotenv loading. CI and CI/CD scripts invoke tsdown from the project root, so process.cwd() reliably resolves to the project root when loading .env.

packages/tm-core/src/services/task-service.ts (3)

17-17: LGTM: Logger integration follows best practices.

The logger import and instantiation are correctly implemented and will support the error logging added later in the service.

Also applies to: 55-55


136-147: LGTM: In-memory filtering fallback logic is sound.

The conditional application of in-memory filters correctly handles cases where storage-level filtering cannot be used, maintaining backward compatibility.


160-161: LGTM: Error logging implementation is correct.

The logger call before throwing the error ensures visibility while the TaskMasterError provides structured error information with relevant context.

packages/tm-core/src/task-master-core.ts (4)

17-24: LGTM: Export-related imports are properly organized.

All necessary imports for the ExportService integration are present and correctly structured, including the service implementation, types, and required dependencies.


57-60: LGTM: Service member declaration follows established patterns.

The ExportService member declaration and type re-exports follow the same patterns used for other services in TaskMasterCore, maintaining consistency.

Also applies to: 70-70, 95-95


126-128: LGTM: ExportService initialization is correctly implemented.

The service initialization properly instantiates ExportService with required dependencies and follows the established initialization pattern.


262-287: LGTM: Export API methods correctly implemented.

The three public export methods properly delegate to the ExportService and provide a clean API surface. The previous review comment about type precision for the context field in validateExportContext has been addressed - it now correctly uses UserContext | null instead of any.

scripts/modules/commands.js (1)

17-23: Approve consolidated @tm/cli imports
Verified that registerAllCommands, checkForUpdate, performAutoUpdate, and displayUpgradeNotification are exported from @tm/cli; imports are correct.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a508b01 and 683b849.

📒 Files selected for processing (2)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Allow filtering tasks by status within the current tag context, handle subtask display in lists, and use consistent table formats.

Applied to files:

  • packages/tm-core/src/services/task-service.ts
🧬 Code graph analysis (2)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (55-71)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (59-59)
  • TaskMasterCore (66-350)
packages/tm-core/src/services/task-service.ts (2)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (7)
apps/cli/src/commands/export.command.ts (7)

1-26: LGTM!

The imports are correctly structured for ESM-first packages (commander, chalk, inquirer, ora) and the ExportCommandResult interface is well-defined with clear semantics.


32-64: LGTM!

The command configuration is well-structured with clear options and positional arguments. The option naming and action handler setup follow Commander.js best practices.


69-84: LGTM!

The service initialization logic correctly implements a lazy initialization pattern with proper error handling and clear error messages.


89-203: LGTM!

The main execution flow is well-structured with proper authentication checks, context validation, user confirmation, and comprehensive error handling. The export result display provides clear feedback to the user.

Note: The excludeSubtasks logic on line 163 is correct (options?.excludeSubtasks || false), which properly defaults to false (include subtasks) when the flag is not provided.


208-297: LGTM!

The brief resolution logic is robust and handles multiple input formats (URLs, paths, raw IDs). The extractBriefId method uses a permissive approach that supports various ID formats, with invalid inputs being caught by the downstream API call in resolveBriefInput. The ID pattern matching in isLikelyId correctly covers UUID, ULID, and slug formats.


302-335: LGTM!

The confirmation flow provides clear context to the user with organization and brief information before prompting. The use of inquirer for the confirmation prompt follows best practices for interactive CLI tools.


340-355: LGTM!

The error handling logic appropriately distinguishes between authentication errors and generic errors, providing helpful guidance to the user. The inclusion of stack traces in DEBUG mode is a good practice for troubleshooting.

- call api endpoint instead of using supabase client
- add storage-level filtering for api storage and file storage
  - make sure tasks are being manipulated by the storage services instead of other services manually manipulating the tasks
@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/feat/extract.tasks branch from 374ab07 to 89aa6a6 Compare October 6, 2025 13:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/tm-core/src/services/task-service.ts (2)

441-461: Null-safe filtering: avoid .toLowerCase() and .length on possibly undefined fields

details and subtasks may be absent. Current code can throw at runtime.

Apply this diff to guard safely:

-const inDetails = task.details.toLowerCase().includes(searchLower);
+const inDetails = (task.details ?? '').toLowerCase().includes(searchLower);
@@
-const hasSubtasks = task.subtasks.length > 0;
+const hasSubtasks = (task.subtasks?.length ?? 0) > 0;

29-33: Tag field: align docs with behavior

Interface says "only present if explicitly provided", but implementation always returns tag. Either always include (update JSDoc) or only include when options.tag is provided.

scripts/modules/commands.js (1)

3244-3256: Fix undefined variable in error message

tasksPath is not defined in this scope; this will throw if hit. Use the resolved path from taskMaster.

Apply this diff:

-					console.error(
-						chalk.red(`Error: No valid tasks found in ${tasksPath}`)
-					);
+					console.error(
+						chalk.red(
+							`Error: No valid tasks found in ${taskMaster.getTasksPath()}`
+						)
+					);
♻️ Duplicate comments (2)
packages/tm-core/src/errors/task-master-error.ts (1)

54-55: Consider BRIEF_NOT_FOUND for consistency with existing patterns.

The codebase defines domain-specific "not found" error codes (TASK_NOT_FOUND, FILE_NOT_FOUND, PROVIDER_NOT_FOUND). Adding a generic NOT_FOUND diverges from this pattern and reduces error handling precision.

Since this code is used when a brief cannot be found (line 216 in export.service.ts), BRIEF_NOT_FOUND would align better with the existing naming convention.

Apply this diff for consistency:

 	// Generic errors
 	INTERNAL_ERROR: 'INTERNAL_ERROR',
 	INVALID_INPUT: 'INVALID_INPUT',
 	NOT_IMPLEMENTED: 'NOT_IMPLEMENTED',
 	UNKNOWN_ERROR: 'UNKNOWN_ERROR',
-	NOT_FOUND: 'NOT_FOUND'
+	
+	// Resource-specific not found errors (grouped with TASK_NOT_FOUND, etc.)
+	BRIEF_NOT_FOUND: 'BRIEF_NOT_FOUND'

Then update the usage in export.service.ts:

 		if (!brief) {
 			throw new TaskMasterError(
 				'Brief not found or you do not have access',
-				ERROR_CODES.NOT_FOUND
+				ERROR_CODES.BRIEF_NOT_FOUND
 			);
 		}
apps/cli/src/command-registry.ts (1)

208-231: Add empty-registry fallback message in formatted list

Return a friendly message when no commands are registered to avoid empty output.

Consider:

 static getFormattedCommandList(): string {
+	if (this.commands.length === 0) {
+		return '\nNo commands registered.\n';
+	}
 	// existing formatting...
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 683b849 and 89aa6a6.

📒 Files selected for processing (22)
  • apps/cli/src/command-registry.ts (1 hunks)
  • apps/cli/src/commands/auth.command.ts (1 hunks)
  • apps/cli/src/commands/context.command.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (1 hunks)
  • apps/cli/src/commands/list.command.ts (1 hunks)
  • apps/cli/src/commands/set-status.command.ts (1 hunks)
  • apps/cli/src/commands/show.command.ts (1 hunks)
  • apps/cli/src/commands/start.command.ts (1 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • packages/tm-core/src/errors/task-master-error.ts (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/interfaces/storage.interface.ts (3 hunks)
  • packages/tm-core/src/repositories/supabase/supabase-task-repository.ts (3 hunks)
  • packages/tm-core/src/repositories/task-repository.interface.ts (1 hunks)
  • packages/tm-core/src/services/export.service.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (1 hunks)
  • packages/tm-core/src/services/task-service.ts (3 hunks)
  • packages/tm-core/src/storage/api-storage.ts (3 hunks)
  • packages/tm-core/src/storage/file-storage/file-storage.ts (2 hunks)
  • packages/tm-core/src/task-master-core.ts (6 hunks)
  • scripts/modules/commands.js (4 hunks)
  • tsdown.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
scripts/modules/commands.js

📄 CodeRabbit inference engine (.cursor/rules/ai_services.mdc)

scripts/modules/commands.js: Centralize all LLM calls through generateTextService or generateObjectService.
Do not import or call anything from the old ai-services.js, ai-client-factory.js, or ai-client-utils.js files.
Do not fetch AI-specific parameters (model ID, max tokens, temp) using config-manager.js getters for the AI call. Pass the role instead.
Do not implement fallback or retry logic outside ai-services-unified.js.
Do not handle API key resolution outside the service layer (it uses utils.js internally).
Determine the appropriate role (main, research, fallback) in your core logic and pass it to the service.
Pass the session object (received in the context parameter, especially from direct function wrappers) to the service call when in MCP context.
Use generateTextService and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as generateObjectService has shown unreliability with some providers/schemas.
Be aware of potential reliability issues with generateObjectService across different providers and complex schemas. Prefer generateTextService + manual parsing as a more robust alternative for structured data needs.

scripts/modules/commands.js: All new user-facing commands should be added to 'scripts/modules/commands.js'.
Use consistent patterns for option naming and help text in CLI commands.
Follow the Commander.js model for subcommand structure in CLI commands.
When using callbacks (like in Commander.js commands), define them separately to allow testing the callback logic independently.
Add help text to the command definition and update 'dev_workflow.mdc' with command reference when adding a new feature.
Follow the established pattern in 'commands.js' for CLI command implementation, using Commander.js for argument parsing, including comprehensive help text and examples, and supporting tagged task context awareness.
Provide clear error messages for common failu...

Files:

  • scripts/modules/commands.js
scripts/modules/*.js

📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)

Each module in scripts/modules/ should be focused on a single responsibility, following the modular architecture (e.g., commands.js for CLI command handling, task-manager.js for task data and core logic, dependency-manager.js for dependency management, ui.js for CLI output formatting, ai-services-unified.js for AI service integration, config-manager.js for configuration management, utils.js for utility functions).

scripts/modules/*.js: Export all core functions, helper functions, and utility methods needed by your new function or command from their respective modules. Explicitly review the module's export block to ensure every required dependency is included.
Pass all required parameters to functions you call within your implementation and verify that direct function parameters match their core function counterparts.
Use consistent file naming conventions: 'task_${id.toString().padStart(3, '0')}.txt', use path.join for composing file paths, and use appropriate file extensions (.txt for tasks, .json for data).
Use structured error objects with code and message properties, include clear error messages, and handle both function-specific and file system errors.
Import all silent mode utilities together from 'scripts/modules/utils.js' and always use isSilentMode() to check global silent mode status. Wrap core function calls within direct functions using enableSilentMode() and disableSilentMode() in a try/finally block if the core function might produce console output.
Core functions should check outputFormat === 'text' before displaying UI elements and use internal logging that respects silent mode.
Design functions to accept dependencies as parameters (dependency injection) and avoid hard-coded dependencies that are difficult to mock.
Keep pure logic separate from I/O operations or UI rendering to allow testing the logic without mocking complex dependencies.
When implementing core logic for new features, do so in 'scripts/modules/' before CLI or MCP interfaces, and d...

Files:

  • scripts/modules/commands.js
scripts/modules/**

📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)

When using the MCP server, restart it if core logic in scripts/modules or MCP tool/direct function definitions change.

Files:

  • scripts/modules/commands.js
scripts/modules/*

📄 CodeRabbit inference engine (.cursor/rules/tags.mdc)

scripts/modules/*: Every command that reads or writes tasks.json must be tag-aware
All command files must import getCurrentTag from utils.js
Every CLI command that operates on tasks must include the --tag CLI option
All commands must resolve the tag using the pattern: options.tag || getCurrentTag(projectRoot) || 'master'
All commands must find projectRoot with error handling before proceeding
All commands must pass { projectRoot, tag } as context to core functions
MCP direct functions must accept and use a context object containing projectRoot and tag, and pass them to core functions
Do not hard-code tag resolution (e.g., const tag = options.tag || 'master';); always use getCurrentTag
Do not omit the --tag CLI option in commands that operate on tasks
Do not omit the context parameter when calling core functions from commands
Do not call readJSON or writeJSON without passing projectRoot and tag

Files:

  • scripts/modules/commands.js
**/*.js

📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)

**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.

Files:

  • scripts/modules/commands.js
🧠 Learnings (21)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-18T17:08:48.695Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.
📚 Learning: 2025-07-31T22:07:49.716Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/commands.mdc:0-0
Timestamp: 2025-07-31T22:07:49.716Z
Learning: Applies to scripts/modules/commands.js : Export the registerCommands function and keep the CLI setup code clean and maintainable.

Applied to files:

  • apps/cli/src/index.ts
  • apps/cli/src/command-registry.ts
  • scripts/modules/commands.js
  • apps/cli/src/commands/export.command.ts
📚 Learning: 2025-09-26T19:05:47.555Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:11-13
Timestamp: 2025-09-26T19:05:47.555Z
Learning: In the eyaltoledano/claude-task-master repository, internal tm/ packages use a specific export pattern where the "exports" field points to TypeScript source files (./src/index.ts) while "main" points to compiled output (./dist/index.js) and "types" points to source files (./src/index.ts). This pattern is used consistently across internal packages like tm/core and tm/ai-sdk-provider-grok-cli because they are consumed directly during build-time bundling with tsdown rather than being published as separate packages.

Applied to files:

  • packages/tm-core/src/services/index.ts
  • packages/tm-core/src/index.ts
  • packages/tm-core/src/task-master-core.ts
📚 Learning: 2025-09-03T12:16:15.866Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1178
File: packages/tm-core/package.json:13-64
Timestamp: 2025-09-03T12:16:15.866Z
Learning: For internal packages in the claude-task-master project, Crunchyman-ralph prefers pointing package.json "types" entries to src .ts files rather than dist .d.ts files for better developer experience (DX), as the packages are not being exported as SDKs.

Applied to files:

  • packages/tm-core/src/services/index.ts
📚 Learning: 2025-09-26T19:10:32.906Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: tsconfig.json:22-28
Timestamp: 2025-09-26T19:10:32.906Z
Learning: In the eyaltoledano/claude-task-master repository, all internal tm/ package path mappings in tsconfig.json consistently point to TypeScript source files (e.g., "./packages/*/src/index.ts") rather than built JavaScript. This is intentional architecture because tsdown bundles internal packages directly from source during build time, eliminating the need for separate compilation of internal packages.

Applied to files:

  • packages/tm-core/src/services/index.ts
📚 Learning: 2025-09-26T19:03:33.225Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: package.json:130-132
Timestamp: 2025-09-26T19:03:33.225Z
Learning: In the eyaltoledano/claude-task-master repository, packages are bundled using tsdown during the build process, which means dependencies imported by the source code (including tm internal packages like tm/ai-sdk-provider-grok-cli) are included in the final bundle and don't need to be available as separate runtime dependencies, so they should remain as devDependencies rather than being moved to dependencies.

Applied to files:

  • packages/tm-core/src/services/index.ts
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Extract tasks from PRD documents using AI, create them in the current tag context (defaulting to 'master'), provide clear prompts to guide AI task generation, and validate/clean up AI-generated tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to scripts/modules/utils.js : Use tagged task system aware functions for task finding and manipulation, handle both task and subtask operations, and validate task IDs before operations.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to scripts/modules/task-manager/*.js : Files in scripts/modules/task-manager/ should each handle a specific action related to task management (e.g., add-task.js, expand-task.js), supporting the tagged task lists system and backward compatibility.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Provide functions for updating task status within the current tag context, handling both individual tasks and subtasks, and considering subtask status when updating parent tasks.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be accessed and updated through the tag resolution layer using getTasksForTag(data, tagName) and setTasksForTag(data, tagName, tasks); direct manipulation of the tagged structure in core functions is not allowed.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Tasks must be organized into separate contexts (tags) within tasks.json, using the tagged format: {"master": {"tasks": [...]}, "feature-branch": {"tasks": [...]}}. Legacy format {"tasks": [...]} must be silently migrated to the tagged format on first use.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use tag resolution functions to maintain backward compatibility, returning legacy format to core functions and not exposing the tagged structure to existing core logic.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/task-manager.js : Features that create, read, update, or delete tasks belong in 'scripts/modules/task-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:40.548Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:40.548Z
Learning: Applies to scripts/modules/dependency-manager.js : Provide clear error messages for non-existent dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Manage dependencies with task-master add-dependency and remove-dependency; validate and fix using validate-dependencies and fix-dependencies

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/dependency-manager.js : Features that handle task relationships belong in 'scripts/modules/dependency-manager.js'.

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Check for existing dependencies to prevent duplicates

Applied to files:

  • scripts/modules/commands.js
📚 Learning: 2025-07-18T17:09:45.690Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/dependencies.mdc:0-0
Timestamp: 2025-07-18T17:09:45.690Z
Learning: Applies to scripts/modules/dependency-manager.js : Format dependency lists consistently for visualization

Applied to files:

  • scripts/modules/commands.js
🧬 Code graph analysis (11)
packages/tm-core/src/storage/file-storage/file-storage.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-82)
packages/tm-core/src/storage/api-storage.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-82)
packages/tm-core/src/interfaces/storage.interface.ts (1)
packages/tm-core/src/types/index.ts (2)
  • TaskStatus (20-28)
  • Task (57-82)
packages/tm-core/src/services/task-service.ts (3)
packages/tm-core/src/logger/factory.ts (1)
  • getLogger (23-44)
packages/tm-core/src/entities/task.entity.ts (1)
  • TaskEntity (17-275)
packages/tm-core/src/logger/logger.ts (1)
  • error (163-166)
apps/cli/src/command-registry.ts (2)
apps/cli/src/index.ts (4)
  • CommandRegistry (17-17)
  • ExportCommand (13-13)
  • registerAllCommands (18-18)
  • registerCommandsByCategory (19-19)
apps/cli/src/commands/export.command.ts (1)
  • ExportCommand (32-379)
packages/tm-core/src/repositories/task-repository.interface.ts (1)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/services/export.service.ts (1)
packages/tm-core/src/storage/file-storage/file-storage.ts (1)
  • FileStorage (20-662)
packages/tm-core/src/repositories/supabase/supabase-task-repository.ts (2)
packages/tm-core/src/interfaces/storage.interface.ts (1)
  • LoadTasksOptions (11-16)
packages/tm-core/src/types/index.ts (1)
  • Task (57-82)
scripts/modules/commands.js (2)
apps/cli/src/command-registry.ts (1)
  • registerAllCommands (238-240)
apps/cli/src/index.ts (1)
  • registerAllCommands (18-18)
apps/cli/src/commands/export.command.ts (2)
packages/tm-core/src/services/export.service.ts (1)
  • ExportResult (55-71)
packages/tm-core/src/task-master-core.ts (2)
  • ExportResult (59-59)
  • TaskMasterCore (66-350)
packages/tm-core/src/task-master-core.ts (3)
packages/tm-core/src/services/export.service.ts (3)
  • ExportService (86-496)
  • ExportTasksOptions (39-50)
  • ExportResult (55-71)
packages/tm-core/src/auth/auth-manager.ts (1)
  • AuthManager (26-280)
packages/tm-core/src/auth/types.ts (1)
  • UserContext (16-22)
🔇 Additional comments (25)
tsdown.config.ts (2)

3-4: LGTM!

The imports are correct and necessary for loading environment variables at build time.


6-7: Add explicit quiet option for build predictability.

Consider adding quiet: true to the dotenv config to ensure consistent, clean build output across dotenv versions. While the current version (16.6.1) defaults quiet to true, dotenv 17.0.0 will change this default to false, which could introduce unexpected informational logs in build output.

Apply this diff:

-config({ path: resolve(process.cwd(), '.env') });
+config({ path: resolve(process.cwd(), '.env'), quiet: true });

Based on learnings: "Prefer explicit options (path/override/quiet) in CI / production to avoid surprises."

Likely an incorrect or invalid review comment.

apps/cli/src/commands/start.command.ts (1)

496-502: LGTM! Registration API standardized.

The updated register method follows the centralized command registry pattern, providing a single, consistent entry point for command registration. The return of the StartCommand instance enables method chaining and programmatic access.

Based on learnings: The change aligns with the coding guideline to export the registerCommands function and keep CLI setup clean and maintainable.

apps/cli/src/commands/set-status.command.ts (1)

290-296: LGTM! Consistent registration pattern.

The registration method update mirrors the pattern in StartCommand, ensuring consistency across the CLI command suite.

packages/tm-core/src/services/export.service.ts (3)

247-306: Storage-level filtering resolves transformation concern.

The transformTasksForBulkImport method processes whatever tasks are passed to it. Since exportTasks filters at the storage layer (lines 139-142), subtasks are already excluded before transformation when excludeSubtasks: true. This is the correct design—transformation should not duplicate filtering logic.


95-196: Robust export workflow with proper validation.

The exportTasks method implements a well-structured export flow:

  • Authentication validation upfront
  • Proper org/brief ID resolution with helpful error messages
  • Storage-level filtering for status and subtasks
  • Early exit for empty results
  • Clean error handling

139-142: Subtask exclusion handled in FileStorage.loadTasks
FileStorage.loadTasks (packages/tm-core/src/storage/file-storage/file-storage.ts:111-116) empties subtasks when options.excludeSubtasks is true; no additional filtering required.

packages/tm-core/src/repositories/task-repository.interface.ts (2)

2-2: LGTM! Clean interface extension.

The addition of LoadTasksOptions import properly supports the enhanced getTasks method signature.


6-6: LGTM! Backward-compatible signature update.

The optional options parameter maintains backward compatibility while enabling filtered task loading for export and other use cases.

packages/tm-core/src/index.ts (1)

14-16: LGTM! Public API surface appropriately extended.

The export-related types are now exposed as part of the core package's public API, enabling downstream consumers (like the CLI) to import them cleanly.

packages/tm-core/src/services/index.ts (1)

8-13: LGTM! Service barrel exports align with internal package pattern.

The export of ExportService and its types follows the established barrel pattern and enables the CLI to import these from @tm/core, as discussed in previous reviews.

Based on learnings: Internal tm/ packages consume these exports directly during build-time bundling via tsdown.

apps/cli/src/index.ts (1)

13-21: LGTM! CLI public API cleanly extended.

The additions expose the new ExportCommand and the centralized CommandRegistry infrastructure, following the established export pattern for CLI commands.

Based on learnings: This aligns with the guideline to export the registerCommands function and maintain clean CLI setup.

apps/cli/src/commands/context.command.ts (1)

697-703: LGTM!

The registration method correctly constructs the command with an optional name parameter, registers it on the provided program, and returns the instance. This aligns well with the centralized command registration pattern introduced in this PR.

packages/tm-core/src/storage/api-storage.ts (1)

150-167: LGTM!

The addition of the optional options parameter to loadTasks maintains backward compatibility while enabling filtered task loading. The options are correctly forwarded to the repository layer, enabling database-level filtering for status and subtask exclusion.

apps/cli/src/commands/auth.command.ts (1)

496-502: LGTM!

The registration method follows the same pattern as other commands in this PR, providing a single entry point for command registration that's compatible with the centralized command registry.

apps/cli/src/commands/show.command.ts (1)

325-331: LGTM!

The registration method is consistent with the other command classes, providing a unified entry point for command registration.

packages/tm-core/src/repositories/supabase/supabase-task-repository.ts (1)

60-96: LGTM!

The updated getTasks method correctly applies optional filtering at the database level:

  • Status filtering uses the existing mapStatusToDatabase helper to ensure proper status mapping
  • Subtask exclusion filters at the database level using is('parent_task_id', null), which is efficient
  • The query builder pattern allows conditional filter application while maintaining the existing ordering logic

The implementation maintains backward compatibility and pushes filtering to the database layer for optimal performance.

packages/tm-core/src/storage/file-storage/file-storage.ts (1)

96-118: Verify the subtask exclusion approach.

The status filtering logic is correct. However, the subtask exclusion approach differs from the API storage implementation:

  • API storage: Filters at the database level, never fetching subtasks
  • File storage: Loads all tasks with subtasks from the file, then clears the subtasks array

While both approaches produce the correct result, the file storage version still loads and parses subtask data from the file before discarding it. For large task sets, this could have a minor performance impact.

Consider whether this performance difference is acceptable, or if you'd prefer to filter subtasks earlier in the loading pipeline (e.g., in extractTasks within FormatHandler).

apps/cli/src/commands/list.command.ts (1)

477-483: LGTM!

The registration method maintains consistency with the other command classes, supporting the centralized registration pattern.

packages/tm-core/src/interfaces/storage.interface.ts (2)

8-16: LGTM!

The LoadTasksOptions interface is well-designed with clear documentation:

  • status?: TaskStatus enables filtering by task status
  • excludeSubtasks?: boolean enables excluding subtasks from the results

Both fields are optional, ensuring the interface is flexible and backward-compatible.


34-39: LGTM!

The interface updates correctly add the optional options parameter to the loadTasks method signature in both IStorage and BaseStorage. The documentation comments accurately reflect the new filtering capabilities, and backward compatibility is preserved since the parameter is optional.

Also applies to: 219-219

packages/tm-core/src/services/task-service.ts (1)

118-136: Storage pushdown and total count handling look solid

Pushing single-status filter to storage and preserving excludeSubtasks for total recalculation is correct and fixes the earlier total/filtered mismatch. Good addition.

packages/tm-core/src/task-master-core.ts (1)

126-129: Export service integration is clean and consistent

Initialization and public wrappers (exportTasks/exportFromBriefInput/validateExportContext) are straightforward and type-correct.

Also applies to: 267-287

scripts/modules/commands.js (1)

1670-1675: Centralized command registry usage LGTM

Delegating to registerAllCommands reduces duplication and keeps CLI setup clean.

apps/cli/src/commands/export.command.ts (1)

158-165: Correct flag forwarding for exclude-subtasks

excludeSubtasks mapping now matches the option name; flow and messaging look good.

Comment on lines +355 to +427
private async performExport(
orgId: string,
briefId: string,
tasks: any[]
): Promise<void> {
// Check if we should use the API endpoint or direct Supabase
const useAPIEndpoint = process.env.TM_PUBLIC_BASE_DOMAIN;

if (useAPIEndpoint) {
// Use the new bulk import API endpoint
const apiUrl = `${process.env.TM_PUBLIC_BASE_DOMAIN}/ai/api/v1/briefs/${briefId}/tasks/bulk`;

// Transform tasks to flat structure for API
const flatTasks = this.transformTasksForBulkImport(tasks);

// Prepare request body
const requestBody = {
source: 'task-master-cli',
accountId: orgId,
options: {
dryRun: false,
stopOnError: false
},
tasks: flatTasks
};

// Get auth token
const credentials = this.authManager.getCredentials();
if (!credentials || !credentials.token) {
throw new Error('Not authenticated');
}

// Make API request
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${credentials.token}`
},
body: JSON.stringify(requestBody)
});

if (!response.ok) {
const errorText = await response.text();
throw new Error(
`API request failed: ${response.status} - ${errorText}`
);
}

const result = (await response.json()) as BulkTasksResponse;

if (result.failedCount > 0) {
const failedTasks = result.results
.filter((r) => !r.success)
.map((r) => `${r.externalId}: ${r.error}`)
.join(', ');
console.warn(
`Warning: ${result.failedCount} tasks failed to import: ${failedTasks}`
);
}

console.log(
`Successfully exported ${result.successCount} of ${result.totalTasks} tasks to brief ${briefId}`
);
} else {
// Direct Supabase approach is no longer supported
// The extractTasks method has been removed from SupabaseTaskRepository
// as we now exclusively use the API endpoint for exports
throw new Error(
'Export API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable to enable task export.'
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider timeout for fetch call.

The fetch call at line 388 has no timeout configured. If the API endpoint becomes unresponsive, the export operation will hang indefinitely.

Add an AbortSignal with timeout to the fetch call:

+		// Set a reasonable timeout (e.g., 60 seconds for bulk operations)
+		const controller = new AbortController();
+		const timeoutId = setTimeout(() => controller.abort(), 60000);
+
 		// Make API request
-		const response = await fetch(apiUrl, {
+		try {
+			const response = await fetch(apiUrl, {
 			method: 'POST',
 			headers: {
 				'Content-Type': 'application/json',
 				Authorization: `Bearer ${credentials.token}`
 			},
-			body: JSON.stringify(requestBody)
+			body: JSON.stringify(requestBody),
+			signal: controller.signal
 		});
+		} catch (error) {
+			if (error.name === 'AbortError') {
+				throw new Error('Export request timed out after 60 seconds');
+			}
+			throw error;
+		} finally {
+			clearTimeout(timeoutId);
+		}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/tm-core/src/services/export.service.ts around lines 355 to 427, the
fetch call has no timeout and can hang indefinitely; create an AbortController,
start a timer (e.g. 30s or configurable via env) that calls controller.abort(),
pass controller.signal into fetch options, clear the timer after fetch
completes, and handle the abort case by catching the AbortError and throwing a
descriptive timeout error (or retry if desired); this ensures the export
operation fails fast when the API is unresponsive.

@Crunchyman-ralph Crunchyman-ralph merged commit 7265a6c into next Oct 6, 2025
8 checks passed
@Crunchyman-ralph Crunchyman-ralph deleted the ralph/feat/extract.tasks branch October 6, 2025 14:04
github-actions bot added a commit that referenced this pull request Oct 6, 2025
  This PR was automatically generated to update documentation based on recent changes.

  Original commit: feat: implement export tasks (#1260)\n\n\n

  Co-authored-by: Claude <claude-assistant@anthropic.com>
@coderabbitai coderabbitai bot mentioned this pull request Nov 12, 2025
16 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant