Skip to content

chore: refactor tm-core to host more of our "core" commands#1331

Merged
Crunchyman-ralph merged 9 commits intonextfrom
ralph/chore/refactor.tm.core
Oct 21, 2025
Merged

chore: refactor tm-core to host more of our "core" commands#1331
Crunchyman-ralph merged 9 commits intonextfrom
ralph/chore/refactor.tm.core

Conversation

@Crunchyman-ralph
Copy link
Collaborator

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

  • update-task coming up next

What type of PR is this?

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

Description

  • This PR refactors tm-core to use a domain-driven architecture with a unified facade pattern:
    • Created unified TmCore facade - Single entry point via createTmCore({ projectPath })
    • Organized into domain modules - auth, config, git, tasks, workflow
    • Moved files to domain structure - All services organized under src/modules/
    • Created domain facades - Clean public API for each domain
  • This is an internal refactoring of tm-core package. The changes enable:
    • Better code organization by domain
    • Cleaner public API via unified facade
    • Easier navigation and maintenance

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

    • Introduced a centralized TmCore facade with domain APIs: Tasks, Auth, Config, Workflow, Git and Integration (task listing/start/validate, OAuth flows, workflow lifecycle, Git ops, exports).
  • Refactor

    • Consolidated public API into domain-centered exports and reorganized module entry points.
    • Standardized storage API to expose concrete storage type via getStorageType().
    • Added storage display info API for auth-backed brief/file fallbacks.
    • Executor and execution surfaces reworked into a single execution module.
  • Chores

    • Bumped version to 0.30.0.
    • Added TypeScript definitions for fs-extra.

@changeset-bot
Copy link

changeset-bot bot commented Oct 20, 2025

⚠️ No Changeset found

Latest commit: 0c6b915

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 20, 2025

Walkthrough

Introduces a new TmCore façade (createTmCore/TmCore), reorganizes @tm/core into domain facades and managers/services/adapters, renames storage methods (getType → getStorageType), rewrites many import/export paths, removes several old index barrels, and updates CLI/extension callers to the new public API.

Changes

Cohort / File(s) Summary
Version & deps
package.json
Bumped version to 0.30.0; added @types/fs-extra to dependencies/devDependencies.
Core façade & entry
packages/tm-core/src/tm-core.ts, packages/tm-core/src/index.ts, packages/tm-core/src/task-master-core.ts
Add TmCore, TmCoreOptions, and createTmCore; remove old TaskMasterCore implementation; centralize public API surface and rewire exports to modules/*.
Domain facades
packages/tm-core/src/modules/*/(*-domain.ts)
Add new domain facades: TasksDomain, AuthDomain, WorkflowDomain, GitDomain, ConfigDomain, IntegrationDomain exposing typed domain APIs delegating to managers/services.
Module reorganization & barrels
packages/tm-core/src/modules/**/index.ts, .../managers/*, .../services/*, .../adapters/*
Move many modules into managers/services/adapters/orchestrators/providers folders and update barrel re-exports accordingly.
Executors / execution module
packages/tm-core/src/executors/index.ts (removed), packages/tm-core/src/modules/execution/index.ts (added)
Remove old executors barrel; add new modules/execution index re-exporting types, BaseExecutor, ClaudeExecutor, ExecutorFactory, ExecutorService.
Storage API & interface changes
packages/tm-core/src/common/interfaces/storage.interface.ts, modules/storage/adapters/**
Add `getStorageType(): 'file'
Common import consolidation
many packages/tm-core/src/modules/** files
Replace many relative imports with centralized common/ paths for types, errors, logger, and interfaces (e.g., ../types../../../common/types).
Auth surface & session logic
packages/tm-core/src/modules/auth/**, packages/tm-core/src/auth/index.ts
Add AuthDomain and StorageDisplayInfo; enhance supabase session storage (parsing, rotation, stricter saves, logging); reorganize/adjust auth index exports (some barrels removed).
Task services & loader
packages/tm-core/src/modules/tasks/services/*
TaskLoaderService now accepts a TaskService instance (removes lazy init); TaskService.getStorageType() returns concrete `'file'
Git adapter typing & domain
packages/tm-core/src/modules/git/adapters/git-adapter.ts, packages/tm-core/src/modules/git/git-domain.ts
Explicit StatusResult type import from simple-git; add GitDomain facade with rich git API delegating to GitAdapter and commit message generator.
Integration & export service
packages/tm-core/src/modules/integration/**
Add IntegrationDomain facade; rewire ExportService and Supabase client imports to new locations.
Reports & complexity manager
packages/tm-core/src/modules/reports/**
Move ComplexityReportManager to managers/ path and update imports.
Storage adapters & format handlers
packages/tm-core/src/modules/storage/adapters/*
Update paths and type imports; FileStorage/ApiStorage method renames to getStorageType(); update format handler type imports.
Services barrel removal
packages/tm-core/src/services/index.ts
Remove previous services barrel re-exports (services moved into module indices).
Scaffolding modules
packages/tm-core/src/modules/commands/index.ts, .../dependencies/index.ts, .../ui/index.ts
Add placeholder scaffold files (TODOs) for future migrations.
Large refactors across consumers
apps/cli/**, apps/extension/**, apps/mcp/**
Replace createTaskMasterCore/TaskMasterCore with createTmCore/TmCore; update code to use domain facades (e.g., tmCore.tasks.get, tmCore.config.getActiveTag()); remove many explicit close() calls.
Tests & specs
various *.spec.ts, packages/tm-core/tests/integration/**
Update import paths and mocks to match reorganized modules and new barrels.
Docs & migration plan
CLAUDE.md, update-task-migration-plan.md
Add architecture/guidelines doc and a detailed migration plan for update-task command.
CI & scripts
.github/workflows/*.yml, apps/extension/package.json, apps/extension/docs/**
Rename script check-typestypecheck and update workflow steps; minor workflow step removals/cleanup; docs updated.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI / Extension
    participant Factory as createTmCore()
    participant TmCore as TmCore (façade)
    participant Config as ConfigManager
    participant Tasks as TasksDomain
    participant Auth as AuthDomain
    participant Services as Underlying services

    CLI->>Factory: createTmCore({ projectPath, configuration? })
    Factory->>TmCore: new TmCore(options)
    TmCore->>Config: instantiate & apply overrides
    TmCore->>Tasks: construct TasksDomain(ConfigManager)
    TmCore->>Auth: construct AuthDomain(ConfigManager)
    Tasks->>Services: wire TaskService, TaskExecutionService, TaskLoaderService
    Auth->>Services: wire AuthManager, CredentialStore, OAuthService
    TmCore-->>CLI: return TmCore (tasks, auth, config, workflow, git, integration)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

Possibly related PRs

  • Feat: add typescript and start refactoring #1190 — Monorepo/TypeScript refactor that reorganizes @tm/core modules and public API; overlaps heavily with the TmCore introduction and export changes.
  • Release 0.27.0 #1224 — Large refactor modifying @tm/core public API and module layout; touches domain facades, re-exports, and many of the same modules.
  • fix: auth refresh #1314 — Auth/token/session changes; related to supabase-session-storage and AuthManager edits present here.

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 PR title "chore: refactor tm-core to host more of our 'core' commands" is related to the changeset but lacks precision about the primary architectural changes. The PR's main objective is to refactor tm-core using a domain-driven architecture with unified domain facades (TasksDomain, AuthDomain, WorkflowDomain, etc.) and create a single entry point via createTmCore. While the title correctly identifies that tm-core is being refactored, the phrase "to host more of our 'core' commands" is somewhat vague and doesn't clearly capture the core architectural transformation—primarily the introduction of domain facades and centralized business logic. The title is concise and related to the changeset, but a more precise description of the domain-driven refactoring would better reflect the main changes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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/chore/refactor.tm.core

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: 10

Caution

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

⚠️ Outside diff range comments (4)
packages/tm-core/src/modules/tasks/entities/task.entity.ts (1)

202-210: Fix ID collision bug and type inconsistency in subtask ID generation.

This method has two issues:

  1. ID collision (critical): Using this.subtasks.length + 1 for ID generation can create collisions. If a subtask is removed from the middle of the array, the next generated ID may match an existing subtask's ID.

  2. Type inconsistency (major): The method creates a numeric ID, but the constructor (lines 54-58) normalizes all subtask IDs to strings. This means subtasks added via addSubtask have a different ID type than subtasks loaded from storage, which can cause comparison failures or unexpected behavior.

Apply this diff to fix both issues:

 addSubtask(subtask: Omit<Subtask, 'id' | 'parentId'>): void {
-  const nextId = this.subtasks.length + 1;
+  const maxId = this.subtasks.reduce((max, s) => {
+    const numId = typeof s.id === 'string' ? parseInt(s.id, 10) : s.id;
+    return Math.max(max, isNaN(numId) ? 0 : numId);
+  }, 0);
+  const nextId = String(maxId + 1);
   this.subtasks.push({
     ...subtask,
     id: nextId,
     parentId: this.id
   });
   this.updatedAt = new Date().toISOString();
 }
packages/tm-core/src/modules/auth/services/credential-store.test.ts (1)

24-26: Fix the mock path to match the actual import.

The mock path '../logger/index.js' doesn't match the actual import in credential-store.ts (line 9), which is '../../../common/logger/index.js'. This mock won't be applied, potentially causing test failures.

Apply this diff to fix the mock path:

-vi.mock('../logger/index.js', () => ({
+vi.mock('../../../common/logger/index.js', () => ({
 	getLogger: () => mockLogger
 }));
packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1)

16-20: Fix incorrect mock paths for services.

The mock paths use './services/...' which would resolve to managers/services/... since the test file is in the managers/ directory. The services are actually at the config module level.

Apply this fix:

-vi.mock('./services/config-loader.service.js');
-vi.mock('./services/config-merger.service.js');
-vi.mock('./services/runtime-state-manager.service.js');
-vi.mock('./services/config-persistence.service.js');
-vi.mock('./services/environment-config-provider.service.js');
+vi.mock('../services/config-loader.service.js');
+vi.mock('../services/config-merger.service.js');
+vi.mock('../services/runtime-state-manager.service.js');
+vi.mock('../services/config-persistence.service.js');
+vi.mock('../services/environment-config-provider.service.js');
packages/tm-core/src/modules/storage/index.ts (1)

26-55: Enable stripInternal in tsconfig.json and add @internal JSDoc to placeholders.

StorageAdapter and PlaceholderStorage are publicly accessible via the "./storage" export in package.json and will leak into generated .d.ts files. With stripInternal currently disabled, the @deprecated annotation alone won't prevent emission.

  • Add "stripInternal": true to packages/tm-core/tsconfig.jsoncompilerOptions
  • Add @internal JSDoc tag to both StorageAdapter interface and PlaceholderStorage class (in addition to existing @deprecated on the class)

This ensures they're stripped from published typings while remaining available for internal tests.

🧹 Nitpick comments (17)
packages/tm-core/src/modules/tasks/parser/index.ts (1)

9-10: Remove or clarify the status of commented-out parser exports.

The commented parser implementations should either be removed or retained with a clear TODO/issue reference indicating the expected timeline for implementation.

Apply this diff to remove stale comments or convert to TODO:

-// Parser implementations will be defined here
-// export * from './prd-parser.js';
-// export * from './task-parser.js';
-// export * from './markdown-parser.js';

Alternatively, if these are intentional placeholders, convert to a tracked TODO:

-// Parser implementations will be defined here
-// export * from './prd-parser.js';
-// export * from './task-parser.js';
-// export * from './markdown-parser.js';
+// TODO: Implement and export specific parsers in related tasks
+// - PRD parser (prd-parser.js)
+// - Task parser (task-parser.js)  
+// - Markdown parser (markdown-parser.js)
packages/tm-core/src/modules/dependencies/index.ts (1)

1-8: Clarify the status and timeline for this placeholder module.

This file establishes the Dependencies domain structure but provides no public exports or functionality. While placeholder modules are reasonable for documenting intended architecture, verify that:

  1. This module will be implemented during this PR or explicitly deferred to follow-up work.
  2. The TmCore facade (or domain-specific facade) will reference this module once implemented, so it's not left orphaned.

Based on learnings, the Dependencies domain should eventually expose cycle detection (DFS), self-dependency handling, duplicate prevention, and validation capabilities migrated from scripts/modules/dependency-manager.js.

Would you like me to help implement the migration from the existing dependency-manager.js, or should this placeholder be addressed in a follow-up PR after the refactoring is merged?

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

66-70: Pre-existing TODO: Incomplete repository implementation.

The TODO comment indicates that SupabaseTaskRepository doesn't fully implement all TaskRepository methods yet and requires a type cast. While this is a pre-existing issue (not introduced by this refactor), consider tracking this technical debt.

Would you like me to open a new issue to track completing the SupabaseTaskRepository implementation?

packages/tm-core/src/modules/config/config-domain.ts (2)

34-36: Tighten return types; avoid any on public surface.

  • getModelConfig currently returns any. Expose a concrete type (e.g., ModelConfig) or unknown if intentionally opaque.
  • getConfigSources also returns untyped data; consider a readonly, structured type for debuggability and stability.

This keeps the facade’s API self-documenting and reduces downstream any leakage.

Also applies to: 110-112


52-57: Clarify "explicit vs computed" API config semantics.

You expose both isApiExplicitlyConfigured() and RuntimeStorageConfig.apiConfigured (computed). Add docstrings clarifying the difference or consolidate to one authoritative check to prevent ambiguity for consumers.

Also applies to: 27-29

packages/tm-core/src/modules/tasks/tasks-domain.ts (1)

104-116: Make return types explicit for public methods.

For a stable public API, annotate return types instead of relying on inference:

  • checkInProgressConflicts(...): Promise
  • getNextAvailable(): Promise<string | null>
  • getExecutionOrder(...): Subtask[]
  • detectTestCommand/checkGitWorkingTree/validateRequiredTools/detectDefaultBranch: concrete result types from PreflightChecker

This enhances discoverability and prevents accidental type regressions.

Also applies to: 120-123, 144-146, 160-169, 174-176, 181-183

packages/tm-core/src/modules/auth/auth-domain.ts (1)

20-23: Consider optional dependency injection for testability.

Allow passing an AuthManager instance to the constructor (defaulting to singleton) to simplify unit testing/mocking:

- constructor() {
-   this.authManager = AuthManager.getInstance();
- }
+ constructor(manager: AuthManager = AuthManager.getInstance()) {
+   this.authManager = manager;
+ }

Non-breaking and improves test ergonomics.

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

32-43: Export surface is broad; prefer minimal, domain-level exports to avoid lock-in.

This file re-exports many internals (including service-layer types). It increases coupling and raises semver risk when services change. Recommend:

  • Curate a minimal public surface (only what downstreams consume).
  • Avoid re-exporting from service files; add domain-level types barrels (e.g., modules/tasks/types.ts) and export from there.
  • Replace export * with explicit named exports for stability and discoverability.

Based on learnings.

Also applies to: 46-62, 70-102


86-89: Expose commit message validation/parse types alongside CommitMessageOptions.

GitDomain exposes validateCommitMessage/parseCommitMessage; consumers will likely need ValidationResult and ParsedCommitMessage. Re-export them here for a coherent public API.

Apply:

 export type {
-  CommitMessageOptions
+  CommitMessageOptions,
+  ValidationResult,
+  ParsedCommitMessage
 } from './modules/git/services/commit-message-generator.js';

46-62: Don’t leak service file paths in public API.

Types are exported from task-service, task-execution-service, and preflight-checker.service. Suggest creating modules/tasks/public-types.ts that re-exports stable shapes; then re-export from that file here. It lets you refactor services without breaking API.

Example new file (modules/tasks/public-types.ts):

export type { TaskListResult, GetTaskListOptions } from './services/task-service.js';
export type { StartTaskOptions, StartTaskResult, ConflictCheckResult } from './services/task-execution-service.js';
export type { PreflightResult, CheckResult } from './services/preflight-checker.service.js';

Then update index.ts:

-export type { TaskListResult, GetTaskListOptions } from './modules/tasks/services/task-service.js';
-export type { StartTaskOptions, StartTaskResult, ConflictCheckResult } from './modules/tasks/services/task-execution-service.js';
-export type { PreflightResult, CheckResult } from './modules/tasks/services/preflight-checker.service.js';
+export type * from './modules/tasks/public-types.js';
packages/tm-core/src/modules/git/git-domain.ts (7)

6-10: Decouple public API from simple-git types.

getStatus() returns simple-git’s StatusResult, coupling consumers to a vendor. Prefer a domain Status shape (e.g., GitStatus) and map in the adapter, keeping third-party details internal.

Apply:

-import type { StatusResult } from 'simple-git';
+// import domain type instead of vendor type
+import type { GitStatus } from './types.js' // define this in modules/git/types.ts

-async getStatus(): Promise<StatusResult> {
+async getStatus(): Promise<GitStatus> {
   return this.gitAdapter.getStatus();
}

Also applies to: 58-60


189-214: Avoid any in public API for logs/remotes; define domain types.

Returning any/any[] weakens the contract. Define and return domain types, e.g., CommitLogEntry, CommitSummary, RemoteInfo.

Apply:

-async getCommitLog(options?: { maxCount?: number }): Promise<any[]> {
+async getCommitLog(options?: { maxCount?: number }): Promise<CommitLogEntry[]> {
   return this.gitAdapter.getCommitLog(options);
}

-async getLastCommit(): Promise<any> {
+async getLastCommit(): Promise<CommitSummary> {
   return this.gitAdapter.getLastCommit();
}

-async getRemotes(): Promise<any[]> {
+async getRemotes(): Promise<RemoteInfo[]> {
   return this.gitAdapter.getRemotes();
}

And export these types from modules/git/types.ts, then from the package index.


218-237: Add explicit return types for validator/parser methods.

Annotate return types to lock the public contract and aid consumers.

Apply:

-import { CommitMessageGenerator } from './services/commit-message-generator.js';
-import type { CommitMessageOptions } from './services/commit-message-generator.js';
+import { CommitMessageGenerator } from './services/commit-message-generator.js';
+import type { CommitMessageOptions, ValidationResult, ParsedCommitMessage } from './services/commit-message-generator.js';

-validateCommitMessage(message: string) {
+validateCommitMessage(message: string): ValidationResult {
   return this.commitGenerator.validateConventionalCommit(message);
}

-parseCommitMessage(message: string) {
+parseCommitMessage(message: string): ParsedCommitMessage {
   return this.commitGenerator.parseCommitMessage(message);
}

Also re-export ValidationResult and ParsedCommitMessage from the package root (see related comment in index.ts).


18-21: Enable dependency injection for testability/customization.

Constructor hard-wires GitAdapter and CommitMessageGenerator. Allow optional injection for testing and custom templates/scope mappings.

Apply:

-export class GitDomain {
+export class GitDomain {
   private gitAdapter: GitAdapter;
   private commitGenerator: CommitMessageGenerator;

-  constructor(projectPath: string) {
-    this.gitAdapter = new GitAdapter(projectPath);
-    this.commitGenerator = new CommitMessageGenerator();
-  }
+  constructor(
+    projectPath: string,
+    deps?: {
+      gitAdapter?: GitAdapter;
+      commitGenerator?: CommitMessageGenerator;
+      commitTemplates?: Record<string, string>;
+      scopeMappings?: Record<string, string>;
+      scopePriorities?: Record<string, number>;
+    }
+  ) {
+    this.gitAdapter = deps?.gitAdapter ?? new GitAdapter(projectPath);
+    this.commitGenerator =
+      deps?.commitGenerator ??
+      new CommitMessageGenerator(deps?.commitTemplates, deps?.scopeMappings, deps?.scopePriorities);
+  }

65-74: Status summary shape: document and type it.

getStatusSummary returns an inline object type. Extract a named type (e.g., GitStatusSummary) and export it so callers can import a stable type.


174-184: Commit options: document behavior and edge cases.

Options like enforceNonDefaultBranch and force can be dangerous. Add JSDoc specifying precedence, defaults, and error semantics (e.g., what happens on default branch when enforceNonDefaultBranch = true).


202-207: Consider exposing remote names/URLs directly.

hasRemote() is coarse. Returning RemoteInfo[] (even when empty) can eliminate the need for a separate boolean call and reduce round-trips.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a3cb24 and bf2d549.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (67)
  • package.json (2 hunks)
  • packages/tm-core/src/common/interfaces/index.ts (1 hunks)
  • packages/tm-core/src/executors/index.ts (0 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/modules/ai/index.ts (1 hunks)
  • packages/tm-core/src/modules/ai/providers/base-provider.ts (2 hunks)
  • packages/tm-core/src/modules/auth/auth-domain.ts (1 hunks)
  • packages/tm-core/src/modules/auth/index.ts (1 hunks)
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/auth/managers/auth-manager.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/credential-store.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/oauth-service.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/organization.service.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (1 hunks)
  • packages/tm-core/src/modules/commands/index.ts (1 hunks)
  • packages/tm-core/src/modules/config/config-domain.ts (1 hunks)
  • packages/tm-core/src/modules/config/index.ts (2 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-loader.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-merger.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-persistence.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/environment-config-provider.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.ts (1 hunks)
  • packages/tm-core/src/modules/dependencies/index.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/base-executor.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/claude-executor.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/executor-factory.ts (1 hunks)
  • packages/tm-core/src/modules/execution/index.ts (1 hunks)
  • packages/tm-core/src/modules/execution/services/executor-service.ts (1 hunks)
  • packages/tm-core/src/modules/execution/types.ts (1 hunks)
  • packages/tm-core/src/modules/git/git-domain.ts (1 hunks)
  • packages/tm-core/src/modules/git/index.ts (1 hunks)
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts (1 hunks)
  • packages/tm-core/src/modules/integration/clients/supabase-client.ts (1 hunks)
  • packages/tm-core/src/modules/integration/services/export.service.ts (1 hunks)
  • packages/tm-core/src/modules/reports/index.ts (1 hunks)
  • packages/tm-core/src/modules/reports/managers/complexity-report-manager.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/api-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/format-handler.ts (1 hunks)
  • packages/tm-core/src/modules/storage/index.ts (2 hunks)
  • packages/tm-core/src/modules/storage/services/storage-factory.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/entities/task.entity.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/parser/index.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/dependency-fetcher.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/task-repository.interface.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/preflight-checker.service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/tasks-domain.ts (1 hunks)
  • packages/tm-core/src/modules/ui/index.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts (2 hunks)
  • packages/tm-core/src/modules/workflow/services/workflow-activity-logger.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/services/workflow.service.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/workflow-domain.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (0 hunks)
  • packages/tm-core/src/task-master-core.ts (2 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/tm-core/src/services/index.ts
  • packages/tm-core/src/executors/index.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{test,spec}.{js,ts,jsx,tsx}

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

**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)

Files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
**/*.{test,spec}.*

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

Test files should follow naming conventions: .test., .spec., or _test. depending on the language

Files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
**/?(*.)+(spec|test).ts

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

In JavaScript/TypeScript projects using Jest, test files should match *.test.ts and *.spec.ts patterns

Files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
{packages/*/src/**/*.spec.ts,apps/*/src/**/*.spec.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Place package and app unit test files alongside source as *.spec.ts under src (packages//src//.spec.ts or apps//src//.spec.ts)

Files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}: Do not use async/await in test functions unless the test is explicitly exercising asynchronous behavior
Use synchronous top-level imports in tests; avoid dynamic await import()
Keep test bodies synchronous whenever possible

Files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
**/*.test.ts

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

**/*.test.ts: Use established mocking patterns for dependencies such as bcrypt and Prisma in test files
Test all code paths, including edge cases and error scenarios, in test files
Use descriptive names for test functions, such as should_return_error_for_invalid_input

Files:

  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
package.json

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

Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci

Files:

  • package.json
🧠 Learnings (25)
📚 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:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Use graph traversal algorithms (DFS) to detect cycles

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Detect circular dependencies, validate dependency references, and support cross-tag dependency checking (future enhancement) in dependency analysis utilities.

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Handle both direct and indirect self-dependencies

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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:

  • packages/tm-core/src/modules/dependencies/index.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/modules/execution/index.ts
  • packages/tm-core/src/modules/tasks/services/task-execution-service.ts
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts
  • packages/tm-core/src/modules/execution/types.ts
  • packages/tm-core/src/modules/execution/executors/claude-executor.ts
  • packages/tm-core/src/common/interfaces/index.ts
  • packages/tm-core/src/task-master-core.ts
  • packages/tm-core/src/index.ts
  • packages/tm-core/src/modules/integration/services/export.service.ts
  • package.json
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.

Applied to files:

  • packages/tm-core/src/modules/execution/index.ts
  • packages/tm-core/src/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must import the provider's create<ProviderName> function from ai-sdk/<provider-name>, and import generateText, streamText, generateObject from the core ai package, as well as the log utility from ../../scripts/modules/utils.js.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/ai/index.ts
  • packages/tm-core/src/common/interfaces/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Implement generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object functions in provider modules with basic validation and try/catch error handling.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Create a new provider module file in src/ai-providers/ named <provider-name>.js when adding a new AI provider.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to tests/unit/ai-providers/*.test.js : Create unit tests for the new provider in tests/unit/ai-providers/<provider-name>.test.js, mocking ai-sdk/<provider-name> and core ai module functions, and testing all exported functions for correct behavior and error handling.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/ai/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 implement fallback or retry logic outside `ai-services-unified.js`.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
📚 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 src/ai-providers/*.js : Provider-specific wrappers for Vercel AI SDK functions must be implemented in src/ai-providers/*.js, each file corresponding to a provider.

Applied to files:

  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/ai/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/modules/tasks/services/task-execution-service.ts
  • packages/tm-core/src/modules/execution/types.ts
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts
  • package.json
📚 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:

  • packages/tm-core/src/modules/tasks/services/task-service.ts
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.ts
  • packages/tm-core/src/task-master-core.ts
  • packages/tm-core/src/modules/integration/services/export.service.ts
📚 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: Module dependencies should be mocked before importing the test module, following Jest's hoisting behavior.

Applied to files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must export three functions: generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 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/ai-services.js : Features that use AI models belong in 'scripts/modules/ai-services.js'.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/ai-services-unified.js : Integrate the new provider module with scripts/modules/ai-services-unified.js by importing it and adding an entry to the PROVIDER_FUNCTIONS map.

Applied to files:

  • packages/tm-core/src/modules/ai/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/commands.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:

  • packages/tm-core/src/modules/ai/index.ts
📚 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/commands.js : All new user-facing commands should be added to 'scripts/modules/commands.js'.

Applied to files:

  • packages/tm-core/src/modules/commands/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:

  • packages/tm-core/src/modules/commands/index.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.

Applied to files:

  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
📚 Learning: 2025-10-15T14:43:40.410Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.410Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/modules/auth/services/supabase-session-storage.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:

  • package.json
🧬 Code graph analysis (5)
packages/tm-core/src/modules/workflow/workflow-domain.ts (1)
packages/tm-core/src/modules/workflow/services/workflow.service.ts (1)
  • WorkflowService (77-494)
packages/tm-core/src/modules/tasks/tasks-domain.ts (4)
packages/tm-core/src/modules/tasks/services/task-service.ts (1)
  • TaskService (51-565)
packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1)
  • TaskExecutionService (42-308)
packages/tm-core/src/modules/tasks/services/task-loader.service.ts (2)
  • TaskLoaderService (59-401)
  • TaskValidationResult (27-40)
packages/tm-core/src/modules/tasks/services/preflight-checker.service.ts (1)
  • PreflightChecker (61-395)
packages/tm-core/src/tm-core.ts (5)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (32-184)
packages/tm-core/src/modules/auth/auth-domain.ts (1)
  • AuthDomain (17-127)
packages/tm-core/src/modules/workflow/workflow-domain.ts (1)
  • WorkflowDomain (18-98)
packages/tm-core/src/modules/git/git-domain.ts (1)
  • GitDomain (14-238)
packages/tm-core/src/modules/config/config-domain.ts (1)
  • ConfigDomain (12-113)
packages/tm-core/src/modules/git/git-domain.ts (1)
packages/tm-core/src/modules/git/services/commit-message-generator.ts (1)
  • CommitMessageGenerator (53-205)
packages/tm-core/src/modules/config/config-domain.ts (1)
packages/tm-core/src/common/interfaces/configuration.interface.ts (1)
  • RuntimeStorageConfig (104-119)

Comment on lines +11 to +17
} from '../../../common/types/index.js';
import type { IStorage } from '../../../common/interfaces/storage.interface.js';
import { ConfigManager } from '../../config/managers/config-manager.js';
import { StorageFactory } from '../../storage/services/storage-factory.js';
import { TaskEntity } from '../entities/task.entity.js';
import { ERROR_CODES, TaskMasterError } from '../errors/task-master-error.js';
import { getLogger } from '../logger/factory.js';
import { ERROR_CODES, TaskMasterError } from '../../../common/errors/task-master-error.js';
import { getLogger } from '../../../common/logger/factory.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the logger import path consistency.

Most of the import path updates follow the correct pattern for the centralized common module structure. However, line 17 imports logger from '../../../common/logger/factory.js' while other files in this refactor consistently use '../../../common/logger/index.js'.

Please verify whether factory.js is the correct import or if this should be index.js for consistency.


🏁 Script executed:

#!/bin/bash
# Check which logger export is used across the codebase
echo "=== Logger imports using factory.js ==="
rg -n "from ['\"].*logger/factory\.js['\"]" -g '*.ts' -g '*.js'

echo -e "\n=== Logger imports using index.js ==="
rg -n "from ['\"].*logger/index\.js['\"]" -g '*.ts' -g '*.js'

echo -e "\n=== Check logger module exports ==="
fd -t f "factory.js|index.js" packages/tm-core/src/common/logger/ --exec cat {}

Length of output: 2646


Comment on lines 73 to 80
if (!options.projectPath) {
throw new TaskMasterError(
'Project path is required',
ERROR_CODES.MISSING_CONFIGURATION
);
}

this._projectPath = options.projectPath;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Validate/normalize projectPath.

Comment says “Absolute path”, but only a truthy check is enforced. Validate with path.isAbsolute() and normalize with path.resolve(). Emit a precise error (e.g., INVALID_ARGUMENT) including the received value.

Proposed snippet:

+ import path from 'node:path';
...
- if (!options.projectPath) {
+ if (!options.projectPath) {
    throw new TaskMasterError(
      'Project path is required',
      ERROR_CODES.MISSING_CONFIGURATION
    );
  }
+ if (!path.isAbsolute(options.projectPath)) {
+   throw new TaskMasterError(
+     'Project path must be absolute',
+     ERROR_CODES.MISSING_CONFIGURATION
+   );
+ }
+ options.projectPath = path.resolve(options.projectPath);
📝 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
if (!options.projectPath) {
throw new TaskMasterError(
'Project path is required',
ERROR_CODES.MISSING_CONFIGURATION
);
}
this._projectPath = options.projectPath;
if (!options.projectPath) {
throw new TaskMasterError(
'Project path is required',
ERROR_CODES.MISSING_CONFIGURATION
);
}
if (!path.isAbsolute(options.projectPath)) {
throw new TaskMasterError(
'Project path must be absolute',
ERROR_CODES.MISSING_CONFIGURATION
);
}
options.projectPath = path.resolve(options.projectPath);
this._projectPath = options.projectPath;
🤖 Prompt for AI Agents
In packages/tm-core/src/tm-core.ts around lines 73 to 80, the code only checks
for a truthy projectPath but should enforce an absolute path and normalize it;
update the validation to use path.isAbsolute(options.projectPath) and if it
fails throw a TaskMasterError with ERROR_CODES.INVALID_ARGUMENT and include the
received value in the message, then set this._projectPath to the normalized
absolute path using path.resolve(options.projectPath); also import Node's path
module if not already imported.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/chore/refactor.tm.core branch from a02aa7a to 4131976 Compare October 21, 2025 11:31
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: 0

Caution

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

⚠️ Outside diff range comments (8)
packages/tm-core/src/modules/storage/adapters/api-storage.ts (2)

69-73: Type safety bypassed with unknown cast for incomplete implementation.

The cast as unknown as TaskRepository circumvents TypeScript's type checking for an incomplete implementation. This could lead to runtime exceptions if unimplemented methods are called.

Consider one of these approaches:

  1. Complete the SupabaseTaskRepository implementation to fully satisfy TaskRepository
  2. Create a typed subset interface that SupabaseTaskRepository can safely implement
  3. Add runtime guards that throw descriptive errors for unimplemented methods

Do you want me to open a tracking issue for completing the SupabaseTaskRepository implementation?


687-708: Backup method returns identifier without creating actual backup.

The method fetches tasks and tags but doesn't store them, returning only a formatted string. Callers might assume a backup was created.

Consider adding a console warning or updating the return type to signal incomplete implementation:

 async backup(): Promise<string> {
   await this.ensureInitialized();
   
   try {
+    console.warn('ApiStorage.backup() is not fully implemented - no data is being stored');
+    
     // Export all data
     await this.repository.getTasks(this.projectId);
     await this.repository.getTags(this.projectId);
packages/tm-core/src/task-master-core.ts (1)

384-390: Add storage cleanup to the close() method - missing taskService.close() call.

The close() method only stops the ExecutorService but omits cleanup of TaskService's storage connection. TaskService initializes storage (file or API) in its initialize() method, and both storage adapters implement close() methods:

  • FileStorage.close() calls fileOps.cleanup() to release pending file locks
  • ApiStorage.close() resets state and clears cache

Without calling await this.taskService.close() (or directly await this.taskService.storage.close()), storage resources are never released. The comment "TaskService handles storage cleanup internally" is inaccurate—TaskService has no close method.

async close(): Promise<void> {
	// Stop any running executors
	if (this.executorService) {
		await this.executorService.stopCurrentTask();
	}
	// Close storage connections
	await this.taskService.close();
}

Alternatively, add a close() method to TaskService that delegates to storage:

async close(): Promise<void> {
	if (this.storage) {
		await this.storage.close();
	}
}
packages/tm-core/src/modules/integration/services/export.service.ts (2)

364-371: Add timeout, basic sanitization, and ID encoding for the export API call.

Network call lacks timeout/backoff and doesn’t sanitize base URL or encode briefId. This can hang indefinitely, and malformed base domains (trailing slashes) can 404. Encode IDs and apply a short timeout; consider retries separately.

-      // Use the new bulk import API endpoint
-      const apiUrl = `${apiEndpoint}/ai/api/v1/briefs/${briefId}/tasks`;
+      // Use the new bulk import API endpoint (sanitize base, encode IDs)
+      const base = apiEndpoint.replace(/\/+$/, '');
+      const apiUrl = `${base}/ai/api/v1/briefs/${encodeURIComponent(briefId)}/tasks`;

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

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

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

       // Make API request
-      const response = await fetch(apiUrl, {
+      const controller = new AbortController();
+      const timeout = setTimeout(() => controller.abort(), 30_000);
+      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
       });
+      clearTimeout(timeout);

Optionally add retry/backoff (e.g., 3 attempts with jitter) around fetch for 5xx/429.

Also applies to: 391-405


460-477: Tighten brief ID extraction; current len≥8 fallback yields false positives (e.g., “overview”, “settings”).

Only accept IDs that match known patterns; remove the permissive length checks.

-      if (url) {
-        const qId = url.searchParams.get('id') || url.searchParams.get('briefId');
-        const candidate = (qId || fromParts(url.pathname)) ?? null;
-        if (candidate) {
-          if (this.isLikelyId(candidate) || candidate.length >= 8) {
-            return candidate;
-          }
-        }
-      }
+      if (url) {
+        const qId = url.searchParams.get('id') || url.searchParams.get('briefId');
+        const candidate = (qId || fromParts(url.pathname)) ?? null;
+        if (candidate && this.isLikelyId(candidate)) {
+          return candidate;
+        }
+      }

       // Check if it looks like a path without scheme
       if (raw.includes('/')) {
         const candidate = fromParts(raw);
-        if (candidate && (this.isLikelyId(candidate) || candidate.length >= 8)) {
+        if (candidate && this.isLikelyId(candidate)) {
           return candidate;
         }
       }

       // Return as-is if it looks like an ID
-      if (this.isLikelyId(raw) || raw.length >= 8) {
+      if (this.isLikelyId(raw)) {
         return raw;
       }

Optionally widen slug acceptance but keep strict charset by relaxing the slug regex instead of raw length:

-    const slugRegex = /^[A-Za-z0-9_-]{16,}$/;
+    const slugRegex = /^[A-Za-z0-9_-]{8,}$/;

Also applies to: 481-486, 492-499

packages/tm-core/src/modules/git/adapters/git-adapter.ts (1)

258-261: Fix staged-changes detection; StatusResult.staged isn’t stable across simple-git versions.

Compute staged files from status.files[].index to avoid runtime undefined errors and ensure correctness.

 async hasStagedChanges(): Promise<boolean> {
   const status = await this.git.status();
-  return status.staged.length > 0;
+  return status.files.some((f) => (f.index ?? '').trim() !== '');
 }

 async getStatusSummary(): Promise<{
   isClean: boolean;
   staged: number;
   modified: number;
   deleted: number;
   untracked: number;
   totalChanges: number;
 }> {
   const status = await this.git.status();
-  const staged = status.staged.length;
+  const staged = status.files.filter((f) => (f.index ?? '').trim() !== '').length;
   const modified = status.modified.length;
   const deleted = status.deleted.length;
   const untracked = status.not_added.length;
   const totalChanges = staged + modified + deleted + untracked;

Based on learnings.

Also applies to: 288-311

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

266-276: Add 'completed' to VALID_TASK_STATUSES array

The TaskStatus type from @tm/core includes 'completed', and statusColors has a mapping for it, but VALID_TASK_STATUSES (line 16-24) is missing it. This creates a validation gap where users cannot set tasks to 'completed' status via CLI despite the type supporting it.

Add 'completed' to the VALID_TASK_STATUSES array at line 23 (before the closing bracket).

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

426-439: Fix comparator: Number(id) returns NaN for non‑numeric IDs → unstable sort.

If IDs include strings (e.g., "HAM-123"), the comparator can return NaN, yielding nondeterministic ordering. Use numeric when both numeric; otherwise localeCompare with numeric option.

Apply:

-    // ID (lower first)
-    return Number(a.id) - Number(b.id);
+    // ID (lower first): numeric if both numeric, else natural string compare
+    const aId = String(a.id);
+    const bId = String(b.id);
+    const aNum = Number(aId);
+    const bNum = Number(bId);
+    if (!Number.isNaN(aNum) && !Number.isNaN(bNum)) {
+      return aNum - bNum;
+    }
+    return aId.localeCompare(bId, undefined, { numeric: true });
♻️ Duplicate comments (5)
packages/tm-core/src/tm-core.ts (3)

33-44: Docs: update example to match facade API (authenticateWithOAuth, getModelConfig).

- // Access any domain
- await tmcore.auth.login({ ... });
+ // Access any domain
+ await tmcore.auth.authenticateWithOAuth({ /* ... */ });
...
- const mainModel = tmcore.config.get('models.main');
+ const mainModel = tmcore.config.getModelConfig();

78-87: Validate and normalize projectPath (absolute path required).

+ import path from 'node:path';
...
  private constructor(options: TmCoreOptions) {
    if (!options.projectPath) {
      throw new TaskMasterError(
        'Project path is required',
        ERROR_CODES.MISSING_CONFIGURATION
      );
    }
+   if (!path.isAbsolute(options.projectPath)) {
+     throw new TaskMasterError(
+       'Project path must be absolute',
+       ERROR_CODES.MISSING_CONFIGURATION
+     );
+   }
-   this._projectPath = options.projectPath;
+   this._projectPath = path.resolve(options.projectPath);

47-58: Don’t mutate public readonly fields via (this as any); use private fields + getters.

Replace readonly public fields with private definite-assignment fields and getters; assign directly in initialize() without casts. This preserves type guarantees and avoids hidden init bugs.

Also applies to: 88-97, 103-123

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

22-27: Docs: align example with actual façade methods.

- await tmcore.auth.login({ ... });
+ await tmcore.auth.authenticateWithOAuth({ /* ... */ });
...
- const config = tmcore.config.get('models.main');
+ const mainModel = tmcore.config.getModelConfig();

29-29: Ensure TypeScript preserves .js specifiers (verbatimModuleSyntax).

Since exports/imports use .js specifiers, tsconfig must set verbatimModuleSyntax: true with NodeNext resolution. This was flagged already; just confirming for this entrypoint as well.

#!/bin/bash
# Verify tm-core tsconfig has the required flags
jq '.compilerOptions | {module, moduleResolution, verbatimModuleSyntax}' packages/tm-core/tsconfig.json
🧹 Nitpick comments (27)
CLAUDE.md (1)

36-77: Architecture Guidelines strongly align with PR refactoring objectives.

The new Business Logic Separation guidelines provide clear, prescriptive boundaries that directly support the domain-driven architecture refactor described in the PR. The separation of concerns (all business logic in @tm/core, thin presentation layers in @tm/cli and @tm/mcp) mirrors the unified facade pattern and domain module organization introduced in this PR. The concrete examples (lines 73–76) showing how tmCore.tasks.get(taskId) intelligently handles multiple ID formats make the pattern actionable.

Optional suggestion: Enumerate the domain modules for clarity.

Consider briefly listing the domain modules (auth, config, git, tasks, workflow) established by this refactor to give developers immediate context about what domain facades they should call. Example: "Provides clean facade APIs through domain objects (tasks, auth, workflow, git, config, integration)". This would help junior developers quickly discover the available boundaries.

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

95-98: Consider using optional properties instead of null as any.

The null as any type assertions bypass TypeScript's type safety. While this pattern works with the factory method ensuring initialization, consider making these properties optional (?) instead, which would maintain type safety while still supporting the deferred initialization pattern.

Apply this diff to improve type safety:

 	private constructor() {
 		// Services will be initialized in the initialize() method
-		this.configManager = null as any;
-		this.taskService = null as any;
-		this.taskExecutionService = null as any;
-		this.exportService = null as any;
+		this.configManager = undefined!;
+		this.taskService = undefined!;
+		this.taskExecutionService = undefined!;
+		this.exportService = undefined!;
 	}

Or declare the fields as:

private configManager!: ConfigManager;
private taskService!: TaskService;
// etc.
packages/tm-core/src/modules/config/config-domain.ts (2)

37-39: Add explicit return type annotation for consistency.

The getModelConfig() method lacks an explicit return type annotation. While TypeScript can infer it from the delegated call, adding an explicit return type improves API documentation and catches potential breaking changes.


113-115: Add explicit return type annotation for consistency.

The getConfigSources() method returns any, which bypasses type safety. Consider adding an explicit return type (or at minimum documenting the shape) to improve type safety and API clarity.

packages/tm-core/src/modules/integration/services/export.service.ts (2)

250-257: Replace any[] with a concrete API DTO type for bulk import.

Typed payload improves safety and evolvability.

+type ApiStatus = 'todo' | 'in_progress' | 'done';
+type ApiPriority = 'low' | 'medium' | 'high';
+interface BulkTaskDto {
+  externalId: string;
+  parentExternalId?: string;
+  title: string;
+  description: string;
+  status: ApiStatus;
+  priority: ApiPriority;
+  dependencies: string[];
+  details?: string;
+  testStrategy?: string;
+  complexity?: unknown;
+  metadata?: Record<string, unknown>;
+}

- private transformTasksForBulkImport(tasks: Task[]): any[] {
-   const flatTasks: any[] = [];
+ private transformTasksForBulkImport(tasks: Task[]): BulkTaskDto[] {
+   const flatTasks: BulkTaskDto[] = [];

Also applies to: 308-309


415-423: Avoid console.* in core service; inject and use a logger.

Console noise from services makes headless/SDK use noisy and inconsistent. Prefer a logger abstraction (already present under common/logger).

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

130-136: Type-narrow storageType after guard for stronger typing in the result.

Minor TS polish: narrow after the guard to satisfy Exclude<StorageType, 'auto'> without casts.

-    const storageType =
-      this.tmCore.config.getStorageConfig().type;
-    if (storageType === 'auto') {
+    const { type } = this.tmCore.config.getStorageConfig();
+    if (type === 'auto') {
       throw new Error('Storage type must be resolved before use');
     }
-    const activeTag = options.tag || this.tmCore.config.getActiveTag();
+    const storageType = type; // now inferred as Exclude<..., 'auto'>
+    const activeTag = options.tag || this.tmCore.config.getActiveTag();

Also applies to: 137-143

packages/tm-core/src/modules/git/adapters/git-adapter.ts (2)

121-125: Specify radix in parseInt to avoid edge cases.

Small but safe.

-          ? parseInt(versionResult.patch)
+          ? parseInt(versionResult.patch, 10)
           : versionResult.patch || 0,

507-512: Prefer simple-git’s deleteLocalBranch helper over raw branch -d/-D.

Clearer intent and safer across versions.

-    const deleteOptions = options.force
-      ? ['-D', branchName]
-      : ['-d', branchName];
-    await this.git.branch(deleteOptions);
+    await this.git.deleteLocalBranch(branchName, !!options.force);
packages/tm-core/src/modules/integration/integration-domain.ts (1)

23-31: Expose exportFromBriefInput/validateContext on the facade to remove CLI duplication

CLI re-implements brief parsing and context checks. Make these pass-throughs to centralize logic in ExportService.

Apply this diff:

 export class IntegrationDomain {
   private exportService: ExportService;

   constructor(configManager: ConfigManager) {
     // Get singleton AuthManager instance
     const authManager = AuthManager.getInstance();
     this.exportService = new ExportService(configManager, authManager);
   }

   // ========== Export Operations ==========
 
   /**
    * Export tasks to external systems (e.g., Hamster briefs)
    */
   async exportTasks(options: ExportTasksOptions): Promise<ExportResult> {
     return this.exportService.exportTasks(options);
   }
+
+  /**
+   * Export by accepting a brief ID or URL (resolves org/brief internally)
+   */
+  async exportFromBriefInput(briefInput: string): Promise<ExportResult> {
+    return this.exportService.exportFromBriefInput(briefInput);
+  }
+
+  /**
+   * Validate whether org/brief context is present
+   */
+  async validateContext() {
+    return this.exportService.validateContext();
+  }
 }

This enables CLI to call tmCore.integration without duplicating parsing/validation. Based on learnings.

apps/cli/src/utils/display-helpers.ts (1)

30-39: Coerce 'auto' storage type for display to avoid ambiguous header

When tm-core reports 'auto', pass a concrete type to the header for consistent UX.

Apply this diff:

-  // Display header with computed display info
-  displayHeader({
-    tag: options.tag || 'master',
-    filePath: displayInfo.filePath,
-    storageType: displayInfo.storageType,
-    briefInfo: displayInfo.briefInfo
-  });
+  // Display header with computed display info
+  const { filePath, storageType, briefInfo } = displayInfo;
+  const safeType =
+    (storageType === 'auto' ? options.storageType : storageType) as Exclude<StorageType, 'auto'>;
+  displayHeader({
+    tag: options.tag || 'master',
+    filePath,
+    storageType: safeType,
+    briefInfo
+  });
apps/cli/src/commands/export.command.ts (5)

36-36: Rename to tmCore for consistency

Aligns with other commands and the new facade terminology.

Apply this diff:

-  private taskMasterCore?: TmCore;
+  private tmCore?: TmCore;

Update references accordingly (initializeServices and export call sites).


76-81: Use the same project path option as other commands

Other commands accept -p/--project. Consider adding it here and use it instead of process.cwd() for consistency.


160-167: Delegate URL/ID handling to IntegrationDomain to avoid duplication

Instead of resolving IDs here and then calling exportTasks, call a facade method that accepts the raw input. Pair this with exposing exportFromBriefInput on the facade.

Example change after adding IntegrationDomain.exportFromBriefInput:

- // Use integration domain facade
- const exportResult = await this.taskMasterCore!.integration.exportTasks({
-   orgId,
-   briefId,
-   tag: options?.tag,
-   status: options?.status,
-   excludeSubtasks: options?.excludeSubtasks || false
- });
+ const exportResult = briefOrUrl && !options?.brief
+   ? await this.tmCore!.integration.exportFromBriefInput(briefOrUrl)
+   : await this.tmCore!.integration.exportTasks({
+       orgId,
+       briefId,
+       tag: options?.tag,
+       status: options?.status,
+       excludeSubtasks: options?.excludeSubtasks || false
+     });

Then you can remove resolveBriefInput/extractBriefId/isLikelyId here. Based on learnings.


210-299: Remove duplicated brief parsing and validation logic

extractBriefId/isLikelyId here duplicate logic maintained in core. Prefer a single source of truth (IntegrationDomain/ExportService) to prevent divergence on URL patterns and ID shapes.


53-57: Validate --status against TaskStatus

Currently any string passes through. Validate against the TaskStatus union (and map friendly aliases if needed) to reduce surprises during export.

Would you like a small helper to import TaskStatus and validate/normalize it here?

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

182-186: Remove no-op cleanup block

This finally block does nothing. Either drop it or clear the instance.

Apply this diff:

-    } finally {
-      // Clean up resources
-      if (this.tmCore) {
-      }
-    }
+    }

110-114: Initialize core only once per run (minor)

If this command is chained programmatically, guard against re-creating tmCore repeatedly.

- this.tmCore = await createTmCore({
+ if (!this.tmCore) this.tmCore = await createTmCore({
    projectPath: options.project || process.cwd()
  });
apps/cli/src/commands/start.command.ts (1)

300-303: Avoid accumulating process signal listeners

Use once() so repeated executions don’t stack handlers.

Apply this diff:

-  process.on('SIGINT', cleanup);
-  process.on('SIGTERM', cleanup);
-  process.on('exit', cleanup);
+  process.once('SIGINT', cleanup);
+  process.once('SIGTERM', cleanup);
+  process.once('exit', cleanup);

If this can run multiple times in one process, also consider removing listeners in the 'close'/'error' handlers.

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

92-95: Prefer return over process.exit for CLI validation failures.

Improves testability and programmatic reuse (command runners can decide exit codes).

- if (!this.validateOptions(options)) {
-   process.exit(1);
- }
+ if (!this.validateOptions(options)) {
+   return;
+ }

257-261: Use active tag from core config rather than defaulting to 'master'.

Aligns with show.command.ts and avoids stale default.

- displayCommandHeader(this.tmCore, {
-   tag: tag || 'master',
-   storageType
- });
+ const activeTag = this.tmCore?.config.getActiveTag() || 'master';
+ displayCommandHeader(this.tmCore, {
+   tag: tag ?? activeTag,
+   storageType
+ });

49-55: Import TaskListResult from @tm/core to prevent type drift.

TaskListResult is properly exported from @tm/core and currently has identical shape to the local ListTasksResult (both define storageType: Exclude<StorageType, 'auto'>). Importing from the core package eliminates the need for the unsafe type cast on line 182 and ensures the CLI stays in sync with any future type changes in core.

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

183-191: Fetch multiple tasks in parallel to improve latency.

Large ID lists currently serialize network/disk calls.

- for (const taskId of taskIds) {
-   const result = await this.tmCore.tasks.get(taskId);
-   if (result.task) {
-     tasks.push(result.task);
-   } else {
-     notFound.push(taskId);
-   }
- }
+ const results = await Promise.all(taskIds.map((id) => this.tmCore.tasks.get(id)));
+ results.forEach((r, i) => (r.task ? tasks.push(r.task) : notFound.push(taskIds[i])));

83-96: Avoid hard exits in command flow.

Return early instead of process.exit for better composability and tests.

- if (!this.validateOptions(options)) {
-   process.exit(1);
- }
+ if (!this.validateOptions(options)) {
+   return;
+ }
...
- if (!idArg) {
-   console.error(chalk.red('Error: Please provide a task ID'));
-   process.exit(1);
- }
+ if (!idArg) {
+   console.error(chalk.red('Error: Please provide a task ID'));
+   return;
+ }
packages/tm-core/src/modules/auth/auth-domain.ts (1)

163-182: Keep storageType accurate for API even when context is missing.

Currently falls back to file, which misleads UIs. Return storageType: 'api' with optional briefInfo; only use file when storage is actually file.

- if (storageType === 'api') {
-   const context = this.getContext();
-   if (context?.briefId && context?.briefName) {
-     return {
-       storageType: 'api',
-       briefInfo: {
-         briefId: context.briefId,
-         briefName: context.briefName,
-         orgSlug: context.orgSlug,
-         webAppUrl: this.getWebAppUrl()
-       }
-     };
-   }
- }
-
- // Default to file storage display
- return {
-   storageType: 'file',
-   filePath: path.join('.taskmaster', 'tasks', 'tasks.json')
- };
+ if (storageType === 'api') {
+   const context = this.getContext();
+   return {
+     storageType: 'api',
+     briefInfo: context?.briefId && context?.briefName
+       ? {
+           briefId: context.briefId,
+           briefName: context.briefName,
+           orgSlug: context.orgSlug,
+           webAppUrl: this.getWebAppUrl()
+         }
+       : undefined
+   };
+ }
+ return {
+   storageType: 'file',
+   filePath: path.join(this.configManager.getProjectRoot(), '.taskmaster', 'tasks', 'tasks.json')
+ };
packages/tm-core/src/modules/git/git-domain.ts (1)

164-173: Optionally expose clean/default-branch guards for parity with adapter.

Keeps consumers on the façade only.

   // ========== Commit Operations ==========
+  /**
+   * Ensure working tree is clean before destructive ops.
+   */
+  async ensureCleanWorkingTree(): Promise<void> {
+    return this.gitAdapter.ensureCleanWorkingTree();
+  }
+
+  /**
+   * Ensure we are not on a default branch (main/master/develop).
+   */
+  async ensureNotOnDefaultBranch(): Promise<void> {
+    return this.gitAdapter.ensureNotOnDefaultBranch();
+  }
packages/tm-core/src/index.ts (1)

107-127: Remove ExportService from advanced exports—unused outside tm-core package.

ExportService has no usage across apps/cli, apps/mcp, or other packages. All other advanced exports (AuthManager, WorkflowOrchestrator, WorkflowStateManager, WorkflowService, SubtaskInfo, GitAdapter, CommitMessageGenerator, PreflightChecker, TaskLoaderService) are actively consumed by CLI and MCP as intended. Remove only the unused export.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf2d549 and a02aa7a.

📒 Files selected for processing (37)
  • CLAUDE.md (1 hunks)
  • apps/cli/src/commands/auth.command.ts (1 hunks)
  • apps/cli/src/commands/autopilot.command.ts (4 hunks)
  • apps/cli/src/commands/autopilot/start.command.ts (2 hunks)
  • apps/cli/src/commands/context.command.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (4 hunks)
  • apps/cli/src/commands/list.command.ts (5 hunks)
  • apps/cli/src/commands/next.command.ts (4 hunks)
  • apps/cli/src/commands/set-status.command.ts (5 hunks)
  • apps/cli/src/commands/show.command.ts (7 hunks)
  • apps/cli/src/commands/start.command.ts (8 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • apps/cli/src/ui/components/dashboard.component.ts (1 hunks)
  • apps/cli/src/ui/components/next-task.component.ts (1 hunks)
  • apps/cli/src/ui/components/task-detail.component.ts (1 hunks)
  • apps/cli/src/utils/display-helpers.ts (1 hunks)
  • apps/cli/src/utils/ui.ts (1 hunks)
  • apps/mcp/src/tools/autopilot/start.tool.ts (2 hunks)
  • package.json (1 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/modules/ai/providers/base-provider.ts (2 hunks)
  • packages/tm-core/src/modules/auth/auth-domain.ts (1 hunks)
  • packages/tm-core/src/modules/auth/index.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/organization.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/config-domain.ts (1 hunks)
  • packages/tm-core/src/modules/git/adapters/git-adapter.ts (2 hunks)
  • packages/tm-core/src/modules/git/git-domain.ts (1 hunks)
  • packages/tm-core/src/modules/integration/integration-domain.ts (1 hunks)
  • packages/tm-core/src/modules/integration/services/export.service.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/api-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/services/storage-factory.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/tasks-domain.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts (2 hunks)
  • packages/tm-core/src/modules/workflow/services/workflow-activity-logger.ts (1 hunks)
  • packages/tm-core/src/task-master-core.ts (2 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/tm-core/src/modules/storage/services/storage-factory.ts
  • packages/tm-core/src/modules/ai/providers/base-provider.ts
  • packages/tm-core/src/modules/auth/services/organization.service.ts
  • packages/tm-core/src/modules/auth/index.ts
  • package.json
  • packages/tm-core/src/modules/tasks/tasks-domain.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

Reference documentation at https://docs.task-master.dev rather than local file paths in content

Files:

  • CLAUDE.md
🧠 Learnings (18)
📚 Learning: 2025-07-18T17:16:32.622Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-07-18T17:16:32.622Z
Learning: Applies to scripts/modules/ui.js : Use chalk.blue for informational messages, chalk.green for success, chalk.yellow for warnings, chalk.red for errors, chalk.cyan for prompts/highlights, and chalk.magenta for subtask information

Applied to files:

  • apps/cli/src/ui/components/dashboard.component.ts
  • apps/cli/src/ui/components/next-task.component.ts
  • apps/cli/src/utils/ui.ts
📚 Learning: 2025-07-18T17:09:16.839Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-07-18T17:09:16.839Z
Learning: Display token breakdowns using a detailed, sectioned format, showing tokens per task, file, and prompt, and use formatting utilities like `boxen` and `chalk` for CLI output.

Applied to files:

  • apps/cli/src/ui/components/dashboard.component.ts
  • apps/cli/src/ui/components/next-task.component.ts
  • apps/cli/src/utils/ui.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:

  • apps/cli/src/index.ts
  • apps/cli/src/commands/export.command.ts
  • apps/cli/src/commands/list.command.ts
  • packages/tm-core/src/tm-core.ts
  • apps/cli/src/utils/ui.ts
  • packages/tm-core/src/index.ts
  • packages/tm-core/src/task-master-core.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:

  • apps/cli/src/index.ts
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.

Applied to files:

  • apps/cli/src/commands/export.command.ts
  • packages/tm-core/src/index.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 : 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:

  • apps/cli/src/commands/autopilot/start.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:

  • apps/cli/src/commands/autopilot/start.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 : Use AI to generate detailed subtasks within the current tag context, considering complexity analysis for subtask counts and ensuring proper IDs for newly created subtasks.

Applied to files:

  • apps/cli/src/commands/autopilot/start.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 : The default tag 'master' must be used for all existing and new tasks unless otherwise specified.

Applied to files:

  • apps/cli/src/commands/autopilot/start.command.ts
📚 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:

  • apps/cli/src/commands/autopilot/start.command.ts
📚 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: Use task-master next to select the next actionable task with all dependencies satisfied

Applied to files:

  • apps/cli/src/commands/next.command.ts
  • apps/cli/src/commands/start.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 : 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:

  • apps/cli/src/commands/set-status.command.ts
  • apps/mcp/src/tools/autopilot/start.tool.ts
📚 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 mcp-server/src/tools/utils.js : Use `normalizeProjectRoot(rawPath, log)`, `getRawProjectRootFromSession(session, log)`, and `withNormalizedProjectRoot(executeFn)` in `mcp-server/src/tools/utils.js` to ensure project root paths are normalized for MCP tools.

Applied to files:

  • packages/tm-core/src/tm-core.ts
📚 Learning: 2025-07-18T17:09:13.815Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/context_gathering.mdc:0-0
Timestamp: 2025-07-18T17:09:13.815Z
Learning: Display token breakdowns in CLI output using a detailed, sectioned format, including tasks, files, and prompt tokens, with clear formatting (e.g., using boxen and chalk).

Applied to files:

  • apps/cli/src/utils/ui.ts
📚 Learning: 2025-07-18T17:16:32.622Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ui.mdc:0-0
Timestamp: 2025-07-18T17:16:32.622Z
Learning: Applies to scripts/modules/ui.js : Use getStatusWithColor for status display, formatDependenciesWithStatus for dependency lists, and truncate for overflowing text

Applied to files:

  • apps/cli/src/utils/ui.ts
📚 Learning: 2025-07-18T17:10:53.657Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-07-18T17:10:53.657Z
Learning: Describes the high-level architecture of the Task Master CLI application, including the new tagged task lists system (architecture.mdc).

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-07-18T17:11:36.732Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-07-18T17:11:36.732Z
Learning: Applies to mcp-server/src/tools/*.js : All MCP tool execute methods that require access to the project root MUST be wrapped with the withNormalizedProjectRoot Higher-Order Function (HOF) from mcp-server/src/tools/utils.js.

Applied to files:

  • apps/mcp/src/tools/autopilot/start.tool.ts
📚 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 mcp-server/src/tools/*.js : MCP server tools in mcp-server/src/tools/*.js must have their execute methods wrapped with the withNormalizedProjectRoot higher-order function from tools/utils.js to ensure consistent path handling.

Applied to files:

  • apps/mcp/src/tools/autopilot/start.tool.ts
🧬 Code graph analysis (16)
packages/tm-core/src/modules/config/config-domain.ts (1)
packages/tm-core/src/common/interfaces/configuration.interface.ts (1)
  • RuntimeStorageConfig (104-119)
apps/cli/src/commands/export.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/autopilot.command.ts (2)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/autopilot/start.command.ts (2)
packages/tm-core/src/index.ts (1)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (1)
  • createTmCore (150-152)
apps/cli/src/commands/next.command.ts (2)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/list.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/set-status.command.ts (3)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
packages/tm-core/src/modules/integration/integration-domain.ts (1)
packages/tm-core/src/modules/integration/services/export.service.ts (3)
  • ExportService (89-500)
  • ExportTasksOptions (42-53)
  • ExportResult (58-74)
packages/tm-core/src/modules/auth/auth-domain.ts (2)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
packages/tm-core/src/modules/auth/services/organization.service.ts (3)
  • Organization (17-21)
  • Brief (26-39)
  • RemoteTask (44-60)
apps/cli/src/commands/start.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/show.command.ts (2)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
packages/tm-core/src/modules/git/git-domain.ts (2)
packages/tm-core/src/index.ts (3)
  • GitAdapter (119-119)
  • CommitMessageGenerator (120-120)
  • CommitMessageOptions (91-91)
packages/tm-core/src/modules/git/adapters/git-adapter.ts (1)
  • GitAdapter (15-780)
packages/tm-core/src/tm-core.ts (6)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (29-210)
packages/tm-core/src/modules/auth/auth-domain.ts (1)
  • AuthDomain (38-215)
packages/tm-core/src/modules/workflow/workflow-domain.ts (1)
  • WorkflowDomain (18-98)
packages/tm-core/src/modules/git/git-domain.ts (1)
  • GitDomain (14-247)
packages/tm-core/src/modules/config/config-domain.ts (1)
  • ConfigDomain (15-116)
packages/tm-core/src/modules/integration/integration-domain.ts (1)
  • IntegrationDomain (14-31)
apps/cli/src/utils/display-helpers.ts (3)
packages/tm-core/src/tm-core.ts (1)
  • TmCore (46-141)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
apps/cli/src/ui/components/header.component.ts (1)
  • displayHeader (32-81)
packages/tm-core/src/index.ts (1)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (29-210)
apps/mcp/src/tools/autopilot/start.tool.ts (2)
packages/tm-core/src/index.ts (1)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (1)
  • createTmCore (150-152)
🔇 Additional comments (25)
CLAUDE.md (2)

78-82: Documentation URL reference complies with coding guidelines.

Line 81 correctly references https://docs.task-master.dev instead of local file paths, adhering to the guideline that .md/.mdx files must reference external documentation. This supports maintainability by centralizing documentation authority.


83-86: Changeset Guidelines are practical and user-focused.

The guidance to emphasize user-facing changes over code specifics is a sensible standard for changesets and will improve the quality of user-facing release notes.

packages/tm-core/src/modules/workflow/services/workflow-activity-logger.ts (1)

8-14: All import paths verified and resolve correctly.

The refactored imports all point to existing files in their new locations following the domain-driven architecture reorganization. The .js extensions in the import statements are properly handled by TypeScript's module resolution system, and the type-only imports are correctly marked.

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

5-19: Import paths verified and correctly resolved.

All import paths have been verified to resolve correctly:

  • ../../../../common/types/index.ts
  • ../../../../common/interfaces/storage.interface.ts
  • ../../../reports/managers/complexity-report-manager.ts

The relative path navigation is correct, and the changes align with the PR's domain-driven architecture refactoring. No issues found.

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

6-25: All import paths verified—reorganization is correct.

Import path verification confirmed:

  • ✓ All 6 source files exist
  • ✓ All 16 imported symbols are properly exported from their sources
  • ✓ Import structure aligns with domain-driven architecture

No issues identified.

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

5-63: LGTM! Clean import restructuring for domain-driven architecture.

The import paths have been properly updated to reflect the new module organization, and the type re-exports provide a clean public API surface. The consistent use of .js extensions ensures ESM compatibility.


146-152: Good backward compatibility approach.

The deprecated method properly redirects to the new implementation, maintaining compatibility while guiding users toward the new API.


181-191: Excellent backward compatibility handling.

Removing storageType from the return value while maintaining it internally is a clean way to preserve the existing API contract while the internal implementation evolves.


396-399: LGTM! Clean factory function.

The factory function provides a clean public API entry point as intended by the refactor, properly delegating to the static create method.


130-131: Singleton pattern is consistent with domain-driven design in this codebase.

The code already practices dependency injection. AuthManager.getInstance() is a boundary accessor pattern used consistently across the codebase, and the authManager instance is explicitly passed as a dependency to ExportService (which accepts it as a constructor parameter at line 93 of export.service.ts). This same pattern is followed in integration-domain.ts and auth-domain.ts. The singleton serves as a controlled entry point for a cross-cutting concern while actual services remain dependency-injectable. No changes needed.

apps/cli/src/ui/components/next-task.component.ts (1)

8-8: LGTM!

Import path updated to align with the new centralized public API surface. The change is mechanical and maintains type safety.

apps/cli/src/ui/components/dashboard.component.ts (1)

8-8: LGTM!

Import path updated to align with the new centralized public API surface. The change is mechanical and maintains type safety.

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

11-15: LGTM!

Import path updated to align with the new centralized public API surface. The change consolidates auth-related exports under @tm/core while maintaining all runtime functionality.

apps/cli/src/utils/ui.ts (1)

9-9: LGTM!

Import path updated to align with the new centralized public API surface. The change is mechanical and maintains type safety.

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

11-11: LGTM!

Import path updated to align with the new centralized public API surface. The change consolidates auth-related exports under @tm/core while maintaining all runtime functionality.

apps/cli/src/ui/components/task-detail.component.ts (1)

11-11: LGTM!

Import path updated to align with the new centralized public API surface. The change is mechanical and maintains type safety.

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

44-44: Breaking change confirmed as intentional; verify version strategy and monorepo migration consistency.

The export rename is a deliberate API evolution. The core library's public API (packages/tm-core/src/index.ts) exports only createTmCore, TmCore, type TmCoreOptions, establishing TmCore as the official interface. apps/cli aligns with this by exporting TmCore, and all internal CLI commands are already migrated to use the new API.

However, migration across the monorepo is incomplete: apps/extension still imports the legacy TaskMasterCore. Ensure the version bump reflects this breaking change for external consumers and verify that other packages are updated consistently.

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

106-114: Core init flow LGTM.

Lazy init with resolved project path matches the new facade.

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

70-80: CLI start flow aligns with new TmCore; looks good.

Core init, task fetch, and branch creation via adapter read cleanly.

Also applies to: 95-103, 135-144

apps/mcp/src/tools/autopilot/start.tool.ts (1)

85-96: MCP tool migration to TmCore is correct; wrapper usage is consistent.

Uses withNormalizedProjectRoot, new API surfaces, and strict main-task guard. Good.

Also applies to: 122-131, 142-156

packages/tm-core/src/modules/integration/services/export.service.ts (1)

392-400: The review comment is incorrect—the project explicitly requires Node ≥18.0.0 where fetch is natively available.

The root package.json specifies "node": ">=18.0.0", and Node 18+ includes global fetch by default. The codebase contains no fetch polyfills, confirming the team relies on native availability. The code is correct as-is.

Likely an incorrect or invalid review comment.

packages/tm-core/src/modules/integration/integration-domain.ts (1)

17-21: AuthManager singleton capture can go stale across login/logout

If AuthManager state (token/context) can change after this facade is constructed, capturing the singleton once might drift. Consider resolving the instance per call or subscribing to auth events to refresh internal services.

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

162-168: TmCore initialization pattern looks good

Idempotent factory usage with createTmCore and guarded assignment is clean and consistent with the new facade.

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

148-152: Storage type propagation is correct

Using tmCore.config.getStorageConfig().type keeps the CLI aligned with core config.

packages/tm-core/src/modules/git/git-domain.ts (1)

6-21: GitDomain façade looks consistent and idiomatic.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/chore/refactor.tm.core branch from 4131976 to ba36440 Compare October 21, 2025 11:38
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

Caution

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

⚠️ Outside diff range comments (6)
packages/tm-core/package.json (1)

8-20: Refactor incomplete: missing barrel files break all subpath exports.

The package.json exports point to non-existent barrel files at src/ root level. While implementations have been moved to src/modules/ and src/common/ as part of the domain-driven refactor, the bridge files required to support the export structure were not created. All 11 exports will fail at runtime:

  • Missing src/auth/index.ts, src/storage/index.ts, src/config/index.ts, src/providers/index.ts, src/services/index.ts (should delegate to src/modules/{module}/)
  • Missing src/errors/index.ts, src/logger/index.ts, src/types/index.ts, src/interfaces/index.ts, src/utils/index.ts (should delegate to src/common/{module}/)

The subpath-exports.test.ts test file also expects these barrel files to exist for its relative imports (./auth, ./storage, etc.). Create these barrel files to re-export from their new locations in src/modules/ and src/common/.

apps/extension/src/services/terminal-manager.ts (2)

149-149: Remove or replace the await this.tmCore.close() call — TmCore class has no close() method.

The refactored TmCore class (packages/tm-core/src/tm-core.ts) does not expose a close() method. The call at line 149 of terminal-manager.ts will throw a runtime error. Either add a close() method to TmCore that performs necessary cleanup, or remove this call if no cleanup is required.


52-56: Update API calls to use domain facades on refactored TmCore.

The code makes two incorrect calls on TmCore. The refactored TmCore class (line 46, tm-core.ts) exposes only domain facades (tasks, auth, workflow, git, config, integration) and has no direct startTask or close methods.

  • Line 52: Change this.tmCore!.startTask(taskId, options) to this.tmCore!.tasks.startTask(taskId, options)
  • Line 149: Remove await this.tmCore.close() — no close method exists on TmCore
packages/build-config/CHANGELOG.md (1)

3-10: Remove placeholder "null" version headers from changelog.

These "## null" headers appear to be auto-generated placeholders that should be cleaned up before merging. Changelog entries should either have proper version numbers or be removed entirely if there are no changes to document.

Apply this diff to remove the placeholder headers:

 # @tm/build-config
 
-## null
-
-## null
-
-## null
-
-## null
-
 ## 1.0.1
packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1)

16-20: Fix inconsistent mock paths - must match actual import paths.

The mock paths use './services/*' but the actual imports (lines 9-13) use '../services/*'. Vitest requires mock paths to exactly match the import paths being mocked.

Apply this fix:

 // Mock all services
-vi.mock('./services/config-loader.service.js');
-vi.mock('./services/config-merger.service.js');
-vi.mock('./services/runtime-state-manager.service.js');
-vi.mock('./services/config-persistence.service.js');
-vi.mock('./services/environment-config-provider.service.js');
+vi.mock('../services/config-loader.service.js');
+vi.mock('../services/config-merger.service.js');
+vi.mock('../services/runtime-state-manager.service.js');
+vi.mock('../services/config-persistence.service.js');
+vi.mock('../services/environment-config-provider.service.js');
packages/tm-core/src/modules/storage/adapters/api-storage.ts (1)

69-74: Unsafe cast of SupabaseTaskRepository → TaskRepository will cause runtime failures when missing methods are called.

Verification confirms SupabaseTaskRepository implements only 3 of 13 required methods (getTasks, getTask, updateTask). ApiStorage actively calls missing methods including createTask, deleteTask, getTag, createTag, updateTag, and bulkCreateTasks—each will fail at runtime.

Apply this fail-fast capability check:

 constructor(config: ApiStorageConfig) {
   this.validateConfig(config);
   // Use provided repository or create Supabase repository
   if (config.repository) {
     this.repository = config.repository;
   } else if (config.supabaseClient) {
-    // TODO: SupabaseTaskRepository doesn't implement all TaskRepository methods yet
-    // Cast for now until full implementation is complete
-    this.repository = new SupabaseTaskRepository(
-      config.supabaseClient
-    ) as unknown as TaskRepository;
+    const repo = new SupabaseTaskRepository(config.supabaseClient) as any;
+    this.assertRepositoryCapabilities(repo);
+    this.repository = repo as TaskRepository;
   } else {
     throw new TaskMasterError(
       'Either repository or supabaseClient must be provided',
       ERROR_CODES.MISSING_CONFIGURATION
     );
   }

Add helper at the class:

private assertRepositoryCapabilities(repo: any): void {
  const required = [
    'getTasks','getTask','createTask','updateTask','deleteTask','bulkCreateTasks',
    'getTags','getTag','createTag','updateTag','deleteTag','bulkUpdateTasks','bulkDeleteTasks'
  ];
  const missing = required.filter((m) => typeof repo[m] !== 'function');
  if (missing.length) {
    throw new TaskMasterError(
      `SupabaseTaskRepository missing methods: ${missing.join(', ')}`,
      ERROR_CODES.NOT_IMPLEMENTED,
      { component: 'ApiStorage' }
    );
  }
}
♻️ Duplicate comments (4)
packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts (1)

76-76: Import path reverted to unnecessarily complex traversal.

The import on line 76 uses '../managers/auth-manager.js', which goes up one directory level then back into managers/. Since both the test file and the source file are in the same managers/ directory, this should use a simple relative import './auth-manager.js' for clarity and consistency with other same-directory imports in this file (see lines 21 and 46).

The AI summary indicates this path was changed FROM the correct ./auth-manager.js TO the current path, which appears to be a regression.

Apply this diff:

-import { AuthManager } from '../managers/auth-manager.js';
+import { AuthManager } from './auth-manager.js';
packages/tm-core/src/modules/tasks/services/task-service.ts (1)

17-17: Logger import path inconsistency (previously flagged).

This import uses factory.js while the codebase standard is to use index.js for logger imports. This inconsistency has been previously identified and thoroughly analyzed in past review comments.

packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1)

7-7: Fix incorrect import path for ConfigManager.

The test file is located at packages/tm-core/src/modules/config/managers/config-manager.spec.ts, which is already inside the managers/ directory. The import path './managers/config-manager.js' would incorrectly resolve to managers/managers/config-manager.js.

Apply this fix:

-import { ConfigManager } from './managers/config-manager.js';
+import { ConfigManager } from './config-manager.js';
apps/cli/src/commands/export.command.ts (1)

108-113: Note: async getContext usage differs from ApiStorage.

Here await authManager.getContext() is used; in ApiStorage it’s synchronous. Please resolve the inconsistency per earlier comment.

🧹 Nitpick comments (13)
packages/tm-core/src/modules/ui/index.ts (1)

1-8: Placeholder module looks good as scaffolding.

This placeholder appropriately sets up the structure for the future UI domain migration. The TODO comment clearly indicates the migration source.

Would you like me to help create a tracking issue for the UI migration work from scripts/modules/ui.js? I can generate an issue template with migration steps and acceptance criteria.

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

1-8: Track the TODO with an issue.

This placeholder file establishes the intended structure for the Commands domain migration. Consider creating a tracking issue for the TODO and referencing it in the comment to ensure the migration work isn't forgotten.

Based on learnings, the source file scripts/modules/commands.js should export a registerCommands function and contain user-facing commands. Would you like me to:

  1. Open an issue to track this migration task?
  2. Generate a script to examine the current structure of scripts/modules/commands.js to help plan the migration?

Apply this diff to reference a tracking issue once created:

-// TODO: Migrate commands.js from scripts/modules/
+// TODO: Migrate commands.js from scripts/modules/ (tracked in #ISSUE_NUMBER)
 // export * from './handlers/command-handler.js';
packages/tm-core/src/modules/execution/executors/claude-executor.ts (1)

12-12: Simplify the import path for better clarity.

The import path ../executors/base-executor.js works but is unnecessarily complex. Since both claude-executor.ts and base-executor.ts are in the same executors/ folder, this should use a relative import from the same directory.

Apply this diff to simplify:

-import { BaseExecutor } from '../executors/base-executor.js';
+import { BaseExecutor } from './base-executor.js';
packages/tm-core/src/modules/execution/executors/executor-factory.ts (1)

6-6: Now let me verify the actual imports in the file to see if there are other concerns:

Based on my verification, you shouldn't go back a folder from the same original folder (ex. being in a file in the validation folder and doing import {XyService} from "../validation";). The import path in question follows exactly this antipattern. While the file resolves correctly, this pattern can lead to errors of imports not being defined.

Fix the redundant import path in executor-factory.ts, line 6.

Change:

import { ClaudeExecutor } from '../executors/claude-executor.js';

To:

import { ClaudeExecutor } from './claude-executor.js';

Best practice is to use relative imports when importing from the same folder. Since both executor-factory.ts and claude-executor.ts are in the same executors/ directory, the direct relative import is appropriate.

packages/tm-core/src/modules/tasks/tasks-domain.ts (2)

63-89: Consider returning the subtask object for better ergonomics.

The method finds the subtask (line 80-82) but only returns isSubtask: !!subtask without the actual subtask. Callers must re-parse the ID and search again.

Consider enhancing the return type:

 async get(
   taskId: string,
   tag?: string
-): Promise<{ task: Task | null; isSubtask: boolean }> {
+): Promise<{ task: Task | null; isSubtask: boolean; subtask?: any }> {
   // Parse ID - check for dot notation (subtask)
   const parts = taskId.split('.');
   const parentId = parts[0];
   const subtaskIdPart = parts[1];

   // Fetch the task
   const task = await this.taskService.getTask(parentId, tag);
   if (!task) {
     return { task: null, isSubtask: false };
   }

   // Handle subtask notation (1.2, HAM-123.2)
   if (subtaskIdPart && task.subtasks) {
     const subtask = task.subtasks.find(
       (st) => String(st.id) === subtaskIdPart
     );
     // Return parent task with isSubtask flag
-    return { task, isSubtask: !!subtask };
+    return { task, isSubtask: !!subtask, subtask };
   }

   // It's a regular task
   return { task, isSubtask: false };
 }

108-110: Consider clarifying method names to reduce confusion.

Both getNext() (line 108) and getNextAvailable() (line 147) appear to retrieve the next task, but:

  • getNext() returns Task | null
  • getNextAvailable() returns string | null (just the ID)

The similar names may confuse callers about which method to use.

Consider renaming for clarity:

-async getNext(tag?: string): Promise<Task | null> {
+async getNextTask(tag?: string): Promise<Task | null> {
   return this.taskService.getNextTask(tag);
 }

-async getNextAvailable(): Promise<string | null> {
+async getNextAvailableTaskId(): Promise<string | null> {
   return this.executionService.getNextAvailableTask();
 }

Also applies to: 147-149

packages/tm-core/src/modules/storage/adapters/api-storage.ts (6)

171-176: Brief scoping isn’t pushed to repository; potential cross-brief leakage.

getTasks(this.projectId, options) ignores the selected brief. Pass briefId (or equivalent) so the repo filters server-side.

- const tasks = await this.retryOperation(() =>
-   this.repository.getTasks(this.projectId, options)
- );
+ const tasks = await this.retryOperation(() =>
+   this.repository.getTasks(this.projectId, { ...(options || {}), briefId: context.briefId } as any)
+ );

Confirm LoadTasksOptions (and repository) accept a briefId filter; otherwise add it to the interface.


594-613: renameTag is non-atomic and may orphan references.

Creating new, then deleting old without migrating task references risks inconsistency. Prefer a repository-level atomic rename or a transactional op that updates tag references.

Does the backend offer a single renameTag(projectId, oldTag, newTag)? If not, implement migration of all affected tasks between steps or wrap in a transaction (where supported).


626-641: copyTag may duplicate tasks without dedup semantics.

Cloning tag metadata/tasks naïvely can lead to duplicates if tasks are keyed by tag. Ensure backend semantics are defined (deep copy vs reference) and guard against conflicts.

Document expected behavior and add idempotency (e.g., upsert with conflict handling).


802-816: Retry policy: add jitter and selective retry.

Current exponential backoff lacks jitter and retries all errors. Add jitter and retry only on transient errors (5xx, network).

- const delay = Math.pow(2, attempt) * 1000;
- await new Promise((resolve) => setTimeout(resolve, delay));
+ const base = Math.pow(2, attempt) * 1000;
+ const jitter = Math.random() * 250;
+ await new Promise((r) => setTimeout(r, base + jitter));

Consider classifying errors (e.g., by HTTP status on known repo errors) to avoid retrying 4xx.


258-273: Consider upsert to avoid read-before-write.

You fetch existing then branch create/update. If the backend supports upsert, prefer it to reduce round trips and races.


654-674: getStats can be heavy; prefer backend aggregation.

Pulling all tasks/tags to compute counts doesn’t scale. Provide a repository.getStats(projectId) that returns pre-aggregated stats.

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

41-44: Barrel export is correctly implemented; direct manager imports are widespread but functional.

The review concern is valid. The barrel correctly re-exports ConfigManager and DEFAULT_CONFIG_VALUES, but within packages/tm-core/src, multiple files bypass the barrel and import directly from the manager (e.g., task-master-core.ts, tm-core.ts, task-service.ts, task-loader.service.ts, export.service.ts, and domain files). This won't cause breakage since the manager remains at the same path, but it's inconsistent with the barrel pattern.

The re-exports themselves are correct and won't cause issues. Existing code will continue to work.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a02aa7a and ba36440.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (113)
  • .changeset/dirty-hairs-know.md (0 hunks)
  • .changeset/fix-parent-directory-traversal.md (0 hunks)
  • .changeset/kind-lines-melt.md (0 hunks)
  • .changeset/light-owls-stay.md (0 hunks)
  • .changeset/metal-rocks-help.md (0 hunks)
  • .changeset/open-tips-notice.md (0 hunks)
  • .changeset/pre.json (0 hunks)
  • .changeset/some-dodos-wonder.md (0 hunks)
  • CHANGELOG.md (1 hunks)
  • CLAUDE.md (1 hunks)
  • apps/cli/CHANGELOG.md (1 hunks)
  • apps/cli/package.json (1 hunks)
  • apps/cli/src/commands/auth.command.ts (1 hunks)
  • apps/cli/src/commands/autopilot.command.ts (4 hunks)
  • apps/cli/src/commands/autopilot/start.command.ts (2 hunks)
  • apps/cli/src/commands/context.command.ts (1 hunks)
  • apps/cli/src/commands/export.command.ts (4 hunks)
  • apps/cli/src/commands/list.command.ts (5 hunks)
  • apps/cli/src/commands/next.command.ts (4 hunks)
  • apps/cli/src/commands/set-status.command.ts (5 hunks)
  • apps/cli/src/commands/show.command.ts (7 hunks)
  • apps/cli/src/commands/start.command.ts (8 hunks)
  • apps/cli/src/index.ts (1 hunks)
  • apps/cli/src/ui/components/dashboard.component.ts (1 hunks)
  • apps/cli/src/ui/components/next-task.component.ts (1 hunks)
  • apps/cli/src/ui/components/task-detail.component.ts (1 hunks)
  • apps/cli/src/utils/display-helpers.ts (1 hunks)
  • apps/cli/src/utils/ui.ts (1 hunks)
  • apps/docs/CHANGELOG.md (1 hunks)
  • apps/docs/package.json (1 hunks)
  • apps/extension/package.json (1 hunks)
  • apps/extension/src/services/terminal-manager.ts (3 hunks)
  • apps/mcp/CHANGELOG.md (1 hunks)
  • apps/mcp/package.json (0 hunks)
  • apps/mcp/src/tools/autopilot/start.tool.ts (2 hunks)
  • package.json (2 hunks)
  • packages/ai-sdk-provider-grok-cli/CHANGELOG.md (1 hunks)
  • packages/ai-sdk-provider-grok-cli/package.json (1 hunks)
  • packages/build-config/CHANGELOG.md (1 hunks)
  • packages/build-config/package.json (1 hunks)
  • packages/claude-code-plugin/CHANGELOG.md (1 hunks)
  • packages/tm-core/CHANGELOG.md (1 hunks)
  • packages/tm-core/package.json (1 hunks)
  • packages/tm-core/src/auth/index.ts (0 hunks)
  • packages/tm-core/src/common/interfaces/index.ts (1 hunks)
  • packages/tm-core/src/executors/index.ts (0 hunks)
  • packages/tm-core/src/index.ts (1 hunks)
  • packages/tm-core/src/modules/ai/index.ts (1 hunks)
  • packages/tm-core/src/modules/ai/providers/base-provider.ts (2 hunks)
  • packages/tm-core/src/modules/auth/auth-domain.ts (1 hunks)
  • packages/tm-core/src/modules/auth/index.ts (1 hunks)
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/auth/managers/auth-manager.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/credential-store.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/oauth-service.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/organization.service.ts (1 hunks)
  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (1 hunks)
  • packages/tm-core/src/modules/commands/index.ts (1 hunks)
  • packages/tm-core/src/modules/config/config-domain.ts (1 hunks)
  • packages/tm-core/src/modules/config/index.ts (2 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-loader.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-merger.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/config-persistence.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/environment-config-provider.service.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts (1 hunks)
  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.ts (1 hunks)
  • packages/tm-core/src/modules/dependencies/index.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/base-executor.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/claude-executor.ts (1 hunks)
  • packages/tm-core/src/modules/execution/executors/executor-factory.ts (1 hunks)
  • packages/tm-core/src/modules/execution/index.ts (1 hunks)
  • packages/tm-core/src/modules/execution/services/executor-service.ts (1 hunks)
  • packages/tm-core/src/modules/execution/types.ts (1 hunks)
  • packages/tm-core/src/modules/git/adapters/git-adapter.ts (2 hunks)
  • packages/tm-core/src/modules/git/git-domain.ts (1 hunks)
  • packages/tm-core/src/modules/git/index.ts (1 hunks)
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts (1 hunks)
  • packages/tm-core/src/modules/integration/clients/supabase-client.ts (1 hunks)
  • packages/tm-core/src/modules/integration/integration-domain.ts (1 hunks)
  • packages/tm-core/src/modules/integration/services/export.service.ts (1 hunks)
  • packages/tm-core/src/modules/reports/index.ts (1 hunks)
  • packages/tm-core/src/modules/reports/managers/complexity-report-manager.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/api-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/format-handler.ts (1 hunks)
  • packages/tm-core/src/modules/storage/index.ts (2 hunks)
  • packages/tm-core/src/modules/storage/services/storage-factory.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/entities/task.entity.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/parser/index.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/dependency-fetcher.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/task-repository.interface.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/preflight-checker.service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/services/task-service.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/tasks-domain.ts (1 hunks)
  • packages/tm-core/src/modules/ui/index.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts (2 hunks)
  • packages/tm-core/src/modules/workflow/services/workflow-activity-logger.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/services/workflow.service.ts (1 hunks)
  • packages/tm-core/src/modules/workflow/workflow-domain.ts (1 hunks)
  • packages/tm-core/src/services/index.ts (0 hunks)
  • packages/tm-core/src/task-master-core.ts (2 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
  • update-task-migration-plan.md (1 hunks)
💤 Files with no reviewable changes (12)
  • .changeset/dirty-hairs-know.md
  • .changeset/some-dodos-wonder.md
  • .changeset/open-tips-notice.md
  • .changeset/light-owls-stay.md
  • packages/tm-core/src/auth/index.ts
  • packages/tm-core/src/services/index.ts
  • packages/tm-core/src/executors/index.ts
  • apps/mcp/package.json
  • .changeset/kind-lines-melt.md
  • .changeset/metal-rocks-help.md
  • .changeset/fix-parent-directory-traversal.md
  • .changeset/pre.json
✅ Files skipped from review due to trivial changes (8)
  • packages/build-config/package.json
  • packages/tm-core/CHANGELOG.md
  • apps/docs/CHANGELOG.md
  • apps/docs/package.json
  • packages/tm-core/src/modules/reports/index.ts
  • packages/tm-core/src/modules/workflow/managers/workflow-state-manager.spec.ts
  • apps/mcp/CHANGELOG.md
  • packages/tm-core/src/modules/git/services/branch-name-generator.spec.ts
🚧 Files skipped from review as they are similar to previous changes (32)
  • packages/tm-core/src/modules/auth/services/credential-store.test.ts
  • apps/cli/src/commands/context.command.ts
  • packages/tm-core/src/modules/storage/adapters/file-storage/format-handler.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.spec.ts
  • packages/tm-core/src/modules/execution/services/executor-service.ts
  • packages/tm-core/src/modules/execution/index.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.test.ts
  • packages/tm-core/src/tm-core.ts
  • apps/cli/src/ui/components/task-detail.component.ts
  • packages/tm-core/src/modules/tasks/entities/task.entity.ts
  • packages/tm-core/src/modules/tasks/parser/index.ts
  • packages/tm-core/src/modules/tasks/repositories/supabase/dependency-fetcher.ts
  • packages/tm-core/src/modules/workflow/orchestrators/workflow-orchestrator.ts
  • packages/tm-core/src/modules/config/services/config-loader.service.ts
  • packages/tm-core/src/modules/git/adapters/git-adapter.ts
  • apps/cli/src/ui/components/next-task.component.ts
  • package.json
  • packages/tm-core/src/modules/workflow/workflow-domain.ts
  • packages/tm-core/src/modules/config/services/config-persistence.service.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.ts
  • packages/tm-core/src/modules/git/index.ts
  • packages/tm-core/src/modules/auth/services/organization.service.ts
  • packages/tm-core/src/modules/config/config-domain.ts
  • apps/cli/src/commands/auth.command.ts
  • packages/tm-core/src/modules/auth/index.ts
  • packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts
  • apps/cli/src/utils/ui.ts
  • apps/cli/src/ui/components/dashboard.component.ts
  • packages/tm-core/src/modules/storage/services/storage-factory.ts
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts
  • packages/tm-core/src/modules/integration/integration-domain.ts
  • packages/tm-core/src/common/interfaces/index.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

Reference documentation at https://docs.task-master.dev rather than local file paths in content

Files:

  • CLAUDE.md
  • update-task-migration-plan.md
  • apps/cli/CHANGELOG.md
  • CHANGELOG.md
  • packages/ai-sdk-provider-grok-cli/CHANGELOG.md
  • packages/build-config/CHANGELOG.md
  • packages/claude-code-plugin/CHANGELOG.md
**/*.{test,spec}.{js,ts,jsx,tsx}

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

**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)

Files:

  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
**/*.{test,spec}.*

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

Test files should follow naming conventions: .test., .spec., or _test. depending on the language

Files:

  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
**/?(*.)+(spec|test).ts

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

In JavaScript/TypeScript projects using Jest, test files should match *.test.ts and *.spec.ts patterns

Files:

  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
{packages/*/src/**/*.spec.ts,apps/*/src/**/*.spec.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Place package and app unit test files alongside source as *.spec.ts under src (packages//src//.spec.ts or apps//src//.spec.ts)

Files:

  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}: Do not use async/await in test functions unless the test is explicitly exercising asynchronous behavior
Use synchronous top-level imports in tests; avoid dynamic await import()
Keep test bodies synchronous whenever possible

Files:

  • packages/tm-core/src/modules/config/services/runtime-state-manager.service.spec.ts
  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
🧠 Learnings (38)
📚 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:

  • apps/cli/src/index.ts
  • apps/extension/package.json
  • packages/tm-core/src/modules/integration/services/export.service.ts
  • packages/tm-core/src/modules/execution/executors/claude-executor.ts
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts
  • packages/tm-core/package.json
  • apps/cli/src/commands/export.command.ts
  • packages/tm-core/src/modules/tasks/services/task-execution-service.ts
  • packages/tm-core/src/task-master-core.ts
  • apps/cli/src/commands/list.command.ts
  • packages/tm-core/src/modules/execution/types.ts
  • packages/tm-core/src/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:

  • apps/cli/src/index.ts
  • apps/extension/package.json
  • packages/tm-core/src/modules/tasks/services/task-execution-service.ts
  • packages/tm-core/src/modules/execution/types.ts
📚 Learning: 2025-07-18T17:10:53.657Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-07-18T17:10:53.657Z
Learning: Describes the high-level architecture of the Task Master CLI application, including the new tagged task lists system (architecture.mdc).

Applied to files:

  • CLAUDE.md
  • update-task-migration-plan.md
📚 Learning: 2025-07-18T17:11:36.732Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-07-18T17:11:36.732Z
Learning: Applies to mcp-server/src/tools/*.js : All MCP tool execute methods that require access to the project root MUST be wrapped with the withNormalizedProjectRoot Higher-Order Function (HOF) from mcp-server/src/tools/utils.js.

Applied to files:

  • apps/mcp/src/tools/autopilot/start.tool.ts
📚 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 mcp-server/src/tools/*.js : MCP server tools in mcp-server/src/tools/*.js must have their execute methods wrapped with the withNormalizedProjectRoot higher-order function from tools/utils.js to ensure consistent path handling.

Applied to files:

  • apps/mcp/src/tools/autopilot/start.tool.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 : 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:

  • apps/mcp/src/tools/autopilot/start.tool.ts
  • apps/cli/src/commands/set-status.command.ts
📚 Learning: 2025-10-15T14:43:40.410Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.410Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/modules/auth/services/supabase-session-storage.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:

  • apps/extension/package.json
📚 Learning: 2025-08-07T13:00:22.966Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1090
File: apps/extension/package.json:241-243
Timestamp: 2025-08-07T13:00:22.966Z
Learning: In monorepos, local packages should use "*" as the version constraint in package.json dependencies, as recommended by npm. This ensures the local version from within the same workspace is always used, rather than attempting to resolve from external registries. This applies to packages like task-master-ai within the eyaltoledano/claude-task-master monorepo.

Applied to files:

  • apps/extension/package.json
📚 Learning: 2025-09-26T19:07:10.485Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1252
File: packages/ai-sdk-provider-grok-cli/package.json:21-35
Timestamp: 2025-09-26T19:07:10.485Z
Learning: In the eyaltoledano/claude-task-master repository, the tsdown build configuration uses `noExternal: [/^tm\//]` which means internal tm/ packages are bundled into the final output while external npm dependencies remain external and are resolved from the root package.json dependencies at runtime. This eliminates the need for peer dependencies in internal packages since the root package.json already provides the required external dependencies.

Applied to files:

  • apps/extension/package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must import the provider's create<ProviderName> function from ai-sdk/<provider-name>, and import generateText, streamText, generateObject from the core ai package, as well as the log utility from ../../scripts/modules/utils.js.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
  • packages/tm-core/src/modules/ai/providers/base-provider.ts
📚 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 src/ai-providers/*.js : Provider-specific wrappers for Vercel AI SDK functions must be implemented in src/ai-providers/*.js, each file corresponding to a provider.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must export three functions: generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Create a new provider module file in src/ai-providers/ named <provider-name>.js when adding a new AI provider.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to tests/unit/ai-providers/*.test.js : Create unit tests for the new provider in tests/unit/ai-providers/<provider-name>.test.js, mocking ai-sdk/<provider-name> and core ai module functions, and testing all exported functions for correct behavior and error handling.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 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/ai-services.js : Features that use AI models belong in 'scripts/modules/ai-services.js'.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/ai-services-unified.js : Integrate the new provider module with scripts/modules/ai-services-unified.js by importing it and adding an entry to the PROVIDER_FUNCTIONS map.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Implement generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object functions in provider modules with basic validation and try/catch error handling.

Applied to files:

  • packages/tm-core/src/modules/ai/index.ts
  • packages/tm-core/src/modules/ai/providers/base-provider.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/commands.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:

  • packages/tm-core/src/modules/ai/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:

  • packages/tm-core/src/modules/integration/services/export.service.ts
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts
  • packages/tm-core/src/modules/tasks/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 : Use consistent formatting for task files, include all task properties in text files, and format dependencies with status indicators.

Applied to files:

  • update-task-migration-plan.md
📚 Learning: 2025-10-20T16:44:58.151Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-20T16:44:58.151Z
Learning: Applies to {packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts} : Use synchronous top-level imports in tests; avoid dynamic await import()

Applied to files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.ts
📚 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: Module dependencies should be mocked before importing the test module, following Jest's hoisting behavior.

Applied to files:

  • packages/tm-core/src/modules/auth/managers/auth-manager.spec.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 : 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:

  • apps/cli/src/commands/autopilot/start.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:

  • apps/cli/src/commands/autopilot/start.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 : Use AI to generate detailed subtasks within the current tag context, considering complexity analysis for subtask counts and ensuring proper IDs for newly created subtasks.

Applied to files:

  • apps/cli/src/commands/autopilot/start.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 : The default tag 'master' must be used for all existing and new tasks unless otherwise specified.

Applied to files:

  • apps/cli/src/commands/autopilot/start.command.ts
📚 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:

  • apps/cli/src/commands/autopilot/start.command.ts
📚 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/commands.js : All new user-facing commands should be added to 'scripts/modules/commands.js'.

Applied to files:

  • packages/tm-core/src/modules/commands/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:

  • packages/tm-core/src/modules/commands/index.ts
📚 Learning: 2025-09-22T19:45:04.337Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1232
File: packages/tm-core/package.json:50-51
Timestamp: 2025-09-22T19:45:04.337Z
Learning: In the eyaltoledano/claude-task-master project, Crunchyman-ralph intentionally omits version fields from internal/private packages in package.json files to prevent changesets from releasing new versions of these packages while still allowing them to be processed for dependency updates. The changesets warnings about missing versions are acceptable as they don't break the process and achieve the desired behavior of only releasing public packages.

Applied to files:

  • apps/cli/package.json
📚 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: Use task-master next to select the next actionable task with all dependencies satisfied

Applied to files:

  • apps/cli/src/commands/next.command.ts
  • apps/cli/src/commands/start.command.ts
📚 Learning: 2025-10-08T19:57:00.982Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.

Applied to files:

  • packages/tm-core/src/index.ts
📚 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:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Use graph traversal algorithms (DFS) to detect cycles

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Detect circular dependencies, validate dependency references, and support cross-tag dependency checking (future enhancement) in dependency analysis utilities.

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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 : Handle both direct and indirect self-dependencies

Applied to files:

  • packages/tm-core/src/modules/dependencies/index.ts
📚 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:

  • packages/tm-core/src/modules/dependencies/index.ts
🧬 Code graph analysis (16)
apps/mcp/src/tools/autopilot/start.tool.ts (2)
packages/tm-core/src/index.ts (1)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (1)
  • createTmCore (150-152)
apps/cli/src/commands/autopilot.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/set-status.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/extension/src/services/terminal-manager.ts (2)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/autopilot/start.command.ts (2)
packages/tm-core/src/index.ts (1)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (1)
  • createTmCore (150-152)
apps/cli/src/commands/show.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
packages/tm-core/src/modules/git/git-domain.ts (1)
packages/tm-core/src/modules/git/adapters/git-adapter.ts (1)
  • GitAdapter (15-780)
packages/tm-core/src/modules/auth/auth-domain.ts (2)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
packages/tm-core/src/modules/auth/services/organization.service.ts (3)
  • Organization (17-21)
  • Brief (26-39)
  • RemoteTask (44-60)
apps/cli/src/commands/export.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/list.command.ts (3)
apps/cli/src/index.ts (1)
  • TmCore (44-44)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
apps/cli/src/commands/next.command.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
packages/tm-core/src/modules/tasks/tasks-domain.ts (4)
packages/tm-core/src/modules/tasks/services/task-service.ts (1)
  • TaskService (51-565)
packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1)
  • TaskExecutionService (42-308)
packages/tm-core/src/modules/tasks/services/task-loader.service.ts (1)
  • TaskValidationResult (27-40)
apps/cli/src/commands/autopilot.command.ts (1)
  • PreflightResult (34-40)
packages/tm-core/src/modules/ai/providers/base-provider.ts (1)
packages/tm-core/src/modules/ai/interfaces/ai-provider.interface.ts (3)
  • ProviderInfo (87-109)
  • AIModel (63-82)
  • ProviderUsageStats (213-240)
apps/cli/src/commands/start.command.ts (3)
apps/cli/src/index.ts (1)
  • TmCore (44-44)
packages/tm-core/src/index.ts (2)
  • TmCore (29-29)
  • createTmCore (29-29)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (46-141)
  • createTmCore (150-152)
packages/tm-core/src/index.ts (1)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (29-210)
apps/cli/src/utils/display-helpers.ts (3)
packages/tm-core/src/tm-core.ts (1)
  • TmCore (46-141)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
apps/cli/src/ui/components/header.component.ts (1)
  • displayHeader (32-81)
🪛 LanguageTool
update-task-migration-plan.md

[grammar] ~1111-~1111: Use a hyphen to join words.
Context: ...er, FuzzyTaskSearch` - Port context gathering logic from both old files 2. ...

(QB_NEW_EN_HYPHEN)

packages/build-config/CHANGELOG.md

[grammar] ~9-~9: Hier könnte ein Fehler sein.
Context: ...nfig ## null ## null ## null ## null ## 1.0.1

(QB_NEW_DE)

packages/claude-code-plugin/CHANGELOG.md

[grammar] ~3-~3: Hier könnte ein Fehler sein.
Context: # @tm/claude-code-plugin ## 0.0.3 ## 0.0.2

(QB_NEW_DE)

🪛 markdownlint-cli2 (0.18.1)
packages/ai-sdk-provider-grok-cli/CHANGELOG.md

7-7: Multiple headings with the same content

(MD024, no-duplicate-heading)

packages/build-config/CHANGELOG.md

9-9: Multiple headings with the same content

(MD024, no-duplicate-heading)

@Crunchyman-ralph Crunchyman-ralph changed the base branch from ralph/feat/update.task.remote to next October 21, 2025 14:07
@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/chore/refactor.tm.core branch from 1c9220e to d710f57 Compare October 21, 2025 14:40
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

Caution

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

⚠️ Outside diff range comments (1)
packages/tm-core/src/modules/tasks/services/task-service.ts (1)

372-385: Fix ID sorting: current numeric casts break for non‑numeric IDs (e.g., “HAM-123”).

Number(“HAM-123”) yields NaN, leading to unstable/incorrect ordering in getNextTask. Use a natural/segmented comparator that handles dotted and mixed IDs.

-        // Compare parent then subtask ID numerically
-        const [aPar, aSub] = String(a.id).split('.').map(Number);
-        const [bPar, bSub] = String(b.id).split('.').map(Number);
-        if (aPar !== bPar) return aPar - bPar;
-        return aSub - bSub;
+        return naturalCompareIds(String(a.id), String(b.id));
-  return Number(a.id) - Number(b.id);
+  return naturalCompareIds(String(a.id), String(b.id));

Add this helper (outside the class or as a private static):

function naturalCompareIds(a: string, b: string): number {
  const segA = a.split('.');
  const segB = b.split('.');
  const len = Math.max(segA.length, segB.length);
  for (let i = 0; i < len; i++) {
    const sa = segA[i] ?? '';
    const sb = segB[i] ?? '';
    const na = /^\d+$/.test(sa) ? Number(sa) : NaN;
    const nb = /^\d+$/.test(sb) ? Number(sb) : NaN;
    if (!Number.isNaN(na) && !Number.isNaN(nb)) {
      if (na !== nb) return na - nb;
    } else {
      const cmp = sa.localeCompare(sb, undefined, { numeric: true, sensitivity: 'base' });
      if (cmp !== 0) return cmp;
    }
  }
  return 0;
}

Also applies to: 401-412

♻️ Duplicate comments (5)
packages/tm-core/src/modules/tasks/services/task-service.ts (1)

17-17: Use the logger barrel import for consistency.

-import { getLogger } from '../../../common/logger/factory.js';
+import { getLogger } from '../../../common/logger/index.js';
packages/tm-core/src/tm-core.ts (3)

33-44: Docs show nonexistent APIs; update to façade methods.

- * await tmcore.auth.login({ ... });
+ * await tmcore.auth.authenticateWithOAuth({ ... });
...
- * const mainModel = tmcore.config.get('models.main');
+ * const { main: mainModel } = tmcore.config.getModelConfig();

6-19: ESM/TypeScript config: ensure verbatimModuleSyntax is enabled.

You’re using import type with .js extensions; add "verbatimModuleSyntax": true to packages/tm-core/tsconfig.json to preserve ESM import specifiers.

#!/bin/bash
# Verify NodeNext + verbatimModuleSyntax in tm-core tsconfig
jq '.compilerOptions | {module, moduleResolution, verbatimModuleSyntax}' packages/tm-core/tsconfig.json

98-108: Validate and normalize projectPath (absolute path required).

+import path from 'node:path';
...
-  if (!options.projectPath) {
+  if (!options.projectPath) {
     throw new TaskMasterError(
       'Project path is required',
       ERROR_CODES.MISSING_CONFIGURATION
     );
   }
-
-  this._projectPath = options.projectPath;
+  if (!path.isAbsolute(options.projectPath)) {
+    throw new TaskMasterError(
+      'Project path must be absolute',
+      ERROR_CODES.MISSING_CONFIGURATION
+    );
+  }
+  this._projectPath = path.resolve(options.projectPath);
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)

35-40: Critical: Duplicate TaskService instance remains unresolved.

The past review identified that TaskLoaderService creates its own internal TaskService instance at line 38, resulting in separate state and double initialization. This issue has not been addressed in the current changes.

Please apply the fix suggested in the previous review: pass the shared this.taskService to TaskLoaderService instead of configManager.getProjectRoot(), and update the TaskLoaderService constructor accordingly.

🧹 Nitpick comments (5)
packages/tm-core/src/common/interfaces/storage.interface.ts (1)

167-173: Avoid duplicating the storage type literal; centralize the resolved type.

Prefer a shared alias (e.g., type ResolvedStorageType = Exclude<StorageType,'auto'>) to keep types in sync across layers.

Example:

-	getStorageType(): 'file' | 'api';
+	getStorageType(): ResolvedStorageType;

And in BaseStorage:

-	abstract getStorageType(): 'file' | 'api';
+	abstract getStorageType(): ResolvedStorageType;

Define ResolvedStorageType once under common/types and re-use here and in adapters.

Also applies to: 250-251

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

230-236: Type storage options instead of any; safer and clearer.

-const storageOptions: any = {};
+import type { LoadTasksOptions } from '../../../common/interfaces/storage.interface.js';
+const storageOptions: LoadTasksOptions = {};
...
-const baseOptions: any = {};
+const baseOptions: LoadTasksOptions = {};

Also applies to: 253-260


96-103: Guard optional filter props with optional chaining for TS soundness.

-const canPushStatusFilter =
-  options.filter?.status &&
-  !options.filter.priority &&
-  !options.filter.tags &&
-  !options.filter.assignee &&
-  !options.filter.search &&
-  options.filter.hasSubtasks === undefined;
+const canPushStatusFilter =
+  !!options.filter?.status &&
+  !options.filter?.priority &&
+  !options.filter?.tags &&
+  !options.filter?.assignee &&
+  !options.filter?.search &&
+  options.filter?.hasSubtasks === undefined;

463-477: Defensive null‑safety in filters.

details and subtasks may be undefined on some entities; add fallbacks.

-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;
apps/cli/src/utils/display-helpers.ts (1)

37-42: Use active tag from tmCore when available; avoid defaulting to “master”.

If tmCore is provided, prefer tmCore.config.getActiveTag() to reflect real context.

-displayHeader({
-  tag: options.tag || 'master',
+displayHeader({
+  tag: options.tag || tmCore.config.getActiveTag(),
   filePath: displayInfo.filePath,
   storageType: displayInfo.storageType,
   briefInfo: displayInfo.briefInfo
});
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c9220e and d710f57.

📒 Files selected for processing (9)
  • apps/cli/src/utils/display-helpers.ts (1 hunks)
  • packages/tm-core/src/common/interfaces/storage.interface.ts (2 hunks)
  • packages/tm-core/src/modules/auth/auth-domain.ts (1 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/storage/adapters/api-storage.ts (2 hunks)
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts (2 hunks)
  • packages/tm-core/src/modules/tasks/services/task-service.ts (2 hunks)
  • packages/tm-core/src/modules/tasks/tasks-domain.ts (1 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/tm-core/src/modules/storage/adapters/api-storage.ts
  • packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{test,spec}.{js,ts,jsx,tsx}

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

**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
**/*.{test,spec}.*

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

Test files should follow naming conventions: .test., .spec., or _test. depending on the language

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
**/?(*.)+(spec|test).ts

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

In JavaScript/TypeScript projects using Jest, test files should match *.test.ts and *.spec.ts patterns

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
{packages/*/src/**/*.spec.ts,apps/*/src/**/*.spec.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Place package and app unit test files alongside source as *.spec.ts under src (packages//src//.spec.ts or apps//src//.spec.ts)

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}: Do not use async/await in test functions unless the test is explicitly exercising asynchronous behavior
Use synchronous top-level imports in tests; avoid dynamic await import()
Keep test bodies synchronous whenever possible

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
🧠 Learnings (3)
📚 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/tm-core.ts
📚 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 mcp-server/src/tools/utils.js : Use `normalizeProjectRoot(rawPath, log)`, `getRawProjectRootFromSession(session, log)`, and `withNormalizedProjectRoot(executeFn)` in `mcp-server/src/tools/utils.js` to ensure project root paths are normalized for MCP tools.

Applied to files:

  • packages/tm-core/src/tm-core.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Set mock environment variables in test setup and restore them after each test.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
🧬 Code graph analysis (4)
packages/tm-core/src/modules/tasks/tasks-domain.ts (4)
packages/tm-core/src/modules/tasks/services/task-service.ts (3)
  • TaskService (51-563)
  • GetTaskListOptions (38-45)
  • TaskListResult (22-33)
packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1)
  • TaskExecutionService (42-308)
packages/tm-core/src/modules/tasks/services/task-loader.service.ts (1)
  • TaskValidationResult (27-40)
apps/cli/src/commands/autopilot.command.ts (1)
  • PreflightResult (34-40)
packages/tm-core/src/tm-core.ts (6)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (29-219)
packages/tm-core/src/modules/auth/auth-domain.ts (1)
  • AuthDomain (37-208)
packages/tm-core/src/modules/workflow/workflow-domain.ts (1)
  • WorkflowDomain (18-98)
packages/tm-core/src/modules/git/git-domain.ts (1)
  • GitDomain (14-247)
packages/tm-core/src/modules/config/config-domain.ts (1)
  • ConfigDomain (15-116)
packages/tm-core/src/modules/integration/integration-domain.ts (1)
  • IntegrationDomain (17-34)
packages/tm-core/src/modules/auth/auth-domain.ts (2)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
packages/tm-core/src/modules/auth/services/organization.service.ts (3)
  • Organization (17-21)
  • Brief (26-39)
  • RemoteTask (44-60)
apps/cli/src/utils/display-helpers.ts (3)
packages/tm-core/src/tm-core.ts (1)
  • TmCore (46-151)
packages/tm-core/src/common/types/index.ts (1)
  • StorageType (11-11)
apps/cli/src/ui/components/header.component.ts (1)
  • displayHeader (32-81)
⏰ 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). (3)
  • GitHub Check: typecheck
  • GitHub Check: build
  • GitHub Check: Test
🔇 Additional comments (3)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)

63-89: LGTM! Clean subtask ID handling.

The get() method correctly parses dotted task IDs (e.g., "1.2"), retrieves the parent task, and validates subtask membership. The return structure clearly indicates whether the ID represents a subtask.

packages/tm-core/src/modules/auth/auth-domain.ts (2)

23-32: LGTM! Well-designed interface.

The StorageDisplayInfo interface correctly excludes 'auto' from StorageType since it represents resolved storage information. The optional fields appropriately handle different storage contexts.


188-207: LGTM! Robust URL construction.

The getWebAppUrl() helper correctly handles environment variable fallbacks, protocol detection, and local vs. remote domain differentiation. The logic is defensive and handles edge cases well.

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: 0

Caution

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

⚠️ Outside diff range comments (1)
packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (1)

50-58: Remove unnecessary async from getBriefIdOrThrow() and update all callers.

AuthManager.getContext() is synchronous, so getBriefIdOrThrow() no longer needs to be async. The method has no await operations, yet is still declared as async with a Promise<string> return type, forcing unnecessary awaits at all three call sites (lines 64, 117, 160).

Apply these changes:

-	private async getBriefIdOrThrow(): Promise<string> {
+	private getBriefIdOrThrow(): string {
 		const context = this.authManager.getContext();
 		if (!context?.briefId) {
 			throw new Error(
 				'No brief selected. Please select a brief first using: tm context brief'
 			);
 		}
 		return context.briefId;
 	}

Update callers:

-		const briefId = await this.getBriefIdOrThrow();
+		const briefId = this.getBriefIdOrThrow();
♻️ Duplicate comments (1)
packages/tm-core/src/tm-core.ts (1)

36-44: Fix doc example to match actual API.

The example uses non-existent methods:

  • tmcore.auth.login(...) should be tmcore.auth.authenticateWithOAuth(...)
  • tmcore.config.get('models.main') should be tmcore.config.getModelConfig() or tmcore.config.getConfig()

Based on the AuthDomain and ConfigDomain facades in the codebase.

🧹 Nitpick comments (1)
packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (1)

136-146: Consider removing the type cast to catch type mismatches.

The as AuthCredentials cast on line 146 may mask type errors. If all required fields of AuthCredentials are genuinely populated by this point, the cast should be unnecessary. Consider verifying that:

  • userId is guaranteed to have a value (line 142 has a fallback chain but might not cover all cases)
  • All required fields in AuthCredentials are properly set

If you prefer to keep the cast for practical reasons, consider adding a runtime assertion or comment explaining why the cast is safe.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d710f57 and 3819146.

📒 Files selected for processing (8)
  • apps/cli/src/commands/autopilot.command.ts (7 hunks)
  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (5 hunks)
  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (2 hunks)
  • packages/tm-core/src/modules/tasks/services/task-loader.service.ts (2 hunks)
  • packages/tm-core/src/modules/tasks/tasks-domain.ts (1 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/cli/src/commands/autopilot.command.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{test,spec}.{js,ts,jsx,tsx}

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

**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
**/*.{test,spec}.*

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

Test files should follow naming conventions: .test., .spec., or _test. depending on the language

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
**/?(*.)+(spec|test).ts

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

In JavaScript/TypeScript projects using Jest, test files should match *.test.ts and *.spec.ts patterns

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
{packages/*/src/**/*.spec.ts,apps/*/src/**/*.spec.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Place package and app unit test files alongside source as *.spec.ts under src (packages//src//.spec.ts or apps//src//.spec.ts)

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}

📄 CodeRabbit inference engine (CLAUDE.md)

{packages/*/src/**/*.@(spec|test).ts,apps/*/src/**/*.@(spec|test).ts,packages/*/tests/**/*.@(spec|test).ts,apps/*/tests/**/*.@(spec|test).ts,tests/unit/packages/*/**/*.@(spec|test).ts}: Do not use async/await in test functions unless the test is explicitly exercising asynchronous behavior
Use synchronous top-level imports in tests; avoid dynamic await import()
Keep test bodies synchronous whenever possible

Files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
**/*.test.ts

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

**/*.test.ts: Use established mocking patterns for dependencies such as bcrypt and Prisma in test files
Test all code paths, including edge cases and error scenarios, in test files
Use descriptive names for test functions, such as should_return_error_for_invalid_input

Files:

  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
{packages/*/tests/integration/**/*.test.ts,apps/*/tests/integration/**/*.test.ts}

📄 CodeRabbit inference engine (CLAUDE.md)

Place integration tests under tests/integration as *.test.ts for packages and apps

Files:

  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not import real AI service clients in tests; create fully mocked versions that return predictable responses.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Troubleshoot mock functions not being called by ensuring mocks are defined before imports, referencing the correct mock instance, and verifying import paths.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Follow the test file organization: mocks must be set up before importing modules under test, and spies on mocked modules should be set up after imports.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Be careful with how you mock or stub functions that depend on module state; use factory functions in mocks to ensure proper initialization order.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{integration,e2e}/**/*.test.js : Properly mock session objects when required by functions, and reset environment variables between tests if modified.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Always declare mocks before importing the modules being tested in Jest test files.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Do not try to use the real action implementation without proper mocking, and do not mock Commander partially—either mock it completely or test the action directly.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Follow the mock-first-then-import pattern for all Jest mocks.

Applied to files:

  • packages/tm-core/src/modules/config/managers/config-manager.spec.ts
📚 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 mcp-server/src/tools/utils.js : Use `normalizeProjectRoot(rawPath, log)`, `getRawProjectRootFromSession(session, log)`, and `withNormalizedProjectRoot(executeFn)` in `mcp-server/src/tools/utils.js` to ensure project root paths are normalized for MCP tools.

Applied to files:

  • packages/tm-core/src/tm-core.ts
📚 Learning: 2025-10-15T14:43:40.410Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.410Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts
🧬 Code graph analysis (3)
packages/tm-core/src/modules/tasks/tasks-domain.ts (4)
packages/tm-core/src/modules/tasks/services/task-service.ts (3)
  • TaskService (51-563)
  • GetTaskListOptions (38-45)
  • TaskListResult (22-33)
packages/tm-core/src/modules/tasks/services/task-execution-service.ts (1)
  • TaskExecutionService (42-308)
packages/tm-core/src/modules/tasks/services/task-loader.service.ts (2)
  • TaskLoaderService (58-384)
  • TaskValidationResult (26-39)
apps/cli/src/commands/autopilot.command.ts (1)
  • PreflightResult (34-40)
packages/tm-core/src/modules/tasks/services/task-loader.service.ts (1)
packages/tm-core/src/modules/tasks/services/task-service.ts (1)
  • TaskService (51-563)
packages/tm-core/src/tm-core.ts (6)
packages/tm-core/src/modules/tasks/tasks-domain.ts (1)
  • TasksDomain (29-219)
packages/tm-core/src/modules/auth/auth-domain.ts (1)
  • AuthDomain (37-208)
packages/tm-core/src/modules/workflow/workflow-domain.ts (1)
  • WorkflowDomain (18-98)
packages/tm-core/src/modules/git/git-domain.ts (1)
  • GitDomain (14-247)
packages/tm-core/src/modules/config/config-domain.ts (1)
  • ConfigDomain (15-116)
packages/tm-core/src/modules/integration/integration-domain.ts (1)
  • IntegrationDomain (17-34)
⏰ 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). (3)
  • GitHub Check: Test
  • GitHub Check: build
  • GitHub Check: typecheck
🔇 Additional comments (20)
packages/tm-core/tests/integration/auth-token-refresh.test.ts (1)

13-15: LGTM! Import paths correctly updated to new module structure.

The import paths have been properly updated to reflect the new domain-driven architecture under src/modules/auth/, and the .js extensions follow ESM best practices. No test logic was modified, which is appropriate for this refactoring.

packages/tm-core/src/modules/config/managers/config-manager.spec.ts (1)

8-20: LGTM! Import and mock paths correctly updated.

The refactor properly updates all import paths to reflect the new domain structure:

  • DEFAULT_CONFIG_VALUES correctly imports from the common interfaces module
  • All service imports consistently use ../services/ paths
  • Mock declarations perfectly match their corresponding import paths

The past review concerns have been fully addressed.

packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (6)

10-12: LGTM! Import paths updated for domain structure.

The import path changes align with the broader refactoring to a domain-driven architecture.


27-43: LGTM! Improved session building logic.

Removing the hardcoded expiration default and conditionally including expires_at only when present is the correct approach. This allows Supabase to manage the refresh lifecycle without arbitrary values interfering.


48-69: LGTM! Defensive input handling.

Accepting both string and object formats for sessionData is good defensive programming and handles variability in how Supabase may invoke this method.


74-96: LGTM! Stricter validation prevents partial sessions.

The removal of the explicit allowExpired parameter is safe since getCredentials() defaults to allowExpired: true (based on learnings). The new validation requiring both access token and refresh token prevents partial session states while still allowing Supabase to handle token refresh for expired but complete sessions.

Based on learnings.


114-125: LGTM! Critical validation for atomic token rotation.

The validation ensuring both token and refreshToken are present before saving is essential for preventing partial session states during Supabase's refresh token rotation. The warning log provides good visibility when incomplete updates occur.


127-157: Excellent atomic handling of refresh token rotation.

The implementation correctly:

  • Detects refresh token rotation for debugging visibility
  • Atomically updates all credential fields together
  • Adds comprehensive logging for troubleshooting
  • Synchronously saves to ensure atomicity during refresh

This is exactly the right approach for handling Supabase's token rotation flow.

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

2-11: All refactored import paths resolve correctly and export the expected symbols.

Verification confirms that all seven imports successfully resolve to their source files and all imported symbols are properly exported:

  • Task from index.ts
  • Database and Json from database.types.ts
  • TaskMapper from TaskMapper.ts
  • AuthManager from auth-manager.ts
  • DependencyFetcher from dependency-fetcher.ts
  • TaskWithRelations and TaskDatabaseUpdate from repository-types.ts
  • LoadTasksOptions from storage.interface.ts

The refactoring is complete and correct.

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

6-8: LGTM! Import paths align with refactoring.

The updated import paths to common/types and common/logger are consistent with the domain-driven restructuring. Using import type for TaskService is correct since it's only referenced in type positions.


59-66: Excellent refactor to dependency injection.

Accepting TaskService as a constructor parameter enables sharing a single instance across services, eliminating the duplicate state issue from the previous architecture. The null check is good defensive programming.


121-128: LGTM! Simplified control flow.

Direct usage of this.taskService is safe since the constructor enforces a non-null instance. This removes the complexity of lazy initialization.

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

6-29: LGTM! Clean interface and imports.

The TmCoreOptions interface is clear and well-documented. ESM imports with .js extensions are consistent with the NodeNext module settings.


49-78: LGTM! Type-safe initialization pattern.

Using private definite-assignment fields with public getters avoids the type-casting issues from earlier iterations. The pattern is clean and maintains type safety.


107-113: Path validation is correct.

Good use of path.isAbsolute() and path.resolve() to validate and normalize the project path. The error message helpfully includes the received value.


125-153: LGTM! Initialization sequence is well-structured.

The initialization order (ConfigManager → domains → async setup) is logical. Error handling consistently wraps failures with operation context.

packages/tm-core/src/modules/tasks/tasks-domain.ts (4)

6-24: LGTM! Well-organized imports.

Imports are logically grouped and use type-only imports where appropriate. Consistent ESM .js extensions.


35-40: Excellent! Shared TaskService instance eliminates state duplication.

Line 38 correctly passes the shared this.taskService to TaskLoaderService, ensuring all services operate on the same state. This directly addresses the critical issue from the past review about duplicate TaskService instances.


63-89: LGTM! Subtask ID parsing is well-implemented.

The method cleanly handles both regular task IDs and subtask notation (e.g., "1.2"), returning the parent task with an isSubtask flag. The logic is straightforward and robust.


91-219: LGTM! Comprehensive and well-organized facade API.

The TasksDomain provides a clean, unified interface for task operations. Methods are logically grouped, delegate appropriately to underlying services, and maintain consistent naming conventions.

@Crunchyman-ralph Crunchyman-ralph force-pushed the ralph/chore/refactor.tm.core branch from 3819146 to a3825b7 Compare October 21, 2025 15:58
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

🧹 Nitpick comments (2)
packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (2)

100-101: “Atomic” here is process-local; add file-level atomicity if multi-process is possible.

If multiple CLI instances can refresh simultaneously, consider atomic file writes (write-temp + fs.rename) or advisory locking in CredentialStore to prevent interleaving.


106-106: Reduce log level to avoid noise on every refresh call.

Demote to debug; keep the success/info log below for visibility.

-        this.logger.info('Supabase called setItem - storing refreshed session');
+        this.logger.debug('Supabase called setItem - storing refreshed session');
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3819146 and a3825b7.

📒 Files selected for processing (4)
  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (5 hunks)
  • packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (5 hunks)
  • packages/tm-core/src/tm-core.ts (1 hunks)
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/tm-core/tests/integration/auth-token-refresh.test.ts
  • packages/tm-core/src/tm-core.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1282
File: packages/tm-core/src/utils/index.ts:16-34
Timestamp: 2025-10-08T19:57:00.982Z
Learning: For the tm-core package in the eyaltoledano/claude-task-master repository, the team prefers a minimal, need-based export strategy in index files rather than exposing all internal utilities. Exports should only be added when functions are actually consumed by other packages in the monorepo.
📚 Learning: 2025-10-15T14:43:40.410Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.410Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts
⏰ 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 (5)
packages/tm-core/src/modules/tasks/repositories/supabase/supabase-task-repository.ts (2)

2-11: Import path refactoring looks good.

The updated import paths correctly reflect the new domain-driven architecture with centralized common modules. This aligns with the PR's stated objective.


50-58: ****

AuthManager.getContext() is a synchronous method that returns UserContext | null directly—not a Promise. The method is defined at packages/tm-core/src/modules/auth/managers/auth-manager.ts:180-183 with the signature getContext(): UserContext | null. The change from await this.authManager.getContext() to this.authManager.getContext() is correct and actually fixes the buggy behavior of awaiting a non-Promise value.

Likely an incorrect or invalid review comment.

packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (3)

32-35: LGTM: defer expires_at to Supabase when absent.

Only including expires_at when present is correct and avoids arbitrary defaults.


78-90: Session retrieval criteria are sound (require both tokens, let Supabase refresh).

Requiring both access and refresh tokens and not forcing expiry checks aligns with our design where allowExpired defaults to true in the store.

Based on learnings.


127-135: Nice: rotation detection + debug log aids incident triage.

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: 0

Caution

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

⚠️ Outside diff range comments (1)
apps/extension/src/services/terminal-manager.ts (1)

71-75: Command injection risk: unescaped user content is interpolated into a shell command.

executionOutput may contain quotes/newlines/shell metacharacters. Sending it directly via terminal.sendText is unsafe and shell-dependent.

Apply this minimal, cross‑platform quoting fix and use it when building the command:

-      const command = `claude "${startResult.executionOutput}"`;
+      const command = `claude ${this.quoteForShell(startResult.executionOutput)}`;
       terminal.sendText(command);

Add this helper to the class (POSIX single‑quote strategy; PowerShell single‑quote doubling; normalize newlines):

private quoteForShell(arg: string): string {
  const s = String(arg ?? '').replace(/\r?\n/g, ' ');
  if (process.platform === 'win32') {
    // Prefer PowerShell-safe quoting by default on Windows terminals
    return `'${s.replace(/'/g, "''")}'`;
  }
  // POSIX shells
  return `'${s.replace(/'/g, `'\\''`)}'`;
}

Alternatively (preferred), switch to vscode.tasks with ShellExecution to let VS Code handle quoting per shell.

🧹 Nitpick comments (6)
apps/extension/src/services/terminal-manager.ts (6)

52-56: Validate the tasks.start() contract and narrow types.

You assume { started, executionOutput, error }. Please confirm this is the new stable return shape and, if available, import its type to avoid structural assumptions.


108-114: Memoize core initialization to avoid races and duplicate work.

Concurrent executeTask calls can trigger multiple createTmCore() runs. Memoize with a Promise and have initializeCore return the instance.

Example:

- private tmCore?: TmCore;
+ private tmCore?: TmCore;
+ private tmCoreInit?: Promise<TmCore>;

- private async initializeCore(): Promise<void> {
-   if (!this.tmCore) {
+ private async initializeCore(): Promise<TmCore> {
+   if (!this.tmCore && !this.tmCoreInit) {
      const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
      if (!workspaceRoot) {
        throw new Error('No workspace folder found');
      }
-     this.tmCore = await createTmCore({ projectPath: workspaceRoot });
+     this.tmCoreInit = createTmCore({ projectPath: workspaceRoot }).then(core => {
+       this.tmCore = core;
+       this.tmCoreInit = undefined;
+       return core;
+     }).catch(err => {
+       this.tmCoreInit = undefined;
+       throw err;
+     });
    }
- }
+   return this.tmCore ?? (await this.tmCoreInit!);
+ }

127-131: Dispose terminals when cleaning up entries.

Currently you only remove the map entry. Dispose to avoid leaked terminals if callers assume cleanupTerminal fully cleans resources.

   cleanupTerminal(taskId: string): void {
     const terminal = this.terminals.get(taskId);
     if (terminal) {
+      try { terminal.dispose(); } catch {}
       this.terminals.delete(taskId);
     }
   }

Also consider wiring vscode.window.onDidCloseTerminal to prune the map on user-initiated closes.


147-150: Confirm whether TmCore needs explicit shutdown.

If tm-core wires watchers/IO, a dispose/shutdown might be required. If such API exists, call it; otherwise, clearing the reference is fine.

Example:

if (this.tmCore && typeof (this.tmCore as any).dispose === 'function') {
  try { await (this.tmCore as any).dispose(); } catch (e) { this.logger.error('tm-core dispose failed:', e); }
}
this.tmCore = undefined;

24-24: Optional: avoid non‑null assertions downstream.

After memoized initializeCore returns TmCore, use a local const tmCore = await this.initializeCore() and call tmCore.tasks.start(...) to eliminate this.tmCore! usage.


43-46: Demote or remove debug-only log.

“TaskId type: …” seems temporary. Consider removing or guarding behind a debug flag to reduce log noise.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3825b7 and c2ceedb.

📒 Files selected for processing (3)
  • apps/extension/package.json (1 hunks)
  • apps/extension/src/services/terminal-manager.ts (5 hunks)
  • packages/tm-core/src/task-master-core.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/tm-core/src/task-master-core.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/extension/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
apps/extension/src/services/terminal-manager.ts (1)
packages/tm-core/src/tm-core.ts (2)
  • TmCore (47-161)
  • createTmCore (170-172)
⏰ 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). (3)
  • GitHub Check: typecheck
  • GitHub Check: build
  • GitHub Check: Test
🔇 Additional comments (1)
apps/extension/src/services/terminal-manager.ts (1)

7-7: Migration to the new @tm/core surface looks correct.

Import rename to createTmCore/TmCore is aligned with the unified facade.

@Crunchyman-ralph Crunchyman-ralph merged commit 03b7ef9 into next Oct 21, 2025
8 of 9 checks passed
@Crunchyman-ralph Crunchyman-ralph deleted the ralph/chore/refactor.tm.core branch October 21, 2025 19:16
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: 0

🧹 Nitpick comments (2)
.github/workflows/extension-ci.yml (1)

9-10: Minor: Consistent YAML string quoting.

The path filter strings are now double-quoted, which is cosmetically more consistent with YAML best practices but functionally equivalent to the previous format.

Also applies to: 16-17

packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (1)

78-89: Consider explicitly passing allowExpired: true for consistency.

While getCredentials() defaults to allowExpired: true (per learnings), setItem at lines 110-111 explicitly passes this parameter. For consistency and clarity, consider making it explicit here as well.

Apply this diff for consistency:

-				const credentials = this.store.getCredentials();
+				const credentials = this.store.getCredentials({ allowExpired: true });

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c2ceedb and 0c6b915.

📒 Files selected for processing (5)
  • .github/workflows/extension-ci.yml (2 hunks)
  • .github/workflows/extension-release.yml (2 hunks)
  • apps/extension/docs/extension-CI-setup.md (1 hunks)
  • apps/extension/docs/extension-development-guide.md (1 hunks)
  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (5 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/extension/docs/extension-CI-setup.md
  • apps/extension/docs/extension-development-guide.md
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-15T14:43:40.410Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1314
File: packages/tm-core/src/auth/credential-store.ts:92-94
Timestamp: 2025-10-15T14:43:40.410Z
Learning: In the claude-task-master codebase, `getCredentials()` in `credential-store.ts` defaults to `allowExpired: true` to enable Supabase refresh flows. The Supabase client automatically handles token refresh when credentials are expired but have a valid refresh token. The `SupabaseSessionStorage` updates the credentials after Supabase performs the refresh. This is an intentional design pattern where the credential store is passive storage and Supabase manages the active token lifecycle.

Applied to files:

  • packages/tm-core/src/modules/auth/services/supabase-session-storage.ts
⏰ 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). (3)
  • GitHub Check: typecheck
  • GitHub Check: build
  • GitHub Check: Test
🔇 Additional comments (7)
.github/workflows/extension-release.yml (2)

110-110: Minor: Add notification message to success output.

This is a cosmetic addition to the success notification that informs users about the GitHub release. The change adds useful context to the workflow completion message.


40-40: npm script typecheck exists and is properly configured.

Verification confirms that apps/extension/package.json contains "typecheck": "tsc --noEmit". The script name change from check-types to typecheck is valid and the workflow will execute successfully.

.github/workflows/extension-ci.yml (1)

74-74: No action required—the typecheck script is properly configured.

Verification confirms the typecheck script exists in apps/extension/package.json with value "tsc --noEmit", and the old check-types script has been successfully removed. The workflow change to npm run typecheck introduces no breaking changes.

packages/tm-core/src/modules/auth/services/supabase-session-storage.ts (4)

9-12: LGTM! Import issues from previous review have been resolved.

The imports now correctly use type-only imports for SupportedStorage and AuthCredentials, and the path to CredentialStore has been fixed to reference the same directory.


32-35: Good defensive change: conditionally include expires_at.

Removing the arbitrary 1-hour default and only including expires_at when it exists allows Supabase to handle token refresh properly without incorrect expiry information.


52-59: Excellent fixes: flexible session parsing and proper userId handling.

Two improvements here:

  1. Handling both string and object formats makes the parser more robust
  2. Line 59 no longer defaults userId to 'unknown', which fixes the critical issue from the previous review where the truthy default would bypass downstream validation

110-167: Excellent refactoring! All critical issues from previous review have been resolved.

The atomic update logic is well-implemented with:

  • Safe spreading using ?? {} at line 148 (fixes past crash on null)
  • Proper nullish coalescing (??) for userId and email at lines 137 and 153
  • Robust validation preventing partial session states
  • Clear logging for rotation detection and debugging

The explicit allowExpired: true parameter and comprehensive error handling demonstrate good defensive programming.

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